<commit_before>package mount

import (
	"io"
	"os"
	"path/filepath"
	"strings"

	"fmt"

	"gopkg.in/src-d/go-billy.v4"
	"gopkg.in/src-d/go-billy.v4/helper/polyfill"
)

var separator = string(filepath.Separator)

// Mount is a helper that allows to emulate the behavior of mount in memory.
// Very usufull to create a temporal dir, on filesystem where is a performance
// penalty in doing so.
type Mount struct {
	underlying billy.Filesystem
	source     billy.Filesystem
	mountpoint string
}

// New creates a new filesystem wrapping up 'fs' the intercepts all the calls
// made to `mountpoint` path and redirecting it to `source` filesystem.
func New(fs billy.Basic, mountpoint string, source billy.Basic) *Mount {
	return &Mount{
		underlying: polyfill.New(fs),
		source:     polyfill.New(source),
		mountpoint: cleanPath(mountpoint),
	}
}

func (h *Mount) Create(path string) (billy.File, error) {
	fs, fullpath := h.getBasicAndPath(path)
	if fullpath == "." {
		return nil, os.ErrInvalid
	}

	f, err := fs.Create(fullpath)
	return wrapFile(f, path), err
}

func (h *Mount) Open(path string) (billy.File, error) {
	fs, fullpath := h.getBasicAndPath(path)
	if fullpath == "." {
		return nil, os.ErrInvalid
	}

	f, err := fs.Open(fullpath)
	return wrapFile(f, path), err
}

func (h *Mount) OpenFile(path string, flag int, mode os.FileMode) (billy.File, error) {
	fs, fullpath := h.getBasicAndPath(path)
	if fullpath == "." {
		return nil, os.ErrInvalid
	}

	f, err := fs.OpenFile(fullpath, flag, mode)
	return wrapFile(f, path), err
}

func (h *Mount) Rename(from, to string) error {
	fromInSource := h.isMountpoint(from)
	toInSource := h.isMountpoint(to)

	var fromFS, toFS billy.Basic

	switch {
	case fromInSource && toInSource:
		from = h.mustRelToMountpoint(from)
		to = h.mustRelToMountpoint(to)
		return h.source.Rename(from, to)
	case !fromInSource && !toInSource:
		return h.underlying.Rename(from, to)
	case fromInSource && !toInSource:
		fromFS = h.source
		from = h.mustRelToMountpoint(from)
		toFS = h.underlying
		to = cleanPath(to)
	case !fromInSource && toInSource:
		fromFS = h.underlying
		from = cleanPath(from)
		toFS = h.source
		to = h.mustRelToMountpoint(to)
	}

	if err := copyPath(fromFS, toFS, from, to); err != nil {
		return err
	}

	return fromFS.Remove(from)
}

func (h *Mount) Stat(path string) (os.FileInfo, error) {
	fs, fullpath := h.getBasicAndPath(path)
	return fs.Stat(fullpath)
}

func (h *Mount) Remove(path string) error {
	fs, fullpath := h.getBasicAndPath(path)
	if fullpath == "." {
		return os.ErrInvalid
	}

	return fs.Remove(fullpath)
}

func (h *Mount) ReadDir(path string) ([]os.FileInfo, error) {
	fs, fullpath, err := h.getDirAndPath(path)
	if err != nil {
		return nil, err
	}

	return fs.ReadDir(fullpath)
}

func (h *Mount) MkdirAll(filename string, perm os.FileMode) error {
	fs, fullpath, err := h.getDirAndPath(filename)
	if err != nil {
		return err
	}

	return fs.MkdirAll(fullpath, perm)
}

func (h *Mount) Symlink(target, link string) error {
	fs, fullpath, err := h.getSymlinkAndPath(link)
	if err != nil {
		return err
	}

	resolved := filepath.Join(filepath.Dir(link), target)
	if h.isMountpoint(resolved) != h.isMountpoint(link) {
		return fmt.Errorf("invalid symlink, target is crossing filesystems")
	}

	return fs.Symlink(target, fullpath)
}

func (h *Mount) Join(elem ...string) string {
	return h.underlying.Join(elem...)
}

func (h *Mount) Readlink(link string) (string, error) {
	fs, fullpath, err := h.getSymlinkAndPath(link)
	if err != nil {
		return "", err
	}

	return fs.Readlink(fullpath)
}

func (h *Mount) Lstat(path string) (os.FileInfo, error) {
	fs, fullpath, err := h.getSymlinkAndPath(path)
	if err != nil {
		return nil, err
	}

	return fs.Lstat(fullpath)
}

func (h *Mount) Underlying() billy.Basic {
	return h.underlying
}

func (fs *Mount) getBasicAndPath(path string) (billy.Basic, string) {
	path = cleanPath(path)
	if !fs.isMountpoint(path) {
		return fs.underlying, path
	}

	return fs.source, fs.mustRelToMountpoint(path)
}

func (fs *Mount) getDirAndPath(path string) (billy.Dir, string, error) {
	path = cleanPath(path)
	if !fs.isMountpoint(path) {
		return fs.underlying.(billy.Dir), path, nil
	}

	return fs.source.(billy.Dir), fs.mustRelToMountpoint(path), nil
}

func (fs *Mount) getSymlinkAndPath(path string) (billy.Symlink, string, error) {
	path = cleanPath(path)
	if !fs.isMountpoint(path) {
		return fs.underlying.(billy.Symlink), path, nil
	}

	return fs.source.(billy.Symlink), fs.mustRelToMountpoint(path), nil
}

func (fs *Mount) mustRelToMountpoint(path string) string {
	path = cleanPath(path)
	fullpath, err := filepath.Rel(fs.mountpoint, path)
	if err != nil {
		panic(err)
	}

	return fullpath
}

func (fs *Mount) isMountpoint(path string) bool {
	path = cleanPath(path)
	return strings.HasPrefix(path, fs.mountpoint)
}

func cleanPath(path string) string {
	path = filepath.FromSlash(path)
	rel, err := filepath.Rel(separator, path)
	if err == nil {
		path = rel
	}

	return filepath.Clean(path)
}

// copyPath copies a file across filesystems.
func copyPath(src, dst billy.Basic, srcPath, dstPath string) error {
	dstFile, err := dst.Create(dstPath)
	if err != nil {
		return err
	}

	srcFile, err := src.Open(srcPath)
	if err != nil {
		return nil
	}

	_, err = io.Copy(dstFile, srcFile)
	if err != nil {
		return nil
	}

	err = dstFile.Close()
	if err != nil {
		_ = srcFile.Close()
		return err
	}

	return srcFile.Close()
}

type file struct {
	billy.File
	name string
}

func wrapFile(f billy.File, filename string) billy.File {
	if f == nil {
		return nil
	}

	return &file{
		File: f,
		name: cleanPath(filename),
	}
}

func (f *file) Name() string {
	return f.name
}
<commit_msg>Some errors are lost in copyPath<commit_after>package mount

import (
	"io"
	"os"
	"path/filepath"
	"strings"

	"fmt"

	"gopkg.in/src-d/go-billy.v4"
	"gopkg.in/src-d/go-billy.v4/helper/polyfill"
)

var separator = string(filepath.Separator)

// Mount is a helper that allows to emulate the behavior of mount in memory.
// Very usufull to create a temporal dir, on filesystem where is a performance
// penalty in doing so.
type Mount struct {
	underlying billy.Filesystem
	source     billy.Filesystem
	mountpoint string
}

// New creates a new filesystem wrapping up 'fs' the intercepts all the calls
// made to `mountpoint` path and redirecting it to `source` filesystem.
func New(fs billy.Basic, mountpoint string, source billy.Basic) *Mount {
	return &Mount{
		underlying: polyfill.New(fs),
		source:     polyfill.New(source),
		mountpoint: cleanPath(mountpoint),
	}
}

func (h *Mount) Create(path string) (billy.File, error) {
	fs, fullpath := h.getBasicAndPath(path)
	if fullpath == "." {
		return nil, os.ErrInvalid
	}

	f, err := fs.Create(fullpath)
	return wrapFile(f, path), err
}

func (h *Mount) Open(path string) (billy.File, error) {
	fs, fullpath := h.getBasicAndPath(path)
	if fullpath == "." {
		return nil, os.ErrInvalid
	}

	f, err := fs.Open(fullpath)
	return wrapFile(f, path), err
}

func (h *Mount) OpenFile(path string, flag int, mode os.FileMode) (billy.File, error) {
	fs, fullpath := h.getBasicAndPath(path)
	if fullpath == "." {
		return nil, os.ErrInvalid
	}

	f, err := fs.OpenFile(fullpath, flag, mode)
	return wrapFile(f, path), err
}

func (h *Mount) Rename(from, to string) error {
	fromInSource := h.isMountpoint(from)
	toInSource := h.isMountpoint(to)

	var fromFS, toFS billy.Basic

	switch {
	case fromInSource && toInSource:
		from = h.mustRelToMountpoint(from)
		to = h.mustRelToMountpoint(to)
		return h.source.Rename(from, to)
	case !fromInSource && !toInSource:
		return h.underlying.Rename(from, to)
	case fromInSource && !toInSource:
		fromFS = h.source
		from = h.mustRelToMountpoint(from)
		toFS = h.underlying
		to = cleanPath(to)
	case !fromInSource && toInSource:
		fromFS = h.underlying
		from = cleanPath(from)
		toFS = h.source
		to = h.mustRelToMountpoint(to)
	}

	if err := copyPath(fromFS, toFS, from, to); err != nil {
		return err
	}

	return fromFS.Remove(from)
}

func (h *Mount) Stat(path string) (os.FileInfo, error) {
	fs, fullpath := h.getBasicAndPath(path)
	return fs.Stat(fullpath)
}

func (h *Mount) Remove(path string) error {
	fs, fullpath := h.getBasicAndPath(path)
	if fullpath == "." {
		return os.ErrInvalid
	}

	return fs.Remove(fullpath)
}

func (h *Mount) ReadDir(path string) ([]os.FileInfo, error) {
	fs, fullpath, err := h.getDirAndPath(path)
	if err != nil {
		return nil, err
	}

	return fs.ReadDir(fullpath)
}

func (h *Mount) MkdirAll(filename string, perm os.FileMode) error {
	fs, fullpath, err := h.getDirAndPath(filename)
	if err != nil {
		return err
	}

	return fs.MkdirAll(fullpath, perm)
}

func (h *Mount) Symlink(target, link string) error {
	fs, fullpath, err := h.getSymlinkAndPath(link)
	if err != nil {
		return err
	}

	resolved := filepath.Join(filepath.Dir(link), target)
	if h.isMountpoint(resolved) != h.isMountpoint(link) {
		return fmt.Errorf("invalid symlink, target is crossing filesystems")
	}

	return fs.Symlink(target, fullpath)
}

func (h *Mount) Join(elem ...string) string {
	return h.underlying.Join(elem...)
}

func (h *Mount) Readlink(link string) (string, error) {
	fs, fullpath, err := h.getSymlinkAndPath(link)
	if err != nil {
		return "", err
	}

	return fs.Readlink(fullpath)
}

func (h *Mount) Lstat(path string) (os.FileInfo, error) {
	fs, fullpath, err := h.getSymlinkAndPath(path)
	if err != nil {
		return nil, err
	}

	return fs.Lstat(fullpath)
}

func (h *Mount) Underlying() billy.Basic {
	return h.underlying
}

