<commit_before>package pod

import (
	"encoding/json"
	"fmt"
	"io"
	"syscall"
	"time"

	"github.com/docker/docker/pkg/stdcopy"

	"github.com/hyperhq/hypercontainer-utils/hlog"
	"github.com/hyperhq/hyperd/utils"
	"github.com/hyperhq/runv/api"
	"github.com/hyperhq/runv/hypervisor"
)

type Exec struct {
	Id        string
	Container string
	Cmds      []string
	Terminal  bool
	ExitCode  uint8

	logPrefix string
	finChan   chan bool
}

func (e *Exec) LogPrefix() string {
	return e.logPrefix
}

func (e *Exec) Log(level hlog.LogLevel, args ...interface{}) {
	hlog.HLog(level, e, 1, args...)
}

func (p *XPod) CreateExec(containerId, cmds string, terminal bool) (string, error) {
	c, ok := p.containers[containerId]
	if !ok {
		err := fmt.Errorf("no container available for exec %s", cmds)
		p.Log(ERROR, err)
		return "", err
	}

	if !c.IsAlive() {
		err := fmt.Errorf("container is not available (%v) for exec %s", c.CurrentState(), cmds)
		p.Log(ERROR, err)
		return "", err
	}
	var command []string
	if err := json.Unmarshal([]byte(cmds), &command); err != nil {
		return "", err
	}

	execId := fmt.Sprintf("exec-%s", utils.RandStr(10, "alpha"))

	p.statusLock.Lock()
	p.execs[execId] = &Exec{
		Container: containerId,
		Id:        execId,
		Cmds:      command,
		Terminal:  terminal,
		ExitCode:  255,
		logPrefix: fmt.Sprintf("Pod[%s] Con[%s] Exec[%s] ", p.Id(), containerId[:12], execId),
		finChan:   make(chan bool, 1),
	}
	p.statusLock.Unlock()

	return execId, nil
}

type waitClose struct {
	io.ReadCloser
	wait chan bool
}

func (wc *waitClose) Close() error {
	close(wc.wait)
	return wc.ReadCloser.Close()
}

type writeCloser struct {
	io.Writer
	closer io.Closer
}

func (wc *writeCloser) Close() error {
	return wc.closer.Close()
}

func (p *XPod) StartExec(stdin io.ReadCloser, stdout io.WriteCloser, containerId, execId string) error {
	c, ok := p.containers[containerId]
	if !ok {
		err := fmt.Errorf("no container %s available for exec %s", containerId, execId)
		p.Log(ERROR, err)
		return err
	}

	p.statusLock.RLock()
	es, ok := p.execs[execId]
	p.statusLock.RUnlock()

	if !ok {
		err := fmt.Errorf("no exec %s exists for container %s", execId, containerId)
		p.Log(ERROR, err)
		return err
	}

	wReader := &waitClose{ReadCloser: stdin, wait: make(chan bool)}
	tty := &hypervisor.TtyIO{
		Stdin:  wReader,
		Stdout: stdout,
	}

	if !es.Terminal && stdout != nil {
		tty.Stderr = stdcopy.NewStdWriter(stdout, stdcopy.Stderr)
		tty.Stdout = &writeCloser{stdcopy.NewStdWriter(stdout, stdcopy.Stdout), stdout}
	}

	var fin = true
	for fin {
		select {
		case fin = <-es.finChan:
			es.Log(DEBUG, "try to drain the sync chan")
		default:
			fin = false
			es.Log(DEBUG, "the sync chan is empty")
		}
	}

	go func(es *Exec) {
		result := p.sandbox.WaitProcess(false, []string{execId}, -1)
		if result == nil {
			es.Log(ERROR, "can not wait exec")
			return
		}

		r, ok := <-result
		if !ok {
			es.Log(ERROR, "waiting exec interrupted")
			return
		}

		es.Log(DEBUG, "exec terminated at %v with code %d", r.FinishedAt, r.Code)
		es.ExitCode = uint8(r.Code)
		select {
		case es.finChan <- true:
			es.Log(DEBUG, "wake exec stopped chan")
		default:
			es.Log(WARNING, "exec already set as stopped")
		}
	}(es)

	var envs []string
	for e, v := range c.descript.Envs {
		envs = append(envs, fmt.Sprintf("%s=%s", e, v))
	}

	process := &api.Process{
		Container: es.Container,
		Id:        es.Id,
		Terminal:  es.Terminal,
		Args:      es.Cmds,
		Envs:      envs,
		Workdir:   c.descript.Workdir,
	}

	if c.descript.UGI != nil {
		process.User = c.descript.UGI.User
		process.Group = c.descript.UGI.Group
		process.AdditionalGroup = c.descript.UGI.AdditionalGroups
	}

	err := p.sandbox.AddProcess(process, tty)

	<-wReader.wait
	return err
}

func (p *XPod) GetExecExitCode(containerId, execId string) (uint8, error) {
	p.statusLock.RLock()
	es, ok := p.execs[execId]
	p.statusLock.RUnlock()

	if !ok {
		err := fmt.Errorf("no exec %s exists for container %s", execId, containerId)
		p.Log(ERROR, err)
		return 255, err
	}

	select {
	case <-es.finChan:
		es.finChan <- true
	case <-time.After(time.Second * 10):
		err := fmt.Errorf("wait exec exit code timeout")
		es.Log(ERROR, err)
		return 255, err
	}
	es.Log(INFO, "got exec exit code: %d", es.ExitCode)
	return es.ExitCode, nil
}

func (p *XPod) KillExec(execId string, sig int64) error {
	p.statusLock.RLock()
	es, ok := p.execs[execId]
	p.statusLock.RUnlock()

	if !ok {
		err := fmt.Errorf("no exec %s exists for pod %s", execId, p.Id)
		p.Log(ERROR, err)
		return err
	}

	return p.protectedSandboxOperation(
		func(sb *hypervisor.Vm) error {
			return sb.SignalProcess(es.Container, es.Id, syscall.Signal(sig))
		},
		time.Second*5,
		fmt.Sprintf("Kill process %s with %d", es.Id, sig))
}

func (p *XPod) DeleteExec(containerId, execId string) {
	p.statusLock.Lock()
	delete(p.execs, execId)
	p.statusLock.Unlock()
}

func (p *XPod) CleanupExecs() {
	p.statusLock.Lock()
	p.execs = make(map[string]*Exec)
	p.statusLock.Unlock()
}

func (p *XPod) ExecVM(cmd string, stdin io.ReadCloser, stdout, stderr io.WriteCloser) (int, error) {
	wReader := &waitClose{ReadCloser: stdin, wait: make(chan bool)}
	tty := &hypervisor.TtyIO{
		Stdin:  wReader,
		Stdout: stdout,
		Stderr: stderr,
	}
	res, err := p.sandbox.HyperstartExec(cmd, tty)
	if err != nil {
		return res, err
	}
	<-wReader.wait
	return res, err
}
<commit_msg>simplify writeCloser<commit_after>package pod

import (
	"encoding/json"
	"fmt"
	"io"
	"syscall"
	"time"

	"github.com/docker/docker/pkg/stdcopy"

	"github.com/hyperhq/hypercontainer-utils/hlog"
	"github.com/hyperhq/hyperd/utils"
	"github.com/hyperhq/runv/api"
	"github.com/hyperhq/runv/hypervisor"
)

type Exec struct {
	Id        string
	Container string
	Cmds      []string
	Terminal  bool
	ExitCode  uint8

	logPrefix string
	finChan   chan bool
}

func (e *Exec) LogPrefix() string {
	return e.logPrefix
}

func (e *Exec) Log(level hlog.LogLevel, args ...interface{}) {
	hlog.HLog(level, e, 1, args...)
}

func (p *XPod) CreateExec(containerId, cmds string, terminal bool) (string, error) {
	c, ok := p.containers[containerId]
	if !ok {
		err := fmt.Errorf("no container available for exec %s", cmds)
		p.Log(ERROR, err)
		return "", err
	}

	if !c.IsAlive() {
		err := fmt.Errorf("container is not available (%v) for exec %s", c.CurrentState(), cmds)
		p.Log(ERROR, err)
		return "", err
	}
	var command []string
	if err := json.Unmarshal([]byte(cmds), &command); err != nil {
		return "", err
	}

	execId := fmt.Sprintf("exec-%s", utils.RandStr(10, "alpha"))

	p.statusLock.Lock()
	p.execs[execId] = &Exec{
		Container: containerId,
		Id:        execId,
		Cmds:      command,
		Terminal:  terminal,
		ExitCode:  255,
		logPrefix: fmt.Sprintf("Pod[%s] Con[%s] Exec[%s] ", p.Id(), containerId[:12], execId),
		finChan:   make(chan bool, 1),
	}
	p.statusLock.Unlock()

	return execId, nil
}

type waitClose struct {
	io.ReadCloser
	wait chan bool
}

func (wc *waitClose) Close() error {
	close(wc.wait)
	return wc.ReadCloser.Close()
}

type writeCloser struct {
	io.Writer
	io.Closer
}

func (p *XPod) StartExec(stdin io.ReadCloser, stdout io.WriteCloser, containerId, execId string) error {
	c, ok := p.containers[containerId]
	if !ok {
		err := fmt.Errorf("no container %s available for exec %s", containerId, execId)
		p.Log(ERROR, err)
		return err
	}

	p.statusLock.RLock()
	es, ok := p.execs[execId]
	p.statusLock.RUnlock()

	if !ok {
		err := fmt.Errorf("no exec %s exists for container %s", execId, containerId)
		p.Log(ERROR, err)
		return err
	}

	wReader := &waitClose{ReadCloser: stdin, wait: make(chan bool)}
	tty := &hypervisor.TtyIO{
		Stdin:  wReader,
		Stdout: stdout,
	}

	if !es.Terminal && stdout != nil {
		tty.Stderr = stdcopy.NewStdWriter(stdout, stdcopy.Stderr)
		tty.Stdout = &writeCloser{stdcopy.NewStdWriter(stdout, stdcopy.Stdout), stdout}
	}

	var fin = true
	for fin {
		select {
		case fin = <-es.finChan:
			es.Log(DEBUG, "try to drain the sync chan")
		default:
			fin = false
			es.Log(DEBUG, "the sync chan is empty")
		}
	}

	go func(es *Exec) {
		result := p.sandbox.WaitProcess(false, []string{execId}, -1)
		if result == nil {
			es.Log(ERROR, "can not wait exec")
			return
		}

		r, ok := <-result
		if !ok {
			es.Log(ERROR, "waiting exec interrupted")
			return
		}

		es.Log(DEBUG, "exec terminated at %v with code %d", r.FinishedAt, r.Code)
		es.ExitCode = uint8(r.Code)
		select {
		case es.finChan <- true:
			es.Log(DEBUG, "wake exec stopped chan")
		default:
			es.Log(WARNING, "exec already set as stopped")
		}
	}(es)

	var envs []string
	for e, v := range c.descript.Envs {
		envs = append(envs, fmt.Sprintf("%s=%s", e, v))
	}

	process := &api.Process{
		Container: es.Container,
		Id:        es.Id,
		Terminal:  es.Terminal,
		Args:      es.Cmds,
		Envs:      envs,
		Workdir:   c.descript.Workdir,
	}

	if c.descript.UGI != nil {
		process.User = c.descript.UGI.User
		process.Group = c.descript.UGI.Group
		process.AdditionalGroup = c.descript.UGI.AdditionalGroups
	}

	err := p.sandbox.AddProcess(process, tty)

	<-wReader.wait
	return err
}

func (p *XPod) GetExecExitCode(containerId, execId string) (uint8, error) {
	p.statusLock.RLock()
	es, ok := p.execs[execId]
	p.statusLock.RUnlock()

	if !ok {
		err := fmt.Errorf("no exec %s exists for container %s", execId, containerId)
		p.Log(ERROR, err)
		return 255, err
	}

	select {
	case <-es.finChan:
		es.finChan <- true
	case <-time.After(time.Second * 10):
		err := fmt.Errorf("wait exec exit code timeout")
		es.Log(ERROR, err)
		return 255, err
	}
	es.Log(INFO, "got exec exit code: %d", es.ExitCode)
	return es.ExitCode, nil
}

func (p *XPod) KillExec(execId string, sig int64) error {
	p.statusLock.RLock()
	es, ok := p.execs[execId]
	p.statusLock.RUnlock()

	if !ok {
		err := fmt.Errorf("no exec %s exists for pod %s", execId, p.Id)
		p.Log(ERROR, err)
		return err
	}

	return p.protectedSandboxOperation(
		func(sb *hypervisor.Vm) error {
			return sb.SignalProcess(es.Container, es.Id, syscall.Signal(sig))
		},
		time.Second*5,
		fmt.Sprintf("Kill process %s with %d", es.Id, sig))
}

func (p *XPod) DeleteExec(containerId, execId string) {
	p.statusLock.Lock()
	delete(p.execs, execId)
	p.statusLock.Unlock()
}

func (p *XPod) CleanupExecs() {
	p.statusLock.Lock()
	p.execs = make(map[string]*Exec)
	p.statusLock.Unlock()
}

