<commit_before>package vfmd

import (
	"bytes"
	"regexp"
)

// TODO(akavel): add tests for blocks

type BlockSplitter struct {
}

func (b *BlockSplitter) WriteLine(line []byte) error {
	// TODO(akavel): NIY
	return nil
}

func (b *BlockSplitter) Close() error {
	// TODO(akavel): NIY
	return nil
}

type Block interface {
	// Detect checks if startLine and optionally secondLine signify start
	// of the particular Block kind. If negative, 0 should be returned.
	// If positive, number of lines needed to perform the detection
	// should be returned (1 if startLine was enough for detection, 2 if
	// secondLine was used too and belongs to the block). The further
	// lines after the returned number should be passed to Contine().
	//
	// Note: secondLine==nil means end of file/stream
	Detect(startLine, secondLine []byte) (consumedLines int)
	// Continue checks if the specified line may belong to the block, as
	// reported started by Detect. If the line is detected to be of a
	// next block, this line should be returned, preceded by any earlier
	// consumed lines that are now confirmed to be of the next block too.
	//
	// Note: line==nil means end of file/stream
	Continue(line []byte) (refluxLines [][]byte)
	Lines() [][]byte
}

var (
	reUnorderedList  = regexp.MustCompile(`^( *[\*\-\+] +)[^ ]`)
	reOrderedList    = regexp.MustCompile(`^( *([0-9]+)\. +)[^ ]`)
	reHorizontalRule = regexp.MustCompile(`^ *((\* *\* *\* *[\* ]*)|(\- *\- *\- *[\- ]*)|(_ *_ *_ *[_ ]*))$`)
)

func isBlank(line []byte) bool {
	return len(bytes.Trim(line, " \t")) == 0
}

type BlockBase struct{ L [][]byte }

func (b BlockBase) Lines() [][]byte { return b.L }

type BlockNeverContinue struct{ BlockBase }

func (BlockNeverContinue) Continue(line []byte) (reflux [][]byte) {
	return [][]byte{line}
}

// static assertion of Block interface implementation by the listed types
var _ []Block = []Block{
	&NullBlock{},
	&ReferenceResolutionBlock{},
	&SetextHeaderBlock{},
	&CodeBlock{},
	&AtxHeaderBlock{},
	&QuoteBlock{},
	&HorizontalRuleBlock{},
	&UnorderedListBlock{},
	// &OrderedListBlock{},
	// &ParagraphBlock{},
}

type NullBlock struct{ BlockNeverContinue }

func (b *NullBlock) Detect(line, secondLine []byte) (consumed int) {
	if isBlank(line) {
		b.L = [][]byte{line}
		return 1
	}
	return 0
}

type ReferenceResolutionBlock struct {
	BlockNeverContinue
	unprocessedReferenceID        []byte
	refValueSequence              []byte
	unprocessedUrl                []byte
	refDefinitionTrailingSequence []byte
}

func (b *ReferenceResolutionBlock) Detect(line, secondLine []byte) (consumed int) {
	if bytes.HasPrefix(line, []byte("    ")) {
		return 0
	}
	// TODO(akavel): move the regexp out of function, for speed (or cache it?)
	re := regexp.MustCompile(`^ *\[(([^\\\[\]\!]|\\.|\![^\[])*((\!\[([^\\\[\]]|\\.)*\](\[([^\\\[\]]|\\.)*\])?)?([^\\\[\]]|\\.)*)*)\] *:(.*)$`)
	m := re.FindSubmatch(line)
	if len(m) == 0 {
		return 0
	}
	b.unprocessedReferenceID = m[1]
	b.refValueSequence = m[9] // TODO(akavel): verify if right one
	re = regexp.MustCompile(`^ *([^ \<\>]+|\<[^\<\>]*\>)( .*)?$`)
	m = re.FindSubmatch(b.refValueSequence)
	if len(m) == 0 {
		return 0
	}
	b.unprocessedUrl = m[1]
	b.refDefinitionTrailingSequence = m[2]

	// Detected ok. Now check if 1 or 2 lines.
	b.L = [][]byte{line}
	re = regexp.MustCompile(`^ +("(([^"\\]|\\.)*)"|'(([^'\\]|\\.)*)'|\(([^\\\(\)]|\\.)*\)) *$`)
	if bytes.IndexAny(b.refDefinitionTrailingSequence, " ") == -1 &&
		secondLine != nil &&
		re.Match(secondLine) {
		b.L = [][]byte{line, secondLine}
	} else {
		b.L = [][]byte{line}
	}
	return len(b.L)
}

type SetextHeaderBlock struct {
	BlockNeverContinue
}

func (b *SetextHeaderBlock) Detect(line, secondLine []byte) (consumed int) {
	if secondLine == nil {
		return 0
	}
	re := regexp.MustCompile(`^(-+|=+) *$`)
	if re.Match(secondLine) {
		b.L = [][]byte{line, secondLine}
		return 2
	}
	return 0
}

type CodeBlock struct {
	BlockBase
	maybeEnd bool
}

func (b *CodeBlock) Detect(line, secondLine []byte) (consumed int) {
	if bytes.HasPrefix(line, []byte("    ")) {
		b.L = [][]byte{line}
		return 1
	}
	return 0
}
func (b *CodeBlock) Continue(line []byte) (reflux [][]byte) {
	if b.maybeEnd && !bytes.HasPrefix(line, []byte("    ")) {
		prev := b.L[len(b.L)-1]
		b.L = b.L[:len(b.L)-1]
		return [][]byte{prev, line}
	}
	blank := isBlank(line)
	if !blank && !bytes.HasPrefix(line, []byte("    ")) {
		return [][]byte{line}
	}
	b.maybeEnd = blank
	b.L = append(b.L, line)
	return nil
}

type AtxHeaderBlock struct{ BlockNeverContinue }

func (b *AtxHeaderBlock) Detect(line, secondLine []byte) (consumed int) {
	if bytes.HasPrefix(line, []byte("#")) {
		b.L = [][]byte{line}
		return 1
	}
	return 0
}

type QuoteBlock struct{ BlockBase }

func (b *QuoteBlock) Detect(line, secondLine []byte) (consumed int) {
	ltrim := bytes.TrimLeft(line, " ")
	if len(ltrim) > 0 && ltrim[0] == '>' {
		b.L = [][]byte{line}
		return 1
	}
	return 0
}
func (b *QuoteBlock) Continue(line []byte) (reflux [][]byte) {
	if line == nil {
		return [][]byte{line}
	}
	if isBlank(b.L[len(b.L)-1]) {
		if isBlank(line) ||
			bytes.HasPrefix(line, []byte("    ")) ||
			bytes.TrimLeft(line, " ")[0] != '>' {
			return [][]byte{line}
		}
	} else if !bytes.HasPrefix(line, []byte("    ")) &&
		reHorizontalRule.Match(line) {
		return [][]byte{line}
	}
	b.L = append(b.L, line)
	return nil
}

type HorizontalRuleBlock struct{ BlockNeverContinue }

func (b *HorizontalRuleBlock) Detect(line, secondLine []byte) (consumed int) {
	if reHorizontalRule.Match(line) {
		b.L = [][]byte{line}
		return 1
	}
	return 0
}

type UnorderedListBlock struct {
	BlockBase
	Starter []byte
}

func (b *UnorderedListBlock) Detect(line, secondLine []byte) (consumed int) {
	m := reUnorderedList.FindSubmatch(line)
	if m == nil {
		return 0
	}
	b.L = [][]byte{line}
	b.Starter = m[1]
	return 1
}
func (b *UnorderedListBlock) Continue(line []byte) (reflux [][]byte) {
	if line == nil {
		return [][]byte{line}
	}

	prefix := len(b.Starter)
	if len(line) < prefix {
		prefix = len(line)
	}
	if isBlank(b.L[len(b.L)-1]) {
		if isBlank(line) {
			return [][]byte{line}
		}
		if !bytes.HasPrefix(line, b.Starter) &&
			// FIXME(akavel): spec refers to runes ("characters"), not bytes; fix this everywhere
			// has non-space chars in first prefix characters
			len(bytes.Trim(line[:prefix], " ")) > 0 {
			return [][]byte{line}
		}
	} else {
		if !bytes.HasPrefix(line, b.Starter) &&
			len(bytes.Trim(line[:prefix], " ")) > 0 &&
			!bytes.HasPrefix(line, []byte("    ")) {
			if reUnorderedList.Match(line) ||
				reOrderedList.Match(line) ||
				reHorizontalRule.Match(line) {
				return [][]byte{line}
			}
		}
	}
	b.L = append(b.L, line)
	return nil
}

type OrderedListBlock struct{}
type ParagraphBlock struct{}
<commit_msg>add OrderedListBlock<commit_after>package vfmd

import (
	"bytes"
	"regexp"
)

// TODO(akavel): add tests for blocks

type BlockSplitter struct {
}

func (b *BlockSplitter) WriteLine(line []byte) error {
	// TODO(akavel): NIY
	return nil
}

func (b *BlockSplitter) Close() error {
	// TODO(akavel): NIY
	return nil
}

type Block interface {
	// Detect checks if startLine and optionally secondLine signify start
	// of the particular Block kind. If negative, 0 should be returned.
	// If positive, number of lines needed to perform the detection
	// should be returned (1 if startLine was enough for detection, 2 if
	// secondLine was used too and belongs to the block). The further
	// lines after the returned number should be passed to Contine().
	//
	// Note: secondLine==nil means end of file/stream
	Detect(startLine, secondLine []byte) (consumedLines int)
	// Continue checks if the specified line may belong to the block, as
	// reported started by Detect. If the line is detected to be of a
	// next block, this line should be returned, preceded by any earlier
	// consumed lines that are now confirmed to be of the next block too.
	//
	// Note: line==nil means end of file/stream
	Continue(line []byte) (refluxLines [][]byte)
	Lines() [][]byte
}

var (
	reUnorderedList  = regexp.MustCompile(`^( *[\*\-\+] +)[^ ]`)
	reOrderedList    = regexp.MustCompile(`^( *([0-9]+)\. +)[^ ]`)
	reHorizontalRule = regexp.MustCompile(`^ *((\* *\* *\* *[\* ]*)|(\- *\- *\- *[\- ]*)|(_ *_ *_ *[_ ]*))$`)
)

func isBlank(line []byte) bool {
	return len(bytes.Trim(line, " \t")) == 0
}

type BlockBase struct{ L [][]byte }

func (b BlockBase) Lines() [][]byte { return b.L }
func (b BlockBase) LastLine() []byte {
	if len(b.L) == 0 {
		return nil
	}
	return b.L[len(b.L)-1]
}

type BlockNeverContinue struct{ BlockBase }

func (BlockNeverContinue) Continue(line []byte) (reflux [][]byte) {
	return [][]byte{line}
}

// static assertion of Block interface implementation by the listed types
var _ []Block = []Block{
	&NullBlock{},
	&ReferenceResolutionBlock{},
	&SetextHeaderBlock{},
	&CodeBlock{},
	&AtxHeaderBlock{},
	&QuoteBlock{},
	&HorizontalRuleBlock{},
	&UnorderedListBlock{},
	&OrderedListBlock{},
	// &ParagraphBlock{},
}

type NullBlock struct{ BlockNeverContinue }

func (b *NullBlock) Detect(line, secondLine []byte) (consumed int) {
	if isBlank(line) {
		b.L = [][]byte{line}
		return 1
	}
	return 0
}

type ReferenceResolutionBlock struct {
	BlockNeverContinue
	unprocessedReferenceID        []byte
	refValueSequence              []byte
	unprocessedUrl                []byte
	refDefinitionTrailingSequence []byte
}