func (fs *Mount) getBasicAndPath(path string) (billy.Basic, string) {
	path = cleanPath(path)
	if !fs.isMountpoint(path) {
		return fs.underlying, path
	}

	return fs.source, fs.mustRelToMountpoint(path)
}

func (fs *Mount) getDirAndPath(path string) (billy.Dir, string, error) {
	path = cleanPath(path)
	if !fs.isMountpoint(path) {
		return fs.underlying.(billy.Dir), path, nil
	}

	return fs.source.(billy.Dir), fs.mustRelToMountpoint(path), nil
}

func (fs *Mount) getSymlinkAndPath(path string) (billy.Symlink, string, error) {
	path = cleanPath(path)
	if !fs.isMountpoint(path) {
		return fs.underlying.(billy.Symlink), path, nil
	}

	return fs.source.(billy.Symlink), fs.mustRelToMountpoint(path), nil
}

func (fs *Mount) mustRelToMountpoint(path string) string {
	path = cleanPath(path)
	fullpath, err := filepath.Rel(fs.mountpoint, path)
	if err != nil {
		panic(err)
	}

	return fullpath
}

func (fs *Mount) isMountpoint(path string) bool {
	path = cleanPath(path)
	return strings.HasPrefix(path, fs.mountpoint)
}

func cleanPath(path string) string {
	path = filepath.FromSlash(path)
	rel, err := filepath.Rel(separator, path)
	if err == nil {
		path = rel
	}

	return filepath.Clean(path)
}

// copyPath copies a file across filesystems.
func copyPath(src, dst billy.Basic, srcPath, dstPath string) error {
	dstFile, err := dst.Create(dstPath)
	if err != nil {
		return err
	}

	srcFile, err := src.Open(srcPath)
	if err != nil {
		return err
	}

	_, err = io.Copy(dstFile, srcFile)
	if err != nil {
		return err
	}

	err = dstFile.Close()
	if err != nil {
		_ = srcFile.Close()
		return err
	}

	return srcFile.Close()
}

type file struct {
	billy.File
	name string
}

func wrapFile(f billy.File, filename string) billy.File {
	if f == nil {
		return nil
	}

	return &file{
		File: f,
		name: cleanPath(filename),
	}
}

func (f *file) Name() string {
	return f.name
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/chris-wood/spud/stack/api/portal"
	"github.com/chris-wood/spud/messages/name"
	"github.com/chris-wood/spud/stack/spud"
	"github.com/chris-wood/spud/messages"
	"github.com/chris-wood/spud/messages/interest"
	"fmt"
	"github.com/chris-wood/spud/messages/content"
	"github.com/chris-wood/spud/messages/payload"
)

var done chan int

func displayResponse(response *messages.MessageWrapper) {
	fmt.Println("Response: " + string(response.Payload().Value()))
	done <- 1
}

func generateResponse(request *messages.MessageWrapper) *messages.MessageWrapper {
	data := []byte("Hello world")
	dataPayload := payload.Create(data)
	response := messages.Package(content.CreateWithNameAndPayload(request.Name(), dataPayload))
	return response
}

 func testSession() {
	 myStack, err := spud.CreateRaw(`{"connector": "athena", "link": "loopback", "fwd-address": "127.0.0.1:9696", "keys": ["key.p12"]}`)
	 if err != nil {
		 panic("Could not create the stack")
	 }
	 done = make(chan int)

	 p := portal.NewSecurePortal(myStack)

	 prefix, _ := name.Parse("ccnx:/producer")

	 go p.Serve(prefix, generateResponse)
	 p.Connect(prefix)

	 requestInterest := interest.CreateWithName(prefix)
	 requestWrapper := messages.Package(requestInterest)
	 p.GetAsync(requestWrapper, displayResponse)

	 // sleep until the consumer gets a response
	 <- done
 }

func main() {
	testSession()
}
<commit_msg>Debug code. Need to fix the race condition when running locally.<commit_after>package main

import (
	"github.com/chris-wood/spud/stack/api/portal"
	"github.com/chris-wood/spud/messages/name"
	"github.com/chris-wood/spud/stack/spud"
	"github.com/chris-wood/spud/messages"
	"github.com/chris-wood/spud/messages/interest"
	"fmt"
	"github.com/chris-wood/spud/messages/content"
	"github.com/chris-wood/spud/messages/payload"
)

var done chan int

func displayResponse(response *messages.MessageWrapper) {
	fmt.Println("Response: " + string(response.Payload().Value()))
	done <- 1
}

func generateResponse(request *messages.MessageWrapper) *messages.MessageWrapper {
	data := []byte("Hello world")
	dataPayload := payload.Create(data)
	response := messages.Package(content.CreateWithNameAndPayload(request.Name(), dataPayload))
	return response
}

 func testSession() {
	 myStack, err := spud.CreateRaw(`{"connector": "athena", "link": "loopback", "fwd-address": "127.0.0.1:9696", "keys": ["key.p12"]}`)
	 if err != nil {
		 panic("Could not create the stack")
	 }
	 done = make(chan int)

	 p := portal.NewSecurePortal(myStack)

	 prefix, _ := name.Parse("ccnx:/producer")

	 go p.Serve(prefix, generateResponse)
	 p.Connect(prefix)

	 fmt.Println("SENDING REQUEST FOR", prefix)
	 requestInterest := interest.CreateWithName(prefix)
	 requestWrapper := messages.Package(requestInterest)
	 p.GetAsync(requestWrapper, displayResponse)

	 // sleep until the consumer gets a response
	 <- done
 }

func main() {
	testSession()
}
<|endoftext|>


<commit_before>package routingtable

import (
	"github.com/robertkluin/message-flow/router"
	"testing"
)