func (p *XPod) ExecVM(cmd string, stdin io.ReadCloser, stdout, stderr io.WriteCloser) (int, error) {
	wReader := &waitClose{ReadCloser: stdin, wait: make(chan bool)}
	tty := &hypervisor.TtyIO{
		Stdin:  wReader,
		Stdout: stdout,
		Stderr: stderr,
	}
	res, err := p.sandbox.HyperstartExec(cmd, tty)
	if err != nil {
		return res, err
	}
	<-wReader.wait
	return res, err
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
//	http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

// Package httpclient provides a thin, but testable, wrapper around http.Client.
// It adds an ECS header to requests and provides an interface
package httpclient

import (
	"crypto/tls"
	"net"
	"net/http"
	"time"

	"github.com/aws/amazon-ecs-agent/agent/version"
)

const defaultTimeout = 10 * time.Minute

// Taken from the default http.Client behavior
const defaultDialTimeout = 30 * time.Second
const defaultDialKeepalive = 30 * time.Second

//go:generate go run ../../scripts/generate/mockgen.go net/http RoundTripper mock/$GOFILE

type ecsRoundTripper struct {
	insecureSkipVerify bool
	transport          http.RoundTripper
}

func userAgent() string {
	return version.String() + " (+http://aws.amazon.com/ecs/)"
}

func (client *ecsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	req.Header.Set("User-Agent", userAgent())
	return client.transport.RoundTrip(req)
}

func (client *ecsRoundTripper) CancelRequest(req *http.Request) {
	if def, ok := client.transport.(*http.Transport); ok {
		def.CancelRequest(req)
	}
}

// New returns an ECS httpClient with a roundtrip timeout of the given duration
func New(timeout time.Duration, insecureSkipVerify bool) *http.Client {
	// Transport is the transport requests will be made over
	// Note, these defaults are taken from the golang http library. We do not
	// explicitly do not use theirs to avoid changing their behavior.
	transport := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   defaultDialTimeout,
			KeepAlive: defaultDialKeepalive,
		}).Dial,
		TLSHandshakeTimeout: 10 * time.Second,
	}
	if insecureSkipVerify {
		transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	}
	client := &http.Client{
		Transport: &ecsRoundTripper{insecureSkipVerify, transport},
		Timeout:   timeout,
	}

	return client
}

// OverridableTransport is a transport that provides an override for testing purposes.
type OverridableTransport interface {
	SetTransport(http.RoundTripper)
}

// SetTransport allows you to set the transport. It is exposed so tests may
// override it. It fulfills an interface to allow calling thsi function via
// assertion to the exported interface
func (client *ecsRoundTripper) SetTransport(transport http.RoundTripper) {
	client.transport = transport
}
<commit_msg>httpclient: Add OS to user-agent<commit_after>// Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
//	http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

// Package httpclient provides a thin, but testable, wrapper around http.Client.
// It adds an ECS header to requests and provides an interface
package httpclient

import (
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"time"

	"github.com/aws/amazon-ecs-agent/agent/api"
	"github.com/aws/amazon-ecs-agent/agent/version"
)

const defaultTimeout = 10 * time.Minute

// Taken from the default http.Client behavior
const defaultDialTimeout = 30 * time.Second
const defaultDialKeepalive = 30 * time.Second

//go:generate go run ../../scripts/generate/mockgen.go net/http RoundTripper mock/$GOFILE

type ecsRoundTripper struct {
	insecureSkipVerify bool
	transport          http.RoundTripper
}

func userAgent() string {
	return fmt.Sprintf("%s (%s) (+http://aws.amazon.com/ecs/)", version.String(), api.OSType)
}

func (client *ecsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	req.Header.Set("User-Agent", userAgent())
	return client.transport.RoundTrip(req)
}

func (client *ecsRoundTripper) CancelRequest(req *http.Request) {
	if def, ok := client.transport.(*http.Transport); ok {
		def.CancelRequest(req)
	}
}

// New returns an ECS httpClient with a roundtrip timeout of the given duration
func New(timeout time.Duration, insecureSkipVerify bool) *http.Client {
	// Transport is the transport requests will be made over
	// Note, these defaults are taken from the golang http library. We do not
	// explicitly do not use theirs to avoid changing their behavior.
	transport := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   defaultDialTimeout,
			KeepAlive: defaultDialKeepalive,
		}).Dial,
		TLSHandshakeTimeout: 10 * time.Second,
	}
	if insecureSkipVerify {
		transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	}
	client := &http.Client{
		Transport: &ecsRoundTripper{insecureSkipVerify, transport},
		Timeout:   timeout,
	}

	return client
}

// OverridableTransport is a transport that provides an override for testing purposes.
type OverridableTransport interface {
	SetTransport(http.RoundTripper)
}

// SetTransport allows you to set the transport. It is exposed so tests may
// override it. It fulfills an interface to allow calling thsi function via
// assertion to the exported interface
func (client *ecsRoundTripper) SetTransport(transport http.RoundTripper) {
	client.transport = transport
}
<|endoftext|>


<commit_before>package cache

import (
	"sync"
	"time"

	"github.com/containerd/containerd/mount"
	cdsnapshot "github.com/containerd/containerd/snapshots"
	"github.com/moby/buildkit/cache/metadata"
	"github.com/moby/buildkit/identity"
	"github.com/moby/buildkit/util/flightcontrol"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"golang.org/x/net/context"
)

// Ref is a reference to cacheable objects.
type Ref interface {
	Mountable
	ID() string
	Release(context.Context) error
	Size(ctx context.Context) (int64, error)
	Metadata() *metadata.StorageItem
}

type ImmutableRef interface {
	Ref
	Parent() ImmutableRef
	Finalize(ctx context.Context) error // Make sure reference is flushed to driver
	// Prepare() / ChainID() / Meta()
}

type MutableRef interface {
	Ref
	Commit(context.Context) (ImmutableRef, error)
}

type Mountable interface {
	Mount(ctx context.Context, readonly bool) ([]mount.Mount, error)
}

type cacheRecord struct {
	mu        sync.Mutex
	mutable   bool
	refs      map[Mountable]struct{}
	cm        *cacheManager
	parent    ImmutableRef
	md        *metadata.StorageItem
	view      string
	viewMount []mount.Mount
	dead      bool

	sizeG flightcontrol.Group
	// size  int64

	// these are filled if multiple refs point to same data
	equalMutable   *mutableRef
	equalImmutable *immutableRef
}

// hold manager lock before calling
func (cr *cacheRecord) ref() *immutableRef {
	ref := &immutableRef{cacheRecord: cr}
	cr.refs[ref] = struct{}{}
	return ref
}

// hold manager lock before calling
func (cr *cacheRecord) mref() *mutableRef {
	ref := &mutableRef{cacheRecord: cr}
	cr.refs[ref] = struct{}{}
	return ref
}

func (cr *cacheRecord) Size(ctx context.Context) (int64, error) {
	// this expects that usage() is implemented lazily
	s, err := cr.sizeG.Do(ctx, cr.ID(), func(ctx context.Context) (interface{}, error) {
		cr.mu.Lock()
		s := getSize(cr.md)
		if s != sizeUnknown {
			cr.mu.Unlock()
			return s, nil
		}
		driverID := cr.ID()
		if cr.equalMutable != nil {
			driverID = cr.equalMutable.ID()
		}
		cr.mu.Unlock()
		usage, err := cr.cm.ManagerOpt.Snapshotter.Usage(ctx, driverID)
		if err != nil {
			return s, errors.Wrapf(err, "failed to get usage for %s", cr.ID())
		}
		cr.mu.Lock()
		setSize(cr.md, usage.Size)
		if err := cr.md.Commit(); err != nil {
			return s, err
		}
		cr.mu.Unlock()
		return usage.Size, nil
	})
	return s.(int64), err
}

func (cr *cacheRecord) Parent() ImmutableRef {
	if cr.parent == nil {
		return nil
	}
	return cr.parent.(*immutableRef).ref()
}

func (cr *cacheRecord) Mount(ctx context.Context, readonly bool) ([]mount.Mount, error) {
	cr.mu.Lock()
	defer cr.mu.Unlock()

	if cr.mutable {
		m, err := cr.cm.Snapshotter.Mounts(ctx, cr.ID())
		if err != nil {
			return nil, errors.Wrapf(err, "failed to mount %s", cr.ID())
		}
		if readonly {
			m = setReadonly(m)
		}
		return m, nil
	}

	if cr.equalMutable != nil && readonly {
		m, err := cr.cm.Snapshotter.Mounts(ctx, cr.equalMutable.ID())
		if err != nil {
			return nil, errors.Wrapf(err, "failed to mount %s", cr.equalMutable.ID())
		}
		return setReadonly(m), nil
	}

	if err := cr.finalize(ctx); err != nil {
		return nil, err
	}
	if cr.viewMount == nil { // TODO: handle this better
		cr.view = identity.NewID()
		labels := map[string]string{
			"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
		}
		m, err := cr.cm.Snapshotter.View(ctx, cr.view, cr.ID(), cdsnapshot.WithLabels(labels))
		if err != nil {
			cr.view = ""
			return nil, errors.Wrapf(err, "failed to mount %s", cr.ID())
		}
		cr.viewMount = m
	}
	return cr.viewMount, nil
}

func (cr *cacheRecord) remove(ctx context.Context, removeSnapshot bool) error {
	delete(cr.cm.records, cr.ID())
	if err := cr.cm.md.Clear(cr.ID()); err != nil {
		return err
	}
	if removeSnapshot {
		if err := cr.cm.Snapshotter.Remove(ctx, cr.ID()); err != nil {
			return err
		}
	}
	return nil
}

func (cr *cacheRecord) ID() string {
	return cr.md.ID()
}

type immutableRef struct {
	*cacheRecord
}

type mutableRef struct {
	*cacheRecord
}

func (sr *immutableRef) Release(ctx context.Context) error {
	sr.cm.mu.Lock()
	defer sr.cm.mu.Unlock()

	sr.mu.Lock()
	defer sr.mu.Unlock()

	return sr.release(ctx)
}

func (sr *immutableRef) release(ctx context.Context) error {
	if sr.viewMount != nil {
		if err := sr.cm.Snapshotter.Remove(ctx, sr.view); err != nil {
			return err
		}
		sr.view = ""
		sr.viewMount = nil
	}

	updateLastUsed(sr.md)

	delete(sr.refs, sr)

	if len(sr.refs) == 0 {
		if sr.equalMutable != nil {
			sr.equalMutable.release(ctx)
		}
		// go sr.cm.GC()
	}

	return nil
}

func (sr *immutableRef) Finalize(ctx context.Context) error {
	sr.mu.Lock()
	defer sr.mu.Unlock()

	return sr.finalize(ctx)
}

func (cr *cacheRecord) Metadata() *metadata.StorageItem {
	return cr.md
}

func (cr *cacheRecord) finalize(ctx context.Context) error {
	mutable := cr.equalMutable
	if mutable == nil {
		return nil
	}
	labels := map[string]string{
		"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
	}
	err := cr.cm.Snapshotter.Commit(ctx, cr.ID(), mutable.ID(), cdsnapshot.WithLabels(labels))
	if err != nil {
		return errors.Wrapf(err, "failed to commit %s", mutable.ID())
	}
	mutable.dead = true
	go func() {
		cr.cm.mu.Lock()
		defer cr.cm.mu.Unlock()
		if err := mutable.remove(context.TODO(), false); err != nil {
			logrus.Error(err)
		}
	}()
	cr.equalMutable = nil
	clearEqualMutable(cr.md)
	return cr.md.Commit()
}

func (sr *mutableRef) commit(ctx context.Context) (ImmutableRef, error) {
	if !sr.mutable || len(sr.refs) == 0 {
		return nil, errors.Wrapf(errInvalid, "invalid mutable")
	}

	id := identity.NewID()
	md, _ := sr.cm.md.Get(id)

	rec := &cacheRecord{
		cm:           sr.cm,
		parent:       sr.parent,
		equalMutable: sr,
		refs:         make(map[Mountable]struct{}),
		md:           md,
	}

	if descr := GetDescription(sr.md); descr != "" {
		if err := queueDescription(md, descr); err != nil {
			return nil, err
		}
	}

	if err := initializeMetadata(rec); err != nil {
		return nil, err
	}

	sr.cm.records[id] = rec

	if err := sr.md.Commit(); err != nil {
		return nil, err
	}

	setSize(md, sizeUnknown)
	setEqualMutable(md, sr.ID())
	if err := md.Commit(); err != nil {
		return nil, err
	}

	ref := rec.ref()
	sr.equalImmutable = ref
	return ref, nil
}

func (sr *mutableRef) Commit(ctx context.Context) (ImmutableRef, error) {
	sr.cm.mu.Lock()
	defer sr.cm.mu.Unlock()

	sr.mu.Lock()
	defer sr.mu.Unlock()

	return sr.commit(ctx)
}

func (sr *mutableRef) Release(ctx context.Context) error {
	sr.cm.mu.Lock()
	defer sr.cm.mu.Unlock()

	sr.mu.Lock()
	defer sr.mu.Unlock()

	return sr.release(ctx)
}

func (sr *mutableRef) release(ctx context.Context) error {
	delete(sr.refs, sr)
	updateLastUsed(sr.md)
	if getCachePolicy(sr.md) != cachePolicyRetain {
		if sr.equalImmutable != nil {
			if getCachePolicy(sr.equalImmutable.md) == cachePolicyRetain {
				return nil
			}
			if err := sr.equalImmutable.remove(ctx, false); err != nil {
				return err
			}
		}
		if sr.parent != nil {
			if err := sr.parent.(*immutableRef).release(ctx); err != nil {
				return err
			}
		}
		return sr.remove(ctx, true)
	}
	return nil
}

func setReadonly(mounts []mount.Mount) []mount.Mount {
	for i, m := range mounts {
		opts := make([]string, 0, len(m.Options))
		for _, opt := range m.Options {
			if opt != "rw" {
				opts = append(opts, opt)
			}
		}
		opts = append(opts, "ro")
		mounts[i].Options = opts
	}
	return mounts
}
<commit_msg>cache: remove view on last release<commit_after>package cache

import (
	"sync"
	"time"

	"github.com/containerd/containerd/mount"
	cdsnapshot "github.com/containerd/containerd/snapshots"
	"github.com/moby/buildkit/cache/metadata"
	"github.com/moby/buildkit/identity"
	"github.com/moby/buildkit/util/flightcontrol"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"golang.org/x/net/context"
)