func (b *ReferenceResolutionBlock) Detect(line, secondLine []byte) (consumed int) {
	if bytes.HasPrefix(line, []byte("    ")) {
		return 0
	}
	// TODO(akavel): move the regexp out of function, for speed (or cache it?)
	re := regexp.MustCompile(`^ *\[(([^\\\[\]\!]|\\.|\![^\[])*((\!\[([^\\\[\]]|\\.)*\](\[([^\\\[\]]|\\.)*\])?)?([^\\\[\]]|\\.)*)*)\] *:(.*)$`)
	m := re.FindSubmatch(line)
	if len(m) == 0 {
		return 0
	}
	b.unprocessedReferenceID = m[1]
	b.refValueSequence = m[9] // TODO(akavel): verify if right one
	re = regexp.MustCompile(`^ *([^ \<\>]+|\<[^\<\>]*\>)( .*)?$`)
	m = re.FindSubmatch(b.refValueSequence)
	if len(m) == 0 {
		return 0
	}
	b.unprocessedUrl = m[1]
	b.refDefinitionTrailingSequence = m[2]

	// Detected ok. Now check if 1 or 2 lines.
	b.L = [][]byte{line}
	re = regexp.MustCompile(`^ +("(([^"\\]|\\.)*)"|'(([^'\\]|\\.)*)'|\(([^\\\(\)]|\\.)*\)) *$`)
	if bytes.IndexAny(b.refDefinitionTrailingSequence, " ") == -1 &&
		secondLine != nil &&
		re.Match(secondLine) {
		b.L = [][]byte{line, secondLine}
	} else {
		b.L = [][]byte{line}
	}
	return len(b.L)
}

type SetextHeaderBlock struct {
	BlockNeverContinue
}

func (b *SetextHeaderBlock) Detect(line, secondLine []byte) (consumed int) {
	if secondLine == nil {
		return 0
	}
	re := regexp.MustCompile(`^(-+|=+) *$`)
	if re.Match(secondLine) {
		b.L = [][]byte{line, secondLine}
		return 2
	}
	return 0
}

type CodeBlock struct {
	BlockBase
	maybeEnd bool
}

func (b *CodeBlock) Detect(line, secondLine []byte) (consumed int) {
	if bytes.HasPrefix(line, []byte("    ")) {
		b.L = [][]byte{line}
		return 1
	}
	return 0
}
func (b *CodeBlock) Continue(line []byte) (reflux [][]byte) {
	if b.maybeEnd && !bytes.HasPrefix(line, []byte("    ")) {
		prev := b.LastLine()
		b.L = b.L[:len(b.L)-1]
		return [][]byte{prev, line}
	}
	blank := isBlank(line)
	if !blank && !bytes.HasPrefix(line, []byte("    ")) {
		return [][]byte{line}
	}
	b.maybeEnd = blank
	b.L = append(b.L, line)
	return nil
}

type AtxHeaderBlock struct{ BlockNeverContinue }

func (b *AtxHeaderBlock) Detect(line, secondLine []byte) (consumed int) {
	if bytes.HasPrefix(line, []byte("#")) {
		b.L = [][]byte{line}
		return 1
	}
	return 0
}

type QuoteBlock struct{ BlockBase }

func (b *QuoteBlock) Detect(line, secondLine []byte) (consumed int) {
	ltrim := bytes.TrimLeft(line, " ")
	if len(ltrim) > 0 && ltrim[0] == '>' {
		b.L = [][]byte{line}
		return 1
	}
	return 0
}
func (b *QuoteBlock) Continue(line []byte) (reflux [][]byte) {
	if line == nil {
		return [][]byte{line}
	}
	if isBlank(b.LastLine()) {
		if isBlank(line) ||
			bytes.HasPrefix(line, []byte("    ")) ||
			bytes.TrimLeft(line, " ")[0] != '>' {
			return [][]byte{line}
		}
	} else if !bytes.HasPrefix(line, []byte("    ")) &&
		reHorizontalRule.Match(line) {
		return [][]byte{line}
	}
	b.L = append(b.L, line)
	return nil
}

type HorizontalRuleBlock struct{ BlockNeverContinue }

func (b *HorizontalRuleBlock) Detect(line, secondLine []byte) (consumed int) {
	if reHorizontalRule.Match(line) {
		b.L = [][]byte{line}
		return 1
	}
	return 0
}

type UnorderedListBlock struct {
	BlockBase
	Starter []byte
}

func (b *UnorderedListBlock) Detect(line, secondLine []byte) (consumed int) {
	m := reUnorderedList.FindSubmatch(line)
	if m == nil {
		return 0
	}
	b.L = [][]byte{line}
	b.Starter = m[1]
	return 1
}
func (b *UnorderedListBlock) Continue(line []byte) (reflux [][]byte) {
	if line == nil {
		return [][]byte{line}
	}

	prefix := len(b.Starter)
	if len(line) < prefix {
		prefix = len(line)
	}
	if isBlank(b.LastLine()) {
		if isBlank(line) {
			return [][]byte{line}
		}
		if !bytes.HasPrefix(line, b.Starter) &&
			// FIXME(akavel): spec refers to runes ("characters"), not bytes; fix this everywhere
			// has non-space chars in first prefix characters
			len(bytes.Trim(line[:prefix], " ")) > 0 {
			return [][]byte{line}
		}
	} else {
		if !bytes.HasPrefix(line, b.Starter) &&
			len(bytes.Trim(line[:prefix], " ")) > 0 &&
			!bytes.HasPrefix(line, []byte("    ")) {
			if reUnorderedList.Match(line) ||
				reOrderedList.Match(line) ||
				reHorizontalRule.Match(line) {
				return [][]byte{line}
			}
		}
	}
	b.L = append(b.L, line)
	return nil
}

type OrderedListBlock struct {
	BlockBase
	Starter []byte
}

func (b *OrderedListBlock) Detect(line, secondLine []byte) (consumed int) {
	m := reOrderedList.FindSubmatch(line)
	if m == nil {
		return 0
	}
	b.L = [][]byte{line}
	b.Starter = m[1]
	return 1
}
func (b *OrderedListBlock) Continue(line []byte) (reflux [][]byte) {
	if line == nil {
		return [][]byte{line}
	}

	prefix := len(b.Starter)
	if len(line) < prefix {
		prefix = len(line)
	}
	if isBlank(b.LastLine()) {
		if isBlank(line) {
			return [][]byte{line}
		}
		if !reOrderedList.Match(line) &&
			// TODO(akavel): extract below pattern to hasNonSpaceInFirstChars(line, n)
			len(bytes.Trim(line[:prefix], " ")) > 0 {
			return [][]byte{line}
		}
	} else {
		if !reOrderedList.Match(line) &&
			len(bytes.Trim(line[:prefix], " ")) > 0 &&
			!bytes.HasPrefix(line, []byte("    ")) {
			if reUnorderedList.Match(line) ||
				reHorizontalRule.Match(line) {
				return [][]byte{line}
			}
		}
	}
	b.L = append(b.L, line)
	return nil
}

type ParagraphBlock struct{ BlockBase }

func (b *ParagraphBlock) Detect(line, secondLine []byte) (consumed int) {
	b.L = append(b.L, line)
	return 1
}
<|endoftext|>


<commit_before>package core

import (
	"github.com/grooveshark/golib/gslog"
	"strings"

	"github.com/mediocregopher/hyrax/server/auth"
	"github.com/mediocregopher/hyrax/server/config"
	"github.com/mediocregopher/hyrax/server/core/dist"
	"github.com/mediocregopher/hyrax/server/listen"
	"github.com/mediocregopher/hyrax/translate"
	"github.com/mediocregopher/hyrax/types"
)

// Does all configuration for the hyrax node
func Configure() error {
	if err := gslog.SetLogFile(config.LogFile); err != nil {
		return err
	}
	if err := gslog.SetMinimumLevel(config.LogLevel); err != nil {
		return err
	}

	secrets := config.InitSecrets
	gslog.Info("Loading up the secrets")
	for _, secret := range secrets {
		auth.AddGlobalSecret(secret)
	}

	if err := SetupStorage(); err != nil {
		return err
	}

	listens := config.ListenEndpoints
	for i := range listens {
		if err := listenHandler(listens[i]); err != nil {
			return err
		}
	}

	if err := dist.Clusterize(); err != nil {
		return err
	}

	return nil
}