func TestMemoryGetClientMessageServer(t *testing.T) {
	table := NewMemoryRoutingTable()

	// Client with no mapped services.
	table.SetClientMessageServer("client.2", "server.1")

	// Client with a mapped service, but no message server.
	table.SetClientServiceServer("client.3", "service.1", "server.1")

	type TestCase struct {
		ClientID router.ClientID
		Result   router.ServerID
		Err      *router.RoutingTableError
	}

	tests := []TestCase{
		// client.1 does not exist, there are no mappings for it.
		TestCase{"client.1", "", router.NewRoutingTableError(router.UnknownClient, "")},

		// client.2 messages are mapped to server.1.
		TestCase{"client.2", "server.1", nil},

		// client.3 has service mappings, but no message server defined.
		TestCase{"client.3", "", router.NewRoutingTableError(router.MappingNotFoundError, "")},
	}

	// Load routing data

	for _, test := range tests {
		result, err := table.GetClientMessageServer(test.ClientID)
		if result != test.Result {
			t.Errorf("FAIL: Results didn't match.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err == nil {
			t.Errorf("FAIL: Got an unexpected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err == nil && test.Err != nil {
			t.Errorf("FAIL: Didn't get an expected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err != nil && err.(*router.RoutingTableError).Code != test.Err.Code {
			t.Errorf("FAIL: Got the wrong error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		}
	}
}

func TestMemoryGetClientServiceServer(t *testing.T) {
	table := NewMemoryRoutingTable()

	// Client with no mapped services.
	table.SetClientMessageServer("client.2", "server.1")
	//table.clientTable["client.2"] = newClientRecord("server.1")

	// Client with service.2 mapped.
	table.SetClientServiceServer("client.3", "service.2", "server.1")
	table.SetClientMessageServer("client.3", "server.2")

	type TestCase struct {
		ClientID  router.ClientID
		ServiceID router.ServiceID
		Result    router.ServerID
		Err       *router.RoutingTableError
	}

	tests := []TestCase{
		// client.1 does not exist, there are no mappings for it.
		TestCase{"client.1", "service.1", "", router.NewRoutingTableError(router.UnknownClient, "")},

		// client.2 exists, but there are no service mappings for it.
		TestCase{"client.2", "service.1", "", router.NewRoutingTableError(router.MappingNotFoundError, "")},

		// client.3 exists, but there is no service mappings for service.1.
		TestCase{"client.3", "service.1", "", router.NewRoutingTableError(router.MappingNotFoundError, "")},

		// client.3 exists and there is a mapping to service.2 to server.1.
		TestCase{"client.3", "service.2", "server.1", nil},
	}

	// Load routing data

	for _, test := range tests {
		result, err := table.GetClientServiceServer(test.ClientID, test.ServiceID)
		if result != test.Result {
			t.Errorf("FAIL: Results didn't match.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err == nil {
			t.Errorf("FAIL: Got an unexpected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err == nil && test.Err != nil {
			t.Errorf("FAIL: Didn't get an expected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err != nil && err.(*router.RoutingTableError).Code != test.Err.Code {
			t.Errorf("FAIL: Got the wrong error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		}
	}
}

func TestMemoryGetServiceServer(t *testing.T) {
	table := NewMemoryRoutingTable()

	// Service with a catch-all server.
	table.SetServiceServer("service.2", "server.1")

	// Service with an empty catch-all server.
	table.SetServiceServer("service.3", "")

	type TestCase struct {
		ServiceID router.ServiceID
		Result    router.ServerID
		Err       *router.RoutingTableError
	}

	tests := []TestCase{
		// service.1 does not exist, there is no mapping.
		TestCase{"service.1", "", router.NewRoutingTableError(router.UnknownService, "")},

		// service.2 is mapped to server.1.
		TestCase{"service.2", "server.1", nil},

		// service.3 has a mappings, but no catch-all server defined.
		TestCase{"service.3", "", router.NewRoutingTableError(router.ServerNotFoundError, "")},
	}

	for _, test := range tests {
		result, err := table.GetServiceServer(test.ServiceID)
		if result != test.Result {
			t.Errorf("FAIL: Results didn't match.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err == nil {
			t.Errorf("FAIL: Got an unexpected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err == nil && test.Err != nil {
			t.Errorf("FAIL: Didn't get an expected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err != nil && err.(*router.RoutingTableError).Code != test.Err.Code {
			t.Errorf("FAIL: Got the wrong error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		}
	}
}

func TestMemoryGetServiceRegistrar(t *testing.T) {
	table := NewMemoryRoutingTable()

	// Service with a catch-all server, but no registrar.
	table.SetServiceServer("service.2", "server.1")

	// Service with a registrar, and no server.
	table.SetServiceRegistrar("service.3", "registrar.1")

	// Service with a registrar and server.
	table.SetServiceServer("service.4", "server.2")
	table.SetServiceRegistrar("service.4", "registrar.2")

	// Service with an empty registrar.
	table.SetServiceRegistrar("service.5", "")

	type TestCase struct {
		ServiceID router.ServiceID
		Result    router.ServerID
		Err       *router.RoutingTableError
	}

	tests := []TestCase{
		// service.1 does not exist, there is no mapping.
		TestCase{"service.1", "", router.NewRoutingTableError(router.UnknownService, "")},

		// service.2 has a server, but no registrar.
		TestCase{"service.2", "", router.NewRoutingTableError(router.ServerNotFoundError, "")},

		// service.3 has a registrar.
		TestCase{"service.3", "registrar.1", nil},

		// service.4 has a server and a registrar.
		TestCase{"service.4", "registrar.2", nil},

		// service.5 has an empty registrar.
		TestCase{"service.5", "", router.NewRoutingTableError(router.ServerNotFoundError, "")},
	}

	for _, test := range tests {
		result, err := table.GetServiceRegistrar(test.ServiceID)
		if result != test.Result {
			t.Errorf("FAIL: Results didn't match.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err == nil {
			t.Errorf("FAIL: Got an unexpected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err == nil && test.Err != nil {
			t.Errorf("FAIL: Didn't get an expected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err != nil && err.(*router.RoutingTableError).Code != test.Err.Code {
			t.Errorf("FAIL: Got the wrong error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		}
	}
}

func TestMemoryGetServiceRandomServer(t *testing.T) {
	table := NewMemoryRoutingTable()

	// Service with a catch-all server, but no server pool.
	table.SetServiceServer("service.2", "server.1")

	// Service with a registrar, and no server pool.
	table.SetServiceRegistrar("service.3", "registrar.1")

	// Service with a registrar and server, but no server pool.
	table.SetServiceServer("service.4", "server.2")
	table.SetServiceRegistrar("service.4", "registrar.2")

	// Service with a registrar and server and one server in pool.
	table.SetServiceServer("service.5", "server.2")
	table.SetServiceRegistrar("service.5", "registrar.2")
	table.AddServerToServicePool("service.5", "pool.1")

	// Service with only one server in pool.
	table.AddServerToServicePool("service.6", "pool.1")

	// Service with server removed from pool
	table.AddServerToServicePool("service.7", "pool.1")
	table.AddServerToServicePool("service.7", "pool.2")
	table.AddServerToServicePool("service.7", "pool.3")

	table.RemoveServerFromServicePool("service.7", "pool.1")
	table.RemoveServerFromServicePool("service.7", "pool.2")
	table.RemoveServerFromServicePool("service.7", "pool.3")

	// Service with all but one servers removed from pool
	table.AddServerToServicePool("service.8", "pool.1")
	table.AddServerToServicePool("service.8", "pool.2")
	table.RemoveServerFromServicePool("service.8", "pool.1")

	// Tests of serverList add/remove
	table.RemoveServerFromServicePool("service.9", "pool.1")
	table.AddServerToServicePool("service.9", "pool.1")
	table.AddServerToServicePool("service.9", "pool.1")
	table.RemoveServerFromServicePool("service.9", "pool.1")

	type TestCase struct {
		ServiceID router.ServiceID
		Result    router.ServerID
		Err       *router.RoutingTableError
	}

	tests := []TestCase{
		// service.1 does not exist, there is no mapping.
		TestCase{"service.1", "", router.NewRoutingTableError(router.UnknownService, "")},

		// service.2 has a server, but no server pool.
		TestCase{"service.2", "", router.NewRoutingTableError(router.ServerPoolEmptyError, "")},

		// service.3 has a registrar, but no server pool.
		TestCase{"service.3", "", router.NewRoutingTableError(router.ServerPoolEmptyError, "")},

		// service.4 has a server and registrar, but no server pool.
		TestCase{"service.4", "", router.NewRoutingTableError(router.ServerPoolEmptyError, "")},

		// service.5 has a server, registrar, and single server in the pool.
		TestCase{"service.5", "pool.1", nil},

		// service.6 has only a single server in the pool.
		TestCase{"service.6", "pool.1", nil},

		// service.7 has an emptied server pool.
		TestCase{"service.7", "", router.NewRoutingTableError(router.ServerPoolEmptyError, "")},

		// service.8 has servers added and removed, but one left in the pool.
		TestCase{"service.8", "pool.2", nil},

		// service.9 should have an emptied server pool.
		TestCase{"service.9", "", router.NewRoutingTableError(router.ServerPoolEmptyError, "")},
	}

	for _, test := range tests {
		result, err := table.GetServiceRandomServer(test.ServiceID)
		if result != test.Result {
			t.Errorf("FAIL: Results didn't match.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err == nil {
			t.Errorf("FAIL: Got an unexpected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err == nil && test.Err != nil {
			t.Errorf("FAIL: Didn't get an expected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err != nil && err.(*router.RoutingTableError).Code != test.Err.Code {
			t.Errorf("FAIL: Got the wrong error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		}
	}
}
<commit_msg>Refacotr memory tests to reduce duplication<commit_after>package routingtable

import (
	"github.com/robertkluin/message-flow/router"
	"testing"
)

type TestCase struct {
	Args   []interface{}
	Result router.ServerID
	Err    *router.RoutingTableError
}

func evalTests(t *testing.T, tests []TestCase, runner func(test TestCase) (router.ServerID, error)) {
	for _, test := range tests {
		//result, err := table.GetClientMessageServer(test.ClientID)
		result, err := runner(test)
		if result != test.Result {
			t.Errorf("FAIL: Results didn't match.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err == nil {
			t.Errorf("FAIL: Got an unexpected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err == nil && test.Err != nil {
			t.Errorf("FAIL: Didn't get an expected error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		} else if err != nil && test.Err != nil && err.(*router.RoutingTableError).Code != test.Err.Code {
			t.Errorf("FAIL: Got the wrong error.\n\tTest Case: %+v\n\tActual: {result: \"%v\", err: %+v}",
				test, result, err)
		}
	}
}

func TestMemoryGetClientMessageServer(t *testing.T) {
	table := NewMemoryRoutingTable()

	// Client with no mapped services.
	table.SetClientMessageServer("client.2", "server.1")

	// Client with a mapped service, but no message server.
	table.SetClientServiceServer("client.3", "service.1", "server.1")

	mkArgs := func(clientID router.ClientID) []interface{} {
		return []interface{}{clientID}
	}

	tests := []TestCase{
		// client.1 does not exist, there are no mappings for it.
		TestCase{mkArgs("client.1"), "", router.NewRoutingTableError(router.UnknownClient, "")},

		// client.2 messages are mapped to server.1.
		TestCase{mkArgs("client.2"), "server.1", nil},

		// client.3 has service mappings, but no message server defined.
		TestCase{mkArgs("client.3"), "", router.NewRoutingTableError(router.MappingNotFoundError, "")},
	}

	evalTests(t, tests, func(test TestCase) (router.ServerID, error) {
		arg, _ := test.Args[0].(router.ClientID)
		return table.GetClientMessageServer(arg)
	})
}

func TestMemoryGetClientServiceServer(t *testing.T) {
	table := NewMemoryRoutingTable()

	// Client with no mapped services.
	table.SetClientMessageServer("client.2", "server.1")
	//table.clientTable["client.2"] = newClientRecord("server.1")

	// Client with service.2 mapped.
	table.SetClientServiceServer("client.3", "service.2", "server.1")
	table.SetClientMessageServer("client.3", "server.2")

	mkArgs := func(clientID router.ClientID, serviceID router.ServiceID) []interface{} {
		return []interface{}{clientID, serviceID}
	}

	tests := []TestCase{
		// client.1 does not exist, there are no mappings for it.
		TestCase{mkArgs("client.1", "service.1"), "", router.NewRoutingTableError(router.UnknownClient, "")},

		// client.2 exists, but there are no service mappings for it.
		TestCase{mkArgs("client.2", "service.1"), "", router.NewRoutingTableError(router.MappingNotFoundError, "")},

		// client.3 exists, but there is no service mappings for service.1.
		TestCase{mkArgs("client.3", "service.1"), "", router.NewRoutingTableError(router.MappingNotFoundError, "")},

		// client.3 exists and there is a mapping to service.2 to server.1.
		TestCase{mkArgs("client.3", "service.2"), "server.1", nil},
	}

	evalTests(t, tests, func(test TestCase) (router.ServerID, error) {
		clientID, _ := test.Args[0].(router.ClientID)
		serviceID, _ := test.Args[1].(router.ServiceID)
		return table.GetClientServiceServer(clientID, serviceID)
	})
}

func TestMemoryGetServiceServer(t *testing.T) {
	table := NewMemoryRoutingTable()

	// Service with a catch-all server.
	table.SetServiceServer("service.2", "server.1")

	// Service with an empty catch-all server.
	table.SetServiceServer("service.3", "")

	mkArgs := func(serviceID router.ServiceID) []interface{} {
		return []interface{}{serviceID}
	}

	tests := []TestCase{
		// service.1 does not exist, there is no mapping.
		TestCase{mkArgs("service.1"), "", router.NewRoutingTableError(router.UnknownService, "")},

		// service.2 is mapped to server.1.
		TestCase{mkArgs("service.2"), "server.1", nil},

		// service.3 has a mappings, but no catch-all server defined.
		TestCase{mkArgs("service.3"), "", router.NewRoutingTableError(router.ServerNotFoundError, "")},
	}

	evalTests(t, tests, func(test TestCase) (router.ServerID, error) {
		serviceID, _ := test.Args[0].(router.ServiceID)
		return table.GetServiceServer(serviceID)
	})
}

func TestMemoryGetServiceRegistrar(t *testing.T) {
	table := NewMemoryRoutingTable()

	// Service with a catch-all server, but no registrar.
	table.SetServiceServer("service.2", "server.1")

	// Service with a registrar, and no server.
	table.SetServiceRegistrar("service.3", "registrar.1")

	// Service with a registrar and server.
	table.SetServiceServer("service.4", "server.2")
	table.SetServiceRegistrar("service.4", "registrar.2")

	// Service with an empty registrar.
	table.SetServiceRegistrar("service.5", "")

	mkArgs := func(serviceID router.ServiceID) []interface{} {
		return []interface{}{serviceID}
	}

	tests := []TestCase{
		// service.1 does not exist, there is no mapping.
		TestCase{mkArgs("service.1"), "", router.NewRoutingTableError(router.UnknownService, "")},

		// service.2 has a server, but no registrar.
		TestCase{mkArgs("service.2"), "", router.NewRoutingTableError(router.ServerNotFoundError, "")},

		// service.3 has a registrar.
		TestCase{mkArgs("service.3"), "registrar.1", nil},

		// service.4 has a server and a registrar.
		TestCase{mkArgs("service.4"), "registrar.2", nil},

		// service.5 has an empty registrar.
		TestCase{mkArgs("service.5"), "", router.NewRoutingTableError(router.ServerNotFoundError, "")},
	}

	evalTests(t, tests, func(test TestCase) (router.ServerID, error) {
		serviceID, _ := test.Args[0].(router.ServiceID)
		return table.GetServiceRegistrar(serviceID)
	})
}

func TestMemoryGetServiceRandomServer(t *testing.T) {
	table := NewMemoryRoutingTable()

	// Service with a catch-all server, but no server pool.
	table.SetServiceServer("service.2", "server.1")

	// Service with a registrar, and no server pool.
	table.SetServiceRegistrar("service.3", "registrar.1")

	// Service with a registrar and server, but no server pool.
	table.SetServiceServer("service.4", "server.2")
	table.SetServiceRegistrar("service.4", "registrar.2")

	// Service with a registrar and server and one server in pool.
	table.SetServiceServer("service.5", "server.2")
	table.SetServiceRegistrar("service.5", "registrar.2")
	table.AddServerToServicePool("service.5", "pool.1")

	// Service with only one server in pool.
	table.AddServerToServicePool("service.6", "pool.1")

	// Service with server removed from pool
	table.AddServerToServicePool("service.7", "pool.1")
	table.AddServerToServicePool("service.7", "pool.2")
	table.AddServerToServicePool("service.7", "pool.3")

	table.RemoveServerFromServicePool("service.7", "pool.1")
	table.RemoveServerFromServicePool("service.7", "pool.2")
	table.RemoveServerFromServicePool("service.7", "pool.3")

	// Service with all but one servers removed from pool
	table.AddServerToServicePool("service.8", "pool.1")
	table.AddServerToServicePool("service.8", "pool.2")
	table.RemoveServerFromServicePool("service.8", "pool.1")

	// Tests of serverList add/remove
	table.RemoveServerFromServicePool("service.9", "pool.1")
	table.AddServerToServicePool("service.9", "pool.1")
	table.AddServerToServicePool("service.9", "pool.1")
	table.RemoveServerFromServicePool("service.9", "pool.1")

	mkArgs := func(serviceID router.ServiceID) []interface{} {
		return []interface{}{serviceID}
	}

	tests := []TestCase{
		// service.1 does not exist, there is no mapping.
		TestCase{mkArgs("service.1"), "", router.NewRoutingTableError(router.UnknownService, "")},

		// service.2 has a server, but no server pool.
		TestCase{mkArgs("service.2"), "", router.NewRoutingTableError(router.ServerPoolEmptyError, "")},

		// service.3 has a registrar, but no server pool.
		TestCase{mkArgs("service.3"), "", router.NewRoutingTableError(router.ServerPoolEmptyError, "")},

		// service.4 has a server and registrar, but no server pool.
		TestCase{mkArgs("service.4"), "", router.NewRoutingTableError(router.ServerPoolEmptyError, "")},

		// service.5 has a server, registrar, and single server in the pool.
		TestCase{mkArgs("service.5"), "pool.1", nil},

		// service.6 has only a single server in the pool.
		TestCase{mkArgs("service.6"), "pool.1", nil},

		// service.7 has an emptied server pool.
		TestCase{mkArgs("service.7"), "", router.NewRoutingTableError(router.ServerPoolEmptyError, "")},

		// service.8 has servers added and removed, but one left in the pool.
		TestCase{mkArgs("service.8"), "pool.2", nil},

		// service.9 should have an emptied server pool.
		TestCase{mkArgs("service.9"), "", router.NewRoutingTableError(router.ServerPoolEmptyError, "")},
	}

	evalTests(t, tests, func(test TestCase) (router.ServerID, error) {
		serviceID, _ := test.Args[0].(router.ServiceID)
		return table.GetServiceRandomServer(serviceID)
	})
}
<|endoftext|>


<commit_before>package spec

import (
	"github.com/appc/spec/schema/types"
	"github.com/n0rad/go-erlog/data"
	"github.com/n0rad/go-erlog/errs"
)

type CntBuild struct {
	Image types.ACIdentifier `json:"image"`
}

func (b *CntBuild) NoBuildImage() bool {
	return b.Image == ""
}

type AciManifest struct {
	NameAndVersion ACFullname    `json:"name"`
	From           interface{}   `json:"from"`
	Build          CntBuild      `json:"build"`
	Aci            AciDefinition `json:"aci"`
}

func (m *AciManifest) GetFroms() ([]ACFullname, error) {
	var froms []ACFullname
	switch v := m.From.(type) {
	case string:
		froms = []ACFullname{*NewACFullName(m.From.(string))}
	case []interface{}:
		for _, from := range m.From.([]interface{}) {
			froms = append(froms, *NewACFullName(from.(string)))
		}
	default:
		return nil, errs.WithF(data.WithField("type", v), "Invalid from type format")
	}
	return froms, nil
}

type AciDefinition struct {
	App           CntApp            `json:"app,omitempty"`
	Annotations   types.Annotations `json:"annotations,omitempty"`
	Dependencies  []ACFullname      `json:"dependencies,omitempty"`
	PathWhitelist []string          `json:"pathWhitelist,omitempty"`
}

type CntApp struct {
	Exec             types.Exec         `json:"exec"`
	User             string             `json:"user"`
	Group            string             `json:"group"`
	WorkingDirectory string             `json:"workingDirectory,omitempty"`
	Environment      types.Environment  `json:"environment,omitempty"`
	MountPoints      []types.MountPoint `json:"mountPoints,omitempty"`
	Ports            []types.Port       `json:"ports,omitempty"`
	Isolators        types.Isolators    `json:"isolators,omitempty"`
}
<commit_msg>fix issue on non existing from tag<commit_after>package spec

import (
	"github.com/appc/spec/schema/types"
	"github.com/n0rad/go-erlog/data"
	"github.com/n0rad/go-erlog/errs"
)

type CntBuild struct {
	Image types.ACIdentifier `json:"image"`
}

func (b *CntBuild) NoBuildImage() bool {
	return b.Image == ""
}

type AciManifest struct {
	NameAndVersion ACFullname    `json:"name"`
	From           interface{}   `json:"from"`
	Build          CntBuild      `json:"build"`
	Aci            AciDefinition `json:"aci"`
}

func (m *AciManifest) GetFroms() ([]ACFullname, error) {
	var froms []ACFullname
	switch v := m.From.(type) {
	case string:
		froms = []ACFullname{*NewACFullName(m.From.(string))}
	case []interface{}:
		for _, from := range m.From.([]interface{}) {
			froms = append(froms, *NewACFullName(from.(string)))
		}
	case nil:
		return froms, nil
	default:
		return nil, errs.WithF(data.WithField("type", v), "Invalid from type format")
	}
	return froms, nil
}

type AciDefinition struct {
	App           CntApp            `json:"app,omitempty"`
	Annotations   types.Annotations `json:"annotations,omitempty"`
	Dependencies  []ACFullname      `json:"dependencies,omitempty"`
	PathWhitelist []string          `json:"pathWhitelist,omitempty"`
}

type CntApp struct {
	Exec             types.Exec         `json:"exec"`
	User             string             `json:"user"`
	Group            string             `json:"group"`
	WorkingDirectory string             `json:"workingDirectory,omitempty"`
	Environment      types.Environment  `json:"environment,omitempty"`
	MountPoints      []types.MountPoint `json:"mountPoints,omitempty"`
	Ports            []types.Port       `json:"ports,omitempty"`
	Isolators        types.Isolators    `json:"isolators,omitempty"`
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License 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 csp provides a safehttp.Interceptor which applies Content-Security Policies
// to responses.
//
// Two default policies are provided:
//  - A strict nonce based CSP
//  - A framing policy which sets frame-ancestors to 'self'
package csp

import (
	"context"
	"crypto/rand"
	"encoding/base64"
	"errors"
	"fmt"
	"strings"

	"github.com/google/go-safeweb/safehttp/plugins/htmlinject"

	"github.com/google/go-safeweb/safehttp"
)

var randReader = rand.Reader

// nonceSize is the size of the nonces in bytes. According to the CSP3 spec it should
// be larger than 16 bytes. 20 bytes was picked to be future proof.
// https://www.w3.org/TR/CSP3/#security-nonces
const nonceSize = 20

func generateNonce() string {
	b := make([]byte, nonceSize)
	_, err := randReader.Read(b)
	if err != nil {
		panic(fmt.Errorf("failed to generate entropy using crypto/rand/RandReader: %v", err))
	}
	return base64.StdEncoding.EncodeToString(b)
}

// Policy defines a CSP policy.
type Policy interface {
	// Serialize serializes this policy for use in a Content-Security-Policy header
	// or in a Content-Security-Policy-Report-Only header. A nonce will be provided
	// to serialize which can be used in 'nonce-{random-nonce}' values in directives.
	Serialize(nonce string) string
}

type ctxKey struct{}

// Nonce retrieves the nonce from the given context. If there is no nonce stored
// in the context, an error will be returned.
func Nonce(ctx context.Context) (string, error) {
	v := ctx.Value(ctxKey{})
	if v == nil {
		return "", errors.New("no nonce in context")
	}
	return v.(string), nil
}

// StrictPolicy can be used to build a strict, nonce-based CSP.
//
// See https://csp.withgoogle.com/docs/strict-csp.html for more info.
type StrictPolicy struct {
	// NoStrictDynamic controls whether script-src should contain the 'strict-dynamic'
	// value.
	//
	// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#strict-dynamic
	// for more info.
	NoStrictDynamic bool
	// UnsafeEval controls whether script-src should contain the 'unsafe-eval' value.
	// If enabled, the eval() JavaScript function is allowed.
	UnsafeEval bool
	// BaseURI controls the base-uri directive. If BaseURI is an empty string the
	// directive will be set to 'none'. The base-uri directive restricts the URLs
	// which can be used in a document's <base> element.
	//
	// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/base-uri
	// for more info.
	BaseURI string
	// ReportURI controls the report-uri directive. If ReportUri is empty, no report-uri
	// directive will be set.
	ReportURI string
	// Hashes adds a set of hashes to script-src. An example of a hash would be:
	//  sha256-CihokcEcBW4atb/CW/XWsvWwbTjqwQlE9nj9ii5ww5M=
	// which is the SHA256 hash for the script "console.log(1)".
	//
	// For more info, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src
	Hashes []string
}

// Serialize serializes this policy for use in a Content-Security-Policy header
// or in a Content-Security-Policy-Report-Only header. A nonce will be provided
// to Serialize which can be used in 'nonce-{random-nonce}' values in directives.
func (s StrictPolicy) Serialize(nonce string) string {
	var b strings.Builder

	// object-src 'none'; script-src 'unsafe-inline' 'nonce-{random}'
	b.WriteString("object-src 'none'; script-src 'unsafe-inline' 'nonce-")
	b.WriteString(nonce)
	b.WriteByte('\'')

	if !s.NoStrictDynamic {
		b.WriteString(" 'strict-dynamic' https: http:")
	}

	if s.UnsafeEval {
		b.WriteString(" 'unsafe-eval'")
	}

	for _, h := range s.Hashes {
		b.WriteString(" '")
		b.WriteString(h)
		b.WriteByte('\'')
	}

	b.WriteString("; base-uri ")
	if s.BaseURI == "" {
		b.WriteString("'none'")
	} else {
		b.WriteString(s.BaseURI)
	}

	if s.ReportURI != "" {
		b.WriteString("; report-uri ")
		b.WriteString(s.ReportURI)
	}

	return b.String()

}

// FramingPolicy can be used to create a new CSP policy with frame-ancestors
// set to 'self'.
//
// TODO: allow relaxation on specific endpoints according to #77.
type FramingPolicy struct {
	// ReportURI controls the report-uri directive. If ReportUri is empty, no report-uri
	// directive will be set.
	ReportURI string
}

// Serialize serializes this policy for use in a Content-Security-Policy header
// or in a Content-Security-Policy-Report-Only header. A nonce will be provided
// to Serialize which can be used in 'nonce-{random-nonce}' values in directives.
func (f FramingPolicy) Serialize(nonce string) string {
	var b strings.Builder
	b.WriteString("frame-ancestors 'self'")

	if f.ReportURI != "" {
		b.WriteString("; report-uri ")
		b.WriteString(f.ReportURI)
	}

	return b.String()
}

// Interceptor intercepts requests and applies CSP policies.
type Interceptor struct {
	// TODO: move it to a safehttp.InterceptorConfig implementation to enable
	// per-handler configuration.

	// Enforce specifies which policies will be set as the Content-Security-Policy
	// header.
	Enforce []Policy
	// ReportOnly specifies which policies will be set as the Content-Security-Policy-Report-Only
	// header.
	ReportOnly []Policy
}

var _ safehttp.Interceptor = Interceptor{}

// Default creates a new CSP interceptor with a strict nonce-based policy and a
// framing policy, both in enforcement mode.
func Default(reportURI string) Interceptor {
	return Interceptor{
		Enforce: []Policy{
			StrictPolicy{ReportURI: reportURI},
			FramingPolicy{ReportURI: reportURI},
		},
	}
}

// Before claims and sets the Content-Security-Policy header and the
// Content-Security-Policy-Report-Only header.
func (it Interceptor) Before(w safehttp.ResponseWriter, r *safehttp.IncomingRequest, _ safehttp.InterceptorConfig) safehttp.Result {
	nonce := generateNonce()
	r.SetContext(context.WithValue(r.Context(), ctxKey{}, nonce))

	var CSPs []string
	for _, p := range it.Enforce {
		CSPs = append(CSPs, p.Serialize(nonce))
	}
	var reportCSPs []string
	for _, p := range it.ReportOnly {
		reportCSPs = append(reportCSPs, p.Serialize(nonce))
	}

	h := w.Header()
	setCSP := h.Claim("Content-Security-Policy")
	setCSPReportOnly := h.Claim("Content-Security-Policy-Report-Only")

	setCSP(CSPs)
	setCSPReportOnly(reportCSPs)

	return safehttp.NotWritten()
}

// Commit adds the nonce to the safehttp.TemplateResponse which is going to be
// injected as the value of the nonce attribute in <script> and <link> tags. The
// nonce is going to be unique for each safehttp.IncomingRequest.
func (it Interceptor) Commit(w safehttp.ResponseHeadersWriter, r *safehttp.IncomingRequest, resp safehttp.Response, cfg safehttp.InterceptorConfig) {
	tmplResp, ok := resp.(*safehttp.TemplateResponse)
	if !ok {
		return
	}

	nonce, err := Nonce(r.Context())
	if err != nil {
		// The nonce should have been added in the Before stage and, if that is
		// not the case, a server misconfiguration occured.
		panic("no CSP nonce")
	}

	// TODO(maramihali@): Change the key when function names are exported by
	// htmlinject
	// TODO: What should happen if the CSPNonce is not present in the
	// tr.FuncMap?
	tmplResp.FuncMap[htmlinject.CSPNoncesDefaultFuncName] = func() string { return nonce }
}

// OnError is a no-op, required to satisfy the safehttp.Interceptor interface.
func (it Interceptor) OnError(w safehttp.ResponseHeadersWriter, r *safehttp.IncomingRequest, resp safehttp.Response, _ safehttp.InterceptorConfig) {
	return
}
<commit_msg>TODO comments cleanups.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License 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 csp provides a safehttp.Interceptor which applies Content-Security Policies
// to responses.
//
// Two default policies are provided:
//  - A strict nonce based CSP
//  - A framing policy which sets frame-ancestors to 'self'
package csp

import (
	"context"
	"crypto/rand"
	"encoding/base64"
	"errors"
	"fmt"
	"strings"

	"github.com/google/go-safeweb/safehttp/plugins/htmlinject"

	"github.com/google/go-safeweb/safehttp"
)

var randReader = rand.Reader

// nonceSize is the size of the nonces in bytes. According to the CSP3 spec it should
// be larger than 16 bytes. 20 bytes was picked to be future proof.
// https://www.w3.org/TR/CSP3/#security-nonces
const nonceSize = 20

func generateNonce() string {
	b := make([]byte, nonceSize)
	_, err := randReader.Read(b)
	if err != nil {
		panic(fmt.Errorf("failed to generate entropy using crypto/rand/RandReader: %v", err))
	}
	return base64.StdEncoding.EncodeToString(b)
}

// Policy defines a CSP policy.
type Policy interface {
	// Serialize serializes this policy for use in a Content-Security-Policy header
	// or in a Content-Security-Policy-Report-Only header. A nonce will be provided
	// to serialize which can be used in 'nonce-{random-nonce}' values in directives.
	Serialize(nonce string) string
}

type ctxKey struct{}

// Nonce retrieves the nonce from the given context. If there is no nonce stored
// in the context, an error will be returned.
func Nonce(ctx context.Context) (string, error) {
	v := ctx.Value(ctxKey{})
	if v == nil {
		return "", errors.New("no nonce in context")
	}
	return v.(string), nil
}

// StrictPolicy can be used to build a strict, nonce-based CSP.
//
// See https://csp.withgoogle.com/docs/strict-csp.html for more info.
type StrictPolicy struct {
	// NoStrictDynamic controls whether script-src should contain the 'strict-dynamic'
	// value.
	//
	// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#strict-dynamic
	// for more info.
	NoStrictDynamic bool
	// UnsafeEval controls whether script-src should contain the 'unsafe-eval' value.
	// If enabled, the eval() JavaScript function is allowed.
	UnsafeEval bool
	// BaseURI controls the base-uri directive. If BaseURI is an empty string the
	// directive will be set to 'none'. The base-uri directive restricts the URLs
	// which can be used in a document's <base> element.
	//
	// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/base-uri
	// for more info.
	BaseURI string
	// ReportURI controls the report-uri directive. If ReportUri is empty, no report-uri
	// directive will be set.
	ReportURI string
	// Hashes adds a set of hashes to script-src. An example of a hash would be:
	//  sha256-CihokcEcBW4atb/CW/XWsvWwbTjqwQlE9nj9ii5ww5M=
	// which is the SHA256 hash for the script "console.log(1)".
	//
	// For more info, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src
	Hashes []string
}

// Serialize serializes this policy for use in a Content-Security-Policy header
// or in a Content-Security-Policy-Report-Only header. A nonce will be provided
// to Serialize which can be used in 'nonce-{random-nonce}' values in directives.
func (s StrictPolicy) Serialize(nonce string) string {
	var b strings.Builder

	// object-src 'none'; script-src 'unsafe-inline' 'nonce-{random}'
	b.WriteString("object-src 'none'; script-src 'unsafe-inline' 'nonce-")
	b.WriteString(nonce)
	b.WriteByte('\'')

	if !s.NoStrictDynamic {
		b.WriteString(" 'strict-dynamic' https: http:")
	}

	if s.UnsafeEval {
		b.WriteString(" 'unsafe-eval'")
	}

	for _, h := range s.Hashes {
		b.WriteString(" '")
		b.WriteString(h)
		b.WriteByte('\'')
	}

	b.WriteString("; base-uri ")
	if s.BaseURI == "" {
		b.WriteString("'none'")
	} else {
		b.WriteString(s.BaseURI)
	}

	if s.ReportURI != "" {
		b.WriteString("; report-uri ")
		b.WriteString(s.ReportURI)
	}

	return b.String()

}

// FramingPolicy can be used to create a new CSP policy with frame-ancestors
// set to 'self'.
//
// TODO: allow relaxation on specific endpoints according to #77.
type FramingPolicy struct {
	// ReportURI controls the report-uri directive. If ReportUri is empty, no report-uri
	// directive will be set.
	ReportURI string
}

// Serialize serializes this policy for use in a Content-Security-Policy header
// or in a Content-Security-Policy-Report-Only header. A nonce will be provided
// to Serialize which can be used in 'nonce-{random-nonce}' values in directives.
func (f FramingPolicy) Serialize(nonce string) string {
	var b strings.Builder
	b.WriteString("frame-ancestors 'self'")

	if f.ReportURI != "" {
		b.WriteString("; report-uri ")
		b.WriteString(f.ReportURI)
	}

	return b.String()
}

// Interceptor intercepts requests and applies CSP policies.
type Interceptor struct {
	// TODO: move it to a safehttp.InterceptorConfig implementation to enable
	// per-handler configuration.

	// Enforce specifies which policies will be set as the Content-Security-Policy
	// header.
	Enforce []Policy
	// ReportOnly specifies which policies will be set as the Content-Security-Policy-Report-Only
	// header.
	ReportOnly []Policy
}

var _ safehttp.Interceptor = Interceptor{}

// Default creates a new CSP interceptor with a strict nonce-based policy and a
// framing policy, both in enforcement mode.
func Default(reportURI string) Interceptor {
	return Interceptor{
		Enforce: []Policy{
			StrictPolicy{ReportURI: reportURI},
			FramingPolicy{ReportURI: reportURI},
		},
	}
}

// Before claims and sets the Content-Security-Policy header and the
// Content-Security-Policy-Report-Only header.
func (it Interceptor) Before(w safehttp.ResponseWriter, r *safehttp.IncomingRequest, _ safehttp.InterceptorConfig) safehttp.Result {
	nonce := generateNonce()
	r.SetContext(context.WithValue(r.Context(), ctxKey{}, nonce))

	var CSPs []string
	for _, p := range it.Enforce {
		CSPs = append(CSPs, p.Serialize(nonce))
	}
	var reportCSPs []string
	for _, p := range it.ReportOnly {
		reportCSPs = append(reportCSPs, p.Serialize(nonce))
	}

	h := w.Header()
	setCSP := h.Claim("Content-Security-Policy")
	setCSPReportOnly := h.Claim("Content-Security-Policy-Report-Only")

	setCSP(CSPs)
	setCSPReportOnly(reportCSPs)

	return safehttp.NotWritten()
}

// Commit adds the nonce to the safehttp.TemplateResponse which is going to be
// injected as the value of the nonce attribute in <script> and <link> tags. The
// nonce is going to be unique for each safehttp.IncomingRequest.
func (it Interceptor) Commit(w safehttp.ResponseHeadersWriter, r *safehttp.IncomingRequest, resp safehttp.Response, cfg safehttp.InterceptorConfig) {
	tmplResp, ok := resp.(*safehttp.TemplateResponse)
	if !ok {
		return
	}

	nonce, err := Nonce(r.Context())
	if err != nil {
		// The nonce should have been added in the Before stage and, if that is
		// not the case, a server misconfiguration occured.
		panic("no CSP nonce")
	}

	tmplResp.FuncMap[htmlinject.CSPNoncesDefaultFuncName] = func() string { return nonce }
}

// OnError is a no-op, required to satisfy the safehttp.Interceptor interface.
func (it Interceptor) OnError(w safehttp.ResponseHeadersWriter, r *safehttp.IncomingRequest, resp safehttp.Response, _ safehttp.InterceptorConfig) {
	return
}
<|endoftext|>


<commit_before>package arg

import (
	"fmt"
	"io"
	"os"
	"strings"
)

// the width of the left column
const colWidth = 25

// to allow monkey patching in tests
var stderr = os.Stderr

// Fail prints usage information to stderr and exits with non-zero status
func (p *Parser) Fail(msg string) {
	p.failWithCommand(msg, p.cmd)
}

// failWithCommand prints usage information for the given subcommand to stderr and exits with non-zero status
func (p *Parser) failWithCommand(msg string, cmd *command) {
	p.writeUsageForCommand(stderr, cmd)
	fmt.Fprintln(stderr, "error:", msg)
	osExit(-1)
}

// WriteUsage writes usage information to the given writer
func (p *Parser) WriteUsage(w io.Writer) {
	cmd := p.cmd
	if p.lastCmd != nil {
		cmd = p.lastCmd
	}
	p.writeUsageForCommand(w, cmd)
}

// writeUsageForCommand writes usage information for the given subcommand
func (p *Parser) writeUsageForCommand(w io.Writer, cmd *command) {
	var positionals, options []*spec
	for _, spec := range cmd.specs {
		if spec.positional {
			positionals = append(positionals, spec)
		} else {
			options = append(options, spec)
		}
	}

	if p.version != "" {
		fmt.Fprintln(w, p.version)
	}

	// make a list of ancestor commands so that we print with full context
	var ancestors []string
	ancestor := cmd
	for ancestor != nil {
		ancestors = append(ancestors, ancestor.name)
		ancestor = ancestor.parent
	}

	// print the beginning of the usage string
	fmt.Fprint(w, "Usage:")
	for i := len(ancestors) - 1; i >= 0; i-- {
		fmt.Fprint(w, " "+ancestors[i])
	}

	// write the option component of the usage message
	for _, spec := range options {
		// prefix with a space
		fmt.Fprint(w, " ")
		if !spec.required {
			fmt.Fprint(w, "[")
		}
		fmt.Fprint(w, synopsis(spec, "--"+spec.long))
		if !spec.required {
			fmt.Fprint(w, "]")
		}
	}

	// write the positional component of the usage message
	for _, spec := range positionals {
		// prefix with a space
		fmt.Fprint(w, " ")
		if spec.multiple {
			if !spec.required {
				fmt.Fprint(w, "[")
			}
			fmt.Fprintf(w, "%s [%s ...]", spec.placeholder, spec.placeholder)
			if !spec.required {
				fmt.Fprint(w, "]")
			}
		} else {
			fmt.Fprint(w, spec.placeholder)
		}
	}

	// if the program supports subcommands, give a hint to the user about their existence
	if len(cmd.subcommands) > 0 {
		fmt.Fprint(w, " <command> [<args>]")
	}

	fmt.Fprint(w, "\n")
}

func printTwoCols(w io.Writer, left, help string, defaultVal string, envVal string) {
	lhs := "  " + left
	fmt.Fprint(w, lhs)
	if help != "" {
		if len(lhs)+2 < colWidth {
			fmt.Fprint(w, strings.Repeat(" ", colWidth-len(lhs)))
		} else {
			fmt.Fprint(w, "\n"+strings.Repeat(" ", colWidth))
		}
		fmt.Fprint(w, help)
	}

	bracketsContent := []string{}

	if defaultVal != "" {
		bracketsContent = append(bracketsContent,
			fmt.Sprintf("default: %s", defaultVal),
		)
	}

	if envVal != "" {
		bracketsContent = append(bracketsContent,
			fmt.Sprintf("env: %s", envVal),
		)
	}

	if len(bracketsContent) > 0 {
		fmt.Fprintf(w, " [%s]", strings.Join(bracketsContent, ", "))
	}
	fmt.Fprint(w, "\n")
}

// WriteHelp writes the usage string followed by the full help string for each option
func (p *Parser) WriteHelp(w io.Writer) {
	cmd := p.cmd
	if p.lastCmd != nil {
		cmd = p.lastCmd
	}
	p.writeHelpForCommand(w, cmd)
}

// writeHelp writes the usage string for the given subcommand
func (p *Parser) writeHelpForCommand(w io.Writer, cmd *command) {
	var positionals, options []*spec
	for _, spec := range cmd.specs {
		if spec.positional {
			positionals = append(positionals, spec)
		} else {
			options = append(options, spec)
		}
	}

	if p.description != "" {
		fmt.Fprintln(w, p.description)
	}
	p.writeUsageForCommand(w, cmd)

	// write the list of positionals
	if len(positionals) > 0 {
		fmt.Fprint(w, "\nPositional arguments:\n")
		for _, spec := range positionals {
			printTwoCols(w, spec.placeholder, spec.help, "", "")
		}
	}

	// write the list of options
	if len(options) > 0 || cmd.parent == nil {
		fmt.Fprint(w, "\nOptions:\n")
		for _, spec := range options {
			p.printOption(w, spec)
		}
	}

	// obtain a flattened list of options from all ancestors
	var globals []*spec
	ancestor := cmd.parent
	for ancestor != nil {
		globals = append(globals, ancestor.specs...)
		ancestor = ancestor.parent
	}

	// write the list of global options
	if len(globals) > 0 {
		fmt.Fprint(w, "\nGlobal options:\n")
		for _, spec := range globals {
			p.printOption(w, spec)
		}
	}

	// write the list of built in options
	p.printOption(w, &spec{
		boolean: true,
		long:    "help",
		short:   "h",
		help:    "display this help and exit",
	})
	if p.version != "" {
		p.printOption(w, &spec{
			boolean: true,
			long:    "version",
			help:    "display version and exit",
		})
	}

	// write the list of subcommands
	if len(cmd.subcommands) > 0 {
		fmt.Fprint(w, "\nCommands:\n")
		for _, subcmd := range cmd.subcommands {
			printTwoCols(w, subcmd.name, subcmd.help, "", "")
		}
	}
}

func (p *Parser) printOption(w io.Writer, spec *spec) {
	left := synopsis(spec, "--"+spec.long)
	if spec.short != "" {
		left += ", " + synopsis(spec, "-"+spec.short)
	}
	printTwoCols(w, left, spec.help, spec.defaultVal, spec.env)
}

func synopsis(spec *spec, form string) string {
	if spec.boolean {
		return form
	}
	return form + " " + spec.placeholder
}

func ptrTo(s string) *string {
	return &s
}
<commit_msg>refactor: remove unused function<commit_after>package arg

import (
	"fmt"
	"io"
	"os"
	"strings"
)

// the width of the left column
const colWidth = 25

// to allow monkey patching in tests
var stderr = os.Stderr

// Fail prints usage information to stderr and exits with non-zero status
func (p *Parser) Fail(msg string) {
	p.failWithCommand(msg, p.cmd)
}

// failWithCommand prints usage information for the given subcommand to stderr and exits with non-zero status
func (p *Parser) failWithCommand(msg string, cmd *command) {
	p.writeUsageForCommand(stderr, cmd)
	fmt.Fprintln(stderr, "error:", msg)
	osExit(-1)
}

// WriteUsage writes usage information to the given writer
func (p *Parser) WriteUsage(w io.Writer) {
	cmd := p.cmd
	if p.lastCmd != nil {
		cmd = p.lastCmd
	}
	p.writeUsageForCommand(w, cmd)
}

// writeUsageForCommand writes usage information for the given subcommand
func (p *Parser) writeUsageForCommand(w io.Writer, cmd *command) {
	var positionals, options []*spec
	for _, spec := range cmd.specs {
		if spec.positional {
			positionals = append(positionals, spec)
		} else {
			options = append(options, spec)
		}
	}

	if p.version != "" {
		fmt.Fprintln(w, p.version)
	}

	// make a list of ancestor commands so that we print with full context
	var ancestors []string
	ancestor := cmd
	for ancestor != nil {
		ancestors = append(ancestors, ancestor.name)
		ancestor = ancestor.parent
	}

	// print the beginning of the usage string
	fmt.Fprint(w, "Usage:")
	for i := len(ancestors) - 1; i >= 0; i-- {
		fmt.Fprint(w, " "+ancestors[i])
	}

	// write the option component of the usage message
	for _, spec := range options {
		// prefix with a space
		fmt.Fprint(w, " ")
		if !spec.required {
			fmt.Fprint(w, "[")
		}
		fmt.Fprint(w, synopsis(spec, "--"+spec.long))
		if !spec.required {
			fmt.Fprint(w, "]")
		}
	}

	// write the positional component of the usage message
	for _, spec := range positionals {
		// prefix with a space
		fmt.Fprint(w, " ")
		if spec.multiple {
			if !spec.required {
				fmt.Fprint(w, "[")
			}
			fmt.Fprintf(w, "%s [%s ...]", spec.placeholder, spec.placeholder)
			if !spec.required {
				fmt.Fprint(w, "]")
			}
		} else {
			fmt.Fprint(w, spec.placeholder)
		}
	}

	// if the program supports subcommands, give a hint to the user about their existence
	if len(cmd.subcommands) > 0 {
		fmt.Fprint(w, " <command> [<args>]")
	}

	fmt.Fprint(w, "\n")
}

func printTwoCols(w io.Writer, left, help string, defaultVal string, envVal string) {
	lhs := "  " + left
	fmt.Fprint(w, lhs)
	if help != "" {
		if len(lhs)+2 < colWidth {
			fmt.Fprint(w, strings.Repeat(" ", colWidth-len(lhs)))
		} else {
			fmt.Fprint(w, "\n"+strings.Repeat(" ", colWidth))
		}
		fmt.Fprint(w, help)
	}

	bracketsContent := []string{}

	if defaultVal != "" {
		bracketsContent = append(bracketsContent,
			fmt.Sprintf("default: %s", defaultVal),
		)
	}

	if envVal != "" {
		bracketsContent = append(bracketsContent,
			fmt.Sprintf("env: %s", envVal),
		)
	}

	if len(bracketsContent) > 0 {
		fmt.Fprintf(w, " [%s]", strings.Join(bracketsContent, ", "))
	}
	fmt.Fprint(w, "\n")
}

// WriteHelp writes the usage string followed by the full help string for each option
func (p *Parser) WriteHelp(w io.Writer) {
	cmd := p.cmd
	if p.lastCmd != nil {
		cmd = p.lastCmd
	}
	p.writeHelpForCommand(w, cmd)
}

// writeHelp writes the usage string for the given subcommand
func (p *Parser) writeHelpForCommand(w io.Writer, cmd *command) {
	var positionals, options []*spec
	for _, spec := range cmd.specs {
		if spec.positional {
			positionals = append(positionals, spec)
		} else {
			options = append(options, spec)
		}
	}

	if p.description != "" {
		fmt.Fprintln(w, p.description)
	}
	p.writeUsageForCommand(w, cmd)

	// write the list of positionals
	if len(positionals) > 0 {
		fmt.Fprint(w, "\nPositional arguments:\n")
		for _, spec := range positionals {
			printTwoCols(w, spec.placeholder, spec.help, "", "")
		}
	}

	// write the list of options
	if len(options) > 0 || cmd.parent == nil {
		fmt.Fprint(w, "\nOptions:\n")
		for _, spec := range options {
			p.printOption(w, spec)
		}
	}

	// obtain a flattened list of options from all ancestors
	var globals []*spec
	ancestor := cmd.parent
	for ancestor != nil {
		globals = append(globals, ancestor.specs...)
		ancestor = ancestor.parent
	}

	// write the list of global options
	if len(globals) > 0 {
		fmt.Fprint(w, "\nGlobal options:\n")
		for _, spec := range globals {
			p.printOption(w, spec)
		}
	}

	// write the list of built in options
	p.printOption(w, &spec{
		boolean: true,
		long:    "help",
		short:   "h",
		help:    "display this help and exit",
	})
	if p.version != "" {
		p.printOption(w, &spec{
			boolean: true,
			long:    "version",
			help:    "display version and exit",
		})
	}

	// write the list of subcommands
	if len(cmd.subcommands) > 0 {
		fmt.Fprint(w, "\nCommands:\n")
		for _, subcmd := range cmd.subcommands {
			printTwoCols(w, subcmd.name, subcmd.help, "", "")
		}
	}
}

func (p *Parser) printOption(w io.Writer, spec *spec) {
	left := synopsis(spec, "--"+spec.long)
	if spec.short != "" {
		left += ", " + synopsis(spec, "-"+spec.short)
	}
	printTwoCols(w, left, spec.help, spec.defaultVal, spec.env)
}

func synopsis(spec *spec, form string) string {
	if spec.boolean {
		return form
	}
	return form + " " + spec.placeholder
}
<|endoftext|>


<commit_before>package card_holder_test

import (
	"github.com/sorribas/shamir3pass"
	. "github.com/whereswaldon/cryptage/v2/card_holder"
	. "github.com/whereswaldon/cryptage/v2/types"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var Faces []CardFace = []CardFace{"ACE", "KING", "QUEEN"}

var _ = Describe("CardHolder", func() {
	Describe("Creating a CardHolder from scratch", func() {
		Context("When the key is nil", func() {
			It("Should return an error", func() {
				holder, err := NewHolder(nil, Faces)
				Expect(err).ToNot(BeNil())
				Expect(holder).To(BeNil())
			})
		})
		Context("When the faces are nil", func() {
			It("Should return an error", func() {
				key := shamir3pass.GenerateKey(1024)
				holder, err := NewHolder(&key, nil)
				Expect(err).ToNot(BeNil())
				Expect(holder).To(BeNil())
			})
		})
		Context("When the faces are empty", func() {
			It("Should return an error", func() {
				key := shamir3pass.GenerateKey(1024)
				faces := make([]CardFace, 0)
				holder, err := NewHolder(&key, faces)
				Expect(err).ToNot(BeNil())
				Expect(holder).To(BeNil())
			})
		})
		Context("When the arguments are valid", func() {
			It("Should return a CardHolder an a nil error", func() {
				key := shamir3pass.GenerateKey(1024)
				holder, err := NewHolder(&key, Faces)
				Expect(err).To(BeNil())
				Expect(holder).ToNot(BeNil())
			})
		})
	})
})
<commit_msg>Implement tests for encrypted CardHolder initialization<commit_after>package card_holder_test

import (
	"github.com/sorribas/shamir3pass"
	. "github.com/whereswaldon/cryptage/v2/card_holder"
	. "github.com/whereswaldon/cryptage/v2/types"
	"math/big"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var Faces []CardFace = []CardFace{"ACE", "KING", "QUEEN"}
var EncryptedFaces []*big.Int = []*big.Int{big.NewInt(0), big.NewInt(1), big.NewInt(2)}

var _ = Describe("CardHolder", func() {
	Describe("Creating a CardHolder from scratch", func() {
		Context("When the key is nil", func() {
			It("Should return an error", func() {
				holder, err := NewHolder(nil, Faces)
				Expect(err).ToNot(BeNil())
				Expect(holder).To(BeNil())
			})
		})
		Context("When the faces are nil", func() {
			It("Should return an error", func() {
				key := shamir3pass.GenerateKey(1024)
				holder, err := NewHolder(&key, nil)
				Expect(err).ToNot(BeNil())
				Expect(holder).To(BeNil())
			})
		})
		Context("When the faces are empty", func() {
			It("Should return an error", func() {
				key := shamir3pass.GenerateKey(1024)
				faces := make([]CardFace, 0)
				holder, err := NewHolder(&key, faces)
				Expect(err).ToNot(BeNil())
				Expect(holder).To(BeNil())
			})
		})
		Context("When the arguments are valid", func() {
			It("Should return a CardHolder an a nil error", func() {
				key := shamir3pass.GenerateKey(1024)
				holder, err := NewHolder(&key, Faces)
				Expect(err).To(BeNil())
				Expect(holder).ToNot(BeNil())
			})
		})
	})
	Describe("Creating a CardHolder from encrypted cards", func() {
		Context("When the key is nil", func() {
			It("Should return an error", func() {
				holder, err := HolderFromEncrypted(nil, EncryptedFaces)
				Expect(err).ToNot(BeNil())
				Expect(holder).To(BeNil())
			})
		})
		Context("When the faces are nil", func() {
			It("Should return an error", func() {
				key := shamir3pass.GenerateKey(1024)
				holder, err := HolderFromEncrypted(&key, nil)
				Expect(err).ToNot(BeNil())
				Expect(holder).To(BeNil())
			})
		})
		Context("When the faces are empty", func() {
			It("Should return an error", func() {
				key := shamir3pass.GenerateKey(1024)
				faces := make([]*big.Int, 0)
				holder, err := HolderFromEncrypted(&key, faces)
				Expect(err).ToNot(BeNil())
				Expect(holder).To(BeNil())
			})
		})
		Context("When the arguments are valid", func() {
			It("Should return a CardHolder an a nil error", func() {
				key := shamir3pass.GenerateKey(1024)
				holder, err := HolderFromEncrypted(&key, EncryptedFaces)
				Expect(err).To(BeNil())
				Expect(holder).ToNot(BeNil())
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"github.com/mndrix/tap-go"
	"github.com/opencontainers/runtime-tools/cgroups"
	"github.com/opencontainers/runtime-tools/validation/util"
)

func main() {
	var limit int64 = 50593792
	var swappiness uint64 = 50

	t := tap.New()
	t.Header(0)
	defer t.AutoPlan()

	g, err := util.GetDefaultGenerator()
	if err != nil {
		util.Fatal(err)
	}
	g.SetLinuxCgroupsPath(cgroups.AbsCgroupPath)
	g.SetLinuxResourcesMemoryLimit(limit)
	g.SetLinuxResourcesMemoryReservation(limit)
	g.SetLinuxResourcesMemorySwap(limit)
	g.SetLinuxResourcesMemoryKernel(limit)
	g.SetLinuxResourcesMemoryKernelTCP(limit)
	g.SetLinuxResourcesMemorySwappiness(swappiness)
	g.SetLinuxResourcesMemoryDisableOOMKiller(true)
	err = util.RuntimeOutsideValidate(g, t, util.ValidateLinuxResourcesMemory)
	if err != nil {
		util.Fatal(err)
	}
}
<commit_msg>validation: test linux_cgroups_memory with different values<commit_after>package main

import (
	"fmt"
	"runtime"

	"github.com/mndrix/tap-go"
	"github.com/opencontainers/runtime-tools/cgroups"
	"github.com/opencontainers/runtime-tools/validation/util"
)

func main() {
	if "linux" != runtime.GOOS {
		util.Fatal(fmt.Errorf("linux-specific cgroup test"))
	}

	t := tap.New()
	t.Header(0)

	cases := []struct {
		limit      int64
		swappiness uint64
	}{
		{50593792, 10},
		{50593792, 50},
		{50593792, 100},
		{151781376, 10},
		{151781376, 50},
		{151781376, 100},
	}

	for _, c := range cases {
		g, err := util.GetDefaultGenerator()
		if err != nil {
			util.Fatal(err)
		}
		g.SetLinuxCgroupsPath(cgroups.AbsCgroupPath)
		g.SetLinuxResourcesMemoryLimit(c.limit)
		g.SetLinuxResourcesMemoryReservation(c.limit)
		g.SetLinuxResourcesMemorySwap(c.limit)
		g.SetLinuxResourcesMemoryKernel(c.limit)
		g.SetLinuxResourcesMemoryKernelTCP(c.limit)
		g.SetLinuxResourcesMemorySwappiness(c.swappiness)
		g.SetLinuxResourcesMemoryDisableOOMKiller(true)
		err = util.RuntimeOutsideValidate(g, t, util.ValidateLinuxResourcesMemory)
		if err != nil {
			t.Fail(err.Error())
		}
	}

	t.AutoPlan()
}
<|endoftext|>


<commit_before>// Package dnsimple implements a client for the DNSimple API.
//
// In order to use this package you will need a DNSimple account and your API Token.
package dnsimple

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"time"
)

const (
	libraryVersion = "0.1"
	baseURL        = "https://api.dnsimple.com/"
	userAgent      = "dnsimple-go/" + libraryVersion

	apiVersion = "v2"
)

type Client struct {
	// HTTP client used to communicate with the API.
	HttpClient *http.Client

	// Credentials used for accessing the DNSimple API
	Credentials Credentials

	// Base URL for API requests.
	// Defaults to the public DNSimple API, but can be set to a different endpoint (e.g. the sandbox).
	// BaseURL should always be specified with a trailing slash.
	BaseURL string

	// User agent used when communicating with the DNSimple API.
	UserAgent string

	// Services used for talking to different parts of the DNSimple API.
	Contacts  *ContactsService
	Domains   *DomainsService
	Registrar *RegistrarService
	Users     *UsersService

	// Set to true to output debugging logs during API calls
	Debug bool
}

// NewClient returns a new DNSimple API client  using the given
// credentials.
func NewClient(credentials Credentials) *Client {
	c := &Client{Credentials: credentials, HttpClient: &http.Client{}, BaseURL: baseURL, UserAgent: userAgent}
	c.Contacts = &ContactsService{client: c}
	c.Domains = &DomainsService{client: c}
	c.Registrar = &RegistrarService{client: c}
	c.Users = &UsersService{client: c}
	return c
}

// NewRequest creates an API request.
// The path is expected to be a relative path and will be resolved
// according to the BaseURL of the Client. Paths should always be specified without a preceding slash.
func (client *Client) NewRequest(method, path string, payload interface{}) (*http.Request, error) {
	url := client.BaseURL + fmt.Sprintf("%s/%s", apiVersion, path)

	//log.Printf("%v %v", method, url)

	body := new(bytes.Buffer)
	if payload != nil {
		err := json.NewEncoder(body).Encode(payload)
		if err != nil {
			return nil, err
		}
	}

	req, err := http.NewRequest(method, url, body)
	if err != nil {
		return nil, err
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("User-Agent", client.UserAgent)
	req.Header.Add(client.Credentials.HttpHeader())

	return req, nil
}

func (c *Client) get(path string, v interface{}) (*Response, error) {
	return c.Do("GET", path, nil, v)
}

func (c *Client) post(path string, payload, v interface{}) (*Response, error) {
	return c.Do("POST", path, payload, v)
}

func (c *Client) put(path string, payload, v interface{}) (*Response, error) {
	return c.Do("PUT", path, payload, v)
}

func (c *Client) delete(path string, payload interface{}) (*Response, error) {
	return c.Do("DELETE", path, payload, nil)
}

// Do sends an API request and returns the API response.
// The API response is JSON decoded and stored in the value pointed by v,
// or returned as an error if an API error has occurred.
// If v implements the io.Writer interface, the raw response body will be written to v,
// without attempting to decode it.
func (c *Client) Do(method, path string, payload, v interface{}) (*Response, error) {
	req, err := c.NewRequest(method, path, payload)

	if c.Debug {
		log.Printf("Executing request (%v): %#v", req.URL, req)
	}

	if err != nil {
		return nil, err
	}

	res, err := c.HttpClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	if c.Debug {
		log.Printf("Response received: %#v", res)
	}

	response := &Response{Response: res}

	err = CheckResponse(res)
	if err != nil {
		return response, err
	}

	if v != nil {
		if w, ok := v.(io.Writer); ok {
			io.Copy(w, res.Body)
		} else {
			err = json.NewDecoder(res.Body).Decode(v)
		}
	}

	return response, err
}

// A Response represents an API response.
type Response struct {
	*http.Response
}

// An ErrorResponse represents an error caused by an API request.
type ErrorResponse struct {
	Response *http.Response // HTTP response that caused this error
	Message  string         `json:"message"` // human-readable message
}

// Error implements the error interface.
func (r *ErrorResponse) Error() string {
	return fmt.Sprintf("%v %v: %d %v",
		r.Response.Request.Method, r.Response.Request.URL,
		r.Response.StatusCode, r.Message)
}

// CheckResponse checks the API response for errors, and returns them if present.
// A response is considered an error if the status code is different than 2xx. Specific requests
// may have additional requirements, but this is sufficient in most of the cases.
func CheckResponse(r *http.Response) error {
	if code := r.StatusCode; 200 <= code && code <= 299 {
		return nil
	}

	errorResponse := &ErrorResponse{Response: r}
	err := json.NewDecoder(r.Body).Decode(errorResponse)
	if err != nil {
		return err
	}

	return errorResponse
}

// Date custom type.
type Date struct {
	time.Time
}

// UnmarshalJSON handles the deserialization of the custom Date type.
func (d *Date) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return fmt.Errorf("date should be a string, got %s", data)
	}
	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		return fmt.Errorf("invalid date: %v", err)
	}
	d.Time = t
	return nil
}
<commit_msg>Change library version to keep track of its usage<commit_after>// Package dnsimple implements a client for the DNSimple API.
//
// In order to use this package you will need a DNSimple account and your API Token.
package dnsimple

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"time"
)

const (
	libraryVersion = "1.0.0.dev"
	baseURL        = "https://api.dnsimple.com/"
	userAgent      = "dnsimple-go/" + libraryVersion

	apiVersion = "v2"
)

type Client struct {
	// HTTP client used to communicate with the API.
	HttpClient *http.Client

	// Credentials used for accessing the DNSimple API
	Credentials Credentials

	// Base URL for API requests.
	// Defaults to the public DNSimple API, but can be set to a different endpoint (e.g. the sandbox).
	// BaseURL should always be specified with a trailing slash.
	BaseURL string

	// User agent used when communicating with the DNSimple API.
	UserAgent string

	// Services used for talking to different parts of the DNSimple API.
	Contacts  *ContactsService
	Domains   *DomainsService
	Registrar *RegistrarService
	Users     *UsersService

	// Set to true to output debugging logs during API calls
	Debug bool
}

// NewClient returns a new DNSimple API client  using the given
// credentials.
func NewClient(credentials Credentials) *Client {
	c := &Client{Credentials: credentials, HttpClient: &http.Client{}, BaseURL: baseURL, UserAgent: userAgent}
	c.Contacts = &ContactsService{client: c}
	c.Domains = &DomainsService{client: c}
	c.Registrar = &RegistrarService{client: c}
	c.Users = &UsersService{client: c}
	return c
}

// NewRequest creates an API request.
// The path is expected to be a relative path and will be resolved
// according to the BaseURL of the Client. Paths should always be specified without a preceding slash.
func (client *Client) NewRequest(method, path string, payload interface{}) (*http.Request, error) {
	url := client.BaseURL + fmt.Sprintf("%s/%s", apiVersion, path)

	//log.Printf("%v %v", method, url)

	body := new(bytes.Buffer)
	if payload != nil {
		err := json.NewEncoder(body).Encode(payload)
		if err != nil {
			return nil, err
		}
	}

	req, err := http.NewRequest(method, url, body)
	if err != nil {
		return nil, err
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("User-Agent", client.UserAgent)
	req.Header.Add(client.Credentials.HttpHeader())

	return req, nil
}

func (c *Client) get(path string, v interface{}) (*Response, error) {
	return c.Do("GET", path, nil, v)
}

func (c *Client) post(path string, payload, v interface{}) (*Response, error) {
	return c.Do("POST", path, payload, v)
}

func (c *Client) put(path string, payload, v interface{}) (*Response, error) {
	return c.Do("PUT", path, payload, v)
}

func (c *Client) delete(path string, payload interface{}) (*Response, error) {
	return c.Do("DELETE", path, payload, nil)
}

// Do sends an API request and returns the API response.
// The API response is JSON decoded and stored in the value pointed by v,
// or returned as an error if an API error has occurred.
// If v implements the io.Writer interface, the raw response body will be written to v,
// without attempting to decode it.
func (c *Client) Do(method, path string, payload, v interface{}) (*Response, error) {
	req, err := c.NewRequest(method, path, payload)

	if c.Debug {
		log.Printf("Executing request (%v): %#v", req.URL, req)
	}

	if err != nil {
		return nil, err
	}

	res, err := c.HttpClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	if c.Debug {
		log.Printf("Response received: %#v", res)
	}

	response := &Response{Response: res}

	err = CheckResponse(res)
	if err != nil {
		return response, err
	}

	if v != nil {
		if w, ok := v.(io.Writer); ok {
			io.Copy(w, res.Body)
		} else {
			err = json.NewDecoder(res.Body).Decode(v)
		}
	}

	return response, err
}

// A Response represents an API response.
type Response struct {
	*http.Response
}

// An ErrorResponse represents an error caused by an API request.
type ErrorResponse struct {
	Response *http.Response // HTTP response that caused this error
	Message  string         `json:"message"` // human-readable message
}

// Error implements the error interface.
func (r *ErrorResponse) Error() string {
	return fmt.Sprintf("%v %v: %d %v",
		r.Response.Request.Method, r.Response.Request.URL,
		r.Response.StatusCode, r.Message)
}

// CheckResponse checks the API response for errors, and returns them if present.
// A response is considered an error if the status code is different than 2xx. Specific requests
// may have additional requirements, but this is sufficient in most of the cases.
func CheckResponse(r *http.Response) error {
	if code := r.StatusCode; 200 <= code && code <= 299 {
		return nil
	}

	errorResponse := &ErrorResponse{Response: r}
	err := json.NewDecoder(r.Body).Decode(errorResponse)
	if err != nil {
		return err
	}

	return errorResponse
}

// Date custom type.
type Date struct {
	time.Time
}

// UnmarshalJSON handles the deserialization of the custom Date type.
func (d *Date) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return fmt.Errorf("date should be a string, got %s", data)
	}
	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		return fmt.Errorf("invalid date: %v", err)
	}
	d.Time = t
	return nil
}
<|endoftext|>


<commit_before>package nodefs

import (
	"log"
	"sync"
)

// HandleMap translates objects in Go space to 64-bit handles that can
// be given out to -say- the linux kernel.
//
// The 32 bits version of this is a threadsafe wrapper around a map.
//
// To use it, include Handled as first member of the structure
// you wish to export.
//
// This structure is thread-safe.
type handleMap interface {
	Register(obj *handled) (handle, generation uint64)
	Count() int
	Decode(uint64) *handled
	Forget(handle uint64, count int) (bool, *handled)
	Handle(obj *handled) uint64
	Has(uint64) bool
}

type handled struct {
	check  uint32
	handle uint64
	count  int
}

func (h *handled) verify() {
	if h.count < 0 {
		log.Panicf("negative lookup count %d", h.count)
	}
	if (h.count == 0) != (h.handle == 0) {
		log.Panicf("registration mismatch: lookup %d id %d", h.count, h.handle)
	}
}

const _ALREADY_MSG = "Object already has a handle"

////////////////////////////////////////////////////////////////
// portable version using 32 bit integers.

type portableHandleMap struct {
	sync.RWMutex
	used    int
	handles []*handled
	freeIds []uint64
}

func newPortableHandleMap() *portableHandleMap {
	return &portableHandleMap{
		// Avoid handing out ID 0 and 1.
		handles: []*handled{nil, nil},
	}
}

func (m *portableHandleMap) Register(obj *handled) (handle, generation uint64) {
	m.Lock()
	if obj.count == 0 {
		if obj.check != 0 {
			panic(_ALREADY_MSG)
		}

		if len(m.freeIds) == 0 {
			handle = uint64(len(m.handles))
			m.handles = append(m.handles, obj)
		} else {
			handle = m.freeIds[len(m.freeIds)-1]
			m.freeIds = m.freeIds[:len(m.freeIds)-1]
			m.handles[handle] = obj
		}
		m.used++
		obj.handle = handle
	} else {
		handle = obj.handle
	}
	obj.count++
	m.Unlock()
	return
}

func (m *portableHandleMap) Handle(obj *handled) (h uint64) {
	m.RLock()
	if obj.count == 0 {
		h = 0
	} else {
		h = obj.handle
	}
	m.RUnlock()
	return h
}

func (m *portableHandleMap) Count() int {
	m.RLock()
	c := m.used
	m.RUnlock()
	return c
}

func (m *portableHandleMap) Decode(h uint64) *handled {
	m.RLock()
	v := m.handles[h]
	m.RUnlock()
	return v
}

func (m *portableHandleMap) Forget(h uint64, count int) (forgotten bool, obj *handled) {
	m.Lock()
	obj = m.handles[h]
	obj.count -= count
	if obj.count < 0 {
		log.Panicf("underflow: handle %d, count %d, object %d", h, count, obj.count)
	} else if obj.count == 0 {
		m.handles[h] = nil
		m.freeIds = append(m.freeIds, h)
		m.used--
		forgotten = true
		obj.handle = 0
	}
	m.Unlock()
	return forgotten, obj
}

func (m *portableHandleMap) Has(h uint64) bool {
	m.RLock()
	ok := m.handles[h] != nil
	m.RUnlock()
	return ok
}
<commit_msg>Increment generation on inode reuse<commit_after>package nodefs

import (
	"log"
	"sync"
)

// HandleMap translates objects in Go space to 64-bit handles that can
// be given out to -say- the linux kernel.
//
// The 32 bits version of this is a threadsafe wrapper around a map.
//
// To use it, include Handled as first member of the structure
// you wish to export.
//
// This structure is thread-safe.
type handleMap interface {
	Register(obj *handled) (handle, generation uint64)
	Count() int
	Decode(uint64) *handled
	Forget(handle uint64, count int) (bool, *handled)
	Handle(obj *handled) uint64
	Has(uint64) bool
}

type handled struct {
	check  uint32
	handle uint64
	count  int
}

func (h *handled) verify() {
	if h.count < 0 {
		log.Panicf("negative lookup count %d", h.count)
	}
	if (h.count == 0) != (h.handle == 0) {
		log.Panicf("registration mismatch: lookup %d id %d", h.count, h.handle)
	}
}

const _ALREADY_MSG = "Object already has a handle"

////////////////////////////////////////////////////////////////
// portable version using 32 bit integers.

type portableHandleMap struct {
	sync.RWMutex
	generation uint64
	used       int
	handles    []*handled
	freeIds    []uint64
}

func newPortableHandleMap() *portableHandleMap {
	return &portableHandleMap{
		// Avoid handing out ID 0 and 1.
		handles: []*handled{nil, nil},
	}
}

func (m *portableHandleMap) Register(obj *handled) (handle, generation uint64) {
	m.Lock()
	if obj.count == 0 {
		if obj.check != 0 {
			panic(_ALREADY_MSG)
		}

		if len(m.freeIds) == 0 {
			handle = uint64(len(m.handles))
			m.handles = append(m.handles, obj)
		} else {
			handle = m.freeIds[len(m.freeIds)-1]
			m.freeIds = m.freeIds[:len(m.freeIds)-1]
			m.generation++
			m.handles[handle] = obj
		}
		m.used++
		obj.handle = handle
	} else {
		handle = obj.handle
	}
	obj.count++
	generation = m.generation
	m.Unlock()
	return
}

func (m *portableHandleMap) Handle(obj *handled) (h uint64) {
	m.RLock()
	if obj.count == 0 {
		h = 0
	} else {
		h = obj.handle
	}
	m.RUnlock()
	return h
}

func (m *portableHandleMap) Count() int {
	m.RLock()
	c := m.used
	m.RUnlock()
	return c
}

func (m *portableHandleMap) Decode(h uint64) *handled {
	m.RLock()
	v := m.handles[h]
	m.RUnlock()
	return v
}

func (m *portableHandleMap) Forget(h uint64, count int) (forgotten bool, obj *handled) {
	m.Lock()
	obj = m.handles[h]
	obj.count -= count
	if obj.count < 0 {
		log.Panicf("underflow: handle %d, count %d, object %d", h, count, obj.count)
	} else if obj.count == 0 {
		m.handles[h] = nil
		m.freeIds = append(m.freeIds, h)
		m.used--
		forgotten = true
		obj.handle = 0
	}
	m.Unlock()
	return forgotten, obj
}

func (m *portableHandleMap) Has(h uint64) bool {
	m.RLock()
	ok := m.handles[h] != nil
	m.RUnlock()
	return ok
}
<|endoftext|>