// Ref is a reference to cacheable objects.
type Ref interface {
	Mountable
	ID() string
	Release(context.Context) error
	Size(ctx context.Context) (int64, error)
	Metadata() *metadata.StorageItem
}

type ImmutableRef interface {
	Ref
	Parent() ImmutableRef
	Finalize(ctx context.Context) error // Make sure reference is flushed to driver
	// Prepare() / ChainID() / Meta()
}

type MutableRef interface {
	Ref
	Commit(context.Context) (ImmutableRef, error)
}

type Mountable interface {
	Mount(ctx context.Context, readonly bool) ([]mount.Mount, error)
}

type cacheRecord struct {
	mu        sync.Mutex
	mutable   bool
	refs      map[Mountable]struct{}
	cm        *cacheManager
	parent    ImmutableRef
	md        *metadata.StorageItem
	view      string
	viewMount []mount.Mount
	dead      bool

	sizeG flightcontrol.Group
	// size  int64

	// these are filled if multiple refs point to same data
	equalMutable   *mutableRef
	equalImmutable *immutableRef
}

// hold manager lock before calling
func (cr *cacheRecord) ref() *immutableRef {
	ref := &immutableRef{cacheRecord: cr}
	cr.refs[ref] = struct{}{}
	return ref
}

// hold manager lock before calling
func (cr *cacheRecord) mref() *mutableRef {
	ref := &mutableRef{cacheRecord: cr}
	cr.refs[ref] = struct{}{}
	return ref
}

func (cr *cacheRecord) Size(ctx context.Context) (int64, error) {
	// this expects that usage() is implemented lazily
	s, err := cr.sizeG.Do(ctx, cr.ID(), func(ctx context.Context) (interface{}, error) {
		cr.mu.Lock()
		s := getSize(cr.md)
		if s != sizeUnknown {
			cr.mu.Unlock()
			return s, nil
		}
		driverID := cr.ID()
		if cr.equalMutable != nil {
			driverID = cr.equalMutable.ID()
		}
		cr.mu.Unlock()
		usage, err := cr.cm.ManagerOpt.Snapshotter.Usage(ctx, driverID)
		if err != nil {
			return s, errors.Wrapf(err, "failed to get usage for %s", cr.ID())
		}
		cr.mu.Lock()
		setSize(cr.md, usage.Size)
		if err := cr.md.Commit(); err != nil {
			return s, err
		}
		cr.mu.Unlock()
		return usage.Size, nil
	})
	return s.(int64), err
}

func (cr *cacheRecord) Parent() ImmutableRef {
	if cr.parent == nil {
		return nil
	}
	return cr.parent.(*immutableRef).ref()
}

func (cr *cacheRecord) Mount(ctx context.Context, readonly bool) ([]mount.Mount, error) {
	cr.mu.Lock()
	defer cr.mu.Unlock()

	if cr.mutable {
		m, err := cr.cm.Snapshotter.Mounts(ctx, cr.ID())
		if err != nil {
			return nil, errors.Wrapf(err, "failed to mount %s", cr.ID())
		}
		if readonly {
			m = setReadonly(m)
		}
		return m, nil
	}

	if cr.equalMutable != nil && readonly {
		m, err := cr.cm.Snapshotter.Mounts(ctx, cr.equalMutable.ID())
		if err != nil {
			return nil, errors.Wrapf(err, "failed to mount %s", cr.equalMutable.ID())
		}
		return setReadonly(m), nil
	}

	if err := cr.finalize(ctx); err != nil {
		return nil, err
	}
	if cr.viewMount == nil { // TODO: handle this better
		cr.view = identity.NewID()
		labels := map[string]string{
			"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
		}
		m, err := cr.cm.Snapshotter.View(ctx, cr.view, cr.ID(), cdsnapshot.WithLabels(labels))
		if err != nil {
			cr.view = ""
			return nil, errors.Wrapf(err, "failed to mount %s", cr.ID())
		}
		cr.viewMount = m
	}
	return cr.viewMount, nil
}

func (cr *cacheRecord) remove(ctx context.Context, removeSnapshot bool) error {
	delete(cr.cm.records, cr.ID())
	if err := cr.cm.md.Clear(cr.ID()); err != nil {
		return err
	}
	if removeSnapshot {
		if err := cr.cm.Snapshotter.Remove(ctx, cr.ID()); err != nil {
			return err
		}
	}
	return nil
}

func (cr *cacheRecord) ID() string {
	return cr.md.ID()
}

type immutableRef struct {
	*cacheRecord
}

type mutableRef struct {
	*cacheRecord
}

func (sr *immutableRef) Release(ctx context.Context) error {
	sr.cm.mu.Lock()
	defer sr.cm.mu.Unlock()

	sr.mu.Lock()
	defer sr.mu.Unlock()

	return sr.release(ctx)
}

func (sr *immutableRef) release(ctx context.Context) error {
	updateLastUsed(sr.md)

	delete(sr.refs, sr)

	if len(sr.refs) == 0 {
		if sr.viewMount != nil { // TODO: release viewMount earlier if possible
			if err := sr.cm.Snapshotter.Remove(ctx, sr.view); err != nil {
				return err
			}
			sr.view = ""
			sr.viewMount = nil
		}

		if sr.equalMutable != nil {
			sr.equalMutable.release(ctx)
		}
		// go sr.cm.GC()
	}

	return nil
}

func (sr *immutableRef) Finalize(ctx context.Context) error {
	sr.mu.Lock()
	defer sr.mu.Unlock()

	return sr.finalize(ctx)
}

func (cr *cacheRecord) Metadata() *metadata.StorageItem {
	return cr.md
}

func (cr *cacheRecord) finalize(ctx context.Context) error {
	mutable := cr.equalMutable
	if mutable == nil {
		return nil
	}
	labels := map[string]string{
		"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
	}
	err := cr.cm.Snapshotter.Commit(ctx, cr.ID(), mutable.ID(), cdsnapshot.WithLabels(labels))
	if err != nil {
		return errors.Wrapf(err, "failed to commit %s", mutable.ID())
	}
	mutable.dead = true
	go func() {
		cr.cm.mu.Lock()
		defer cr.cm.mu.Unlock()
		if err := mutable.remove(context.TODO(), false); err != nil {
			logrus.Error(err)
		}
	}()
	cr.equalMutable = nil
	clearEqualMutable(cr.md)
	return cr.md.Commit()
}

func (sr *mutableRef) commit(ctx context.Context) (ImmutableRef, error) {
	if !sr.mutable || len(sr.refs) == 0 {
		return nil, errors.Wrapf(errInvalid, "invalid mutable")
	}

	id := identity.NewID()
	md, _ := sr.cm.md.Get(id)

	rec := &cacheRecord{
		cm:           sr.cm,
		parent:       sr.parent,
		equalMutable: sr,
		refs:         make(map[Mountable]struct{}),
		md:           md,
	}

	if descr := GetDescription(sr.md); descr != "" {
		if err := queueDescription(md, descr); err != nil {
			return nil, err
		}
	}

	if err := initializeMetadata(rec); err != nil {
		return nil, err
	}

	sr.cm.records[id] = rec

	if err := sr.md.Commit(); err != nil {
		return nil, err
	}

	setSize(md, sizeUnknown)
	setEqualMutable(md, sr.ID())
	if err := md.Commit(); err != nil {
		return nil, err
	}

	ref := rec.ref()
	sr.equalImmutable = ref
	return ref, nil
}

func (sr *mutableRef) Commit(ctx context.Context) (ImmutableRef, error) {
	sr.cm.mu.Lock()
	defer sr.cm.mu.Unlock()

	sr.mu.Lock()
	defer sr.mu.Unlock()

	return sr.commit(ctx)
}

func (sr *mutableRef) Release(ctx context.Context) error {
	sr.cm.mu.Lock()
	defer sr.cm.mu.Unlock()

	sr.mu.Lock()
	defer sr.mu.Unlock()

	return sr.release(ctx)
}

func (sr *mutableRef) release(ctx context.Context) error {
	delete(sr.refs, sr)
	updateLastUsed(sr.md)
	if getCachePolicy(sr.md) != cachePolicyRetain {
		if sr.equalImmutable != nil {
			if getCachePolicy(sr.equalImmutable.md) == cachePolicyRetain {
				return nil
			}
			if err := sr.equalImmutable.remove(ctx, false); err != nil {
				return err
			}
		}
		if sr.parent != nil {
			if err := sr.parent.(*immutableRef).release(ctx); err != nil {
				return err
			}
		}
		return sr.remove(ctx, true)
	}
	return nil
}

func setReadonly(mounts []mount.Mount) []mount.Mount {
	for i, m := range mounts {
		opts := make([]string, 0, len(m.Options))
		for _, opt := range m.Options {
			if opt != "rw" {
				opts = append(opts, opt)
			}
		}
		opts = append(opts, "ro")
		mounts[i].Options = opts
	}
	return mounts
}
<|endoftext|>


<commit_before>package caddy

import (
	"net"
	"strconv"
	"testing"
)

/*
// TODO
func TestCaddyStartStop(t *testing.T) {
	caddyfile := "localhost:1984"

	for i := 0; i < 2; i++ {
		_, err := Start(CaddyfileInput{Contents: []byte(caddyfile)})
		if err != nil {
			t.Fatalf("Error starting, iteration %d: %v", i, err)
		}

		client := http.Client{
			Timeout: time.Duration(2 * time.Second),
		}
		resp, err := client.Get("http://localhost:1984")
		if err != nil {
			t.Fatalf("Expected GET request to succeed (iteration %d), but it failed: %v", i, err)
		}
		resp.Body.Close()

		err = Stop()
		if err != nil {
			t.Fatalf("Error stopping, iteration %d: %v", i, err)
		}
	}
}
*/

func TestIsLoopback(t *testing.T) {
	for i, test := range []struct {
		input  string
		expect bool
	}{
		{"example.com", false},
		{"localhost", true},
		{"localhost:1234", true},
		{"localhost:", true},
		{"127.0.0.1", true},
		{"127.0.0.1:443", true},
		{"127.0.1.5", true},
		{"10.0.0.5", false},
		{"12.7.0.1", false},
		{"[::1]", true},
		{"[::1]:1234", true},
		{"::1", true},
		{"::", false},
		{"[::]", false},
		{"local", false},
	} {
		if got, want := IsLoopback(test.input), test.expect; got != want {
			t.Errorf("Test %d (%s): expected %v but was %v", i, test.input, want, got)
		}
	}
}