func listenHandler(l *types.ListenEndpoint) error {
	// TODO we need to store these somewhere so we can close them when we're
	// done
	trans, err := translate.StringToTranslator(l.Format)
	if err != nil {
		gslog.Fatal(err.Error())
	}

	switch strings.ToLower(l.Type) {
	case "tcp":
		if err := listen.TcpListen(l.Addr, trans); err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>slightly better logging<commit_after>package core

import (
	"github.com/grooveshark/golib/gslog"
	"strings"

	"github.com/mediocregopher/hyrax/server/auth"
	"github.com/mediocregopher/hyrax/server/config"
	"github.com/mediocregopher/hyrax/server/core/dist"
	"github.com/mediocregopher/hyrax/server/listen"
	"github.com/mediocregopher/hyrax/translate"
	"github.com/mediocregopher/hyrax/types"
)

// Does all configuration for the hyrax node
func Configure() error {
	if err := gslog.SetMinimumLevel(config.LogLevel); err != nil {
		return err
	}
	gslog.Infof("Setting logging point to %s", config.LogFile)
	if err := gslog.SetLogFile(config.LogFile); err != nil {
		return err
	}

	secrets := config.InitSecrets
	gslog.Info("Loading up the secrets")
	for _, secret := range secrets {
		auth.AddGlobalSecret(secret)
	}

	if err := SetupStorage(); err != nil {
		return err
	}

	listens := config.ListenEndpoints
	for i := range listens {
		if err := listenHandler(listens[i]); err != nil {
			return err
		}
	}

	if err := dist.Clusterize(); err != nil {
		return err
	}

	return nil
}

func listenHandler(l *types.ListenEndpoint) error {
	// TODO we need to store these somewhere so we can close them when we're
	// done
	trans, err := translate.StringToTranslator(l.Format)
	if err != nil {
		gslog.Fatal(err.Error())
	}

	switch strings.ToLower(l.Type) {
	case "tcp":
		if err := listen.TcpListen(l.Addr, trans); err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package actors_test

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"

	"github.com/cloudfoundry/cli/cf/actors"
	fakeBits "github.com/cloudfoundry/cli/cf/api/application_bits/fakes"
	"github.com/cloudfoundry/cli/cf/api/resources"
	"github.com/cloudfoundry/cli/cf/app_files"
	"github.com/cloudfoundry/cli/cf/app_files/fakes"
	"github.com/cloudfoundry/cli/cf/models"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Push Actor", func() {
	var (
		appBitsRepo  *fakeBits.FakeApplicationBitsRepository
		appFiles     *fakes.FakeAppFiles
		fakezipper   *fakes.FakeZipper
		actor        actors.PushActor
		fixturesDir  string
		appDir       string
		allFiles     []models.AppFileFields
		presentFiles []resources.AppFileResource
	)

	BeforeEach(func() {
		appBitsRepo = &fakeBits.FakeApplicationBitsRepository{}
		appFiles = &fakes.FakeAppFiles{}
		fakezipper = &fakes.FakeZipper{}
		actor = actors.NewPushActor(appBitsRepo, fakezipper, appFiles)
		fixturesDir = filepath.Join("..", "..", "fixtures", "applications")
		allFiles = []models.AppFileFields{
			models.AppFileFields{Path: "example-app/.cfignore"},
			models.AppFileFields{Path: "example-app/app.rb"},
			models.AppFileFields{Path: "example-app/config.ru"},
			models.AppFileFields{Path: "example-app/Gemfile"},
			models.AppFileFields{Path: "example-app/Gemfile.lock"},
			models.AppFileFields{Path: "example-app/ignore-me"},
			models.AppFileFields{Path: "example-app/manifest.yml"},
		}
	})

	Describe("GatherFiles", func() {
		var tmpDir string

		BeforeEach(func() {
			presentFiles = []resources.AppFileResource{
				resources.AppFileResource{Path: "example-app/ignore-me"},
			}

			appDir = filepath.Join(fixturesDir, "example-app.zip")
			appFiles.AppFilesInDirReturns(allFiles, nil)
			appBitsRepo.GetApplicationFilesReturns(presentFiles, nil)
			var err error
			tmpDir, err = ioutil.TempDir("", "gather-files")
			Expect(err).NotTo(HaveOccurred())
		})

		AfterEach(func() {
			os.RemoveAll(tmpDir)
		})

		It("returns files to upload with file mode unchanged", func() {
			if runtime.GOOS == "windows" {
				Skip("This does not run on windows")
			}

			info, err := os.Lstat(filepath.Join(fixturesDir, "example-app/ignore-me"))
			Expect(err).NotTo(HaveOccurred())

			expectedFileMode := fmt.Sprintf("%#o", info.Mode())

			actualFiles, _, err := actor.GatherFiles(fixturesDir, tmpDir)
			Expect(err).NotTo(HaveOccurred())

			expectedFiles := []resources.AppFileResource{
				resources.AppFileResource{
					Path: "example-app/ignore-me",
					Mode: expectedFileMode,
				},
			}

			Expect(actualFiles).To(Equal(expectedFiles))
		})

		It("returns files to upload with file mode always being executable", func() {
			if runtime.GOOS != "windows" {
				Skip("This runs only on windows")
			}

			info, err := os.Lstat(filepath.Join(fixturesDir, "example-app/ignore-me"))
			Expect(err).NotTo(HaveOccurred())

			expectedFileMode := fmt.Sprintf("%#o", info.Mode()|0700)

			actualFiles, _, err := actor.GatherFiles(fixturesDir, tmpDir)
			Expect(err).NotTo(HaveOccurred())

			expectedFiles := []resources.AppFileResource{
				resources.AppFileResource{
					Path: "example-app/ignore-me",
					Mode: expectedFileMode,
				},
			}

			Expect(actualFiles).To(Equal(expectedFiles))
		})

		It("returns an error if it cannot walk the files", func() {
			appFiles.AppFilesInDirReturns(nil, errors.New("error"))
			_, _, err := actor.GatherFiles(appDir, tmpDir)
			Expect(err).To(HaveOccurred())
		})

		It("returns an error if we cannot reach the cc", func() {
			appBitsRepo.GetApplicationFilesReturns(nil, errors.New("error"))
			_, _, err := actor.GatherFiles(appDir, tmpDir)
			Expect(err).To(HaveOccurred())
		})

		Context("when using .cfignore", func() {
			BeforeEach(func() {
				appBitsRepo.GetApplicationFilesReturns(nil, nil)
				appDir = filepath.Join(fixturesDir, "exclude-a-default-cfignore")
			})

			It("includes the .cfignore file in the upload directory", func() {
				files, _, err := actor.GatherFiles(appDir, tmpDir)
				Expect(err).NotTo(HaveOccurred())

				_, err = os.Stat(filepath.Join(tmpDir, ".cfignore"))
				Expect(os.IsNotExist(err)).To(BeFalse())
				Expect(len(files)).To(Equal(0))
			})
		})
	})

	Describe(".UploadApp", func() {
		It("Simply delegates to the UploadApp function on the app bits repo, which is not worth testing", func() {})
	})

	Describe("ProcessPath", func() {
		var (
			wasCalled     bool
			wasCalledWith string
		)

		BeforeEach(func() {
			zipper := &app_files.ApplicationZipper{}
			actor = actors.NewPushActor(appBitsRepo, zipper, appFiles)
		})

		Context("when given a zip file", func() {
			var zipFile string

			BeforeEach(func() {
				zipFile = filepath.Join(fixturesDir, "example-app.zip")
			})

			It("extracts the zip when given a zip file", func() {
				f := func(tempDir string) {
					for _, file := range allFiles {
						actualFilePath := filepath.Join(tempDir, file.Path)
						_, err := os.Stat(actualFilePath)
						Expect(err).NotTo(HaveOccurred())
					}
				}
				err := actor.ProcessPath(zipFile, f)
				Expect(err).NotTo(HaveOccurred())
			})

			It("calls the provided function with the directory that it extracted to", func() {
				f := func(tempDir string) {
					wasCalled = true
					wasCalledWith = tempDir
				}
				err := actor.ProcessPath(zipFile, f)
				Expect(err).NotTo(HaveOccurred())
				Expect(wasCalled).To(BeTrue())
				Expect(wasCalledWith).NotTo(Equal(zipFile))
			})

			It("cleans up the directory that it extracted to", func() {
				var tempDirWas string
				f := func(tempDir string) {
					tempDirWas = tempDir
				}
				err := actor.ProcessPath(zipFile, f)
				Expect(err).NotTo(HaveOccurred())
				_, err = os.Stat(tempDirWas)
				Expect(err).To(HaveOccurred())
			})

			It("returns an error if the unzipping fails", func() {
				e := errors.New("some-error")
				fakezipper.UnzipReturns(e)
				fakezipper.IsZipFileReturns(true)
				actor = actors.NewPushActor(appBitsRepo, fakezipper, appFiles)

				f := func(tempDir string) {}
				err := actor.ProcessPath(zipFile, f)
				Expect(err).To(HaveOccurred())
			})
		})

		It("calls the provided function with the provided directory", func() {
			appDir = filepath.Join(fixturesDir, "example-app")
			f := func(tempDir string) {
				wasCalled = true
				wasCalledWith = tempDir
			}
			err := actor.ProcessPath(appDir, f)
			Expect(err).NotTo(HaveOccurred())
			Expect(wasCalled).To(BeTrue())
			Expect(wasCalledWith).To(Equal(appDir))
		})
	})
})
<commit_msg>Backfill Push actor tests<commit_after>package actors_test

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"

	"github.com/cloudfoundry/cli/cf/actors"
	fakeBits "github.com/cloudfoundry/cli/cf/api/application_bits/fakes"
	"github.com/cloudfoundry/cli/cf/api/resources"
	"github.com/cloudfoundry/cli/cf/app_files"
	"github.com/cloudfoundry/cli/cf/app_files/fakes"
	"github.com/cloudfoundry/cli/cf/models"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Push Actor", func() {
	var (
		appBitsRepo  *fakeBits.FakeApplicationBitsRepository
		appFiles     *fakes.FakeAppFiles
		fakezipper   *fakes.FakeZipper
		actor        actors.PushActor
		fixturesDir  string
		appDir       string
		allFiles     []models.AppFileFields
		presentFiles []resources.AppFileResource
	)

	BeforeEach(func() {
		appBitsRepo = &fakeBits.FakeApplicationBitsRepository{}
		appFiles = &fakes.FakeAppFiles{}
		fakezipper = &fakes.FakeZipper{}
		actor = actors.NewPushActor(appBitsRepo, fakezipper, appFiles)
		fixturesDir = filepath.Join("..", "..", "fixtures", "applications")
		allFiles = []models.AppFileFields{
			models.AppFileFields{Path: "example-app/.cfignore"},
			models.AppFileFields{Path: "example-app/app.rb"},
			models.AppFileFields{Path: "example-app/config.ru"},
			models.AppFileFields{Path: "example-app/Gemfile"},
			models.AppFileFields{Path: "example-app/Gemfile.lock"},
			models.AppFileFields{Path: "example-app/ignore-me"},
			models.AppFileFields{Path: "example-app/manifest.yml"},
		}
	})

	Describe("GatherFiles", func() {
		var tmpDir string

		BeforeEach(func() {
			presentFiles = []resources.AppFileResource{
				resources.AppFileResource{Path: "example-app/ignore-me"},
			}

			appDir = filepath.Join(fixturesDir, "example-app.zip")
			appFiles.AppFilesInDirReturns(allFiles, nil)
			appBitsRepo.GetApplicationFilesReturns(presentFiles, nil)
			var err error
			tmpDir, err = ioutil.TempDir("", "gather-files")
			Expect(err).NotTo(HaveOccurred())
		})

		AfterEach(func() {
			os.RemoveAll(tmpDir)
		})

		Context("when we cannot get the app files", func() {
			var expectedErr error

			BeforeEach(func() {
				expectedErr = errors.New("error")
				appFiles.AppFilesInDirReturns(nil, expectedErr)
			})

			It("returns an error", func() {
				_, _, err := actor.GatherFiles(appDir, tmpDir)
				Expect(err).To(HaveOccurred())
				Expect(err).To(Equal(expectedErr))
			})
		})

		Context("when we cannot reach CC", func() {
			var expectedErr error

			BeforeEach(func() {
				expectedErr = errors.New("error")
				appBitsRepo.GetApplicationFilesReturns(nil, expectedErr)
			})

			It("returns an error if we cannot reach the cc", func() {
				_, _, err := actor.GatherFiles(appDir, tmpDir)
				Expect(err).To(HaveOccurred())
				Expect(err).To(Equal(expectedErr))
			})
		})

		Context("when we cannot copy the app files", func() {
			var expectedErr error

			BeforeEach(func() {
				expectedErr = errors.New("error")
				appFiles.CopyFilesReturns(expectedErr)
			})

			It("returns an error", func() {
				_, _, err := actor.GatherFiles(appDir, tmpDir)
				Expect(err).To(HaveOccurred())
				Expect(err).To(Equal(expectedErr))
			})
		})

		Context("when using .cfignore", func() {
			BeforeEach(func() {
				appDir = filepath.Join(fixturesDir, "exclude-a-default-cfignore")
				// Ignore app files for this test as .cfignore is not one of them
				appBitsRepo.GetApplicationFilesReturns(nil, nil)
			})

			It("copies the .cfignore file to the upload directory", func() {
				_, _, err := actor.GatherFiles(appDir, tmpDir)
				Expect(err).NotTo(HaveOccurred())

				_, err = os.Stat(filepath.Join(tmpDir, ".cfignore"))
				Expect(os.IsNotExist(err)).To(BeFalse())
			})
		})

		It("returns files to upload with file mode unchanged on non-Windows platforms", func() {
			if runtime.GOOS == "windows" {
				Skip("This does not run on windows")
			}

			info, err := os.Lstat(filepath.Join(fixturesDir, "example-app/ignore-me"))
			Expect(err).NotTo(HaveOccurred())

			expectedFileMode := fmt.Sprintf("%#o", info.Mode())

			actualFiles, _, err := actor.GatherFiles(fixturesDir, tmpDir)
			Expect(err).NotTo(HaveOccurred())

			expectedFiles := []resources.AppFileResource{
				resources.AppFileResource{
					Path: "example-app/ignore-me",
					Mode: expectedFileMode,
				},
			}

			Expect(actualFiles).To(Equal(expectedFiles))
		})

		It("returns files to upload with file mode always being executable on Windows platforms", func() {
			if runtime.GOOS != "windows" {
				Skip("This runs only on windows")
			}

			info, err := os.Lstat(filepath.Join(fixturesDir, "example-app/ignore-me"))
			Expect(err).NotTo(HaveOccurred())

			expectedFileMode := fmt.Sprintf("%#o", info.Mode()|0700)

			actualFiles, _, err := actor.GatherFiles(fixturesDir, tmpDir)
			Expect(err).NotTo(HaveOccurred())

			expectedFiles := []resources.AppFileResource{
				resources.AppFileResource{
					Path: "example-app/ignore-me",
					Mode: expectedFileMode,
				},
			}

			Expect(actualFiles).To(Equal(expectedFiles))
		})
	})

	Describe(".UploadApp", func() {
		It("Simply delegates to the UploadApp function on the app bits repo, which is not worth testing", func() {})
	})

	Describe("ProcessPath", func() {
		var (
			wasCalled     bool
			wasCalledWith string
		)

		BeforeEach(func() {
			zipper := &app_files.ApplicationZipper{}
			actor = actors.NewPushActor(appBitsRepo, zipper, appFiles)
		})

		Context("when given a zip file", func() {
			var zipFile string

			BeforeEach(func() {
				zipFile = filepath.Join(fixturesDir, "example-app.zip")
			})

			It("extracts the zip when given a zip file", func() {
				f := func(tempDir string) {
					for _, file := range allFiles {
						actualFilePath := filepath.Join(tempDir, file.Path)
						_, err := os.Stat(actualFilePath)
						Expect(err).NotTo(HaveOccurred())
					}
				}
				err := actor.ProcessPath(zipFile, f)
				Expect(err).NotTo(HaveOccurred())
			})

			It("calls the provided function with the directory that it extracted to", func() {
				f := func(tempDir string) {
					wasCalled = true
					wasCalledWith = tempDir
				}
				err := actor.ProcessPath(zipFile, f)
				Expect(err).NotTo(HaveOccurred())
				Expect(wasCalled).To(BeTrue())
				Expect(wasCalledWith).NotTo(Equal(zipFile))
			})

			It("cleans up the directory that it extracted to", func() {
				var tempDirWas string
				f := func(tempDir string) {
					tempDirWas = tempDir
				}
				err := actor.ProcessPath(zipFile, f)
				Expect(err).NotTo(HaveOccurred())
				_, err = os.Stat(tempDirWas)
				Expect(err).To(HaveOccurred())
			})

			It("returns an error if the unzipping fails", func() {
				e := errors.New("some-error")
				fakezipper.UnzipReturns(e)
				fakezipper.IsZipFileReturns(true)
				actor = actors.NewPushActor(appBitsRepo, fakezipper, appFiles)

				f := func(tempDir string) {}
				err := actor.ProcessPath(zipFile, f)
				Expect(err).To(HaveOccurred())
			})
		})

		It("calls the provided function with the provided directory", func() {
			appDir = filepath.Join(fixturesDir, "example-app")
			f := func(tempDir string) {
				wasCalled = true
				wasCalledWith = tempDir
			}
			err := actor.ProcessPath(appDir, f)
			Expect(err).NotTo(HaveOccurred())
			Expect(wasCalled).To(BeTrue())
			Expect(wasCalledWith).To(Equal(appDir))
		})
	})
})
<|endoftext|>