func TestListenerAddrEqual(t *testing.T) {
	ln1, err := net.Listen("tcp", "[::]:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln1.Close()

	ln1port := strconv.Itoa(ln1.Addr().(*net.TCPAddr).Port)

	ln2, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln2.Close()

	ln2port := strconv.Itoa(ln2.Addr().(*net.TCPAddr).Port)

	for i, test := range []struct {
		ln     net.Listener
		addr   string
		expect bool
	}{
		{ln1, ":1234", false},
		{ln1, "0.0.0.0:1234", false},
		{ln1, "0.0.0.0", false},
		{ln1, ":" + ln1port + "", true},
		{ln1, "0.0.0.0:" + ln1port + "", true},
		{ln2, ":" + ln2port + "", false},
		{ln2, "127.0.0.1:1234", false},
		{ln2, "127.0.0.1", false},
		{ln2, "127.0.0.1:" + ln2port + "", true},
	} {
		if got, want := listenerAddrEqual(test.ln, test.addr), test.expect; got != want {
			t.Errorf("Test %d (%s == %s): expected %v but was %v", i, test.addr, test.ln.Addr().String(), want, got)
		}
	}
}
<commit_msg>Minor test cleanup<commit_after>package caddy

import (
	"net"
	"strconv"
	"testing"
)

/*
// TODO
func TestCaddyStartStop(t *testing.T) {
	caddyfile := "localhost:1984"

	for i := 0; i < 2; i++ {
		_, err := Start(CaddyfileInput{Contents: []byte(caddyfile)})
		if err != nil {
			t.Fatalf("Error starting, iteration %d: %v", i, err)
		}

		client := http.Client{
			Timeout: time.Duration(2 * time.Second),
		}
		resp, err := client.Get("http://localhost:1984")
		if err != nil {
			t.Fatalf("Expected GET request to succeed (iteration %d), but it failed: %v", i, err)
		}
		resp.Body.Close()

		err = Stop()
		if err != nil {
			t.Fatalf("Error stopping, iteration %d: %v", i, err)
		}
	}
}
*/

func TestIsLoopback(t *testing.T) {
	for i, test := range []struct {
		input  string
		expect bool
	}{
		{"example.com", false},
		{"localhost", true},
		{"localhost:1234", true},
		{"localhost:", true},
		{"127.0.0.1", true},
		{"127.0.0.1:443", true},
		{"127.0.1.5", true},
		{"10.0.0.5", false},
		{"12.7.0.1", false},
		{"[::1]", true},
		{"[::1]:1234", true},
		{"::1", true},
		{"::", false},
		{"[::]", false},
		{"local", false},
	} {
		if got, want := IsLoopback(test.input), test.expect; got != want {
			t.Errorf("Test %d (%s): expected %v but was %v", i, test.input, want, got)
		}
	}
}

func TestListenerAddrEqual(t *testing.T) {
	ln1, err := net.Listen("tcp", "[::]:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln1.Close()
	ln1port := strconv.Itoa(ln1.Addr().(*net.TCPAddr).Port)

	ln2, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln2.Close()
	ln2port := strconv.Itoa(ln2.Addr().(*net.TCPAddr).Port)

	for i, test := range []struct {
		ln     net.Listener
		addr   string
		expect bool
	}{
		{ln1, ":1234", false},
		{ln1, "0.0.0.0:1234", false},
		{ln1, "0.0.0.0", false},
		{ln1, ":" + ln1port, true},
		{ln1, "0.0.0.0:" + ln1port, true},
		{ln2, ":" + ln2port, false},
		{ln2, "127.0.0.1:1234", false},
		{ln2, "127.0.0.1", false},
		{ln2, "127.0.0.1:" + ln2port, true},
	} {
		if got, want := listenerAddrEqual(test.ln, test.addr), test.expect; got != want {
			t.Errorf("Test %d (%s == %s): expected %v but was %v", i, test.addr, test.ln.Addr().String(), want, got)
		}
	}
}
<|endoftext|>


<commit_before>package server

import (
	"fmt"
	"net/http"
	"net/url"

	"github.com/julienschmidt/httprouter"
	sous "github.com/opentable/sous/lib"
	"github.com/opentable/sous/util/restful"
)

type (
	// R11nResource is a handler factory for r11n handlers.
	R11nResource struct {
		userExtractor
		context ComponentLocator
	}

	// GETR11nHandler handles getting r11ns.
	GETR11nHandler struct {
		WaitForResolution bool
		QueueSet          *sous.R11nQueueSet
		DeploymentID      sous.DeploymentID
		DeploymentIDErr   error
		R11nID            sous.R11nID
		R11nIDErr         error
	}
)

func newR11nResource(ctx ComponentLocator) *R11nResource {
	return &R11nResource{context: ctx}
}

func r11nIDFromRoute(p httprouter.Params) (sous.R11nID, error) {
	ridStr, err := url.PathUnescape(p.ByName("R11nID"))
	if err != nil {
		return "", fmt.Errorf("unescaping path: %s", err)
	}
	return sous.R11nID(ridStr), nil
}

// Get returns a configured GETR11nHandler.
func (mr *R11nResource) Get(_ http.ResponseWriter, _ *http.Request, p httprouter.Params) restful.Exchanger {
	did, didErr := deploymentIDFromRoute(p)
	rid, ridErr := r11nIDFromRoute(p)
	return &GETR11nHandler{
		DeploymentID:    did,
		DeploymentIDErr: didErr,
		R11nID:          rid,
		R11nIDErr:       ridErr,
	}
}

// Exchange returns the targeted r11nResponse and 200 if it exists, other
// non-200 responses otherwise.
func (gmh *GETR11nHandler) Exchange() (interface{}, int) {
	if gmh.DeploymentIDErr != nil {
		return nil, 404
	}
	queues := gmh.QueueSet.Queues()
	queue, ok := queues[gmh.DeploymentID]
	if !ok {
		return deploymentResponse{}, 404
	}
	qr, ok := queue.ByID(gmh.R11nID)
	if !ok {
		return r11nResponse{}, 404
	}
	if gmh.WaitForResolution {
		qr.Rectification.Wait()
	}
	return r11nResponse{
		QueuePosition: qr.Pos,
	}, 200
}

type r11nResponse struct {
	QueuePosition int
}
<commit_msg>server: hook up wait query string<commit_after>package server

import (
	"fmt"
	"net/http"
	"net/url"

	"github.com/julienschmidt/httprouter"
	sous "github.com/opentable/sous/lib"
	"github.com/opentable/sous/util/restful"
)

type (
	// R11nResource is a handler factory for r11n handlers.
	R11nResource struct {
		userExtractor
		context ComponentLocator
	}

	// GETR11nHandler handles getting r11ns.
	GETR11nHandler struct {
		WaitForResolution bool
		QueueSet          *sous.R11nQueueSet
		DeploymentID      sous.DeploymentID
		DeploymentIDErr   error
		R11nID            sous.R11nID
		R11nIDErr         error
	}
)

func newR11nResource(ctx ComponentLocator) *R11nResource {
	return &R11nResource{context: ctx}
}

func r11nIDFromRoute(p httprouter.Params) (sous.R11nID, error) {
	ridStr, err := url.PathUnescape(p.ByName("R11nID"))
	if err != nil {
		return "", fmt.Errorf("unescaping path: %s", err)
	}
	return sous.R11nID(ridStr), nil
}

// Get returns a configured GETR11nHandler.
func (mr *R11nResource) Get(_ http.ResponseWriter, r *http.Request, p httprouter.Params) restful.Exchanger {
	did, didErr := deploymentIDFromRoute(p)
	rid, ridErr := r11nIDFromRoute(p)
	wait := r.URL.Query().Get("wait") == "true"
	return &GETR11nHandler{
		DeploymentID:      did,
		DeploymentIDErr:   didErr,
		R11nID:            rid,
		R11nIDErr:         ridErr,
		WaitForResolution: wait,
	}
}

// Exchange returns the targeted r11nResponse and 200 if it exists, other
// non-200 responses otherwise.
func (gmh *GETR11nHandler) Exchange() (interface{}, int) {
	if gmh.DeploymentIDErr != nil {
		return nil, 404
	}
	queues := gmh.QueueSet.Queues()
	queue, ok := queues[gmh.DeploymentID]
	if !ok {
		return deploymentResponse{}, 404
	}
	qr, ok := queue.ByID(gmh.R11nID)
	if !ok {
		return r11nResponse{}, 404
	}
	if gmh.WaitForResolution {
		qr.Rectification.Wait()
	}
	return r11nResponse{
		QueuePosition: qr.Pos,
	}, 200
}

type r11nResponse struct {
	QueuePosition int
}
<|endoftext|>


<commit_before>package server

import (
	"fmt"
	"ldpserver/rdf"
	"ldpserver/util"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

var dataPath string
var theServer Server
var rootUrl = "http://localhost:9001/"
var slug = ""

func init() {
	dataPath, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	theServer = NewServer(rootUrl, dataPath)
}

func TestBadSlug(t *testing.T) {
	_, err := theServer.CreateRdfSource("", "/", "/invalid/")
	if err == nil {
		t.Error("Failed to detect an invalid slug")
	}
}

func TestCreateRdf(t *testing.T) {
	node, err := theServer.CreateRdfSource("", "/", slug)
	if !node.IsRdf() {
		t.Errorf("Error creating RDF. Error: %s", err)
	}

	node, err = theServer.GetNode(node.Path())
	if err != nil || node.Uri() != util.UriConcat(rootUrl, node.Path()) {
		t.Errorf("err %s, uri %s", err, node.Uri())
	}
}

func TestCreateDirectContainer(t *testing.T) {
	// Create a helper node
	helperNode, err := theServer.CreateRdfSource("", "/", "other")

	// Create the direct container (pointing to the helper node)
	dcTriple1 := fmt.Sprintf("<> <%s> <%s> .\n", rdf.LdpMembershipResource, helperNode.Uri())
	dcTriple2 := fmt.Sprintf("<> <%s> <hasXYZ> .\n", rdf.LdpHasMemberRelation)
	dcTriples := dcTriple1 + dcTriple2
	dcNode, err := theServer.CreateRdfSource(dcTriples, "/", "dc")
	if err != nil {
		t.Errorf("Error creating direct container", err)
	}

	dcNode, err = theServer.GetNode(dcNode.Path())
	if err != nil {
		t.Errorf("Error fetching direct container", err)
	}

	if !dcNode.IsBasicContainer() {
		t.Errorf("Direct container fetched but not marked as a BASIC container %s", dcNode.Content())
	}
	if !dcNode.IsDirectContainer() {
		t.Errorf("Direct container fetched but not marked as a DIRECT container %s", dcNode.Content())
	}

	// Add a child to the direct container
	childNode, err := theServer.CreateRdfSource("", dcNode.Path(), "child")
	if err != nil {
		t.Errorf("Error adding child to Direct Container %s", err)
	}

	// Reload our helper node and make sure the child is referenced on it.
	helperNode, err = theServer.GetNode(helperNode.Path())
	if !helperNode.HasTriple("<hasXYZ>", "<"+childNode.Uri()+">") {
		t.Error("Helper node did not get new triple when adding to a Direct Container")
	}
}

func TestCreateChildRdf(t *testing.T) {
	parentNode, _ := theServer.CreateRdfSource("", "/", slug)

	rdfNode, err := theServer.CreateRdfSource("", parentNode.Path(), slug)
	if err != nil {
		t.Errorf("Error creating child RDF node under %s", err, parentNode.Uri())
	}

	if !strings.HasPrefix(rdfNode.Uri(), parentNode.Uri()) || rdfNode.Uri() == parentNode.Uri() {
		t.Errorf("Child URI %s does not seem to be under the parent URI %s", rdfNode.Uri(), parentNode.Uri())
	}

	invalidPath := parentNode.Path() + "/invalid"
	invalidNode, err := theServer.CreateRdfSource("", invalidPath, slug)
	if err == nil {
		t.Errorf("A node was added to an invalid path %s %s", err, invalidNode.Uri())
	}

	reader := util.FakeReaderCloser{Text: "HELLO"}
	nonRdfNode, err := theServer.CreateNonRdfSource(reader, parentNode.Path(), slug)
	if err != nil {
		t.Errorf("Error creating child non-RDF node under %s. Error: %s", parentNode.Uri(), err)
	}

	if !strings.HasPrefix(nonRdfNode.Uri(), parentNode.Uri()) || nonRdfNode.Uri() == parentNode.Uri() {
		t.Errorf("Child URI %s does not seem to be under the parent URI %s", nonRdfNode.Uri(), parentNode.Uri())
	}

	_, err = theServer.CreateRdfSource("", nonRdfNode.Path(), slug)
	if err == nil {
		t.Errorf("A child was added to a non-RDF node! %s", nonRdfNode.Uri())
	}
}

func TestCreateRdfWithTriples(t *testing.T) {
	triples := "<> <b> <c> .\n<x> <y> <z> .\n"
	node, err := theServer.CreateRdfSource(triples, "/", slug)
	if err != nil || !node.IsRdf() {
		t.Errorf("Error creating RDF")
	}

	node, err = theServer.GetNode(node.Path())
	if err != nil || node.Uri() != util.UriConcat(rootUrl, node.Path()) {
		t.Errorf("err %v, uri %s", err, node.Uri())
	}

	if !node.HasTriple("<b>", "<c>") {
		t.Errorf("Blank node not handled correctly %s", node.Uri())
		t.Errorf(node.DebugString())
	}

	if node.HasTriple("x", "z") {
		t.Errorf("Unexpected tripled for new subject %s", node.Uri())
	}
}

func TestCreateNonRdf(t *testing.T) {
	reader := util.FakeReaderCloser{Text: "HELLO"}
	node, err := theServer.CreateNonRdfSource(reader, "/", slug)
	if err != nil || node.IsRdf() {
		t.Errorf("Error creating Non RDF")
	}

	node, err = theServer.GetNode(node.Path())
	if err != nil || node.Uri() != util.UriConcat(rootUrl, node.Path()) {
		t.Errorf("err %v, uri %s", err, node.Uri())
	}

	if node.IsRdf() {
		t.Errorf("Node created as RDF instead of Non-RDF")
	}

	if node.Content() != "HELLO" {
		t.Errorf("Non-RDF content is not the expected one, %s", node.Content())
	}
}

func TestCreateWithDuplicateSlug(t *testing.T) {
	_, err := theServer.CreateRdfSource("", "/", "slug1")
	if err != nil {
		t.Error("Could not create new resource")
	}

	node, err := theServer.CreateRdfSource("", "/", "slug1")
	if err != nil {
		t.Error("Error creating node with duplicate slug")
	}

	if strings.HasSuffix(node.Uri(), "/slug1") {
		t.Error("Failed to generate a new slug")
	}
}

func TestPatchRdf(t *testing.T) {
	triples := "<> <p1> <o1> .\n<> <p2> <o2> .\n"
	node, _ := theServer.CreateRdfSource(triples, "/", slug)
	node, _ = theServer.GetNode(node.Path())
	if !node.HasTriple("<p1>", "<o1>") || !node.HasTriple("<p2>", "<o2>") {
		t.Errorf("Expected triple not found %s", node.Content())
	}

	newTriples := "<> <p3> <o3> .\n"
	err := node.Patch(newTriples)
	if err != nil {
		t.Errorf("Error during Patch %s", err)
	} else if !node.HasTriple("<p1>", "<o1>") ||
		!node.HasTriple("<p2>", "<o2>") ||
		!node.HasTriple("<p3>", "<o3>") {
		t.Errorf("Expected triple not after patch found %s", node.Content())
	}
}

func TestPatchNonRdf(t *testing.T) {
	reader1 := util.FakeReaderCloser{Text: "HELLO"}
	node, _ := theServer.CreateNonRdfSource(reader1, "/", slug)
	node, _ = theServer.GetNode(node.Path())
	if node.Content() != "HELLO" {
		t.Errorf("Unexpected non-RDF content found %s", node.Content())
	}

	if err := node.Patch("whatever"); err == nil {
		t.Errorf("Shouldn't be able to patch non-RDF")
	}
}
<commit_msg>Includes tests for replace RDF<commit_after>package server

import (
	"fmt"
	"ldpserver/ldp"
	"ldpserver/rdf"
	"ldpserver/util"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

var dataPath string
var theServer Server
var rootUrl = "http://localhost:9001/"
var emptySlug = ""

func init() {
	dataPath, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	theServer = NewServer(rootUrl, dataPath)
}

func TestBadSlug(t *testing.T) {
	_, err := theServer.CreateRdfSource("", "/", "/invalid/")
	if err == nil {
		t.Error("Failed to detect an invalid slug")
	}
}

func TestCreateRdf(t *testing.T) {
	_, err := theServer.CreateRdfSource("", "/", "slugA")
	if err != nil {
		t.Errorf("Error creating RDF. Error: %s", err)
	}

	node, err := theServer.GetNode("/slugA")
	if err != nil {
		t.Errorf("Error fetching new node /slugA. Error: %s", err)
	}

	if !node.IsRdf() {
		t.Errorf("RDF source was created but not as RDF")
	}

	node2, err := theServer.CreateRdfSource("", "/", "slugA")
	if err != nil {
		t.Errorf("Error %s while attemping to create duplicate node", err)
	}

	if node2.Path() == "/slugA" {
		t.Errorf("A duplicate node was created")
	}
}

func TestReplaceRdf(t *testing.T) {
	triples := "<> xx:version \"version1\" ."
	node, err := theServer.CreateRdfSource(triples, "/", emptySlug)

	path := node.Path()[1:]
	etag := node.Etag()
	triples = "<> xx:version \"version2\" ."
	node, err = theServer.ReplaceRdfSource(triples, "/", path, etag)
	if err != nil {
		t.Errorf("Error replacing RDF node: %s", err)
	}

	if !node.HasTriple("xx:version", "\"version2\"") {
		t.Errorf("Error replacing RDF node. Updated triple not found")
	}

	_, err = theServer.ReplaceRdfSource(triples, "/", path, "bad-etag")
	if err != ldp.EtagMismatchError {
		t.Errorf("Failed to detect etag mismatch: %s", err)
	}

	_, err = theServer.ReplaceRdfSource(triples, "/", path, "")
	if err != ldp.EtagMissingError {
		t.Errorf("Failed to detect missing etag: %s", err)
	}
}

func TestCreateDirectContainer(t *testing.T) {
	// Create a helper node
	helperNode, err := theServer.CreateRdfSource("", "/", "other")

	// Create the direct container (pointing to the helper node)
	dcTriple1 := fmt.Sprintf("<> <%s> <%s> .\n", rdf.LdpMembershipResource, helperNode.Uri())
	dcTriple2 := fmt.Sprintf("<> <%s> <hasXYZ> .\n", rdf.LdpHasMemberRelation)
	dcTriples := dcTriple1 + dcTriple2
	dcNode, err := theServer.CreateRdfSource(dcTriples, "/", "dc")
	if err != nil {
		t.Errorf("Error creating direct container", err)
	}

	dcNode, err = theServer.GetNode(dcNode.Path())
	if err != nil {
		t.Errorf("Error fetching direct container", err)
	}

	if !dcNode.IsBasicContainer() {
		t.Errorf("Direct container fetched but not marked as a BASIC container %s", dcNode.Content())
	}
	if !dcNode.IsDirectContainer() {
		t.Errorf("Direct container fetched but not marked as a DIRECT container %s", dcNode.Content())
	}

	// Add a child to the direct container
	childNode, err := theServer.CreateRdfSource("", dcNode.Path(), "child")
	if err != nil {
		t.Errorf("Error adding child to Direct Container %s", err)
	}

	// Reload our helper node and make sure the child is referenced on it.
	helperNode, err = theServer.GetNode(helperNode.Path())
	if !helperNode.HasTriple("<hasXYZ>", "<"+childNode.Uri()+">") {
		t.Error("Helper node did not get new triple when adding to a Direct Container")
	}
}

func TestCreateChildRdf(t *testing.T) {
	parentNode, _ := theServer.CreateRdfSource("", "/", emptySlug)

	rdfNode, err := theServer.CreateRdfSource("", parentNode.Path(), emptySlug)
	if err != nil {
		t.Errorf("Error creating child RDF node under %s", err, parentNode.Uri())
	}

	if !strings.HasPrefix(rdfNode.Uri(), parentNode.Uri()) || rdfNode.Uri() == parentNode.Uri() {
		t.Errorf("Child URI %s does not seem to be under the parent URI %s", rdfNode.Uri(), parentNode.Uri())
	}

	invalidPath := parentNode.Path() + "/invalid"
	invalidNode, err := theServer.CreateRdfSource("", invalidPath, emptySlug)
	if err == nil {
		t.Errorf("A node was added to an invalid path %s %s", err, invalidNode.Uri())
	}

	reader := util.FakeReaderCloser{Text: "HELLO"}
	nonRdfNode, err := theServer.CreateNonRdfSource(reader, parentNode.Path(), emptySlug)
	if err != nil {
		t.Errorf("Error creating child non-RDF node under %s. Error: %s", parentNode.Uri(), err)
	}

	if !strings.HasPrefix(nonRdfNode.Uri(), parentNode.Uri()) || nonRdfNode.Uri() == parentNode.Uri() {
		t.Errorf("Child URI %s does not seem to be under the parent URI %s", nonRdfNode.Uri(), parentNode.Uri())
	}

	_, err = theServer.CreateRdfSource("", nonRdfNode.Path(), emptySlug)
	if err == nil {
		t.Errorf("A child was added to a non-RDF node! %s", nonRdfNode.Uri())
	}
}

func TestCreateRdfWithTriples(t *testing.T) {
	triples := "<> <b> <c> .\n<x> <y> <z> .\n"
	node, err := theServer.CreateRdfSource(triples, "/", emptySlug)
	if err != nil || !node.IsRdf() {
		t.Errorf("Error creating RDF")
	}

	node, err = theServer.GetNode(node.Path())
	if err != nil || node.Uri() != util.UriConcat(rootUrl, node.Path()) {
		t.Errorf("err %v, uri %s", err, node.Uri())
	}

	if !node.HasTriple("<b>", "<c>") {
		t.Errorf("Blank node not handled correctly %s", node.Uri())
		t.Errorf(node.DebugString())
	}

	if node.HasTriple("x", "z") {
		t.Errorf("Unexpected tripled for new subject %s", node.Uri())
	}
}

func TestCreateNonRdf(t *testing.T) {
	reader := util.FakeReaderCloser{Text: "HELLO"}
	node, err := theServer.CreateNonRdfSource(reader, "/", emptySlug)
	if err != nil {
		t.Errorf("Error creating Non RDF")
	}

	if node.IsRdf() {
		t.Errorf("Created RDF rather than Non RDF")
	}

	node, err = theServer.GetNode(node.Path())
	if err != nil || node.Uri() != util.UriConcat(rootUrl, node.Path()) {
		t.Errorf("err %v, uri %s", err, node.Uri())
	}

	if node.IsRdf() {
		t.Errorf("Node created as RDF instead of Non-RDF")
	}

	if node.Content() != "HELLO" {
		t.Errorf("Non-RDF content is not the expected one, %s", node.Content())
	}
}

func TestPatchRdf(t *testing.T) {
	triples := "<> <p1> <o1> .\n<> <p2> <o2> .\n"
	node, _ := theServer.CreateRdfSource(triples, "/", emptySlug)
	node, _ = theServer.GetNode(node.Path())
	if !node.HasTriple("<p1>", "<o1>") || !node.HasTriple("<p2>", "<o2>") {
		t.Errorf("Expected triple not found %s", node.Content())
	}

	newTriples := "<> <p3> <o3> .\n"
	err := node.Patch(newTriples)
	if err != nil {
		t.Errorf("Error during Patch %s", err)
	} else if !node.HasTriple("<p1>", "<o1>") ||
		!node.HasTriple("<p2>", "<o2>") ||
		!node.HasTriple("<p3>", "<o3>") {
		t.Errorf("Expected triple not after patch found %s", node.Content())
	}
}

func TestPatchNonRdf(t *testing.T) {
	reader1 := util.FakeReaderCloser{Text: "HELLO"}
	node, _ := theServer.CreateNonRdfSource(reader1, "/", emptySlug)
	node, _ = theServer.GetNode(node.Path())
	if node.Content() != "HELLO" {
		t.Errorf("Unexpected non-RDF content found %s", node.Content())
	}

	if err := node.Patch("whatever"); err == nil {
		t.Errorf("Shouldn't be able to patch non-RDF")
	}
}
<|endoftext|>


<commit_before>package golog

type PackageLogger struct {
	pack string
	LevelLogger
}

func NewDefaultPackageLogger(pack string) *PackageLogger {
	return &PackageLogger{pack, &levelLoggerImpl{
		DefaultLogger,
		func(int) *LogLocation { return &LogLocation{Package: pack} },
	}}
}
<commit_msg>Package logger doesn't need to store pack<commit_after>package golog

type PackageLogger struct {
	LevelLogger
}

func NewDefaultPackageLogger(pack string) *PackageLogger {
	return &PackageLogger{&levelLoggerImpl{
		DefaultLogger,
		func(int) *LogLocation { return &LogLocation{Package: pack} },
	}}
}
<|endoftext|>


<commit_before>package mapper

import (
	"log"
	"testing"

	"github.com/stretchr/testify/assert"
)

func allLabelsFor(label string) []string {
	allLabels := []string{}
	for t := label; t != ""; t = ParentType(t) {
		allLabels = append(allLabels, t)
	}
	return allLabels
}

var thingLabels = allLabelsFor("Thing")
var conceptLabels = allLabelsFor("Concept")
var roleLabels = allLabelsFor("Role")
var boardRoleLabels = allLabelsFor("BoardRole")
var brandLabels = allLabelsFor("Brand")
var personLabels = allLabelsFor("Person")
var organisationLabels = allLabelsFor("Organisation")
var membershipLabels = allLabelsFor("Membership")
var companyLabels = allLabelsFor("Company")
var publicCompanyLabels = allLabelsFor("PublicCompany")
var privateCompanyLabels = allLabelsFor("PrivateCompany")
var classificationLabels = allLabelsFor("Classification")
var industryClassificationLabels = allLabelsFor("IndustryClassification")
var subjectLabels = allLabelsFor("Subject")
var sectionLabels = allLabelsFor("Section")
var genreLabels = allLabelsFor("Genre")
var topicLabels = allLabelsFor("Topic")
var locationLabels = allLabelsFor("Location")

var thingURI = "http://www.ft.com/ontology/core/Thing"
var conceptURI = "http://www.ft.com/ontology/concept/Concept"
var roleURI = "http://www.ft.com/ontology/organisation/Role"
var boardRoleURI = "http://www.ft.com/ontology/organisation/BoardRole"
var classificationURI = "http://www.ft.com/ontology/classification/Classification"
var industryClassificationURI = "http://www.ft.com/ontology/industry/IndustryClassification"
var personURI = "http://www.ft.com/ontology/person/Person"
var brandURI = "http://www.ft.com/ontology/product/Brand"
var organisationURI = "http://www.ft.com/ontology/organisation/Organisation"
var membershipURI = "http://www.ft.com/ontology/organisation/Membership"
var companyURI = "http://www.ft.com/ontology/company/Company"
var publicCompanyURI = "http://www.ft.com/ontology/company/PublicCompany"
var privateCompanyURI = "http://www.ft.com/ontology/company/PrivateCompany"
var subjectURI = "http://www.ft.com/ontology/Subject"
var sectionURI = "http://www.ft.com/ontology/Section"
var genreURI = "http://www.ft.com/ontology/Genre"
var topicURI = "http://www.ft.com/ontology/Topic"
var locationURI = "http://www.ft.com/ontology/Location"

var uuid = "92f4ec09-436d-4092-a88c-96f54e34007c"

var env = "prod"
var envTest = "test"

var baseAPIURL = "http://api.ft.com/"
var thingAPIURL = baseAPIURL + "things/" + uuid
var personAPIURL = baseAPIURL + "people/" + uuid
var organisationAPIURL = baseAPIURL + "organisations/" + uuid
var contentAPIURL = baseAPIURL + "content/" + uuid
var brandAPIURL = baseAPIURL + "brands/" + uuid

func TestTypeURIsForPeople(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, personURI}, TypeURIs(personLabels))
}

func TestTypeURIsForOrganisations(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, organisationURI}, TypeURIs(organisationLabels))
}

func TestTypeURIsForMemberships(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, membershipURI}, TypeURIs(membershipLabels))
}

func TestTypeURIsForRoles(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, roleURI}, TypeURIs(roleLabels))
}

func TestTypeURIsForBoardRoles(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, roleURI, boardRoleURI}, TypeURIs(boardRoleLabels))
}

func TestTypeURIsForCompany(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, organisationURI, companyURI}, TypeURIs(companyLabels))
}

func TestTypeURIsForPublicCompany(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, organisationURI, companyURI, publicCompanyURI}, TypeURIs(publicCompanyLabels))
}

func TestTypeURIsForPrivateCompany(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, organisationURI, companyURI, privateCompanyURI}, TypeURIs(privateCompanyLabels))
}

func TestTypeURIsForBrand(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, classificationURI, brandURI}, TypeURIs(brandLabels))
}

func TestTypeURIsForSubject(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, classificationURI, subjectURI}, TypeURIs(subjectLabels))
}

func TestTypeURIsForSection(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, classificationURI, sectionURI}, TypeURIs(sectionLabels))
}

func TestTypeURIsForGenre(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, classificationURI, genreURI}, TypeURIs(genreLabels))
}

func TestTypeURIsForTopic(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, topicURI}, TypeURIs(topicLabels))
}

func TestTypeURIsForLocation(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, locationURI}, TypeURIs(locationLabels))
}

func TestTypeURIsForIndustryClassification(t *testing.T) {
	log.Printf("labels =%v", industryClassificationLabels)
	assert.New(t).EqualValues([]string{thingURI, conceptURI, classificationURI, industryClassificationURI}, TypeURIs(industryClassificationLabels))
}

func TestContentAPIURLs(t *testing.T) {
	neoLabels := []string{"Content"}
	assert.New(t).EqualValues(contentAPIURL, APIURL(uuid, neoLabels, env))
}

func TestCompanyAPIURLs(t *testing.T) {
	neoLabels := []string{"PublicCompany", "Organisation", "Company"}
	assert.New(t).EqualValues(organisationAPIURL, APIURL(uuid, neoLabels, env))
}

func TestOrganisationAPIURLs(t *testing.T) {
	neoLabels := []string{"Organisation", "Concept", "Thing"}
	assert.New(t).EqualValues(organisationAPIURL, APIURL(uuid, neoLabels, env))
}