<commit_before>package constants

const (
	// Version is the current version of picfit
	Version = "0.8.0"
)

var (
	// Branch is the compiled branch
	Branch string

	// Revision is the compiled revision
	Revision string

	// LatestCommitMessage is the latest commit message
	LatestCommitMessage string

	// BuildTime is the compiled build time
	BuildTime string

	// Compiler is the compiler used during build
	Compiler string
)

const (
	BottomLeft  = "bottom-left"
	BottomRight = "bottom-right"
	TopLeft     = "top-left"
	TopRight    = "top-right"
)

var StickPositions = []string{
	BottomLeft,
	BottomRight,
	TopLeft,
	TopRight,
}
<commit_msg>chore: bump version<commit_after>package constants

const (
	// Version is the current version of picfit
	Version = "0.9.0"
)

var (
	// Branch is the compiled branch
	Branch string

	// Revision is the compiled revision
	Revision string

	// LatestCommitMessage is the latest commit message
	LatestCommitMessage string

	// BuildTime is the compiled build time
	BuildTime string

	// Compiler is the compiler used during build
	Compiler string
)

const (
	BottomLeft  = "bottom-left"
	BottomRight = "bottom-right"
	TopLeft     = "top-left"
	TopRight    = "top-right"
)

var StickPositions = []string{
	BottomLeft,
	BottomRight,
	TopLeft,
	TopRight,
}
<|endoftext|>


<commit_before>package state

import (
	"fmt"

	"github.com/hashicorp/go-memdb"
)

// schemaFn is an interface function used to create and return
// new memdb schema structs for constructing an in-memory db.
type schemaFn func() *memdb.TableSchema

// stateStoreSchema is used to return the combined schema for
// the state store.
func stateStoreSchema() *memdb.DBSchema {
	// Create the root DB schema
	db := &memdb.DBSchema{
		Tables: make(map[string]*memdb.TableSchema),
	}

	// Collect the needed schemas
	schemas := []schemaFn{
		indexTableSchema,
		nodesTableSchema,
		servicesTableSchema,
		checksTableSchema,
		kvsTableSchema,
		tombstonesTableSchema,
		sessionsTableSchema,
		sessionChecksTableSchema,
		aclsTableSchema,
		coordinatesTableSchema,
		preparedQueriesTableSchema,
	}

	// Add the tables to the root schema
	for _, fn := range schemas {
		schema := fn()
		if _, ok := db.Tables[schema.Name]; ok {
			panic(fmt.Sprintf("duplicate table name: %s", schema.Name))
		}
		db.Tables[schema.Name] = schema
	}
	return db
}

// indexTableSchema returns a new table schema used for
// tracking various indexes for the Raft log.
func indexTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "index",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Key",
					Lowercase: true,
				},
			},
		},
	}
}

// nodesTableSchema returns a new table schema used for
// storing node information.
func nodesTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "nodes",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Node",
					Lowercase: true,
				},
			},
		},
	}
}

// servicesTableSchema returns a new TableSchema used to
// store information about services.
func servicesTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "services",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "Node",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "ServiceID",
							Lowercase: true,
						},
					},
				},
			},
			"node": &memdb.IndexSchema{
				Name:         "node",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Node",
					Lowercase: true,
				},
			},
			"service": &memdb.IndexSchema{
				Name:         "service",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "ServiceName",
					Lowercase: true,
				},
			},
		},
	}
}

// checksTableSchema returns a new table schema used for
// storing and indexing health check information. Health
// checks have a number of different attributes we want to
// filter by, so this table is a bit more complex.
func checksTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "checks",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "Node",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "CheckID",
							Lowercase: true,
						},
					},
				},
			},
			"status": &memdb.IndexSchema{
				Name:         "status",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Status",
					Lowercase: false,
				},
			},
			"service": &memdb.IndexSchema{
				Name:         "service",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "ServiceName",
					Lowercase: true,
				},
			},
			"node": &memdb.IndexSchema{
				Name:         "node",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Node",
					Lowercase: true,
				},
			},
			"node_service": &memdb.IndexSchema{
				Name:         "node_service",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "Node",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "ServiceID",
							Lowercase: true,
						},
					},
				},
			},
		},
	}
}

// kvsTableSchema returns a new table schema used for storing
// key/value data from consul's kv store.
func kvsTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "kvs",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Key",
					Lowercase: false,
				},
			},
			"session": &memdb.IndexSchema{
				Name:         "session",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "Session",
				},
			},
		},
	}
}

// tombstonesTableSchema returns a new table schema used for
// storing tombstones during KV delete operations to prevent
// the index from sliding backwards.
func tombstonesTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "tombstones",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Key",
					Lowercase: false,
				},
			},
		},
	}
}

// sessionsTableSchema returns a new TableSchema used for
// storing session information.
func sessionsTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "sessions",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "ID",
				},
			},
			"node": &memdb.IndexSchema{
				Name:         "node",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Node",
					Lowercase: true,
				},
			},
		},
	}
}

// sessionChecksTableSchema returns a new table schema used
// for storing session checks.
func sessionChecksTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "session_checks",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "Node",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "CheckID",
							Lowercase: true,
						},
						&memdb.UUIDFieldIndex{
							Field: "Session",
						},
					},
				},
			},
			"node_check": &memdb.IndexSchema{
				Name:         "node_check",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "Node",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "CheckID",
							Lowercase: true,
						},
					},
				},
			},
			"session": &memdb.IndexSchema{
				Name:         "session",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "Session",
				},
			},
		},
	}
}

// aclsTableSchema returns a new table schema used for
// storing ACL information.
func aclsTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "acls",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "ID",
					Lowercase: false,
				},
			},
		},
	}
}

// coordinatesTableSchema returns a new table schema used for storing
// network coordinates.
func coordinatesTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "coordinates",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Node",
					Lowercase: true,
				},
			},
		},
	}
}

// preparedQueriesTableSchema returns a new table schema used for storing
// prepared queries.
func preparedQueriesTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "prepared-queries",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "ID",
				},
			},
			"name": &memdb.IndexSchema{
				Name:         "name",
				AllowMissing: true,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Name",
					Lowercase: true,
				},
			},
			"session": &memdb.IndexSchema{
				Name:         "session",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "Session",
				},
			},
		},
	}
}
<commit_msg>one line schema change to not allow missing for sessions Table node index, Fixes #1774<commit_after>package state

import (
	"fmt"

	"github.com/hashicorp/go-memdb"
)

// schemaFn is an interface function used to create and return
// new memdb schema structs for constructing an in-memory db.
type schemaFn func() *memdb.TableSchema

// stateStoreSchema is used to return the combined schema for
// the state store.
func stateStoreSchema() *memdb.DBSchema {
	// Create the root DB schema
	db := &memdb.DBSchema{
		Tables: make(map[string]*memdb.TableSchema),
	}

	// Collect the needed schemas
	schemas := []schemaFn{
		indexTableSchema,
		nodesTableSchema,
		servicesTableSchema,
		checksTableSchema,
		kvsTableSchema,
		tombstonesTableSchema,
		sessionsTableSchema,
		sessionChecksTableSchema,
		aclsTableSchema,
		coordinatesTableSchema,
		preparedQueriesTableSchema,
	}

	// Add the tables to the root schema
	for _, fn := range schemas {
		schema := fn()
		if _, ok := db.Tables[schema.Name]; ok {
			panic(fmt.Sprintf("duplicate table name: %s", schema.Name))
		}
		db.Tables[schema.Name] = schema
	}
	return db
}

// indexTableSchema returns a new table schema used for
// tracking various indexes for the Raft log.
func indexTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "index",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Key",
					Lowercase: true,
				},
			},
		},
	}
}

// nodesTableSchema returns a new table schema used for
// storing node information.
func nodesTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "nodes",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Node",
					Lowercase: true,
				},
			},
		},
	}
}

// servicesTableSchema returns a new TableSchema used to
// store information about services.
func servicesTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "services",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "Node",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "ServiceID",
							Lowercase: true,
						},
					},
				},
			},
			"node": &memdb.IndexSchema{
				Name:         "node",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Node",
					Lowercase: true,
				},
			},
			"service": &memdb.IndexSchema{
				Name:         "service",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "ServiceName",
					Lowercase: true,
				},
			},
		},
	}
}

// checksTableSchema returns a new table schema used for
// storing and indexing health check information. Health
// checks have a number of different attributes we want to
// filter by, so this table is a bit more complex.
func checksTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "checks",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "Node",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "CheckID",
							Lowercase: true,
						},
					},
				},
			},
			"status": &memdb.IndexSchema{
				Name:         "status",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Status",
					Lowercase: false,
				},
			},
			"service": &memdb.IndexSchema{
				Name:         "service",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "ServiceName",
					Lowercase: true,
				},
			},
			"node": &memdb.IndexSchema{
				Name:         "node",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Node",
					Lowercase: true,
				},
			},
			"node_service": &memdb.IndexSchema{
				Name:         "node_service",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "Node",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "ServiceID",
							Lowercase: true,
						},
					},
				},
			},
		},
	}
}

// kvsTableSchema returns a new table schema used for storing
// key/value data from consul's kv store.
func kvsTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "kvs",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Key",
					Lowercase: false,
				},
			},
			"session": &memdb.IndexSchema{
				Name:         "session",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "Session",
				},
			},
		},
	}
}

// tombstonesTableSchema returns a new table schema used for
// storing tombstones during KV delete operations to prevent
// the index from sliding backwards.
func tombstonesTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "tombstones",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Key",
					Lowercase: false,
				},
			},
		},
	}
}

// sessionsTableSchema returns a new TableSchema used for
// storing session information.
func sessionsTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "sessions",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "ID",
				},
			},
			"node": &memdb.IndexSchema{
				Name:         "node",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Node",
					Lowercase: true,
				},
			},
		},
	}
}

// sessionChecksTableSchema returns a new table schema used
// for storing session checks.
func sessionChecksTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "session_checks",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "Node",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "CheckID",
							Lowercase: true,
						},
						&memdb.UUIDFieldIndex{
							Field: "Session",
						},
					},
				},
			},
			"node_check": &memdb.IndexSchema{
				Name:         "node_check",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "Node",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "CheckID",
							Lowercase: true,
						},
					},
				},
			},
			"session": &memdb.IndexSchema{
				Name:         "session",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "Session",
				},
			},
		},
	}
}

// aclsTableSchema returns a new table schema used for
// storing ACL information.
func aclsTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "acls",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "ID",
					Lowercase: false,
				},
			},
		},
	}
}

// coordinatesTableSchema returns a new table schema used for storing
// network coordinates.
func coordinatesTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "coordinates",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Node",
					Lowercase: true,
				},
			},
		},
	}
}

// preparedQueriesTableSchema returns a new table schema used for storing
// prepared queries.
func preparedQueriesTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "prepared-queries",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "ID",
				},
			},
			"name": &memdb.IndexSchema{
				Name:         "name",
				AllowMissing: true,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Name",
					Lowercase: true,
				},
			},
			"session": &memdb.IndexSchema{
				Name:         "session",
				AllowMissing: true,
				Unique:       false,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "Session",
				},
			},
		},
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package container

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

var (
	ContainerDir        = "/var/lib/juju/containers"
	RemovedContainerDir = "/var/lib/juju/removed-containers"
)

// NewDirectory creates a new directory for the container name in the
// directory identified by `ContainerDir`.
func NewDirectory(containerName string) (directory string, err error) {
	directory = jujuContainerDirectory(containerName)
	logger.Tracef("create directory: %s", directory)
	if err = os.MkdirAll(directory, 0755); err != nil {
		logger.Errorf("failed to create container directory: %v", err)
		return "", err
	}
	return directory, nil
}

// RemoveDirectory moves the container directory from `ContainerDir`
// to `RemovedContainerDir` and makes sure that the names don't clash.
func RemoveDirectory(containerName string) error {
	// Move the directory.
	logger.Tracef("create old container dir: %s", RemovedContainerDir)
	if err := os.MkdirAll(RemovedContainerDir, 0755); err != nil {
		logger.Errorf("failed to create removed container directory: %v", err)
		return err
	}
	removedDir, err := uniqueDirectory(RemovedContainerDir, containerName)
	if err != nil {
		logger.Errorf("was not able to generate a unique directory: %v", err)
		return err
	}
	if err := os.Rename(jujuContainerDirectory(containerName), removedDir); err != nil {
		logger.Errorf("failed to rename container directory: %v", err)
		return err
	}
	return nil

}

func jujuContainerDirectory(containerName string) string {
	return filepath.Join(ContainerDir, containerName)
}

// uniqueDirectory returns "path/name" if that directory doesn't exist.  If it
// does, the method starts appending .1, .2, etc until a unique name is found.
func uniqueDirectory(path, name string) (string, error) {
	dir := filepath.Join(path, name)
	_, err := os.Stat(dir)
	if os.IsNotExist(err) {
		return dir, nil
	}
	for i := 1; ; i++ {
		dir := filepath.Join(path, fmt.Sprintf("%s.%d", name, i))
		_, err := os.Stat(dir)
		if os.IsNotExist(err) {
			return dir, nil
		} else if err != nil {
			return "", err
		}
	}
}
<commit_msg>s/jujuContainerDirectory/dirForName/<commit_after>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package container

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

var (
	ContainerDir        = "/var/lib/juju/containers"
	RemovedContainerDir = "/var/lib/juju/removed-containers"
)

// NewDirectory creates a new directory for the container name in the
// directory identified by `ContainerDir`.
func NewDirectory(containerName string) (directory string, err error) {
	directory = dirForName(containerName)
	logger.Tracef("create directory: %s", directory)
	if err = os.MkdirAll(directory, 0755); err != nil {
		logger.Errorf("failed to create container directory: %v", err)
		return "", err
	}
	return directory, nil
}

// RemoveDirectory moves the container directory from `ContainerDir`
// to `RemovedContainerDir` and makes sure that the names don't clash.
func RemoveDirectory(containerName string) error {
	// Move the directory.
	logger.Tracef("create old container dir: %s", RemovedContainerDir)
	if err := os.MkdirAll(RemovedContainerDir, 0755); err != nil {
		logger.Errorf("failed to create removed container directory: %v", err)
		return err
	}
	removedDir, err := uniqueDirectory(RemovedContainerDir, containerName)
	if err != nil {
		logger.Errorf("was not able to generate a unique directory: %v", err)
		return err
	}
	if err := os.Rename(dirForName(containerName), removedDir); err != nil {
		logger.Errorf("failed to rename container directory: %v", err)
		return err
	}
	return nil

}

func dirForName(containerName string) string {
	return filepath.Join(ContainerDir, containerName)
}