func TestPeopleAPIURLs(t *testing.T) {
	neoLabels := []string{"Person"}
	assert.New(t).EqualValues(personAPIURL, APIURL(uuid, neoLabels, env))

}

func TestBrandAPIURLs(t *testing.T) {
	neoLabels := []string{"Brand"}
	assert.New(t).EqualValues(brandAPIURL, APIURL(uuid, neoLabels, env))

}

func TestDefaultAPIURLs(t *testing.T) {
	neoLabels := []string{"thing", "relationship", "otherPrivateType"}
	assert.New(t).EqualValues(thingAPIURL, APIURL(uuid, neoLabels, env))

}

func TestMostSpecific(t *testing.T) {
	assert := assert.New(t)

	for _, t := range []struct {
		input    []string
		expected string
		err      error
	}{
		{
			[]string{"Organisation"},
			"Organisation",
			nil,
		}, {
			[]string{"Organisation", "PublicCompany", "Company"},
			"PublicCompany",
			nil,
		}, {
			[]string{"PublicCompany", "Organisation"},
			"PublicCompany",
			nil,
		}, {
			[]string{"Organisation", "PublicCompany", "PrivateCompany", "Company"},
			"",
			ErrNotHierarchy,
		}, {
			[]string{"zzzzzz", "yyyyyy"},
			"",
			ErrNotHierarchy,
		},
	} {
		ms, err := mostSpecific(t.input)
		assert.Equal(t.expected, ms)
		assert.Equal(t.err, err)
	}
}

func TestTypeSorter(t *testing.T) {
	assert := assert.New(t)

	for _, t := range []struct {
		input    []string
		expected []string
		err      error
	}{
		{
			[]string{"Organisation"},
			[]string{"Organisation"},
			nil,
		}, {
			[]string{"Organisation", "PublicCompany", "Company"},
			[]string{"Organisation", "Company", "PublicCompany"},
			nil,
		}, {
			[]string{"PublicCompany", "Organisation"},
			[]string{"Organisation", "PublicCompany"},
			nil,
		}, {
			[]string{"Content", "Thing"},
			[]string{"Thing", "Content"},
			nil,
		}, {
			[]string{"Organisation", "PublicCompany", "PrivateCompany", "Company"},
			[]string{"Organisation", "PublicCompany", "PrivateCompany", "Company"},
			ErrNotHierarchy,
		}, {
			[]string{"zzzzzz", "yyyyyy"},
			[]string{"zzzzzz", "yyyyyy"},
			ErrNotHierarchy,
		},
	} {
		sorted, err := SortTypes(t.input)
		assert.Equal(t.expected, sorted)
		assert.Equal(t.err, err)
	}
}
<commit_msg>Make change suggested by George. Cheers George<commit_after>package mapper

import (
	"log"
	"testing"

	"github.com/stretchr/testify/assert"
)

func allLabelsFor(label string) []string {
	allLabels := []string{}
	for t := label; t != ""; t = ParentType(t) {
		allLabels = append(allLabels, t)
	}
	return allLabels
}

var (
	thingLabels                  = allLabelsFor("Thing")
	conceptLabels                = allLabelsFor("Concept")
	roleLabels                   = allLabelsFor("Role")
	boardRoleLabels              = allLabelsFor("BoardRole")
	brandLabels                  = allLabelsFor("Brand")
	personLabels                 = allLabelsFor("Person")
	organisationLabels           = allLabelsFor("Organisation")
	membershipLabels             = allLabelsFor("Membership")
	companyLabels                = allLabelsFor("Company")
	publicCompanyLabels          = allLabelsFor("PublicCompany")
	privateCompanyLabels         = allLabelsFor("PrivateCompany")
	classificationLabels         = allLabelsFor("Classification")
	industryClassificationLabels = allLabelsFor("IndustryClassification")
	subjectLabels                = allLabelsFor("Subject")
	sectionLabels                = allLabelsFor("Section")
	genreLabels                  = allLabelsFor("Genre")
	topicLabels                  = allLabelsFor("Topic")
	locationLabels               = allLabelsFor("Location")

	thingURI                  = "http://www.ft.com/ontology/core/Thing"
	conceptURI                = "http://www.ft.com/ontology/concept/Concept"
	roleURI                   = "http://www.ft.com/ontology/organisation/Role"
	boardRoleURI              = "http://www.ft.com/ontology/organisation/BoardRole"
	classificationURI         = "http://www.ft.com/ontology/classification/Classification"
	industryClassificationURI = "http://www.ft.com/ontology/industry/IndustryClassification"
	personURI                 = "http://www.ft.com/ontology/person/Person"
	brandURI                  = "http://www.ft.com/ontology/product/Brand"
	organisationURI           = "http://www.ft.com/ontology/organisation/Organisation"
	membershipURI             = "http://www.ft.com/ontology/organisation/Membership"
	companyURI                = "http://www.ft.com/ontology/company/Company"
	publicCompanyURI          = "http://www.ft.com/ontology/company/PublicCompany"
	privateCompanyURI         = "http://www.ft.com/ontology/company/PrivateCompany"
	subjectURI                = "http://www.ft.com/ontology/Subject"
	sectionURI                = "http://www.ft.com/ontology/Section"
	genreURI                  = "http://www.ft.com/ontology/Genre"
	topicURI                  = "http://www.ft.com/ontology/Topic"
	locationURI               = "http://www.ft.com/ontology/Location"

	uuid = "92f4ec09-436d-4092-a88c-96f54e34007c"

	env     = "prod"
	envTest = "test"

	baseAPIURL         = "http://api.ft.com/"
	thingAPIURL        = baseAPIURL + "things/" + uuid
	personAPIURL       = baseAPIURL + "people/" + uuid
	organisationAPIURL = baseAPIURL + "organisations/" + uuid
	contentAPIURL      = baseAPIURL + "content/" + uuid
	brandAPIURL        = baseAPIURL + "brands/" + uuid
)

func TestTypeURIsForPeople(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, personURI}, TypeURIs(personLabels))
}

func TestTypeURIsForOrganisations(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, organisationURI}, TypeURIs(organisationLabels))
}

func TestTypeURIsForMemberships(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, membershipURI}, TypeURIs(membershipLabels))
}

func TestTypeURIsForRoles(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, roleURI}, TypeURIs(roleLabels))
}

func TestTypeURIsForBoardRoles(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, roleURI, boardRoleURI}, TypeURIs(boardRoleLabels))
}

func TestTypeURIsForCompany(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, organisationURI, companyURI}, TypeURIs(companyLabels))
}

func TestTypeURIsForPublicCompany(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, organisationURI, companyURI, publicCompanyURI}, TypeURIs(publicCompanyLabels))
}

func TestTypeURIsForPrivateCompany(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, organisationURI, companyURI, privateCompanyURI}, TypeURIs(privateCompanyLabels))
}

func TestTypeURIsForBrand(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, classificationURI, brandURI}, TypeURIs(brandLabels))
}

func TestTypeURIsForSubject(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, classificationURI, subjectURI}, TypeURIs(subjectLabels))
}

func TestTypeURIsForSection(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, classificationURI, sectionURI}, TypeURIs(sectionLabels))
}

func TestTypeURIsForGenre(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, classificationURI, genreURI}, TypeURIs(genreLabels))
}

func TestTypeURIsForTopic(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, topicURI}, TypeURIs(topicLabels))
}

func TestTypeURIsForLocation(t *testing.T) {
	assert.New(t).EqualValues([]string{thingURI, conceptURI, locationURI}, TypeURIs(locationLabels))
}

func TestTypeURIsForIndustryClassification(t *testing.T) {
	log.Printf("labels =%v", industryClassificationLabels)
	assert.New(t).EqualValues([]string{thingURI, conceptURI, classificationURI, industryClassificationURI}, TypeURIs(industryClassificationLabels))
}

func TestContentAPIURLs(t *testing.T) {
	neoLabels := []string{"Content"}
	assert.New(t).EqualValues(contentAPIURL, APIURL(uuid, neoLabels, env))
}

func TestCompanyAPIURLs(t *testing.T) {
	neoLabels := []string{"PublicCompany", "Organisation", "Company"}
	assert.New(t).EqualValues(organisationAPIURL, APIURL(uuid, neoLabels, env))
}

func TestOrganisationAPIURLs(t *testing.T) {
	neoLabels := []string{"Organisation", "Concept", "Thing"}
	assert.New(t).EqualValues(organisationAPIURL, APIURL(uuid, neoLabels, env))
}

func TestPeopleAPIURLs(t *testing.T) {
	neoLabels := []string{"Person"}
	assert.New(t).EqualValues(personAPIURL, APIURL(uuid, neoLabels, env))

}

func TestBrandAPIURLs(t *testing.T) {
	neoLabels := []string{"Brand"}
	assert.New(t).EqualValues(brandAPIURL, APIURL(uuid, neoLabels, env))

}

func TestDefaultAPIURLs(t *testing.T) {
	neoLabels := []string{"thing", "relationship", "otherPrivateType"}
	assert.New(t).EqualValues(thingAPIURL, APIURL(uuid, neoLabels, env))

}

func TestMostSpecific(t *testing.T) {
	assert := assert.New(t)

	for _, t := range []struct {
		input    []string
		expected string
		err      error
	}{
		{
			[]string{"Organisation"},
			"Organisation",
			nil,
		}, {
			[]string{"Organisation", "PublicCompany", "Company"},
			"PublicCompany",
			nil,
		}, {
			[]string{"PublicCompany", "Organisation"},
			"PublicCompany",
			nil,
		}, {
			[]string{"Organisation", "PublicCompany", "PrivateCompany", "Company"},
			"",
			ErrNotHierarchy,
		}, {
			[]string{"zzzzzz", "yyyyyy"},
			"",
			ErrNotHierarchy,
		},
	} {
		ms, err := mostSpecific(t.input)
		assert.Equal(t.expected, ms)
		assert.Equal(t.err, err)
	}
}

func TestTypeSorter(t *testing.T) {
	assert := assert.New(t)

	for _, t := range []struct {
		input    []string
		expected []string
		err      error
	}{
		{
			[]string{"Organisation"},
			[]string{"Organisation"},
			nil,
		}, {
			[]string{"Organisation", "PublicCompany", "Company"},
			[]string{"Organisation", "Company", "PublicCompany"},
			nil,
		}, {
			[]string{"PublicCompany", "Organisation"},
			[]string{"Organisation", "PublicCompany"},
			nil,
		}, {
			[]string{"Content", "Thing"},
			[]string{"Thing", "Content"},
			nil,
		}, {
			[]string{"Organisation", "PublicCompany", "PrivateCompany", "Company"},
			[]string{"Organisation", "PublicCompany", "PrivateCompany", "Company"},
			ErrNotHierarchy,
		}, {
			[]string{"zzzzzz", "yyyyyy"},
			[]string{"zzzzzz", "yyyyyy"},
			ErrNotHierarchy,
		},
	} {
		sorted, err := SortTypes(t.input)
		assert.Equal(t.expected, sorted)
		assert.Equal(t.err, err)
	}
}
<|endoftext|>


<commit_before>package log

import (
	"os"
	"path/filepath"
	"runtime"
)

var (
	pid         = os.Getpid()
	hostname, _ = os.Hostname()
	appname     = filepath.Base(os.Args[0])
)

// CallerInfo encapsulates information about a piece of code that called a certain log function,
// such as file name, line number, etc.
type CallerInfo struct {
	FileName string
	FilePath string
	FuncName string
	LineNo   int
}

// getCallerInfo returns information about a certain log function invoker
// such as file name, function name and line number
func getCallerInfo(depth int) *CallerInfo {
	if pc, filePath, lineNo, ok := runtime.Caller(depth + 1); !ok {
		return &CallerInfo{"unknown_file", "unknown_path", "unknown_func", 0}
	} else {
		return &CallerInfo{filepath.Base(filePath), filePath, runtime.FuncForPC(pc).Name(), lineNo}
	}
}
<commit_msg>Fixed the last comment<commit_after>package log

import (
	"os"
	"path/filepath"
	"runtime"
)

var (
	pid      = os.Getpid()
	hostname = "" // will be set in the init function
	appname  = filepath.Base(os.Args[0])
)

func init() {
	// determine the hostname but do not stop if it fails
	var err error
	if hostname, err = os.Hostname(); err != nil {
		hostname = "unknown_host"
	}
}

// CallerInfo encapsulates information about a piece of code that called a certain log function,
// such as file name, line number, etc.
type CallerInfo struct {
	FileName string
	FilePath string
	FuncName string
	LineNo   int
}

// getCallerInfo returns information about a certain log function invoker
// such as file name, function name and line number
func getCallerInfo(depth int) *CallerInfo {
	if pc, filePath, lineNo, ok := runtime.Caller(depth + 1); !ok {
		return &CallerInfo{"unknown_file", "unknown_path", "unknown_func", 0}
	} else {
		return &CallerInfo{filepath.Base(filePath), filePath, runtime.FuncForPC(pc).Name(), lineNo}
	}
}
<|endoftext|>


<commit_before>package mem