// uniqueDirectory returns "path/name" if that directory doesn't exist.  If it
// does, the method starts appending .1, .2, etc until a unique name is found.
func uniqueDirectory(path, name string) (string, error) {
	dir := filepath.Join(path, name)
	_, err := os.Stat(dir)
	if os.IsNotExist(err) {
		return dir, nil
	}
	for i := 1; ; i++ {
		dir := filepath.Join(path, fmt.Sprintf("%s.%d", name, i))
		_, err := os.Stat(dir)
		if os.IsNotExist(err) {
			return dir, nil
		} else if err != nil {
			return "", err
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.

package server

import (
	"net/http"
	"strings"
	"testing"
	"time"
)

func TestServer(t *testing.T) {
	LoadConfig("config-push-proxy.json")
	Start()

	msg := PushNotification{}
	msg.Platform = PUSH_NOTIFY_APPLE
	msg.Message = "test"
	msg.Badge = 1
	msg.DeviceId = "test"
	msg.ServerId = "test"

	client := http.Client{}
	rq, _ := http.NewRequest("POST", "http://localhost:8066/api/v1/send_push", strings.NewReader(msg.ToJson()))

	if _, err := client.Do(rq); err != nil {
		t.Fatal(err)
	}

	time.Sleep(time.Second * 2)
	Stop()
}
<commit_msg>Fixing build<commit_after>// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.

package server

import (
	"net/http"
	"strings"
	"testing"
	"time"
)

func TestServer(t *testing.T) {
	LoadConfig("config-push-proxy.json")
	Start()
	time.Sleep(time.Second * 2)

	msg := PushNotification{}
	msg.Platform = PUSH_NOTIFY_APPLE
	msg.Message = "test"
	msg.Badge = 1
	msg.DeviceId = "test"
	msg.ServerId = "test"

	client := http.Client{}
	rq, _ := http.NewRequest("POST", "http://localhost:8066/api/v1/send_push", strings.NewReader(msg.ToJson()))

	if _, err := client.Do(rq); err != nil {
		t.Fatal(err)
	}

	Stop()
}
<|endoftext|>


<commit_before>package language

import "fmt"

func main() {
	sound := RandomSound()
	fmt.Println(sound)
}
<commit_msg>Worked on SoundPattern<commit_after>package language

import "fmt"

func main() {
	sound := RandomSound()
	fmt.Println(sound)
}

type TristateBool byte

const (
	TristateFalse TristateBool = iota
	TristateTrue
	TristateUnknown
)

type SoundPattern struct {
	Points  []ArticulationPoint
	Manners []ArticulationManner
	Shapes  []TongueShape
	Rounded TristateBool
	Nasal   TristateBool
	Voices  []Voice
}

func (pattern *SoundPattern) Fits(sound Sound) bool {
	if pattern.Points != nil && !containsPoint(pattern.Points, sound.Point) {
		return false
	}
	if pattern.Manners != nil && !containsManner(pattern.Manners, sound.Manner) {
		return false
	}
	if pattern.Shapes != nil && !containsShape(pattern.Shapes, sound.Shape) {
		return false
	}
	if pattern.Voices != nil && !containsVoice(pattern.Voices, sound.Voice) {
		return false
	}
	if pattern.Rounded != TristateUnknown && pattern.Rounded.ToBool() != sound.Rounded {
		return false
	}
	if pattern.Nasal != TristateUnknown && pattern.Nasal.ToBool() != sound.Nasal {
		return false
	}
	return true
}

func containsPoint(s []ArticulationPoint, e ArticulationPoint) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func containsManner(s []ArticulationManner, e ArticulationManner) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func containsShape(s []TongueShape, e TongueShape) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func containsVoice(s []Voice, e Voice) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func (tristate TristateBool) ToBool() bool {
	if tristate == TristateTrue {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright 2015 Comcast Cable Communications Management, 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
//
//     http://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.
//
// End Copyright

package service

import (
	"bytes"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"testing"
	"time"

	"github.com/Comcast/rulio/sys"
)

func TestHTTP(t *testing.T) {
	port := "localhost:9999" // Sorry.

	sys, ctx := sys.ExampleSystem("Test")
	service := &Service{
		System: sys,
	}
	server, err := NewHTTPService(ctx, service)
	if err != nil {
		t.Fatal(err)
	}

	go func() {
		if err = server.Start(ctx, port); err != nil {
			t.Fatal(err)
		}
	}()
	time.Sleep(time.Second)

	serviceRequest := func(m map[string]interface{}) (map[string]interface{}, string) {
		out := &bytes.Buffer{}
		result, err := service.ProcessRequest(ctx, m, out)
		if err != nil {
			t.Fatal(err)
		}
		return result, out.String()
	}

	_, version := serviceRequest(map[string]interface{}{
		"uri": "/api/version",
	})
	log.Printf("version: %s", version)

	httpRequest := func(uri string, body string) string {
		if body == "" {
			body = "{}"
		}
		buf := bytes.NewBufferString(body)

		resp, err := http.Post("http://"+port+uri, "application/json", buf)
		if err != nil {
			t.Fatal(err)
		}
		bs, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			t.Fatal(err)
		}

		return string(bs)
	}

	version = httpRequest("api/version", "")
	log.Printf("version: %s", version)

	request := `location: here
rule:
  when:
    pattern:
      person: "?x"
      latlon: "?there"
  condition:
    and:
      - pattern:
          person: "?y"
          latlon: "?near"
      - code: |
          console.log("checking " + x + "," + y + " at " + JSON.stringify(there) + "," + JSON.stringify(near)); true;
      - code: "x != y"
  action:
    code: |
      console.log(x + " is near " + y);
      var json = JSON.stringify({uri: "/api/loc/events/ingest", location: "there", event: {near: [x,y]}});
      console.log("emitting " + json);
      got = Env.http("POST", "$ENDPOINT" + "/api/json", json);
`
	rid := httpRequest("api/loc/rules/add", request)
	log.Printf("rid: %s", rid)
	if !strings.HasPrefix(rid, `{"id":`) {
		t.Fatalf("unexpected '%s'", rid)
	}

	request = `{"location":"here",
"rule": {"when":{"pattern":{"wants":"?x"}},
         "action":{"code":"var msg = 'eat ' + x; console.log(msg); msg;"}}}`

	rid = httpRequest("api/loc/rules/add", request)
	log.Printf("rid: %s", rid)
	if !strings.HasPrefix(rid, `{"id":`) {
		t.Fatalf("unexpected '%s'", rid)
	}

	request = `{"event": {"wants":"tacos"}}`
	got := httpRequest("api/loc/events/ingest?location=here", request)
	if strings.Index(got, `"values":["eat tacos"]`) < 0 {
		t.Fatalf("unexpected '%s'", got)
	}

	request = `location: there
rule:
  when:
    pattern:
      wants: "?x"
  action:
    code: |
      var msg = 'eat ' + x; console.log(msg); msg;
`
	rid = httpRequest("api/loc/rules/add", request)
	log.Printf("rid: %s", rid)
	if !strings.HasPrefix(rid, `{"id":`) {
		t.Fatalf("unexpected '%s'", rid)
	}

	request = `{"event": {"wants":"tacos"}}`
	got = httpRequest("api/loc/events/ingest?location=there", request)
	if strings.Index(got, `"values":["eat tacos"]`) < 0 {
		t.Fatalf("unexpected '%s'", got)
	}

	defer func() {
		serviceRequest(map[string]interface{}{
			"uri": "/api/sys/admin/shutdown",
		})
		log.Printf("stopping")
	}()
}
<commit_msg>Fix missing slash in test case<commit_after>// Copyright 2015 Comcast Cable Communications Management, 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
//
//     http://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.
//
// End Copyright

package service

import (
	"bytes"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"testing"
	"time"

	"github.com/Comcast/rulio/sys"
)

func TestHTTP(t *testing.T) {
	port := "localhost:9999" // Sorry.

	sys, ctx := sys.ExampleSystem("Test")
	service := &Service{
		System: sys,
	}
	server, err := NewHTTPService(ctx, service)
	if err != nil {
		t.Fatal(err)
	}

	go func() {
		if err = server.Start(ctx, port); err != nil {
			t.Fatal(err)
		}
	}()
	time.Sleep(time.Second)

	serviceRequest := func(m map[string]interface{}) (map[string]interface{}, string) {
		out := &bytes.Buffer{}
		result, err := service.ProcessRequest(ctx, m, out)
		if err != nil {
			t.Fatal(err)
		}
		return result, out.String()
	}

	_, version := serviceRequest(map[string]interface{}{
		"uri": "/api/version",
	})
	log.Printf("version: %s", version)

	httpRequest := func(uri string, body string) string {
		if body == "" {
			body = "{}"
		}
		buf := bytes.NewBufferString(body)

		resp, err := http.Post("http://"+port+"/"+uri, "application/json", buf)
		if err != nil {
			t.Fatal(err)
		}
		bs, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			t.Fatal(err)
		}

		return string(bs)
	}

	version = httpRequest("api/version", "")
	log.Printf("version: %s", version)

	request := `location: here
rule:
  when:
    pattern:
      person: "?x"
      latlon: "?there"
  condition:
    and:
      - pattern:
          person: "?y"
          latlon: "?near"
      - code: |
          console.log("checking " + x + "," + y + " at " + JSON.stringify(there) + "," + JSON.stringify(near)); true;
      - code: "x != y"
  action:
    code: |
      console.log(x + " is near " + y);
      var json = JSON.stringify({uri: "/api/loc/events/ingest", location: "there", event: {near: [x,y]}});
      console.log("emitting " + json);
      got = Env.http("POST", "$ENDPOINT" + "/api/json", json);
`
	rid := httpRequest("api/loc/rules/add", request)
	log.Printf("rid: %s", rid)
	if !strings.HasPrefix(rid, `{"id":`) {
		t.Fatalf("unexpected '%s'", rid)
	}

	request = `{"location":"here",
"rule": {"when":{"pattern":{"wants":"?x"}},
         "action":{"code":"var msg = 'eat ' + x; console.log(msg); msg;"}}}`

	rid = httpRequest("api/loc/rules/add", request)
	log.Printf("rid: %s", rid)
	if !strings.HasPrefix(rid, `{"id":`) {
		t.Fatalf("unexpected '%s'", rid)
	}

	request = `{"event": {"wants":"tacos"}}`
	got := httpRequest("api/loc/events/ingest?location=here", request)
	if strings.Index(got, `"values":["eat tacos"]`) < 0 {
		t.Fatalf("unexpected '%s'", got)
	}

	request = `location: there
rule:
  when:
    pattern:
      wants: "?x"
  action:
    code: |
      var msg = 'eat ' + x; console.log(msg); msg;
`
	rid = httpRequest("api/loc/rules/add", request)
	log.Printf("rid: %s", rid)
	if !strings.HasPrefix(rid, `{"id":`) {
		t.Fatalf("unexpected '%s'", rid)
	}

	request = `{"event": {"wants":"tacos"}}`
	got = httpRequest("api/loc/events/ingest?location=there", request)
	if strings.Index(got, `"values":["eat tacos"]`) < 0 {
		t.Fatalf("unexpected '%s'", got)
	}

	defer func() {
		serviceRequest(map[string]interface{}{
			"uri": "/api/sys/admin/shutdown",
		})
		log.Printf("stopping")
	}()
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"strings"

	cmds "github.com/jbenet/go-ipfs/commands"
)

type TestOutput struct {
	Foo string
	Bar int
}

var Root = &cmds.Command{
	Options: []cmds.Option{
		cmds.Option{[]string{"config", "c"}, cmds.String},
		cmds.Option{[]string{"debug", "D"}, cmds.Bool},
		cmds.Option{[]string{"help", "h"}, cmds.Bool},
		cmds.Option{[]string{"local", "L"}, cmds.Bool},
	},
	Help: `ipfs - global versioned p2p merkledag file system

Basic commands:

    init          Initialize ipfs local configuration.
    add <path>    Add an object to ipfs.
    cat <ref>     Show ipfs object data.
    ls <ref>      List links from an object.
    refs <ref>    List link hashes from an object.

Tool commands:

    config        Manage configuration.
    update        Download and apply go-ipfs updates.
    version       Show ipfs version information.
    commands      List all available commands.

Advanced Commands:

    mount         Mount an ipfs read-only mountpoint.
    serve         Serve an interface to ipfs.
    net-diag      Print network diagnostic

Plumbing commands:

    block         Interact with raw blocks in the datastore
    object        Interact with raw dag nodes

Use "ipfs help <command>" for more information about a command.
`,
}

var rootSubcommands = map[string]*cmds.Command{
	"cat":      catCmd,
	"ls":       lsCmd,
	"commands": commandsCmd,
	"publish":  publishCmd,
	"add":      addCmd,

	// test subcommands
	// TODO: remove these when we don't need them anymore
	"beep": &cmds.Command{
		Run: func(res cmds.Response, req cmds.Request) {
			v := &TestOutput{"hello, world", 1337}
			res.SetValue(v)
		},
		Format: func(res cmds.Response) (string, error) {
			v := res.Value().(*TestOutput)
			s := fmt.Sprintf("Foo: %s\n", v.Foo)
			s += fmt.Sprintf("Bar: %v\n", v.Bar)
			return s, nil
		},
		Type: &TestOutput{},
	},
	"boop": &cmds.Command{
		Run: func(res cmds.Response, req cmds.Request) {
			v := strings.NewReader("hello, world")
			res.SetValue(v)
		},
	},
	"warp": &cmds.Command{
		Options: []cmds.Option{
			cmds.Option{[]string{"power", "p"}, cmds.Float},
		},
		Run: func(res cmds.Response, req cmds.Request) {
			threshold := 1.21

			if power, found := req.Option("power"); found && power.(float64) >= threshold {
				res.SetValue(struct {
					Status string
					Power  float64
				}{"Flux capacitor activated!", power.(float64)})

			} else {
				err := fmt.Errorf("Insufficient power (%v jiggawatts required)", threshold)
				res.SetError(err, cmds.ErrClient)
			}
		},
	},
	"args": &cmds.Command{
		Run: func(res cmds.Response, req cmds.Request) {
			res.SetValue(req.Arguments())
		},
	},
}

func init() {
	Root.Subcommands = rootSubcommands
}
<commit_msg>core/commands2: Added logging<commit_after>package commands

import (
	"fmt"
	"strings"

	cmds "github.com/jbenet/go-ipfs/commands"
	u "github.com/jbenet/go-ipfs/util"
)

var log = u.Logger("core/commands")

type TestOutput struct {
	Foo string
	Bar int
}

var Root = &cmds.Command{
	Options: []cmds.Option{
		cmds.Option{[]string{"config", "c"}, cmds.String},
		cmds.Option{[]string{"debug", "D"}, cmds.Bool},
		cmds.Option{[]string{"help", "h"}, cmds.Bool},
		cmds.Option{[]string{"local", "L"}, cmds.Bool},
	},
	Help: `ipfs - global versioned p2p merkledag file system

Basic commands:

    init          Initialize ipfs local configuration.
    add <path>    Add an object to ipfs.
    cat <ref>     Show ipfs object data.
    ls <ref>      List links from an object.
    refs <ref>    List link hashes from an object.

Tool commands:

    config        Manage configuration.
    update        Download and apply go-ipfs updates.
    version       Show ipfs version information.
    commands      List all available commands.

Advanced Commands:

    mount         Mount an ipfs read-only mountpoint.
    serve         Serve an interface to ipfs.
    net-diag      Print network diagnostic

Plumbing commands:

    block         Interact with raw blocks in the datastore
    object        Interact with raw dag nodes

Use "ipfs help <command>" for more information about a command.
`,
}

var rootSubcommands = map[string]*cmds.Command{
	"cat":      catCmd,
	"ls":       lsCmd,
	"commands": commandsCmd,
	"publish":  publishCmd,
	"add":      addCmd,

	// test subcommands
	// TODO: remove these when we don't need them anymore
	"beep": &cmds.Command{
		Run: func(res cmds.Response, req cmds.Request) {
			v := &TestOutput{"hello, world", 1337}
			log.Info("beep")
			res.SetValue(v)
		},
		Format: func(res cmds.Response) (string, error) {
			v := res.Value().(*TestOutput)
			s := fmt.Sprintf("Foo: %s\n", v.Foo)
			s += fmt.Sprintf("Bar: %v\n", v.Bar)
			return s, nil
		},
		Type: &TestOutput{},
	},
	"boop": &cmds.Command{
		Run: func(res cmds.Response, req cmds.Request) {
			v := strings.NewReader("hello, world")
			res.SetValue(v)
		},
	},
	"warp": &cmds.Command{
		Options: []cmds.Option{
			cmds.Option{[]string{"power", "p"}, cmds.Float},
		},
		Run: func(res cmds.Response, req cmds.Request) {
			threshold := 1.21

			if power, found := req.Option("power"); found && power.(float64) >= threshold {
				res.SetValue(struct {
					Status string
					Power  float64
				}{"Flux capacitor activated!", power.(float64)})

			} else {
				err := fmt.Errorf("Insufficient power (%v jiggawatts required)", threshold)
				res.SetError(err, cmds.ErrClient)
			}
		},
	},
	"args": &cmds.Command{
		Run: func(res cmds.Response, req cmds.Request) {
			res.SetValue(req.Arguments())
		},
	},
}

func init() {
	Root.Subcommands = rootSubcommands
	u.SetLogLevel("core/commands", "info")
}
<|endoftext|>


<commit_before>package crypto

import (
	"bytes"
	"crypto/subtle"
	"errors"
	"fmt"
	"io"

	pb "github.com/libp2p/go-libp2p-core/crypto/pb"

	"golang.org/x/crypto/ed25519"
)

// Ed25519PrivateKey is an ed25519 private key.
type Ed25519PrivateKey struct {
	k ed25519.PrivateKey
}

// Ed25519PublicKey is an ed25519 public key.
type Ed25519PublicKey struct {
	k ed25519.PublicKey
}

// GenerateEd25519Key generates a new ed25519 private and public key pair.
func GenerateEd25519Key(src io.Reader) (PrivKey, PubKey, error) {
	pub, priv, err := ed25519.GenerateKey(src)
	if err != nil {
		return nil, nil, err
	}

	return &Ed25519PrivateKey{
			k: priv,
		},
		&Ed25519PublicKey{
			k: pub,
		},
		nil
}

// Type of the private key (Ed25519).
func (k *Ed25519PrivateKey) Type() pb.KeyType {
	return pb.KeyType_Ed25519
}

// Bytes marshals an ed25519 private key to protobuf bytes.
func (k *Ed25519PrivateKey) Bytes() ([]byte, error) {
	return MarshalPrivateKey(k)
}

// Raw private key bytes.
func (k *Ed25519PrivateKey) Raw() ([]byte, error) {
	// The Ed25519 private key contains two 32-bytes curve points, the private
	// key and the public key.
	// It makes it more efficient to get the public key without re-computing an
	// elliptic curve multiplication.
	buf := make([]byte, len(k.k))
	copy(buf, k.k)

	return buf, nil
}

func (k *Ed25519PrivateKey) pubKeyBytes() []byte {
	return k.k[ed25519.PrivateKeySize-ed25519.PublicKeySize:]
}

// Equals compares two ed25519 private keys.
func (k *Ed25519PrivateKey) Equals(o Key) bool {
	edk, ok := o.(*Ed25519PrivateKey)
	if !ok {
		return false
	}

	return subtle.ConstantTimeCompare(k.k, edk.k) == 1
}

// GetPublic returns an ed25519 public key from a private key.
func (k *Ed25519PrivateKey) GetPublic() PubKey {
	return &Ed25519PublicKey{k: k.pubKeyBytes()}
}

// Sign returns a signature from an input message.
func (k *Ed25519PrivateKey) Sign(msg []byte) ([]byte, error) {
	return ed25519.Sign(k.k, msg), nil
}

// Type of the public key (Ed25519).
func (k *Ed25519PublicKey) Type() pb.KeyType {
	return pb.KeyType_Ed25519
}

// Bytes returns a ed25519 public key as protobuf bytes.
func (k *Ed25519PublicKey) Bytes() ([]byte, error) {
	return MarshalPublicKey(k)
}

// Raw public key bytes.
func (k *Ed25519PublicKey) Raw() ([]byte, error) {
	return k.k, nil
}

// Equals compares two ed25519 public keys.
func (k *Ed25519PublicKey) Equals(o Key) bool {
	edk, ok := o.(*Ed25519PublicKey)
	if !ok {
		return false
	}

	return bytes.Equal(k.k, edk.k)
}

// Verify checks a signature agains the input data.
func (k *Ed25519PublicKey) Verify(data []byte, sig []byte) (bool, error) {
	return ed25519.Verify(k.k, data, sig), nil
}

// UnmarshalEd25519PublicKey returns a public key from input bytes.
func UnmarshalEd25519PublicKey(data []byte) (PubKey, error) {
	if len(data) != 32 {
		return nil, errors.New("expect ed25519 public key data size to be 32")
	}

	return &Ed25519PublicKey{
		k: ed25519.PublicKey(data),
	}, nil
}

// UnmarshalEd25519PrivateKey returns a private key from input bytes.
func UnmarshalEd25519PrivateKey(data []byte) (PrivKey, error) {
	switch len(data) {
	case ed25519.PrivateKeySize + ed25519.PublicKeySize:
		// Remove the redundant public key. See issue #36.
		redundantPk := data[ed25519.PrivateKeySize:]
		pk := data[ed25519.PrivateKeySize-ed25519.PublicKeySize : ed25519.PrivateKeySize]
		if !bytes.Equal(pk, redundantPk) {
			return nil, errors.New("expected redundant ed25519 public key to be redundant")
		}

		// No point in storing the extra data.
		newKey := make([]byte, ed25519.PrivateKeySize)
		copy(newKey, data[:ed25519.PrivateKeySize])
		data = newKey
	case ed25519.PrivateKeySize:
	default:
		return nil, fmt.Errorf(
			"expected ed25519 data size to be %d or %d, got %d",
			ed25519.PrivateKeySize,
			ed25519.PrivateKeySize+ed25519.PublicKeySize,
			len(data),
		)
	}

	return &Ed25519PrivateKey{
		k: ed25519.PrivateKey(data),
	}, nil
}
<commit_msg>crypto: use constant time compare when decoding private keys<commit_after>package crypto

import (
	"bytes"
	"crypto/subtle"
	"errors"
	"fmt"
	"io"

	pb "github.com/libp2p/go-libp2p-core/crypto/pb"

	"golang.org/x/crypto/ed25519"
)

// Ed25519PrivateKey is an ed25519 private key.
type Ed25519PrivateKey struct {
	k ed25519.PrivateKey
}

// Ed25519PublicKey is an ed25519 public key.
type Ed25519PublicKey struct {
	k ed25519.PublicKey
}

// GenerateEd25519Key generates a new ed25519 private and public key pair.
func GenerateEd25519Key(src io.Reader) (PrivKey, PubKey, error) {
	pub, priv, err := ed25519.GenerateKey(src)
	if err != nil {
		return nil, nil, err
	}

	return &Ed25519PrivateKey{
			k: priv,
		},
		&Ed25519PublicKey{
			k: pub,
		},
		nil
}

// Type of the private key (Ed25519).
func (k *Ed25519PrivateKey) Type() pb.KeyType {
	return pb.KeyType_Ed25519
}

// Bytes marshals an ed25519 private key to protobuf bytes.
func (k *Ed25519PrivateKey) Bytes() ([]byte, error) {
	return MarshalPrivateKey(k)
}

// Raw private key bytes.
func (k *Ed25519PrivateKey) Raw() ([]byte, error) {
	// The Ed25519 private key contains two 32-bytes curve points, the private
	// key and the public key.
	// It makes it more efficient to get the public key without re-computing an
	// elliptic curve multiplication.
	buf := make([]byte, len(k.k))
	copy(buf, k.k)

	return buf, nil
}

func (k *Ed25519PrivateKey) pubKeyBytes() []byte {
	return k.k[ed25519.PrivateKeySize-ed25519.PublicKeySize:]
}

// Equals compares two ed25519 private keys.
func (k *Ed25519PrivateKey) Equals(o Key) bool {
	edk, ok := o.(*Ed25519PrivateKey)
	if !ok {
		return false
	}

	return subtle.ConstantTimeCompare(k.k, edk.k) == 1
}

// GetPublic returns an ed25519 public key from a private key.
func (k *Ed25519PrivateKey) GetPublic() PubKey {
	return &Ed25519PublicKey{k: k.pubKeyBytes()}
}

// Sign returns a signature from an input message.
func (k *Ed25519PrivateKey) Sign(msg []byte) ([]byte, error) {
	return ed25519.Sign(k.k, msg), nil
}

// Type of the public key (Ed25519).
func (k *Ed25519PublicKey) Type() pb.KeyType {
	return pb.KeyType_Ed25519
}

// Bytes returns a ed25519 public key as protobuf bytes.
func (k *Ed25519PublicKey) Bytes() ([]byte, error) {
	return MarshalPublicKey(k)
}

// Raw public key bytes.
func (k *Ed25519PublicKey) Raw() ([]byte, error) {
	return k.k, nil
}

// Equals compares two ed25519 public keys.
func (k *Ed25519PublicKey) Equals(o Key) bool {
	edk, ok := o.(*Ed25519PublicKey)
	if !ok {
		return false
	}

	return bytes.Equal(k.k, edk.k)
}

// Verify checks a signature agains the input data.
func (k *Ed25519PublicKey) Verify(data []byte, sig []byte) (bool, error) {
	return ed25519.Verify(k.k, data, sig), nil
}

// UnmarshalEd25519PublicKey returns a public key from input bytes.
func UnmarshalEd25519PublicKey(data []byte) (PubKey, error) {
	if len(data) != 32 {
		return nil, errors.New("expect ed25519 public key data size to be 32")
	}

	return &Ed25519PublicKey{
		k: ed25519.PublicKey(data),
	}, nil
}

// UnmarshalEd25519PrivateKey returns a private key from input bytes.
func UnmarshalEd25519PrivateKey(data []byte) (PrivKey, error) {
	switch len(data) {
	case ed25519.PrivateKeySize + ed25519.PublicKeySize:
		// Remove the redundant public key. See issue #36.
		redundantPk := data[ed25519.PrivateKeySize:]
		pk := data[ed25519.PrivateKeySize-ed25519.PublicKeySize : ed25519.PrivateKeySize]
		if subtle.ConstantTimeCompare(pk, redundantPk) == 0 {
			return nil, errors.New("expected redundant ed25519 public key to be redundant")
		}

		// No point in storing the extra data.
		newKey := make([]byte, ed25519.PrivateKeySize)
		copy(newKey, data[:ed25519.PrivateKeySize])
		data = newKey
	case ed25519.PrivateKeySize:
	default:
		return nil, fmt.Errorf(
			"expected ed25519 data size to be %d or %d, got %d",
			ed25519.PrivateKeySize,
			ed25519.PrivateKeySize+ed25519.PublicKeySize,
			len(data),
		)
	}

	return &Ed25519PrivateKey{
		k: ed25519.PrivateKey(data),
	}, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

    http://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 azure

import (
	"fmt"
	"testing"

	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network"
	"github.com/Azure/go-autorest/autorest/to"
	"github.com/stretchr/testify/assert"
)

func TestFindProbe(t *testing.T) {
	tests := []struct {
		msg           string
		existingProbe []network.Probe
		curProbe      network.Probe
		expected      bool
	}{
		{
			msg:      "empty existing probes should return false",
			expected: false,
		},
		{
			msg: "probe names match while ports unmatch should return false",
			existingProbe: []network.Probe{
				{
					Name: to.StringPtr("httpProbe"),
					ProbePropertiesFormat: &network.ProbePropertiesFormat{
						Port: to.Int32Ptr(1),
					},
				},
			},
			curProbe: network.Probe{
				Name: to.StringPtr("httpProbe"),
				ProbePropertiesFormat: &network.ProbePropertiesFormat{
					Port: to.Int32Ptr(2),
				},
			},
			expected: false,
		},
		{
			msg: "probe ports match while names unmatch should return false",
			existingProbe: []network.Probe{
				{
					Name: to.StringPtr("probe1"),
					ProbePropertiesFormat: &network.ProbePropertiesFormat{
						Port: to.Int32Ptr(1),
					},
				},
			},
			curProbe: network.Probe{
				Name: to.StringPtr("probe2"),
				ProbePropertiesFormat: &network.ProbePropertiesFormat{
					Port: to.Int32Ptr(1),
				},
			},
			expected: false,
		},
		{
			msg: "both probe ports and names match should return true",
			existingProbe: []network.Probe{
				{
					Name: to.StringPtr("matchName"),
					ProbePropertiesFormat: &network.ProbePropertiesFormat{
						Port: to.Int32Ptr(1),
					},
				},
			},
			curProbe: network.Probe{
				Name: to.StringPtr("matchName"),
				ProbePropertiesFormat: &network.ProbePropertiesFormat{
					Port: to.Int32Ptr(1),
				},
			},
			expected: true,
		},
	}

	for i, test := range tests {
		findResult := findProbe(test.existingProbe, test.curProbe)
		assert.Equal(t, test.expected, findResult, fmt.Sprintf("TestCase[%d]: %s", i, test.msg))
	}
}
<commit_msg>Add unit tests for findRule()<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

    http://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 azure

import (
	"fmt"
	"testing"

	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network"
	"github.com/Azure/go-autorest/autorest/to"
	"github.com/stretchr/testify/assert"
)

func TestFindProbe(t *testing.T) {
	tests := []struct {
		msg           string
		existingProbe []network.Probe
		curProbe      network.Probe
		expected      bool
	}{
		{
			msg:      "empty existing probes should return false",
			expected: false,
		},
		{
			msg: "probe names match while ports unmatch should return false",
			existingProbe: []network.Probe{
				{
					Name: to.StringPtr("httpProbe"),
					ProbePropertiesFormat: &network.ProbePropertiesFormat{
						Port: to.Int32Ptr(1),
					},
				},
			},
			curProbe: network.Probe{
				Name: to.StringPtr("httpProbe"),
				ProbePropertiesFormat: &network.ProbePropertiesFormat{
					Port: to.Int32Ptr(2),
				},
			},
			expected: false,
		},
		{
			msg: "probe ports match while names unmatch should return false",
			existingProbe: []network.Probe{
				{
					Name: to.StringPtr("probe1"),
					ProbePropertiesFormat: &network.ProbePropertiesFormat{
						Port: to.Int32Ptr(1),
					},
				},
			},
			curProbe: network.Probe{
				Name: to.StringPtr("probe2"),
				ProbePropertiesFormat: &network.ProbePropertiesFormat{
					Port: to.Int32Ptr(1),
				},
			},
			expected: false,
		},
		{
			msg: "both probe ports and names match should return true",
			existingProbe: []network.Probe{
				{
					Name: to.StringPtr("matchName"),
					ProbePropertiesFormat: &network.ProbePropertiesFormat{
						Port: to.Int32Ptr(1),
					},
				},
			},
			curProbe: network.Probe{
				Name: to.StringPtr("matchName"),
				ProbePropertiesFormat: &network.ProbePropertiesFormat{
					Port: to.Int32Ptr(1),
				},
			},
			expected: true,
		},
	}

	for i, test := range tests {
		findResult := findProbe(test.existingProbe, test.curProbe)
		assert.Equal(t, test.expected, findResult, fmt.Sprintf("TestCase[%d]: %s", i, test.msg))
	}
}

func TestFindRule(t *testing.T) {
	tests := []struct {
		msg          string
		existingRule []network.LoadBalancingRule
		curRule      network.LoadBalancingRule
		expected     bool
	}{
		{
			msg:      "empty existing rules should return false",
			expected: false,
		},
		{
			msg: "rule names unmatch should return false",
			existingRule: []network.LoadBalancingRule{
				{
					Name: to.StringPtr("httpProbe1"),
					LoadBalancingRulePropertiesFormat: &network.LoadBalancingRulePropertiesFormat{
						FrontendPort: to.Int32Ptr(1),
					},
				},
			},
			curRule: network.LoadBalancingRule{
				Name: to.StringPtr("httpProbe2"),
				LoadBalancingRulePropertiesFormat: &network.LoadBalancingRulePropertiesFormat{
					FrontendPort: to.Int32Ptr(1),
				},
			},
			expected: false,
		},
		{
			msg: "rule names match while frontend ports unmatch should return false",
			existingRule: []network.LoadBalancingRule{
				{
					Name: to.StringPtr("httpProbe"),
					LoadBalancingRulePropertiesFormat: &network.LoadBalancingRulePropertiesFormat{
						FrontendPort: to.Int32Ptr(1),
					},
				},
			},
			curRule: network.LoadBalancingRule{
				Name: to.StringPtr("httpProbe"),
				LoadBalancingRulePropertiesFormat: &network.LoadBalancingRulePropertiesFormat{
					FrontendPort: to.Int32Ptr(2),
				},
			},
			expected: false,
		},
		{
			msg: "rule names match while backend ports unmatch should return false",
			existingRule: []network.LoadBalancingRule{
				{
					Name: to.StringPtr("httpProbe"),
					LoadBalancingRulePropertiesFormat: &network.LoadBalancingRulePropertiesFormat{
						BackendPort: to.Int32Ptr(1),
					},
				},
			},
			curRule: network.LoadBalancingRule{
				Name: to.StringPtr("httpProbe"),
				LoadBalancingRulePropertiesFormat: &network.LoadBalancingRulePropertiesFormat{
					BackendPort: to.Int32Ptr(2),
				},
			},
			expected: false,
		},
		{
			msg: "rule names match while LoadDistribution unmatch should return false",
			existingRule: []network.LoadBalancingRule{
				{
					Name: to.StringPtr("probe1"),
					LoadBalancingRulePropertiesFormat: &network.LoadBalancingRulePropertiesFormat{
						LoadDistribution: network.Default,
					},
				},
			},
			curRule: network.LoadBalancingRule{
				Name: to.StringPtr("probe2"),
				LoadBalancingRulePropertiesFormat: &network.LoadBalancingRulePropertiesFormat{
					LoadDistribution: network.SourceIP,
				},
			},
			expected: false,
		},
		{
			msg: "both rule names and LoadBalancingRulePropertiesFormats match should return true",
			existingRule: []network.LoadBalancingRule{
				{
					Name: to.StringPtr("matchName"),
					LoadBalancingRulePropertiesFormat: &network.LoadBalancingRulePropertiesFormat{
						BackendPort:      to.Int32Ptr(2),
						FrontendPort:     to.Int32Ptr(2),
						LoadDistribution: network.SourceIP,
					},
				},
			},
			curRule: network.LoadBalancingRule{
				Name: to.StringPtr("matchName"),
				LoadBalancingRulePropertiesFormat: &network.LoadBalancingRulePropertiesFormat{
					BackendPort:      to.Int32Ptr(2),
					FrontendPort:     to.Int32Ptr(2),
					LoadDistribution: network.SourceIP,
				},
			},
			expected: true,
		},
	}

	for i, test := range tests {
		findResult := findRule(test.existingRule, test.curRule)
		assert.Equal(t, test.expected, findResult, fmt.Sprintf("TestCase[%d]: %s", i, test.msg))
	}
}
<|endoftext|>


<commit_before>package brands

import (
	"errors"
	"fmt"

	"github.com/Financial-Times/neo-model-utils-go/mapper"
	log "github.com/Sirupsen/logrus"
	"github.com/jmcvetta/neoism"
)

// Driver interface
type Driver interface {
	Read(id string) (brand Brand, found bool, err error)
	CheckConnectivity() error
}

// CypherDriver struct
type CypherDriver struct {
	db  *neoism.Database
	env string
}

//NewCypherDriver instantiate driver
func NewCypherDriver(db *neoism.Database, env string) CypherDriver {
	return CypherDriver{db, env}
}

// CheckConnectivity tests neo4j by running a simple cypher query
func (pcw CypherDriver) CheckConnectivity() error {
	results := []struct {
		ID int
	}{}
	query := &neoism.CypherQuery{
		Statement: "MATCH (x) RETURN ID(x) LIMIT 1",
		Result:    &results,
	}
	err := pcw.db.Cypher(query)
	log.Debugf("CheckConnectivity results:%+v  err: %+v", results, err)
	return err
}

func (pcw CypherDriver) Read(uuid string) (brand Brand, found bool, err error) {
	results := []struct {
		Brand
	}{}

	query := &neoism.CypherQuery{
		Statement: `
                        MATCH (b:Brand{uuid:{uuid}})
                        OPTIONAL MATCH (b)-[:HAS_PARENT]->(p:Thing)
                        OPTIONAL MATCH (b)<-[:HAS_PARENT]-(c:Thing)
                        RETURN  b.uuid as id, labels(b) as types, b.prefLabel as prefLabel,
                                b.description as description, b.descriptionXML as descriptionXML,
                                b.strapline as strapline, b.imageUrl as _imageUrl,
                                { id: p.uuid, types: labels(p), prefLabel: p.prefLabel } AS parentBrand,
                                collect (
                                { id: c.uuid, types: labels(c), prefLabel: c.prefLabel }
                                ) AS childBrands
                `,
		Parameters: neoism.Props{"uuid": uuid},
		Result:     &results,
	}
	err = pcw.db.Cypher(query)
	if err != nil {
		log.Errorf("Error looking up uuid %s with query %s from neoism: %+v\n", uuid, query.Statement, err)
		return Brand{}, false, fmt.Errorf("Error accessing Brands datastore for uuid: %s", uuid)
	}
	log.Debugf("CypherResult Read Brand for uuid: %s was: %+v", uuid, results)
	if (len(results)) == 0 {
		return Brand{}, false, nil
	} else if len(results) != 1 {
		errMsg := fmt.Sprintf("Multiple brands found with the same uuid:%s !", uuid)
		log.Error(errMsg)
		return Brand{}, true, errors.New(errMsg)
	}
	publicAPITransformation(&results[0].Brand, pcw.env)
	log.Debugf("Returning %v", results[0].Brand)
	return results[0].Brand, true, nil
}

func publicAPITransformation(brand *Brand, env string) {
	if brand.Parent.ID != "" {
		brand.Parent.APIURL = mapper.APIURL(brand.Parent.ID, brand.Parent.Types, env)
		brand.Parent.ID = mapper.IDURL(brand.Parent.ID)
		brand.Parent.Types = mapper.TypeURIs(brand.Parent.Types)
	} else {
		brand.Parent = nil
	}
	if brand.Children[0].ID != "" {
		for idx := range brand.Children {
			brand.Children[idx].APIURL = mapper.APIURL(brand.Children[idx].ID, brand.Children[idx].Types, env)
			brand.Children[idx].ID = mapper.IDURL(brand.Children[idx].ID)
			brand.Children[idx].Types = mapper.TypeURIs(brand.Children[idx].Types)
		}
	} else {
		var empty = []*Thing{}
		brand.Children = empty
	}
	brand.APIURL = mapper.APIURL(brand.ID, brand.Types, env)
	brand.Types = mapper.TypeURIs(brand.Types)
	brand.ID = mapper.IDURL(brand.ID)
}
<commit_msg>Post review updates, pt1<commit_after>package brands

import (
	"errors"
	"fmt"

	"github.com/Financial-Times/neo-model-utils-go/mapper"
	log "github.com/Sirupsen/logrus"
	"github.com/jmcvetta/neoism"
)

// Driver interface
type Driver interface {
	Read(id string) (brand Brand, found bool, err error)
	CheckConnectivity() error
}

// CypherDriver struct
type CypherDriver struct {
	db  *neoism.Database
	env string
}

//NewCypherDriver instantiate driver
func NewCypherDriver(db *neoism.Database, env string) CypherDriver {
	return CypherDriver{db, env}
}

// CheckConnectivity tests neo4j by running a simple cypher query
func (driver CypherDriver) CheckConnectivity() error {
	results := []struct {
		ID int
	}{}
	query := &neoism.CypherQuery{
		Statement: "MATCH (x) RETURN ID(x) LIMIT 1",
		Result:    &results,
	}
	err := driver.db.Cypher(query)
	log.Debugf("CheckConnectivity results:%+v  err: %+v", results, err)
	return err
}

func (driver CypherDriver) Read(uuid string) (brand Brand, found bool, err error) {
	results := []struct {
		Brand
	}{}

	query := &neoism.CypherQuery{
		Statement: `
                        MATCH (b:Brand{uuid:{uuid}})
                        OPTIONAL MATCH (b)-[:HAS_PARENT]->(p:Thing)
                        OPTIONAL MATCH (b)<-[:HAS_PARENT]-(c:Thing)
                        RETURN  b.uuid as id, labels(b) as types, b.prefLabel as prefLabel,
                                b.description as description, b.descriptionXML as descriptionXML,
                                b.strapline as strapline, b.imageUrl as _imageUrl,
                                { id: p.uuid, types: labels(p), prefLabel: p.prefLabel } AS parentBrand,
                                collect (
                                { id: c.uuid, types: labels(c), prefLabel: c.prefLabel }
                                ) AS childBrands
                `,
		Parameters: neoism.Props{"uuid": uuid},
		Result:     &results,
	}
	err = driver.db.Cypher(query)
	if err != nil {
		log.Errorf("Error looking up uuid %s with query %s from neoism: %+v\n", uuid, query.Statement, err)
		return Brand{}, false, fmt.Errorf("Error accessing Brands datastore for uuid: %s", uuid)
	}
	log.Debugf("CypherResult Read Brand for uuid: %s was: %+v", uuid, results)
	if (len(results)) == 0 {
		return Brand{}, false, nil
	} else if len(results) != 1 {
		errMsg := fmt.Sprintf("Multiple brands found with the same uuid:%s !", uuid)
		log.Error(errMsg)
		return Brand{}, true, errors.New(errMsg)
	}
	publicAPITransformation(&results[0].Brand, pcw.env)
	log.Debugf("Returning %v", results[0].Brand)
	return results[0].Brand, true, nil
}

func publicAPITransformation(brand *Brand, env string) {
	if brand.Parent.ID != "" {
		brand.Parent.APIURL = mapper.APIURL(brand.Parent.ID, brand.Parent.Types, env)
		brand.Parent.ID = mapper.IDURL(brand.Parent.ID)
		brand.Parent.Types = mapper.TypeURIs(brand.Parent.Types)
	} else {
		brand.Parent = nil
	}
	if brand.Children[0].ID != "" {
		for idx := range brand.Children {
			brand.Children[idx].APIURL = mapper.APIURL(brand.Children[idx].ID, brand.Children[idx].Types, env)
			brand.Children[idx].ID = mapper.IDURL(brand.Children[idx].ID)
			brand.Children[idx].Types = mapper.TypeURIs(brand.Children[idx].Types)
		}
	} else {
		var empty = []*Thing{}
		brand.Children = empty
	}
	brand.APIURL = mapper.APIURL(brand.ID, brand.Types, env)
	brand.Types = mapper.TypeURIs(brand.Types)
	brand.ID = mapper.IDURL(brand.ID)
}
<|endoftext|>