// Register constants
const (
	LCDC = 0xFF40
	STAT = 0xFF41
	SCY  = 0xFF42
	SCX  = 0xFF43
	LY   = 0xFF44
	LYC  = 0xFF45
	WY   = 0xFF4A
	WX   = 0xFF4B
	DMA  = 0xFF46
	BGP  = 0xFF47
	OBP0 = 0xFF48
	OBP1 = 0xFF49
	NR10 = 0xFF10
	NR11 = 0xFF11
	NR12 = 0xFF12
	NR13 = 0xFF13
	NR14 = 0xFF14
	NR21 = 0xFF16
	NR22 = 0xFF17
	NR23 = 0xFF18
	NR24 = 0xFF19
	NR30 = 0xFF1A
	NR31 = 0xFF1B
	NR32 = 0xFF1C
	NR33 = 0xFF1D
	NR34 = 0xFF1E
	NR41 = 0xFF20
	NR42 = 0xFF21
	NR43 = 0xFF22
	NR44 = 0xFF23
	NR50 = 0xFF24
	NR51 = 0xFF25
	NR52 = 0xFF26
	JOYP = 0xFF00
	SB   = 0xFF01
	SC   = 0xFF02
	DIV  = 0xFF04
	TIMA = 0xFF05
	TMA  = 0xFF06
	TAC  = 0xFF07
	IF   = 0xFF0F
	IE   = 0xFFFF

	//
	// Defaults
	//
	// [0x00] = 0x0f
	// [0x10] = 0x80
	// [0x11] = 0xbf
	// [0x12] = 0xf3
	// [0x14] = 0xbf
	// [0x16] = 0x3f
	// [0x19] = 0xbf
	// [0x1a] = 0x7f
	// [0x1b] = 0xff
	// [0x1c] = 0x9f
	// [0x1e] = 0xbf
	// [0x20] = 0xff
	// [0x23] = 0xbf
	// [0x24] = 0x77
	// [0x25] = 0xf3
	// [0x26] = 0xf1
	// [0x40] = 0x91
	// [0x47] = 0xfc
	// [0x48] = 0xff
	// [0x49] = 0xff

)

// HardwareRegisters represents hardware registers between 0xff00 and 0xff7f
type HardwareRegisters struct {
	IE   byte
	IF   byte
	LCDC byte
	LY   byte
	LYC  byte
	SCX  byte
	SCY  byte
	STAT byte
	WX   byte
	WY   byte

	// JOYP
	storingDirectionInput bool
	DirectionInput        uint8
	ButtonInput           uint8
}

// NewHardwareRegisters creates a new representation of the hardware registers
func NewHardwareRegisters() *HardwareRegisters {
	return &HardwareRegisters{
		DirectionInput: 0x0f,
		ButtonInput:    0x0f,
	}
}

func (mem *Memory) readHardwareRegisters(addr uint16) uint8 {
	switch addr {
	case DMA:
		return 0
	case IE:
		return mem.hwr.IE
	case IF:
		return mem.hwr.IF
	case LCDC:
		return mem.hwr.LCDC
	case STAT:
		return mem.hwr.STAT
	case SCY:
		return mem.hwr.SCY
	case SCX:
		return mem.hwr.SCX
	case LY:
		return mem.hwr.LY
	case LYC:
		return mem.hwr.LYC
	case WY:
		return mem.hwr.WY
	case WX:
		return mem.hwr.WX
	// case BGP:
	// case OBP0:
	// case OBP1:
	// case NR10:
	// case NR11:
	// case NR12:
	// case NR13:
	// case NR14:
	// case NR21:
	// case NR22:
	// case NR23:
	// case NR24:
	// case NR30:
	// case NR31:
	// case NR32:
	// case NR33:
	// case NR34:
	// case NR41:
	// case NR42:
	// case NR43:
	// case NR44:
	// case NR50:
	// case NR51:
	// case NR52:
	case JOYP:
		return mem.hwr.joypRead()
	// case SB:
	// case SC:
	// case DIV:
	// case TIMA:
	// case TMA:
	// case TAC:
	default:
		// fmt.Printf("No read support for hardware register 0x%04x\n", addr)
	}
	return 0 // Temporary default value
}

func (mem *Memory) writeHardwareRegisters(addr uint16, value uint8) {
	switch addr {
	case DMA:
		mem.dma(value)
	case IE:
		mem.hwr.IE = value
	case IF:
		mem.hwr.IF = value
	case LCDC:
		mem.hwr.LCDC = value
	case STAT:
		mem.hwr.STAT = value
	case SCY:
		mem.hwr.SCY = value
	case SCX:
		mem.hwr.SCX = value
	case LY:
		mem.hwr.LY = value
	case LYC:
		mem.hwr.LYC = value
	case WY:
		mem.hwr.WY = value
	case WX:
		mem.hwr.WX = value
	// case BGP:
	// case OBP0:
	// case OBP1:
	// case NR10:
	// case NR11:
	// case NR12:
	// case NR13:
	// case NR14:
	// case NR21:
	// case NR22:
	// case NR23:
	// case NR24:
	// case NR30:
	// case NR31:
	// case NR32:
	// case NR33:
	// case NR34:
	// case NR41:
	// case NR42:
	// case NR43:
	// case NR44:
	// case NR50:
	// case NR51:
	// case NR52:
	case JOYP:
		mem.hwr.joypWrite(value)
	// case SB:
	// case SC:
	// case DIV:
	// case TIMA:
	// case TMA:
	// case TAC:
	default:
		// fmt.Printf("No write support for hardware register 0x%04x\n", addr)
	}
}

func (r *HardwareRegisters) joypRead() uint8 {
	if r.storingDirectionInput {
		return r.DirectionInput
	}
	return r.ButtonInput
}

func (r *HardwareRegisters) joypWrite(value uint8) {
	// Bit 5 - P15 Select Button Keys      (0=Select)
	// Bit 4 - P14 Select Direction Keys   (0=Select)
	if value&0x20 == 0 {
		r.storingDirectionInput = false
	} else if value&0x10 == 0 {
		r.storingDirectionInput = true
	}
}

func (mem *Memory) dma(addrPrefix uint8) {
	srcBaseAddr := uint16(addrPrefix) << 8
	for i := uint16(0x00); i < 0x0a0; i++ {
		mem.oam[i] = mem.Read(srcBaseAddr + i)
	}
}
<commit_msg>Expand out hardware registers<commit_after>package mem

// Register constants
const (
	LCDC = 0xFF40
	STAT = 0xFF41
	SCY  = 0xFF42
	SCX  = 0xFF43
	LY   = 0xFF44
	LYC  = 0xFF45
	WY   = 0xFF4A
	WX   = 0xFF4B
	DMA  = 0xFF46
	BGP  = 0xFF47
	OBP0 = 0xFF48
	OBP1 = 0xFF49
	NR10 = 0xFF10
	NR11 = 0xFF11
	NR12 = 0xFF12
	NR13 = 0xFF13
	NR14 = 0xFF14
	NR21 = 0xFF16
	NR22 = 0xFF17
	NR23 = 0xFF18
	NR24 = 0xFF19
	NR30 = 0xFF1A
	NR31 = 0xFF1B
	NR32 = 0xFF1C
	NR33 = 0xFF1D
	NR34 = 0xFF1E
	NR41 = 0xFF20
	NR42 = 0xFF21
	NR43 = 0xFF22
	NR44 = 0xFF23
	NR50 = 0xFF24
	NR51 = 0xFF25
	NR52 = 0xFF26
	JOYP = 0xFF00
	SB   = 0xFF01
	SC   = 0xFF02
	DIV  = 0xFF04
	TIMA = 0xFF05
	TMA  = 0xFF06
	TAC  = 0xFF07
	IF   = 0xFF0F
	IE   = 0xFFFF

	//
	// Defaults
	//
	// [0x00] = 0x0f
	// [0x10] = 0x80
	// [0x11] = 0xbf
	// [0x12] = 0xf3
	// [0x14] = 0xbf
	// [0x16] = 0x3f
	// [0x19] = 0xbf
	// [0x1a] = 0x7f
	// [0x1b] = 0xff
	// [0x1c] = 0x9f
	// [0x1e] = 0xbf
	// [0x20] = 0xff
	// [0x23] = 0xbf
	// [0x24] = 0x77
	// [0x25] = 0xf3
	// [0x26] = 0xf1
	// [0x40] = 0x91
	// [0x47] = 0xfc
	// [0x48] = 0xff
	// [0x49] = 0xff

)

// HardwareRegisters represents hardware registers between 0xff00 and 0xff7f
type HardwareRegisters struct {
	IE   byte
	IF   byte
	LCDC byte
	LY   byte
	LYC  byte
	SCX  byte
	SCY  byte
	STAT byte
	WX   byte
	WY   byte

	// JOYP
	storingDirectionInput bool
	DirectionInput        uint8
	ButtonInput           uint8
}

// NewHardwareRegisters creates a new representation of the hardware registers
func NewHardwareRegisters() *HardwareRegisters {
	return &HardwareRegisters{
		DirectionInput: 0x0f,
		ButtonInput:    0x0f,
	}
}

func (mem *Memory) readHardwareRegisters(addr uint16) uint8 {
	switch addr {
	case DMA:
		return 0
	case IE:
		return mem.hwr.IE
	case IF:
		return mem.hwr.IF
	case LCDC:
		return mem.hwr.LCDC
	case STAT:
		return mem.hwr.STAT
	case SCY:
		return mem.hwr.SCY
	case SCX:
		return mem.hwr.SCX
	case LY:
		return mem.hwr.LY
	case LYC:
		return mem.hwr.LYC
	case WY:
		return mem.hwr.WY
	case WX:
		return mem.hwr.WX
	// case BGP:
	// case OBP0:
	// case OBP1:
	// case NR10:
	// case NR11:
	// case NR12:
	// case NR13:
	// case NR14:
	// case NR21:
	// case NR22:
	// case NR23:
	// case NR24:
	// case NR30:
	// case NR31:
	// case NR32:
	// case NR33:
	// case NR34:
	// case NR41:
	// case NR42:
	// case NR43:
	// case NR44:
	// case NR50:
	// case NR51:
	// case NR52:
	case JOYP:
		return mem.hwr.joypRead()
	// case SB:
	// case SC:
	// case DIV:
	// case TIMA:
	// case TMA:
	// case TAC:
	default:
		return 0
	}
}

func (mem *Memory) writeHardwareRegisters(addr uint16, value uint8) {
	switch addr {
	case DMA:
		mem.dma(value)
	case IE:
		mem.hwr.IE = value
	case IF:
		mem.hwr.IF = value
	case LCDC:
		mem.hwr.LCDC = value
	case STAT:
		mem.hwr.STAT = value
	case SCY:
		mem.hwr.SCY = value
	case SCX:
		mem.hwr.SCX = value
	case LY:
		mem.hwr.LY = value
	case LYC:
		mem.hwr.LYC = value
	case WY:
		mem.hwr.WY = value
	case WX:
		mem.hwr.WX = value
	case BGP:
		// FIXME palette support
	case OBP0:
		// FIXME sprite palette support
	case OBP1:
		// FIXME sprite palette support
	case NR10:
		// FIXME sound support
	case NR11:
		// FIXME sound support
	case NR12:
		// FIXME sound support
	case NR13:
		// FIXME sound support
	case NR14:
		// FIXME sound support
	case NR21:
		// FIXME sound support
	case NR22:
		// FIXME sound support
	case NR23:
		// FIXME sound support
	case NR24:
		// FIXME sound support
	case NR30:
		// FIXME sound support
	case NR31:
		// FIXME sound support
	case NR32:
		// FIXME sound support
	case NR33:
		// FIXME sound support
	case NR34:
		// FIXME sound support
	case NR41:
		// FIXME sound support
	case NR42:
		// FIXME sound support
	case NR43:
		// FIXME sound support
	case NR44:
		// FIXME sound support
	case NR50:
		// FIXME sound support
	case NR51:
		// FIXME sound support
	case NR52:
		// FIXME sound support
	case JOYP:
		mem.hwr.joypWrite(value)
	case SB:
		// FIXME serial bus support
	case SC:
		// FIXME serial bus support
	case DIV:
		// FIXME timer
	case TIMA:
		// FIXME timer
	case TMA:
		// FIXME timer
	case TAC:
		// FIXME timer
	default:
		// Do nothing
	}
}

func (r *HardwareRegisters) joypRead() uint8 {
	if r.storingDirectionInput {
		return r.DirectionInput
	}
	return r.ButtonInput
}

func (r *HardwareRegisters) joypWrite(value uint8) {
	// Bit 5 - P15 Select Button Keys      (0=Select)
	// Bit 4 - P14 Select Direction Keys   (0=Select)
	if value&0x20 == 0 {
		r.storingDirectionInput = false
	} else if value&0x10 == 0 {
		r.storingDirectionInput = true
	}
}

func (mem *Memory) dma(addrPrefix uint8) {
	srcBaseAddr := uint16(addrPrefix) << 8
	for i := uint16(0x00); i < 0x0a0; i++ {
		mem.oam[i] = mem.Read(srcBaseAddr + i)
	}
}
<|endoftext|>


<commit_before>package brats_test

import (
	"fmt"
	"strings"

	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
)

var _ = Describe("Director external database TLS connections", func() {
	AfterEach(func() {
		stopInnerBosh()
	})

	testDBConnectionOverTLS := func(databaseType string, mutualTLSEnabled bool) {
		external_db_host := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_HOST", strings.ToUpper(databaseType)))
		external_db_user := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_USER", strings.ToUpper(databaseType)))
		external_db_password := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_PASSWORD", strings.ToUpper(databaseType)))
		external_db_name := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_NAME", strings.ToUpper(databaseType)))

		connectionOptions := fmt.Sprintf("external_db/%s_connection_options.yml", databaseType)
		connectionVarFile := fmt.Sprintf("external_db/%s.yml", databaseType)

		startInnerBoshArgs := []string{
			fmt.Sprintf("-o %s", boshDeploymentAssetPath("misc/external-db.yml")),
			fmt.Sprintf("-o %s", boshDeploymentAssetPath("experimental/db-enable-tls.yml")),
			fmt.Sprintf("-o %s", assetPath(connectionOptions)),
			fmt.Sprintf("--vars-file %s", assetPath(connectionVarFile)),
			fmt.Sprintf("-v external_db_host=%s", external_db_host),
			fmt.Sprintf("-v external_db_user=%s", external_db_user),
			fmt.Sprintf("-v external_db_password=%s", external_db_password),
			fmt.Sprintf("-v external_db_name=%s", external_db_name),
		}

		if mutualTLSEnabled {
			external_db_client_certificate := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_CLIENT_CERTIFICATE", strings.ToUpper(databaseType)))
			external_db_client_private_key := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_CLIENT_PRIVATE_KEY", strings.ToUpper(databaseType)))

			tempDir, err := ioutil.TempDir("", "bosh_db_tls")
			if err != nil {
				log.Fatal(err)
			}

			defer os.RemoveAll(tempDir)

			external_db_client_certificate_file := filepath.Join(tempDir, "external_db_client_certificate")
			if err := ioutil.WriteFile(external_db_client_certificate_file, []byte(external_db_client_certificate), 0666); err != nil {
				log.Fatal(err)
			}

			external_db_client_private_key_file := filepath.Join(tempDir, "external_db_client_private_key")
			if err := ioutil.WriteFile(external_db_client_private_key_file, []byte(external_db_client_private_key), 0666); err != nil {
				log.Fatal(err)
			}

			mutualTLSArgs := []string{
				fmt.Sprintf("-o %s", boshDeploymentAssetPath("experimental/db-enable-mutual-tls.yml")),
				fmt.Sprintf("--var-file=db_client_certificate=%s", external_db_client_certificate_file),
				fmt.Sprintf("--var-file=db_client_private_key=%s", external_db_client_private_key_file),
			}

			startInnerBoshArgs = append(startInnerBoshArgs, mutualTLSArgs...)
		}

		startInnerBosh(startInnerBoshArgs...)

		uploadRelease("https://bosh.io/d/github.com/cloudfoundry/syslog-release?v=11")
	}

	DescribeTable("RDS", testDBConnectionOverTLS,
		Entry("allows TLS connections to POSTGRES", "rds_postgres", false),

		// Pending. Check https://www.pivotaltracker.com/story/show/154143917 and https://www.pivotaltracker.com/story/show/153785594/comments/184377346
		PEntry("allows TLS connections to MYSQL, refer to https://www.pivotaltracker.com/story/show/154143917", "rds_mysql", false),
	)

	DescribeTable("GCP", testDBConnectionOverTLS,
		Entry("allows TLS connections to MYSQL", "gcp_mysql", false),
		Entry("allows TLS connections to POSTGRES", "gcp_postgres", false),

		Entry("allows Mutual TLS connections to MYSQL", "gcp_mysql", true),
		Entry("allows Mutual TLS connections to POSTGRES", "gcp_postgres", true),
	)
})
<commit_msg>Unpend MYSQL RDS TLS test<commit_after>package brats_test

import (
	"fmt"
	"strings"

	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
)

var _ = Describe("Director external database TLS connections", func() {
	AfterEach(func() {
		stopInnerBosh()
	})

	testDBConnectionOverTLS := func(databaseType string, mutualTLSEnabled bool) {
		external_db_host := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_HOST", strings.ToUpper(databaseType)))
		external_db_user := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_USER", strings.ToUpper(databaseType)))
		external_db_password := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_PASSWORD", strings.ToUpper(databaseType)))
		external_db_name := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_NAME", strings.ToUpper(databaseType)))

		connectionOptions := fmt.Sprintf("external_db/%s_connection_options.yml", databaseType)
		connectionVarFile := fmt.Sprintf("external_db/%s.yml", databaseType)

		startInnerBoshArgs := []string{
			fmt.Sprintf("-o %s", boshDeploymentAssetPath("misc/external-db.yml")),
			fmt.Sprintf("-o %s", boshDeploymentAssetPath("experimental/db-enable-tls.yml")),
			fmt.Sprintf("-o %s", assetPath(connectionOptions)),
			fmt.Sprintf("--vars-file %s", assetPath(connectionVarFile)),
			fmt.Sprintf("-v external_db_host=%s", external_db_host),
			fmt.Sprintf("-v external_db_user=%s", external_db_user),
			fmt.Sprintf("-v external_db_password=%s", external_db_password),
			fmt.Sprintf("-v external_db_name=%s", external_db_name),
		}

		if mutualTLSEnabled {
			external_db_client_certificate := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_CLIENT_CERTIFICATE", strings.ToUpper(databaseType)))
			external_db_client_private_key := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_CLIENT_PRIVATE_KEY", strings.ToUpper(databaseType)))

			tempDir, err := ioutil.TempDir("", "bosh_db_tls")
			if err != nil {
				log.Fatal(err)
			}

			defer os.RemoveAll(tempDir)

			external_db_client_certificate_file := filepath.Join(tempDir, "external_db_client_certificate")
			if err := ioutil.WriteFile(external_db_client_certificate_file, []byte(external_db_client_certificate), 0666); err != nil {
				log.Fatal(err)
			}

			external_db_client_private_key_file := filepath.Join(tempDir, "external_db_client_private_key")
			if err := ioutil.WriteFile(external_db_client_private_key_file, []byte(external_db_client_private_key), 0666); err != nil {
				log.Fatal(err)
			}

			mutualTLSArgs := []string{
				fmt.Sprintf("-o %s", boshDeploymentAssetPath("experimental/db-enable-mutual-tls.yml")),
				fmt.Sprintf("--var-file=db_client_certificate=%s", external_db_client_certificate_file),
				fmt.Sprintf("--var-file=db_client_private_key=%s", external_db_client_private_key_file),
			}

			startInnerBoshArgs = append(startInnerBoshArgs, mutualTLSArgs...)
		}

		startInnerBosh(startInnerBoshArgs...)

		uploadRelease("https://bosh.io/d/github.com/cloudfoundry/syslog-release?v=11")
	}

	DescribeTable("RDS", testDBConnectionOverTLS,
		Entry("allows TLS connections to POSTGRES", "rds_postgres", false),
		Entry("allows TLS connections to MYSQL", "rds_mysql", false),
	)

	DescribeTable("GCP", testDBConnectionOverTLS,
		Entry("allows TLS connections to MYSQL", "gcp_mysql", false),
		Entry("allows TLS connections to POSTGRES", "gcp_postgres", false),

		Entry("allows Mutual TLS connections to MYSQL", "gcp_mysql", true),
		Entry("allows Mutual TLS connections to POSTGRES", "gcp_postgres", true),
	)
})
<|endoftext|>


<commit_before>package brats_test

import (
	"fmt"
	"strings"

	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
)

var _ = Describe("Director external database TLS connections", func() {
	AfterEach(func() {
		stopInnerBosh()
	})

	testDBConnectionOverTLS := func(databaseType string, mutualTLSEnabled bool) {
		external_db_host := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_HOST", strings.ToUpper(databaseType)))
		external_db_user := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_USER", strings.ToUpper(databaseType)))
		external_db_password := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_PASSWORD", strings.ToUpper(databaseType)))
		external_db_name := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_NAME", strings.ToUpper(databaseType)))

		connectionOptions := fmt.Sprintf("external_db/%s_connection_options.yml", databaseType)
		connectionVarFile := fmt.Sprintf("external_db/%s.yml", databaseType)

		startInnerBoshArgs := []string{
			fmt.Sprintf("-o %s", boshDeploymentAssetPath("misc/external-db.yml")),
			fmt.Sprintf("-o %s", boshDeploymentAssetPath("experimental/db-enable-tls.yml")),
			fmt.Sprintf("-o %s", assetPath(connectionOptions)),
			fmt.Sprintf("--vars-file %s", assetPath(connectionVarFile)),
			fmt.Sprintf("-v external_db_host=%s", external_db_host),
			fmt.Sprintf("-v external_db_user=%s", external_db_user),
			fmt.Sprintf("-v external_db_password=%s", external_db_password),
			fmt.Sprintf("-v external_db_name=%s", external_db_name),
		}

		if mutualTLSEnabled {
			external_db_client_certificate := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_CLIENT_CERTIFICATE", strings.ToUpper(databaseType)))
			external_db_client_private_key := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_CLIENT_PRIVATE_KEY", strings.ToUpper(databaseType)))

			tempDir, err := ioutil.TempDir("", "bosh_db_tls")
			if err != nil {
				log.Fatal(err)
			}

			defer os.RemoveAll(tempDir)

			external_db_client_certificate_file := filepath.Join(tempDir, "external_db_client_certificate")
			if err := ioutil.WriteFile(external_db_client_certificate_file, []byte(external_db_client_certificate), 0666); err != nil {
				log.Fatal(err)
			}

			external_db_client_private_key_file := filepath.Join(tempDir, "external_db_client_private_key")
			if err := ioutil.WriteFile(external_db_client_private_key_file, []byte(external_db_client_private_key), 0666); err != nil {
				log.Fatal(err)
			}

			mutualTLSArgs := []string{
				fmt.Sprintf("-o %s", boshDeploymentAssetPath("experimental/db-enable-mutual-tls.yml")),
				fmt.Sprintf("--var-file=db_client_certificate=%s", external_db_client_certificate_file),
				fmt.Sprintf("--var-file=db_client_private_key=%s", external_db_client_private_key_file),
			}

			startInnerBoshArgs = append(startInnerBoshArgs, mutualTLSArgs...)
		}

		startInnerBosh(startInnerBoshArgs...)

		uploadRelease("https://bosh.io/d/github.com/cloudfoundry/syslog-release?v=11")
	}

	DescribeTable("RDS", testDBConnectionOverTLS,
		Entry("allows TLS connections to POSTGRES", "rds_postgres", false),
		Entry("allows TLS connections to MYSQL", "rds_mysql", false),
	)

	DescribeTable("GCP", testDBConnectionOverTLS,
		Entry("allows TLS connections to MYSQL", "gcp_mysql", false),
		Entry("allows TLS connections to POSTGRES", "gcp_postgres", false),

		Entry("allows Mutual TLS connections to MYSQL", "gcp_mysql", true),
		Entry("allows Mutual TLS connections to POSTGRES", "gcp_postgres", true),
	)
})
<commit_msg>Revert "Unpend MYSQL RDS TLS test"<commit_after>package brats_test

import (
	"fmt"
	"strings"

	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
)

var _ = Describe("Director external database TLS connections", func() {
	AfterEach(func() {
		stopInnerBosh()
	})

	testDBConnectionOverTLS := func(databaseType string, mutualTLSEnabled bool) {
		external_db_host := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_HOST", strings.ToUpper(databaseType)))
		external_db_user := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_USER", strings.ToUpper(databaseType)))
		external_db_password := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_PASSWORD", strings.ToUpper(databaseType)))
		external_db_name := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_NAME", strings.ToUpper(databaseType)))

		connectionOptions := fmt.Sprintf("external_db/%s_connection_options.yml", databaseType)
		connectionVarFile := fmt.Sprintf("external_db/%s.yml", databaseType)

		startInnerBoshArgs := []string{
			fmt.Sprintf("-o %s", boshDeploymentAssetPath("misc/external-db.yml")),
			fmt.Sprintf("-o %s", boshDeploymentAssetPath("experimental/db-enable-tls.yml")),
			fmt.Sprintf("-o %s", assetPath(connectionOptions)),
			fmt.Sprintf("--vars-file %s", assetPath(connectionVarFile)),
			fmt.Sprintf("-v external_db_host=%s", external_db_host),
			fmt.Sprintf("-v external_db_user=%s", external_db_user),
			fmt.Sprintf("-v external_db_password=%s", external_db_password),
			fmt.Sprintf("-v external_db_name=%s", external_db_name),
		}

		if mutualTLSEnabled {
			external_db_client_certificate := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_CLIENT_CERTIFICATE", strings.ToUpper(databaseType)))
			external_db_client_private_key := assertEnvExists(fmt.Sprintf("%s_EXTERNAL_DB_CLIENT_PRIVATE_KEY", strings.ToUpper(databaseType)))

			tempDir, err := ioutil.TempDir("", "bosh_db_tls")
			if err != nil {
				log.Fatal(err)
			}

			defer os.RemoveAll(tempDir)

			external_db_client_certificate_file := filepath.Join(tempDir, "external_db_client_certificate")
			if err := ioutil.WriteFile(external_db_client_certificate_file, []byte(external_db_client_certificate), 0666); err != nil {
				log.Fatal(err)
			}

			external_db_client_private_key_file := filepath.Join(tempDir, "external_db_client_private_key")
			if err := ioutil.WriteFile(external_db_client_private_key_file, []byte(external_db_client_private_key), 0666); err != nil {
				log.Fatal(err)
			}

			mutualTLSArgs := []string{
				fmt.Sprintf("-o %s", boshDeploymentAssetPath("experimental/db-enable-mutual-tls.yml")),
				fmt.Sprintf("--var-file=db_client_certificate=%s", external_db_client_certificate_file),
				fmt.Sprintf("--var-file=db_client_private_key=%s", external_db_client_private_key_file),
			}

			startInnerBoshArgs = append(startInnerBoshArgs, mutualTLSArgs...)
		}

		startInnerBosh(startInnerBoshArgs...)

		uploadRelease("https://bosh.io/d/github.com/cloudfoundry/syslog-release?v=11")
	}

	DescribeTable("RDS", testDBConnectionOverTLS,
		Entry("allows TLS connections to POSTGRES", "rds_postgres", false),

		// Pending. Check https://www.pivotaltracker.com/story/show/154143917 and https://www.pivotaltracker.com/story/show/153785594/comments/184377346
		PEntry("allows TLS connections to MYSQL, refer to https://www.pivotaltracker.com/story/show/154143917", "rds_mysql", false),
	)

	DescribeTable("GCP", testDBConnectionOverTLS,
		Entry("allows TLS connections to MYSQL", "gcp_mysql", false),
		Entry("allows TLS connections to POSTGRES", "gcp_postgres", false),

		Entry("allows Mutual TLS connections to MYSQL", "gcp_mysql", true),
		Entry("allows Mutual TLS connections to POSTGRES", "gcp_postgres", true),
	)
})
<|endoftext|>