<commit_before>package criteria

import (
	"github.com/stretchr/testify/assert"
	"github.com/viant/endly"
	"github.com/viant/toolbox"
	"testing"
)

func Test_EvaluateCriteria(t *testing.T) {

	manager := endly.New()
	context := manager.NewContext(toolbox.NewContext())
	state := context.State()

	state.Put("key1", 0)
	var useCases = []struct {
		Description   string
		DefaultResult bool
		Expression    string
		State         map[string]interface{}
		Expected      bool
		HasError      bool
	}{
		{
			Description: "Simple true expression with ok = true",
			Expression:  "$ok:true",
			State: map[string]interface{}{
				"ok": true,
			},
			Expected: true,
		},
		{
			Description: "Left operand expression",
			Expression:  "$key1",
			State: map[string]interface{}{
				"key1": "123",
			},
			Expected: true,
		},
		{
			Description: "Simple true expression with ok = false",
			Expression:  "$ok:true",
			State: map[string]interface{}{
				"ok": false,
			},
			Expected: false,
		},
		{
			Description:   "Empty expression with default true",
			Expression:    "",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Constant equal",
			Expression:    "a=a",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Empty expression with default false",
			Expression:    "",
			DefaultResult: false,
			Expected:      false,
		},
		{
			Description:   "Not equal",
			Expression:    "1:!0",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Not equal 2",
			Expression:    "1!=0",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Not equal 0",
			Expression:    "$key1:!0", //
			DefaultResult: true,
			Expected:      false,
		},
	}

	for _, useCase := range useCases {
		if len(useCase.State) > 0 {
			for k, v := range useCase.State {
				state.Put(k, v)
			}
		}
		isTrue, err := Evaluate(context, state, useCase.Expression, "test", useCase.DefaultResult)
		if useCase.HasError {
			assert.NotNil(t, err, useCase.Description)
			continue
		}
		assert.EqualValues(t, useCase.Expected, isTrue, useCase.Description)
	}

}
<commit_msg>patched case<commit_after>package criteria

import (
	"github.com/stretchr/testify/assert"
	"github.com/viant/endly"
	"github.com/viant/toolbox"
	"testing"
)

func Test_EvaluateCriteria(t *testing.T) {

	manager := endly.New()
	context := manager.NewContext(toolbox.NewContext())
	state := context.State()

	var useCases = []struct {
		Description   string
		DefaultResult bool
		Expression    string
		State         map[string]interface{}
		Expected      bool
		HasError      bool
	}{
		{
			Description: "Simple true expression with ok = true",
			Expression:  "$ok:true",
			State: map[string]interface{}{
				"ok": true,
			},
			Expected: true,
		},
		{
			Description: "Left operand expression",
			Expression:  "$key1",
			State: map[string]interface{}{
				"key1": "123",
			},
			Expected: true,
		},
		{
			Description: "Simple true expression with ok = false",
			Expression:  "$ok:true",
			State: map[string]interface{}{
				"ok": false,
			},
			Expected: false,
		},
		{
			Description:   "Empty expression with default true",
			Expression:    "",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Constant equal",
			Expression:    "a=a",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Empty expression with default false",
			Expression:    "",
			DefaultResult: false,
			Expected:      false,
		},
		{
			Description:   "Not equal",
			Expression:    "1:!0",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Not equal 2",
			Expression:    "1!=0",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Data substitution",
			Expression:    "$key1:!0", //
			DefaultResult: true,
			Expected:      false,
			State: map[string]interface{}{
				"key1": 0,
			},
		},
	}

	for _, useCase := range useCases {
		if len(useCase.State) > 0 {
			for k, v := range useCase.State {
				state.Put(k, v)
			}
		}
		isTrue, err := Evaluate(context, state, useCase.Expression, "test", useCase.DefaultResult)
		if useCase.HasError {
			assert.NotNil(t, err, useCase.Description)
			continue
		}
		assert.EqualValues(t, useCase.Expected, isTrue, useCase.Description)
	}

}
<|endoftext|>


<commit_before>package criteria

import (
	"github.com/stretchr/testify/assert"
	"github.com/viant/endly"
	"github.com/viant/toolbox"
	"testing"
)

func Test_EvaluateCriteria(t *testing.T) {

	manager := endly.New()
	context := manager.NewContext(toolbox.NewContext())
	state := context.State()

	var useCases = []struct {
		Description   string
		DefaultResult bool
		Expression    string
		State         map[string]interface{}
		Expected      bool
		HasError      bool
	}{
		{
			Description: "Simple true expression with ok = true",
			Expression:  "$ok:true",
			State: map[string]interface{}{
				"ok": true,
			},
			Expected: true,
		},
		{
			Description: "Left operand expression",
			Expression:  "$key1",
			State: map[string]interface{}{
				"key1": "123",
			},
			Expected: true,
		},
		{
			Description: "Simple true expression with ok = false",
			Expression:  "$ok:true",
			State: map[string]interface{}{
				"ok": false,
			},
			Expected: false,
		},
		{
			Description:   "Empty expression with default true",
			Expression:    "",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Constant equal",
			Expression:    "a=a",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Empty expression with default false",
			Expression:    "",
			DefaultResult: false,
			Expected:      false,
		},
	}

	for _, useCase := range useCases {

		if len(useCase.State) > 0 {
			for k, v := range useCase.State {
				state.Put(k, v)
			}
		}
		isTrue, err := Evaluate(context, context.State(), useCase.Expression, "test", useCase.DefaultResult)
		if useCase.HasError {
			assert.NotNil(t, err, useCase.Description)
			continue
		}

		assert.EqualValues(t, useCase.Expected, isTrue, useCase.Description)

	}

}
<commit_msg>patched evaluator with predicate<commit_after>package criteria

import (
	"github.com/stretchr/testify/assert"
	"github.com/viant/endly"
	"github.com/viant/toolbox"
	"testing"
)

func Test_EvaluateCriteria(t *testing.T) {

	manager := endly.New()
	context := manager.NewContext(toolbox.NewContext())
	state := context.State()

	var useCases = []struct {
		Description   string
		DefaultResult bool
		Expression    string
		State         map[string]interface{}
		Expected      bool
		HasError      bool
	}{
		{
			Description: "Simple true expression with ok = true",
			Expression:  "$ok:true",
			State: map[string]interface{}{
				"ok": true,
			},
			Expected: true,
		},
		{
			Description: "Left operand expression",
			Expression:  "$key1",
			State: map[string]interface{}{
				"key1": "123",
			},
			Expected: true,
		},
		{
			Description: "Simple true expression with ok = false",
			Expression:  "$ok:true",
			State: map[string]interface{}{
				"ok": false,
			},
			Expected: false,
		},
		{
			Description:   "Empty expression with default true",
			Expression:    "",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Constant equal",
			Expression:    "a=a",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Empty expression with default false",
			Expression:    "",
			DefaultResult: false,
			Expected:      false,
		},
		{
			Description:   "Not equal",
			Expression:    "1:!0",
			DefaultResult: true,
			Expected:      true,
		},
		{
			Description:   "Not equal 2",
			Expression:    "1!=0",
			DefaultResult: true,
			Expected:      true,
		},
	}

	for _, useCase := range useCases {
		if len(useCase.State) > 0 {
			for k, v := range useCase.State {
				state.Put(k, v)
			}
		}
		isTrue, err := Evaluate(context, context.State(), useCase.Expression, "test", useCase.DefaultResult)
		if useCase.HasError {
			assert.NotNil(t, err, useCase.Description)
			continue
		}
		assert.EqualValues(t, useCase.Expected, isTrue, useCase.Description)
	}

}
<|endoftext|>


<commit_before>package inigo_test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
	"time"

	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/config"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-golang/lager/ginkgoreporter"
	"github.com/pivotal-golang/lager/lagertest"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
	"github.com/tedsuo/ifrit/grouper"

	garden_api "github.com/cloudfoundry-incubator/garden/api"
	"github.com/cloudfoundry-incubator/inigo/helpers"
	"github.com/cloudfoundry-incubator/inigo/inigo_server"
	"github.com/cloudfoundry-incubator/inigo/world"
	Bbs "github.com/cloudfoundry-incubator/runtime-schema/bbs"
	"github.com/cloudfoundry/gunk/diegonats"
	"github.com/cloudfoundry/gunk/timeprovider"
	"github.com/cloudfoundry/storeadapter/etcdstoreadapter"
	"github.com/cloudfoundry/storeadapter/workerpool"
)

var DEFAULT_EVENTUALLY_TIMEOUT = 1 * time.Minute
var DEFAULT_CONSISTENTLY_DURATION = 5 * time.Second

// use this for tests exercising docker; pulling can take a while
const DOCKER_PULL_ESTIMATE = 5 * time.Minute

const StackName = "lucid64"

var builtArtifacts world.BuiltArtifacts
var componentMaker world.ComponentMaker

var (
	plumbing      ifrit.Process
	gardenProcess ifrit.Process
	bbs           *Bbs.BBS
	natsClient    diegonats.NATSClient
	gardenClient  garden_api.Client
)

var _ = SynchronizedBeforeSuite(func() []byte {
	payload, err := json.Marshal(world.BuiltArtifacts{
		Executables:  CompileTestedExecutables(),
		Circuses:     CompileAndZipUpCircuses(),
		DockerCircus: CompileAndZipUpDockerCircus(),
	})
	Ω(err).ShouldNot(HaveOccurred())

	return payload
}, func(encodedBuiltArtifacts []byte) {
	var err error

	err = json.Unmarshal(encodedBuiltArtifacts, &builtArtifacts)
	Ω(err).ShouldNot(HaveOccurred())

	addresses := world.ComponentAddresses{
		GardenLinux:    fmt.Sprintf("127.0.0.1:%d", 10000+config.GinkgoConfig.ParallelNode),
		NATS:           fmt.Sprintf("127.0.0.1:%d", 11000+config.GinkgoConfig.ParallelNode),
		Etcd:           fmt.Sprintf("127.0.0.1:%d", 12000+config.GinkgoConfig.ParallelNode),
		EtcdPeer:       fmt.Sprintf("127.0.0.1:%d", 12500+config.GinkgoConfig.ParallelNode),
		Executor:       fmt.Sprintf("127.0.0.1:%d", 13000+config.GinkgoConfig.ParallelNode),
		Rep:            fmt.Sprintf("127.0.0.1:%d", 14000+config.GinkgoConfig.ParallelNode),
		LoggregatorIn:  fmt.Sprintf("127.0.0.1:%d", 15000+config.GinkgoConfig.ParallelNode),
		LoggregatorOut: fmt.Sprintf("127.0.0.1:%d", 16000+config.GinkgoConfig.ParallelNode),
		FileServer:     fmt.Sprintf("127.0.0.1:%d", 17000+config.GinkgoConfig.ParallelNode),
		Router:         fmt.Sprintf("127.0.0.1:%d", 18000+config.GinkgoConfig.ParallelNode),
		TPS:            fmt.Sprintf("127.0.0.1:%d", 19000+config.GinkgoConfig.ParallelNode),
		FakeCC:         fmt.Sprintf("127.0.0.1:%d", 20000+config.GinkgoConfig.ParallelNode),
	}

	gardenBinPath := os.Getenv("GARDEN_BINPATH")
	gardenRootFSPath := os.Getenv("GARDEN_ROOTFS")
	gardenGraphPath := os.Getenv("GARDEN_GRAPH_PATH")
	externalAddress := os.Getenv("EXTERNAL_ADDRESS")

	if gardenGraphPath == "" {
		gardenGraphPath = os.TempDir()
	}

	Ω(gardenBinPath).ShouldNot(BeEmpty(), "must provide $GARDEN_BINPATH")
	Ω(gardenRootFSPath).ShouldNot(BeEmpty(), "must provide $GARDEN_ROOTFS")
	Ω(externalAddress).ShouldNot(BeEmpty(), "must provide $EXTERNAL_ADDRESS")

	componentMaker = world.ComponentMaker{
		Artifacts: builtArtifacts,
		Addresses: addresses,

		Stack: StackName,

		ExternalAddress: externalAddress,

		GardenBinPath:    gardenBinPath,
		GardenRootFSPath: gardenRootFSPath,
		GardenGraphPath:  gardenGraphPath,
	}
})

var _ = BeforeEach(func() {
	currentTestDescription := CurrentGinkgoTestDescription()
	fmt.Fprintf(GinkgoWriter, "\n%s\n%s\n\n", strings.Repeat("~", 50), currentTestDescription.FullTestText)

	gardenLinux := componentMaker.GardenLinux()

	plumbing = ginkgomon.Invoke(grouper.NewParallel(os.Kill, grouper.Members{
		{"etcd", componentMaker.Etcd()},
		{"nats", componentMaker.NATS()},
	}))

	gardenProcess = ginkgomon.Invoke(gardenLinux)

	gardenClient = gardenLinux.NewClient()

	var err error
	natsClient = diegonats.NewClient()
	_, err = natsClient.Connect([]string{"nats://" + componentMaker.Addresses.NATS})
	Ω(err).ShouldNot(HaveOccurred())

	adapter := etcdstoreadapter.NewETCDStoreAdapter([]string{"http://" + componentMaker.Addresses.Etcd}, workerpool.NewWorkerPool(20))

	err = adapter.Connect()
	Ω(err).ShouldNot(HaveOccurred())

	bbs = Bbs.NewBBS(adapter, timeprovider.NewTimeProvider(), lagertest.NewTestLogger("test"))

	inigo_server.Start(componentMaker.ExternalAddress)
})

var _ = AfterEach(func() {
	inigo_server.Stop(gardenClient)

	helpers.StopProcess(plumbing)

	containers, err := gardenClient.Containers(nil)
	Ω(err).ShouldNot(HaveOccurred())

	// even if containers fail to destroy, stop garden, but still report the
	// errors
	destroyContainerErrors := []error{}
	for _, container := range containers {
		err := gardenClient.Destroy(container.Handle())
		if err != nil {
			destroyContainerErrors = append(destroyContainerErrors, err)
		}
	}

	helpers.StopProcess(gardenProcess)

	Ω(destroyContainerErrors).Should(
		BeEmpty(),
		"%d of %d containers failed to be destroyed!",
		len(destroyContainerErrors),
		len(containers),
	)
})

func TestInigo(t *testing.T) {
	registerDefaultTimeouts()

	RegisterFailHandler(Fail)

	RunSpecsWithDefaultAndCustomReporters(t, "Inigo Integration Suite", []Reporter{
		ginkgoreporter.New(GinkgoWriter),
	})
}

func registerDefaultTimeouts() {
	var err error
	if os.Getenv("DEFAULT_EVENTUALLY_TIMEOUT") != "" {
		DEFAULT_EVENTUALLY_TIMEOUT, err = time.ParseDuration(os.Getenv("DEFAULT_EVENTUALLY_TIMEOUT"))
		if err != nil {
			panic(err)
		}
	}

	if os.Getenv("DEFAULT_CONSISTENTLY_DURATION") != "" {
		DEFAULT_CONSISTENTLY_DURATION, err = time.ParseDuration(os.Getenv("DEFAULT_CONSISTENTLY_DURATION"))
		if err != nil {
			panic(err)
		}
	}

	SetDefaultEventuallyTimeout(DEFAULT_EVENTUALLY_TIMEOUT)
	SetDefaultConsistentlyDuration(DEFAULT_CONSISTENTLY_DURATION)

	// most things hit some component; don't hammer it
	SetDefaultConsistentlyPollingInterval(100 * time.Millisecond)
	SetDefaultEventuallyPollingInterval(500 * time.Millisecond)
}

func CompileTestedExecutables() world.BuiltExecutables {
	var err error

	builtExecutables := world.BuiltExecutables{}

	builtExecutables["garden-linux"], err = gexec.BuildIn(os.Getenv("GARDEN_LINUX_GOPATH"), "github.com/cloudfoundry-incubator/garden-linux", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["loggregator"], err = gexec.BuildIn(os.Getenv("LOGGREGATOR_GOPATH"), "loggregator")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["auctioneer"], err = gexec.BuildIn(os.Getenv("AUCTIONEER_GOPATH"), "github.com/cloudfoundry-incubator/auctioneer", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["exec"], err = gexec.BuildIn(os.Getenv("EXECUTOR_GOPATH"), "github.com/cloudfoundry-incubator/executor/cmd/executor", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["converger"], err = gexec.BuildIn(os.Getenv("CONVERGER_GOPATH"), "github.com/cloudfoundry-incubator/converger", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["rep"], err = gexec.BuildIn(os.Getenv("REP_GOPATH"), "github.com/cloudfoundry-incubator/rep", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["stager"], err = gexec.BuildIn(os.Getenv("STAGER_GOPATH"), "github.com/cloudfoundry-incubator/stager", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["nsync-listener"], err = gexec.BuildIn(os.Getenv("NSYNC_GOPATH"), "github.com/cloudfoundry-incubator/nsync/listener", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["nsync-bulker"], err = gexec.BuildIn(os.Getenv("NSYNC_GOPATH"), "github.com/cloudfoundry-incubator/nsync/bulker", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["file-server"], err = gexec.BuildIn(os.Getenv("FILE_SERVER_GOPATH"), "github.com/cloudfoundry-incubator/file-server", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["route-emitter"], err = gexec.BuildIn(os.Getenv("ROUTE_EMITTER_GOPATH"), "github.com/cloudfoundry-incubator/route-emitter", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["router"], err = gexec.BuildIn(os.Getenv("ROUTER_GOPATH"), "github.com/cloudfoundry/gorouter", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["tps"], err = gexec.BuildIn(os.Getenv("TPS_GOPATH"), "github.com/cloudfoundry-incubator/tps", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	return builtExecutables
}

func CompileAndZipUpCircuses() world.BuiltCircuses {
	builtCircuses := world.BuiltCircuses{}

	tailorPath, err := gexec.BuildIn(os.Getenv("LINUX_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/linux-circus/tailor", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	spyPath, err := gexec.BuildIn(os.Getenv("LINUX_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/linux-circus/spy", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	soldierPath, err := gexec.BuildIn(os.Getenv("LINUX_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/linux-circus/soldier", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	circusDir, err := ioutil.TempDir("", "circus-dir")
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(tailorPath, filepath.Join(circusDir, "tailor"))
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(spyPath, filepath.Join(circusDir, "spy"))
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(soldierPath, filepath.Join(circusDir, "soldier"))
	Ω(err).ShouldNot(HaveOccurred())

	cmd := exec.Command("zip", "-v", "circus.zip", "tailor", "soldier", "spy")
	cmd.Stderr = GinkgoWriter
	cmd.Stdout = GinkgoWriter
	cmd.Dir = circusDir
	err = cmd.Run()
	Ω(err).ShouldNot(HaveOccurred())

	builtCircuses[StackName] = filepath.Join(circusDir, "circus.zip")

	return builtCircuses
}

func CompileAndZipUpDockerCircus() string {
	tailorPath, err := gexec.BuildIn(os.Getenv("DOCKER_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/docker-circus/tailor", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	spyPath, err := gexec.BuildIn(os.Getenv("DOCKER_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/docker-circus/spy", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	soldierPath, err := gexec.BuildIn(os.Getenv("DOCKER_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/docker-circus/soldier", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	circusDir, err := ioutil.TempDir("", "circus-dir")
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(tailorPath, filepath.Join(circusDir, "tailor"))
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(spyPath, filepath.Join(circusDir, "spy"))
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(soldierPath, filepath.Join(circusDir, "soldier"))
	Ω(err).ShouldNot(HaveOccurred())

	cmd := exec.Command("zip", "-v", "docker-circus.zip", "tailor", "soldier", "spy")
	cmd.Stderr = GinkgoWriter
	cmd.Stdout = GinkgoWriter
	cmd.Dir = circusDir
	err = cmd.Run()
	Ω(err).ShouldNot(HaveOccurred())

	return filepath.Join(circusDir, "docker-circus.zip")
}
<commit_msg>update nsync and file-server executable names<commit_after>package inigo_test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
	"time"

	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/config"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-golang/lager/ginkgoreporter"
	"github.com/pivotal-golang/lager/lagertest"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
	"github.com/tedsuo/ifrit/grouper"

	garden_api "github.com/cloudfoundry-incubator/garden/api"
	"github.com/cloudfoundry-incubator/inigo/helpers"
	"github.com/cloudfoundry-incubator/inigo/inigo_server"
	"github.com/cloudfoundry-incubator/inigo/world"
	Bbs "github.com/cloudfoundry-incubator/runtime-schema/bbs"
	"github.com/cloudfoundry/gunk/diegonats"
	"github.com/cloudfoundry/gunk/timeprovider"
	"github.com/cloudfoundry/storeadapter/etcdstoreadapter"
	"github.com/cloudfoundry/storeadapter/workerpool"
)

var DEFAULT_EVENTUALLY_TIMEOUT = 1 * time.Minute
var DEFAULT_CONSISTENTLY_DURATION = 5 * time.Second

// use this for tests exercising docker; pulling can take a while
const DOCKER_PULL_ESTIMATE = 5 * time.Minute

const StackName = "lucid64"

var builtArtifacts world.BuiltArtifacts
var componentMaker world.ComponentMaker

var (
	plumbing      ifrit.Process
	gardenProcess ifrit.Process
	bbs           *Bbs.BBS
	natsClient    diegonats.NATSClient
	gardenClient  garden_api.Client
)

var _ = SynchronizedBeforeSuite(func() []byte {
	payload, err := json.Marshal(world.BuiltArtifacts{
		Executables:  CompileTestedExecutables(),
		Circuses:     CompileAndZipUpCircuses(),
		DockerCircus: CompileAndZipUpDockerCircus(),
	})
	Ω(err).ShouldNot(HaveOccurred())

	return payload
}, func(encodedBuiltArtifacts []byte) {
	var err error

	err = json.Unmarshal(encodedBuiltArtifacts, &builtArtifacts)
	Ω(err).ShouldNot(HaveOccurred())

	addresses := world.ComponentAddresses{
		GardenLinux:    fmt.Sprintf("127.0.0.1:%d", 10000+config.GinkgoConfig.ParallelNode),
		NATS:           fmt.Sprintf("127.0.0.1:%d", 11000+config.GinkgoConfig.ParallelNode),
		Etcd:           fmt.Sprintf("127.0.0.1:%d", 12000+config.GinkgoConfig.ParallelNode),
		EtcdPeer:       fmt.Sprintf("127.0.0.1:%d", 12500+config.GinkgoConfig.ParallelNode),
		Executor:       fmt.Sprintf("127.0.0.1:%d", 13000+config.GinkgoConfig.ParallelNode),
		Rep:            fmt.Sprintf("127.0.0.1:%d", 14000+config.GinkgoConfig.ParallelNode),
		LoggregatorIn:  fmt.Sprintf("127.0.0.1:%d", 15000+config.GinkgoConfig.ParallelNode),
		LoggregatorOut: fmt.Sprintf("127.0.0.1:%d", 16000+config.GinkgoConfig.ParallelNode),
		FileServer:     fmt.Sprintf("127.0.0.1:%d", 17000+config.GinkgoConfig.ParallelNode),
		Router:         fmt.Sprintf("127.0.0.1:%d", 18000+config.GinkgoConfig.ParallelNode),
		TPS:            fmt.Sprintf("127.0.0.1:%d", 19000+config.GinkgoConfig.ParallelNode),
		FakeCC:         fmt.Sprintf("127.0.0.1:%d", 20000+config.GinkgoConfig.ParallelNode),
	}

	gardenBinPath := os.Getenv("GARDEN_BINPATH")
	gardenRootFSPath := os.Getenv("GARDEN_ROOTFS")
	gardenGraphPath := os.Getenv("GARDEN_GRAPH_PATH")
	externalAddress := os.Getenv("EXTERNAL_ADDRESS")

	if gardenGraphPath == "" {
		gardenGraphPath = os.TempDir()
	}

	Ω(gardenBinPath).ShouldNot(BeEmpty(), "must provide $GARDEN_BINPATH")
	Ω(gardenRootFSPath).ShouldNot(BeEmpty(), "must provide $GARDEN_ROOTFS")
	Ω(externalAddress).ShouldNot(BeEmpty(), "must provide $EXTERNAL_ADDRESS")

	componentMaker = world.ComponentMaker{
		Artifacts: builtArtifacts,
		Addresses: addresses,

		Stack: StackName,

		ExternalAddress: externalAddress,

		GardenBinPath:    gardenBinPath,
		GardenRootFSPath: gardenRootFSPath,
		GardenGraphPath:  gardenGraphPath,
	}
})

var _ = BeforeEach(func() {
	currentTestDescription := CurrentGinkgoTestDescription()
	fmt.Fprintf(GinkgoWriter, "\n%s\n%s\n\n", strings.Repeat("~", 50), currentTestDescription.FullTestText)

	gardenLinux := componentMaker.GardenLinux()

	plumbing = ginkgomon.Invoke(grouper.NewParallel(os.Kill, grouper.Members{
		{"etcd", componentMaker.Etcd()},
		{"nats", componentMaker.NATS()},
	}))

	gardenProcess = ginkgomon.Invoke(gardenLinux)

	gardenClient = gardenLinux.NewClient()

	var err error
	natsClient = diegonats.NewClient()
	_, err = natsClient.Connect([]string{"nats://" + componentMaker.Addresses.NATS})
	Ω(err).ShouldNot(HaveOccurred())

	adapter := etcdstoreadapter.NewETCDStoreAdapter([]string{"http://" + componentMaker.Addresses.Etcd}, workerpool.NewWorkerPool(20))

	err = adapter.Connect()
	Ω(err).ShouldNot(HaveOccurred())

	bbs = Bbs.NewBBS(adapter, timeprovider.NewTimeProvider(), lagertest.NewTestLogger("test"))

	inigo_server.Start(componentMaker.ExternalAddress)
})

var _ = AfterEach(func() {
	inigo_server.Stop(gardenClient)

	helpers.StopProcess(plumbing)

	containers, err := gardenClient.Containers(nil)
	Ω(err).ShouldNot(HaveOccurred())

	// even if containers fail to destroy, stop garden, but still report the
	// errors
	destroyContainerErrors := []error{}
	for _, container := range containers {
		err := gardenClient.Destroy(container.Handle())
		if err != nil {
			destroyContainerErrors = append(destroyContainerErrors, err)
		}
	}

	helpers.StopProcess(gardenProcess)

	Ω(destroyContainerErrors).Should(
		BeEmpty(),
		"%d of %d containers failed to be destroyed!",
		len(destroyContainerErrors),
		len(containers),
	)
})

func TestInigo(t *testing.T) {
	registerDefaultTimeouts()

	RegisterFailHandler(Fail)

	RunSpecsWithDefaultAndCustomReporters(t, "Inigo Integration Suite", []Reporter{
		ginkgoreporter.New(GinkgoWriter),
	})
}

func registerDefaultTimeouts() {
	var err error
	if os.Getenv("DEFAULT_EVENTUALLY_TIMEOUT") != "" {
		DEFAULT_EVENTUALLY_TIMEOUT, err = time.ParseDuration(os.Getenv("DEFAULT_EVENTUALLY_TIMEOUT"))
		if err != nil {
			panic(err)
		}
	}

	if os.Getenv("DEFAULT_CONSISTENTLY_DURATION") != "" {
		DEFAULT_CONSISTENTLY_DURATION, err = time.ParseDuration(os.Getenv("DEFAULT_CONSISTENTLY_DURATION"))
		if err != nil {
			panic(err)
		}
	}

	SetDefaultEventuallyTimeout(DEFAULT_EVENTUALLY_TIMEOUT)
	SetDefaultConsistentlyDuration(DEFAULT_CONSISTENTLY_DURATION)

	// most things hit some component; don't hammer it
	SetDefaultConsistentlyPollingInterval(100 * time.Millisecond)
	SetDefaultEventuallyPollingInterval(500 * time.Millisecond)
}

func CompileTestedExecutables() world.BuiltExecutables {
	var err error

	builtExecutables := world.BuiltExecutables{}

	builtExecutables["garden-linux"], err = gexec.BuildIn(os.Getenv("GARDEN_LINUX_GOPATH"), "github.com/cloudfoundry-incubator/garden-linux", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["loggregator"], err = gexec.BuildIn(os.Getenv("LOGGREGATOR_GOPATH"), "loggregator")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["auctioneer"], err = gexec.BuildIn(os.Getenv("AUCTIONEER_GOPATH"), "github.com/cloudfoundry-incubator/auctioneer", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["exec"], err = gexec.BuildIn(os.Getenv("EXECUTOR_GOPATH"), "github.com/cloudfoundry-incubator/executor/cmd/executor", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["converger"], err = gexec.BuildIn(os.Getenv("CONVERGER_GOPATH"), "github.com/cloudfoundry-incubator/converger", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["rep"], err = gexec.BuildIn(os.Getenv("REP_GOPATH"), "github.com/cloudfoundry-incubator/rep", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["stager"], err = gexec.BuildIn(os.Getenv("STAGER_GOPATH"), "github.com/cloudfoundry-incubator/stager", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["nsync-listener"], err = gexec.BuildIn(os.Getenv("NSYNC_GOPATH"), "github.com/cloudfoundry-incubator/nsync/cmd/nsync-listener", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["nsync-bulker"], err = gexec.BuildIn(os.Getenv("NSYNC_GOPATH"), "github.com/cloudfoundry-incubator/nsync/cmd/nsync-bulker", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["file-server"], err = gexec.BuildIn(os.Getenv("FILE_SERVER_GOPATH"), "github.com/cloudfoundry-incubator/file-server/cmd/file-server", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["route-emitter"], err = gexec.BuildIn(os.Getenv("ROUTE_EMITTER_GOPATH"), "github.com/cloudfoundry-incubator/route-emitter", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["router"], err = gexec.BuildIn(os.Getenv("ROUTER_GOPATH"), "github.com/cloudfoundry/gorouter", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	builtExecutables["tps"], err = gexec.BuildIn(os.Getenv("TPS_GOPATH"), "github.com/cloudfoundry-incubator/tps", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	return builtExecutables
}

func CompileAndZipUpCircuses() world.BuiltCircuses {
	builtCircuses := world.BuiltCircuses{}

	tailorPath, err := gexec.BuildIn(os.Getenv("LINUX_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/linux-circus/tailor", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	spyPath, err := gexec.BuildIn(os.Getenv("LINUX_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/linux-circus/spy", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	soldierPath, err := gexec.BuildIn(os.Getenv("LINUX_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/linux-circus/soldier", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	circusDir, err := ioutil.TempDir("", "circus-dir")
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(tailorPath, filepath.Join(circusDir, "tailor"))
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(spyPath, filepath.Join(circusDir, "spy"))
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(soldierPath, filepath.Join(circusDir, "soldier"))
	Ω(err).ShouldNot(HaveOccurred())

	cmd := exec.Command("zip", "-v", "circus.zip", "tailor", "soldier", "spy")
	cmd.Stderr = GinkgoWriter
	cmd.Stdout = GinkgoWriter
	cmd.Dir = circusDir
	err = cmd.Run()
	Ω(err).ShouldNot(HaveOccurred())

	builtCircuses[StackName] = filepath.Join(circusDir, "circus.zip")

	return builtCircuses
}

func CompileAndZipUpDockerCircus() string {
	tailorPath, err := gexec.BuildIn(os.Getenv("DOCKER_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/docker-circus/tailor", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	spyPath, err := gexec.BuildIn(os.Getenv("DOCKER_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/docker-circus/spy", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	soldierPath, err := gexec.BuildIn(os.Getenv("DOCKER_CIRCUS_GOPATH"), "github.com/cloudfoundry-incubator/docker-circus/soldier", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	circusDir, err := ioutil.TempDir("", "circus-dir")
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(tailorPath, filepath.Join(circusDir, "tailor"))
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(spyPath, filepath.Join(circusDir, "spy"))
	Ω(err).ShouldNot(HaveOccurred())

	err = os.Rename(soldierPath, filepath.Join(circusDir, "soldier"))
	Ω(err).ShouldNot(HaveOccurred())

	cmd := exec.Command("zip", "-v", "docker-circus.zip", "tailor", "soldier", "spy")
	cmd.Stderr = GinkgoWriter
	cmd.Stdout = GinkgoWriter
	cmd.Dir = circusDir
	err = cmd.Run()
	Ω(err).ShouldNot(HaveOccurred())

	return filepath.Join(circusDir, "docker-circus.zip")
}
<|endoftext|>


<commit_before>package inigo_test

import (
	"fmt"
	"github.com/onsi/ginkgo/config"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"syscall"
	"testing"

	"github.com/cloudfoundry/gunk/natsrunner"

	"github.com/cloudfoundry/storeadapter/storerunner/etcdstorerunner"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/vito/cmdtest"
	"github.com/vito/gordon"

	"github.com/cloudfoundry-incubator/inigo/executor_runner"
	"github.com/cloudfoundry-incubator/inigo/fileserver_runner"
	"github.com/cloudfoundry-incubator/inigo/inigolistener"
	"github.com/cloudfoundry-incubator/inigo/loggregator_runner"
	"github.com/cloudfoundry-incubator/inigo/stager_runner"
	"github.com/pivotal-cf-experimental/garden/integration/garden_runner"
)

var etcdRunner *etcdstorerunner.ETCDClusterRunner

var gardenRunner *garden_runner.GardenRunner
var wardenClient gordon.Client

var natsRunner *natsrunner.NATSRunner
var natsPort int

var loggregatorRunner *loggregator_runner.LoggregatorRunner
var loggregatorPort int
var loggregatorSharedSecret string

var executorRunner *executor_runner.ExecutorRunner
var executorPath string

var stagerRunner *stager_runner.StagerRunner
var stagerPath string

var fileServerRunner *fileserver_runner.FileServerRunner
var fileServerPath string
var fileServerPort int

var smelterZipPath string

func TestInigo(t *testing.T) {
	registerSignalHandler()
	RegisterFailHandler(Fail)

	setUpEtcd()
	setUpGarden()
	setUpNats()
	setUpLoggregator()
	setUpExecutor()
	setUpStager()
	compileAndZipUpSmelter()
	setUpFileServer()

	RunSpecs(t, "Inigo Integration Suite")

	cleanup()
}

var _ = BeforeEach(func() {
	startGarden()
	etcdRunner.Start()
	natsRunner.Start()
	loggregatorRunner.Start()

	gardenRunner.DestroyContainers()

	inigolistener.Start(wardenClient)
})

var _ = AfterEach(func() {
	executorRunner.Stop()
	stagerRunner.Stop()
	fileServerRunner.Stop()

	loggregatorRunner.Stop()
	natsRunner.Stop()
	etcdRunner.Stop()
})

func setUpEtcd() {
	etcdRunner = etcdstorerunner.NewETCDClusterRunner(5001+config.GinkgoConfig.ParallelNode, 1)
}

func setUpGarden() {
	gardenBinPath := os.Getenv("GARDEN_BINPATH")
	gardenRootfs := os.Getenv("GARDEN_ROOTFS")

	if gardenBinPath == "" || gardenRootfs == "" {
		println("Please define either WARDEN_NETWORK and WARDEN_ADDR (for a running Warden), or")
		println("GARDEN_BINPATH and GARDEN_ROOTFS (for the tests to start it)")
		println("")
		failFast("garden is not set up")
		return
	}

	var err error

	gardenRunner, err = garden_runner.New(gardenBinPath, gardenRootfs)
	if err != nil {
		failFast("garden failed to initialize: " + err.Error())
	}

	gardenRunner.SnapshotsPath = ""
}

var didStartGarden = false

func startGarden() {
	if didStartGarden {
		return
	}
	didStartGarden = true

	err := gardenRunner.Start()
	if err != nil {
		failFast("garden failed to start: " + err.Error())
	}

	wardenClient = gardenRunner.NewClient()

	err = wardenClient.Connect()
	if err != nil {
		failFast("warden is not up")
		return
	}
}

func setUpNats() {
	natsPort = 4222 + config.GinkgoConfig.ParallelNode
	natsRunner = natsrunner.NewNATSRunner(natsPort)
}

func setUpLoggregator() {
	loggregatorPort = 3456 + config.GinkgoConfig.ParallelNode
	loggregatorSharedSecret = "conspiracy"

	// hack around GOPATH to compile loggregator
	originalGopath := os.Getenv("GOPATH")

	os.Setenv("GOPATH", os.Getenv("LOGGREGATOR_GOPATH"))

	loggregatorPath, err := cmdtest.Build("loggregator/loggregator")
	if err != nil {
		failFast("failed to compile loggregator")
	}

	os.Setenv("GOPATH", originalGopath)

	loggregatorRunner = loggregator_runner.New(
		loggregatorPath,
		loggregator_runner.Config{
			IncomingPort:           loggregatorPort,
			OutgoingPort:           8083 + config.GinkgoConfig.ParallelNode,
			MaxRetainedLogMessages: 1000,
			SharedSecret:           loggregatorSharedSecret,
			NatsHost:               "127.0.0.1",
			NatsPort:               natsPort,
		},
	)
}

func setUpExecutor() {
	var err error
	executorPath, err = cmdtest.Build("github.com/cloudfoundry-incubator/executor")
	if err != nil {
		failFast("failed to compile executor")
	}

	executorRunner = executor_runner.New(
		executorPath,
		gardenRunner.Network,
		gardenRunner.Addr,
		etcdRunner.NodeURLS(),
		fmt.Sprintf("127.0.0.1:%d", loggregatorPort),
		loggregatorSharedSecret,
	)
}

func setUpStager() {
	var err error
	stagerPath, err = cmdtest.Build("github.com/cloudfoundry-incubator/stager")
	if err != nil {
		failFast("failed to compile stager")
	}

	stagerRunner = stager_runner.New(
		stagerPath,
		etcdRunner.NodeURLS(),
		[]string{fmt.Sprintf("127.0.0.1:%d", natsPort)},
	)
}

func compileAndZipUpSmelter() {
	smelterPath, err := cmdtest.Build("github.com/cloudfoundry-incubator/linux-smelter")
	if err != nil {
		failFast("failed to compile smelter", err)
	}

	smelterDir := filepath.Dir(smelterPath)
	err = os.Rename(smelterPath, filepath.Join(smelterDir, "run"))
	if err != nil {
		failFast("failed to move smelter", err)
	}

	cmd := exec.Command("zip", "smelter.zip", "run")
	cmd.Dir = smelterDir
	err = cmd.Run()
	if err != nil {
		failFast("failed to zip up smelter", err)
	}

	smelterZipPath = filepath.Join(smelterDir, "smelter.zip")
}

func setUpFileServer() {
	var err error
	fileServerPath, err = cmdtest.Build("github.com/cloudfoundry-incubator/file-server")
	if err != nil {
		failFast("failed to compile file server")
	}
	fileServerPort = 12760 + config.GinkgoConfig.ParallelNode
	fileServerRunner = fileserver_runner.New(fileServerPath, fileServerPort, etcdRunner.NodeURLS())
}

func cleanup() {
	if etcdRunner != nil {
		etcdRunner.Stop()
	}

	if gardenRunner != nil {
		gardenRunner.Stop()
	}

	if natsRunner != nil {
		natsRunner.Stop()
	}

	if loggregatorRunner != nil {
		loggregatorRunner.Stop()
	}

	if executorRunner != nil {
		executorRunner.Stop()
	}

	if stagerRunner != nil {
		stagerRunner.Stop()
	}

	if fileServerRunner != nil {
		fileServerRunner.Stop()
	}
}

func failFast(msg string, errs ...error) {
	println("!!!!! " + msg + " !!!!!")
	if len(errs) > 0 {
		println("error: " + errs[0].Error())
	}
	cleanup()
	os.Exit(1)
}

func registerSignalHandler() {
	c := make(chan os.Signal, 1)

	go func() {
		select {
		case <-c:
			println("cleaning up!")

			cleanup()

			println("goodbye!")
			os.Exit(1)
		}
	}()

	signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
}
<commit_msg>add moar logging<commit_after>package inigo_test

import (
	"fmt"
	"github.com/onsi/ginkgo/config"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"strings"
	"syscall"
	"testing"

	"github.com/cloudfoundry/gunk/natsrunner"

	"github.com/cloudfoundry/storeadapter/storerunner/etcdstorerunner"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/vito/cmdtest"
	"github.com/vito/gordon"

	"github.com/cloudfoundry-incubator/inigo/executor_runner"
	"github.com/cloudfoundry-incubator/inigo/fileserver_runner"
	"github.com/cloudfoundry-incubator/inigo/inigolistener"
	"github.com/cloudfoundry-incubator/inigo/loggregator_runner"
	"github.com/cloudfoundry-incubator/inigo/stager_runner"
	"github.com/pivotal-cf-experimental/garden/integration/garden_runner"
)

var etcdRunner *etcdstorerunner.ETCDClusterRunner

var gardenRunner *garden_runner.GardenRunner
var wardenClient gordon.Client

var natsRunner *natsrunner.NATSRunner
var natsPort int

var loggregatorRunner *loggregator_runner.LoggregatorRunner
var loggregatorPort int
var loggregatorSharedSecret string

var executorRunner *executor_runner.ExecutorRunner
var executorPath string

var stagerRunner *stager_runner.StagerRunner
var stagerPath string

var fileServerRunner *fileserver_runner.FileServerRunner
var fileServerPath string
var fileServerPort int

var smelterZipPath string

func TestInigo(t *testing.T) {
	registerSignalHandler()
	RegisterFailHandler(Fail)

	setUpEtcd()
	setUpGarden()
	setUpNats()
	setUpLoggregator()
	setUpExecutor()
	setUpStager()
	compileAndZipUpSmelter()
	setUpFileServer()

	RunSpecs(t, "Inigo Integration Suite")

	cleanup()
}

var _ = BeforeEach(func() {
	startGarden()
	etcdRunner.Start()
	natsRunner.Start()
	loggregatorRunner.Start()

	gardenRunner.DestroyContainers()

	inigolistener.Start(wardenClient)

	currentTestDescription := CurrentGinkgoTestDescription()
	fmt.Fprintf(GinkgoWriter, "\n%s\n%s\n\n", strings.Repeat("~", 50), currentTestDescription.FullTestText)
})

var _ = AfterEach(func() {
	executorRunner.Stop()
	stagerRunner.Stop()
	fileServerRunner.Stop()

	loggregatorRunner.Stop()
	natsRunner.Stop()
	etcdRunner.Stop()
})

func setUpEtcd() {
	etcdRunner = etcdstorerunner.NewETCDClusterRunner(5001+config.GinkgoConfig.ParallelNode, 1)
}

func setUpGarden() {
	gardenBinPath := os.Getenv("GARDEN_BINPATH")
	gardenRootfs := os.Getenv("GARDEN_ROOTFS")

	if gardenBinPath == "" || gardenRootfs == "" {
		println("Please define either WARDEN_NETWORK and WARDEN_ADDR (for a running Warden), or")
		println("GARDEN_BINPATH and GARDEN_ROOTFS (for the tests to start it)")
		println("")
		failFast("garden is not set up")
		return
	}

	var err error

	gardenRunner, err = garden_runner.New(gardenBinPath, gardenRootfs)
	if err != nil {
		failFast("garden failed to initialize: " + err.Error())
	}

	gardenRunner.SnapshotsPath = ""
}

var didStartGarden = false

func startGarden() {
	if didStartGarden {
		return
	}
	didStartGarden = true

	err := gardenRunner.Start()
	if err != nil {
		failFast("garden failed to start: " + err.Error())
	}

	wardenClient = gardenRunner.NewClient()

	err = wardenClient.Connect()
	if err != nil {
		failFast("warden is not up")
		return
	}
}

func setUpNats() {
	natsPort = 4222 + config.GinkgoConfig.ParallelNode
	natsRunner = natsrunner.NewNATSRunner(natsPort)
}

func setUpLoggregator() {
	loggregatorPort = 3456 + config.GinkgoConfig.ParallelNode
	loggregatorSharedSecret = "conspiracy"

	// hack around GOPATH to compile loggregator
	originalGopath := os.Getenv("GOPATH")

	os.Setenv("GOPATH", os.Getenv("LOGGREGATOR_GOPATH"))

	loggregatorPath, err := cmdtest.Build("loggregator/loggregator")
	if err != nil {
		failFast("failed to compile loggregator")
	}

	os.Setenv("GOPATH", originalGopath)

	loggregatorRunner = loggregator_runner.New(
		loggregatorPath,
		loggregator_runner.Config{
			IncomingPort:           loggregatorPort,
			OutgoingPort:           8083 + config.GinkgoConfig.ParallelNode,
			MaxRetainedLogMessages: 1000,
			SharedSecret:           loggregatorSharedSecret,
			NatsHost:               "127.0.0.1",
			NatsPort:               natsPort,
		},
	)
}

func setUpExecutor() {
	var err error
	executorPath, err = cmdtest.Build("github.com/cloudfoundry-incubator/executor")
	if err != nil {
		failFast("failed to compile executor")
	}

	executorRunner = executor_runner.New(
		executorPath,
		gardenRunner.Network,
		gardenRunner.Addr,
		etcdRunner.NodeURLS(),
		fmt.Sprintf("127.0.0.1:%d", loggregatorPort),
		loggregatorSharedSecret,
	)
}

func setUpStager() {
	var err error
	stagerPath, err = cmdtest.Build("github.com/cloudfoundry-incubator/stager")
	if err != nil {
		failFast("failed to compile stager")
	}

	stagerRunner = stager_runner.New(
		stagerPath,
		etcdRunner.NodeURLS(),
		[]string{fmt.Sprintf("127.0.0.1:%d", natsPort)},
	)
}

func compileAndZipUpSmelter() {
	smelterPath, err := cmdtest.Build("github.com/cloudfoundry-incubator/linux-smelter")
	if err != nil {
		failFast("failed to compile smelter", err)
	}

	smelterDir := filepath.Dir(smelterPath)
	err = os.Rename(smelterPath, filepath.Join(smelterDir, "run"))
	if err != nil {
		failFast("failed to move smelter", err)
	}

	cmd := exec.Command("zip", "smelter.zip", "run")
	cmd.Dir = smelterDir
	err = cmd.Run()
	if err != nil {
		failFast("failed to zip up smelter", err)
	}

	smelterZipPath = filepath.Join(smelterDir, "smelter.zip")
}

func setUpFileServer() {
	var err error
	fileServerPath, err = cmdtest.Build("github.com/cloudfoundry-incubator/file-server")
	if err != nil {
		failFast("failed to compile file server")
	}
	fileServerPort = 12760 + config.GinkgoConfig.ParallelNode
	fileServerRunner = fileserver_runner.New(fileServerPath, fileServerPort, etcdRunner.NodeURLS())
}

func cleanup() {
	if etcdRunner != nil {
		etcdRunner.Stop()
	}

	if gardenRunner != nil {
		gardenRunner.Stop()
	}

	if natsRunner != nil {
		natsRunner.Stop()
	}

	if loggregatorRunner != nil {
		loggregatorRunner.Stop()
	}

	if executorRunner != nil {
		executorRunner.Stop()
	}

	if stagerRunner != nil {
		stagerRunner.Stop()
	}

	if fileServerRunner != nil {
		fileServerRunner.Stop()
	}
}

func failFast(msg string, errs ...error) {
	println("!!!!! " + msg + " !!!!!")
	if len(errs) > 0 {
		println("error: " + errs[0].Error())
	}
	cleanup()
	os.Exit(1)
}

func registerSignalHandler() {
	c := make(chan os.Signal, 1)

	go func() {
		select {
		case <-c:
			println("cleaning up!")

			cleanup()

			println("goodbye!")
			os.Exit(1)
		}
	}()

	signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
}
<|endoftext|>


<commit_before>// Copyright 2019 The Go Cloud Development Kit 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
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package dynamodocstore

import (
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"time"

	dyn "github.com/aws/aws-sdk-go/service/dynamodb"
	"gocloud.dev/internal/docstore/driver"
)

var nullValue = new(dyn.AttributeValue).SetNULL(true)

type encoder struct {
	av *dyn.AttributeValue
}

func (e *encoder) EncodeNil()            { e.av = nullValue }
func (e *encoder) EncodeBool(x bool)     { e.av = new(dyn.AttributeValue).SetBOOL(x) }
func (e *encoder) EncodeInt(x int64)     { e.av = new(dyn.AttributeValue).SetN(strconv.FormatInt(x, 10)) }
func (e *encoder) EncodeUint(x uint64)   { e.av = new(dyn.AttributeValue).SetN(strconv.FormatUint(x, 10)) }
func (e *encoder) EncodeBytes(x []byte)  { e.av = new(dyn.AttributeValue).SetB(x) }
func (e *encoder) EncodeFloat(x float64) { e.av = encodeFloat(x) }

func (e *encoder) ListIndex(int) { panic("impossible") }
func (e *encoder) MapKey(string) { panic("impossible") }

func (e *encoder) EncodeString(x string) {
	if len(x) == 0 {
		e.av = nullValue
	} else {
		e.av = new(dyn.AttributeValue).SetS(x)
	}
}

func (e *encoder) EncodeComplex(x complex128) {
	e.av = new(dyn.AttributeValue).SetL([]*dyn.AttributeValue{encodeFloat(real(x)), encodeFloat(imag(x))})
}

func (e *encoder) EncodeList(n int) driver.Encoder {
	s := make([]*dyn.AttributeValue, n)
	e.av = new(dyn.AttributeValue).SetL(s)
	return &listEncoder{s: s}
}

func (e *encoder) EncodeMap(n int, _ bool) driver.Encoder {
	m := make(map[string]*dyn.AttributeValue, n)
	e.av = new(dyn.AttributeValue).SetM(m)
	return &mapEncoder{m: m}
}

var typeOfGoTime = reflect.TypeOf(time.Time{})

// EncodeSpecial encodes time.Time specially.
func (e *encoder) EncodeSpecial(v reflect.Value) (bool, error) {
	switch v.Type() {
	case typeOfGoTime:
		ts := v.Interface().(time.Time).Format(time.RFC3339Nano)
		e.EncodeString(ts)
	default:
		return false, nil
	}
	return true, nil
}

type listEncoder struct {
	s []*dyn.AttributeValue
	encoder
}

func (e *listEncoder) ListIndex(i int) { e.s[i] = e.av }

type mapEncoder struct {
	m map[string]*dyn.AttributeValue
	encoder
}

func (e *mapEncoder) MapKey(k string) { e.m[k] = e.av }

func encodeDoc(doc driver.Document) (*dyn.AttributeValue, error) {
	var e encoder
	if err := doc.Encode(&e); err != nil {
		return nil, err
	}
	return e.av, nil
}

// Encode only the key fields of the given document.
// pkey and skey are the names of the partition key field and the sort key field.
// pkey must always be non-empty, but skey may be empty if the collection has no sort key.
//
// Currently, we do this by encoding the entire document, then removing everything that is
// not a key field.
// TODO: improve driver.Encoder to make this efficient.
func encodeDocKeyFields(doc driver.Document, pkey, skey string) (*dyn.AttributeValue, error) {
	av, err := encodeDoc(doc)
	if err != nil {
		return nil, err
	}
	// Check that the document has all the key fields.
	hasP := false
	hasS := false
	if skey == "" {
		// If there is no sort key, assume we found it.
		hasS = true
	}
	for f := range av.M {
		switch f {
		case pkey:
			hasP = true
		case skey:
			hasS = true
		default:
			// Delete any non-key field from the result.
			delete(av.M, f)
		}
	}
	if !hasP || !hasS {
		return nil, errors.New("missing key field(s)")
	}
	return av, nil
}

func encodeValue(v interface{}) (*dyn.AttributeValue, error) {
	var e encoder
	if err := driver.Encode(reflect.ValueOf(v), &e); err != nil {
		return nil, err
	}
	return e.av, nil
}

func encodeFloat(f float64) *dyn.AttributeValue {
	return new(dyn.AttributeValue).SetN(strconv.FormatFloat(f, 'f', -1, 64))
}

////////////////////////////////////////////////////////////////

func decodeDoc(item *dyn.AttributeValue, doc driver.Document) error {
	return doc.Decode(decoder{av: item})
}

type decoder struct {
	av *dyn.AttributeValue
}

func (d decoder) String() string {
	return d.av.String()
}

func (d decoder) AsBool() (bool, bool) {
	if d.av.BOOL == nil {
		return false, false
	}
	return *d.av.BOOL, true
}

func (d decoder) AsNull() bool {
	return d.av.NULL != nil
}

func (d decoder) AsString() (string, bool) {
	// Empty string is represented by NULL.
	if d.av.NULL != nil {
		return "", true
	}
	if d.av.S == nil {
		return "", false
	}
	return *d.av.S, true
}

func (d decoder) AsInt() (int64, bool) {
	if d.av.N == nil {
		return 0, false
	}
	i, err := strconv.ParseInt(*d.av.N, 10, 64)
	if err != nil {
		return 0, false
	}
	return i, true
}

func (d decoder) AsUint() (uint64, bool) {
	if d.av.N == nil {
		return 0, false
	}
	u, err := strconv.ParseUint(*d.av.N, 10, 64)
	if err != nil {
		return 0, false
	}
	return u, true
}

func (d decoder) AsFloat() (float64, bool) {
	if d.av.N == nil {
		return 0, false
	}
	f, err := strconv.ParseFloat(*d.av.N, 64)
	if err != nil {
		return 0, false
	}
	return f, true

}

func (d decoder) AsComplex() (complex128, bool) {
	if d.av.L == nil {
		return 0, false
	}
	if len(d.av.L) != 2 {
		return 0, false
	}
	r, ok := decoder{d.av.L[0]}.AsFloat()
	if !ok {
		return 0, false
	}
	i, ok := decoder{d.av.L[1]}.AsFloat()
	if !ok {
		return 0, false
	}
	return complex(r, i), true
}

func (d decoder) AsBytes() ([]byte, bool) {
	if d.av.B == nil {
		return nil, false
	}
	return d.av.B, true
}

func (d decoder) ListLen() (int, bool) {
	if d.av.L == nil {
		return 0, false
	}
	return len(d.av.L), true
}

func (d decoder) DecodeList(f func(i int, vd driver.Decoder) bool) {
	for i, el := range d.av.L {
		if !f(i, decoder{el}) {
			break
		}
	}
}

func (d decoder) MapLen() (int, bool) {
	if d.av.M == nil {
		return 0, false
	}
	return len(d.av.M), true
}

func (d decoder) DecodeMap(f func(key string, vd driver.Decoder) bool) {
	for k, av := range d.av.M {
		if !f(k, decoder{av}) {
			break
		}
	}
}

func (d decoder) AsInterface() (interface{}, error) {
	return toGoValue(d.av)
}

func toGoValue(av *dyn.AttributeValue) (interface{}, error) {
	switch {
	case av.NULL != nil:
		return nil, nil
	case av.BOOL != nil:
		return *av.BOOL, nil
	case av.N != nil:
		f, err := strconv.ParseFloat(*av.N, 64)
		if err != nil {
			return nil, err
		}
		i := int64(f)
		if float64(i) == f {
			return i, nil
		}
		u := uint64(f)
		if float64(u) == f {
			return u, nil
		}
		return f, nil

	case av.B != nil:
		return av.B, nil
	case av.S != nil:
		return *av.S, nil

	case av.L != nil:
		s := make([]interface{}, len(av.L))
		for i, v := range av.L {
			x, err := toGoValue(v)
			if err != nil {
				return nil, err
			}
			s[i] = x
		}
		return s, nil

	case av.M != nil:
		m := make(map[string]interface{}, len(av.M))
		for k, v := range av.M {
			x, err := toGoValue(v)
			if err != nil {
				return nil, err
			}
			m[k] = x
		}
		return m, nil

	default:
		return nil, fmt.Errorf("dynamodocstore: AttributeValue %s not supported", av)
	}
}

func (d decoder) AsSpecial(v reflect.Value) (bool, interface{}, error) {
	unsupportedTypes := `unsupported type, the docstore driver for DynamoDB does
	not decode DynamoDB set types, such as string set, number set and binary set`
	if d.av.SS != nil || d.av.NS != nil || d.av.BS != nil {
		return true, nil, errors.New(unsupportedTypes)
	}
	switch v.Type() {
	case typeOfGoTime:
		if d.av.S == nil {
			return false, nil, errors.New("expected string field for time.Time")
		}
		t, err := time.Parse(time.RFC3339Nano, *d.av.S)
		return true, t, err
	}
	return false, nil, nil
}
<commit_msg>dynamodocstore: encode key fields more efficiently (#1825)<commit_after>// Copyright 2019 The Go Cloud Development Kit 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
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package dynamodocstore

import (
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"time"

	dyn "github.com/aws/aws-sdk-go/service/dynamodb"
	"gocloud.dev/internal/docstore/driver"
)

var nullValue = new(dyn.AttributeValue).SetNULL(true)

type encoder struct {
	av *dyn.AttributeValue
}

func (e *encoder) EncodeNil()            { e.av = nullValue }
func (e *encoder) EncodeBool(x bool)     { e.av = new(dyn.AttributeValue).SetBOOL(x) }
func (e *encoder) EncodeInt(x int64)     { e.av = new(dyn.AttributeValue).SetN(strconv.FormatInt(x, 10)) }
func (e *encoder) EncodeUint(x uint64)   { e.av = new(dyn.AttributeValue).SetN(strconv.FormatUint(x, 10)) }
func (e *encoder) EncodeBytes(x []byte)  { e.av = new(dyn.AttributeValue).SetB(x) }
func (e *encoder) EncodeFloat(x float64) { e.av = encodeFloat(x) }

func (e *encoder) ListIndex(int) { panic("impossible") }
func (e *encoder) MapKey(string) { panic("impossible") }

func (e *encoder) EncodeString(x string) {
	if len(x) == 0 {
		e.av = nullValue
	} else {
		e.av = new(dyn.AttributeValue).SetS(x)
	}
}

func (e *encoder) EncodeComplex(x complex128) {
	e.av = new(dyn.AttributeValue).SetL([]*dyn.AttributeValue{encodeFloat(real(x)), encodeFloat(imag(x))})
}

func (e *encoder) EncodeList(n int) driver.Encoder {
	s := make([]*dyn.AttributeValue, n)
	e.av = new(dyn.AttributeValue).SetL(s)
	return &listEncoder{s: s}
}

func (e *encoder) EncodeMap(n int, _ bool) driver.Encoder {
	m := make(map[string]*dyn.AttributeValue, n)
	e.av = new(dyn.AttributeValue).SetM(m)
	return &mapEncoder{m: m}
}

var typeOfGoTime = reflect.TypeOf(time.Time{})

// EncodeSpecial encodes time.Time specially.
func (e *encoder) EncodeSpecial(v reflect.Value) (bool, error) {
	switch v.Type() {
	case typeOfGoTime:
		ts := v.Interface().(time.Time).Format(time.RFC3339Nano)
		e.EncodeString(ts)
	default:
		return false, nil
	}
	return true, nil
}

type listEncoder struct {
	s []*dyn.AttributeValue
	encoder
}

func (e *listEncoder) ListIndex(i int) { e.s[i] = e.av }

type mapEncoder struct {
	m map[string]*dyn.AttributeValue
	encoder
}

func (e *mapEncoder) MapKey(k string) { e.m[k] = e.av }

func encodeDoc(doc driver.Document) (*dyn.AttributeValue, error) {
	var e encoder
	if err := doc.Encode(&e); err != nil {
		return nil, err
	}
	return e.av, nil
}

// Encode the key fields of the given document into a map AttributeValue.
// pkey and skey are the names of the partition key field and the sort key field.
// pkey must always be non-empty, but skey may be empty if the collection has no sort key.
func encodeDocKeyFields(doc driver.Document, pkey, skey string) (*dyn.AttributeValue, error) {
	m := map[string]*dyn.AttributeValue{}

	set := func(fieldName string) error {
		fieldVal, err := doc.GetField(fieldName)
		if err != nil {
			return err
		}
		attrVal, err := encodeValue(fieldVal)
		if err != nil {
			return err
		}
		m[fieldName] = attrVal
		return nil
	}

	if err := set(pkey); err != nil {
		return nil, err
	}
	if skey != "" {
		if err := set(skey); err != nil {
			return nil, err
		}
	}
	return new(dyn.AttributeValue).SetM(m), nil
}

func encodeValue(v interface{}) (*dyn.AttributeValue, error) {
	var e encoder
	if err := driver.Encode(reflect.ValueOf(v), &e); err != nil {
		return nil, err
	}
	return e.av, nil
}

func encodeFloat(f float64) *dyn.AttributeValue {
	return new(dyn.AttributeValue).SetN(strconv.FormatFloat(f, 'f', -1, 64))
}

////////////////////////////////////////////////////////////////

func decodeDoc(item *dyn.AttributeValue, doc driver.Document) error {
	return doc.Decode(decoder{av: item})
}

type decoder struct {
	av *dyn.AttributeValue
}

func (d decoder) String() string {
	return d.av.String()
}

func (d decoder) AsBool() (bool, bool) {
	if d.av.BOOL == nil {
		return false, false
	}
	return *d.av.BOOL, true
}

func (d decoder) AsNull() bool {
	return d.av.NULL != nil
}

func (d decoder) AsString() (string, bool) {
	// Empty string is represented by NULL.
	if d.av.NULL != nil {
		return "", true
	}
	if d.av.S == nil {
		return "", false
	}
	return *d.av.S, true
}

func (d decoder) AsInt() (int64, bool) {
	if d.av.N == nil {
		return 0, false
	}
	i, err := strconv.ParseInt(*d.av.N, 10, 64)
	if err != nil {
		return 0, false
	}
	return i, true
}

func (d decoder) AsUint() (uint64, bool) {
	if d.av.N == nil {
		return 0, false
	}
	u, err := strconv.ParseUint(*d.av.N, 10, 64)
	if err != nil {
		return 0, false
	}
	return u, true
}

func (d decoder) AsFloat() (float64, bool) {
	if d.av.N == nil {
		return 0, false
	}
	f, err := strconv.ParseFloat(*d.av.N, 64)
	if err != nil {
		return 0, false
	}
	return f, true

}

func (d decoder) AsComplex() (complex128, bool) {
	if d.av.L == nil {
		return 0, false
	}
	if len(d.av.L) != 2 {
		return 0, false
	}
	r, ok := decoder{d.av.L[0]}.AsFloat()
	if !ok {
		return 0, false
	}
	i, ok := decoder{d.av.L[1]}.AsFloat()
	if !ok {
		return 0, false
	}
	return complex(r, i), true
}

func (d decoder) AsBytes() ([]byte, bool) {
	if d.av.B == nil {
		return nil, false
	}
	return d.av.B, true
}

func (d decoder) ListLen() (int, bool) {
	if d.av.L == nil {
		return 0, false
	}
	return len(d.av.L), true
}

func (d decoder) DecodeList(f func(i int, vd driver.Decoder) bool) {
	for i, el := range d.av.L {
		if !f(i, decoder{el}) {
			break
		}
	}
}

func (d decoder) MapLen() (int, bool) {
	if d.av.M == nil {
		return 0, false
	}
	return len(d.av.M), true
}

func (d decoder) DecodeMap(f func(key string, vd driver.Decoder) bool) {
	for k, av := range d.av.M {
		if !f(k, decoder{av}) {
			break
		}
	}
}

func (d decoder) AsInterface() (interface{}, error) {
	return toGoValue(d.av)
}

func toGoValue(av *dyn.AttributeValue) (interface{}, error) {
	switch {
	case av.NULL != nil:
		return nil, nil
	case av.BOOL != nil:
		return *av.BOOL, nil
	case av.N != nil:
		f, err := strconv.ParseFloat(*av.N, 64)
		if err != nil {
			return nil, err
		}
		i := int64(f)
		if float64(i) == f {
			return i, nil
		}
		u := uint64(f)
		if float64(u) == f {
			return u, nil
		}
		return f, nil

	case av.B != nil:
		return av.B, nil
	case av.S != nil:
		return *av.S, nil

	case av.L != nil:
		s := make([]interface{}, len(av.L))
		for i, v := range av.L {
			x, err := toGoValue(v)
			if err != nil {
				return nil, err
			}
			s[i] = x
		}
		return s, nil

	case av.M != nil:
		m := make(map[string]interface{}, len(av.M))
		for k, v := range av.M {
			x, err := toGoValue(v)
			if err != nil {
				return nil, err
			}
			m[k] = x
		}
		return m, nil

	default:
		return nil, fmt.Errorf("dynamodocstore: AttributeValue %s not supported", av)
	}
}

func (d decoder) AsSpecial(v reflect.Value) (bool, interface{}, error) {
	unsupportedTypes := `unsupported type, the docstore driver for DynamoDB does
	not decode DynamoDB set types, such as string set, number set and binary set`
	if d.av.SS != nil || d.av.NS != nil || d.av.BS != nil {
		return true, nil, errors.New(unsupportedTypes)
	}
	switch v.Type() {
	case typeOfGoTime:
		if d.av.S == nil {
			return false, nil, errors.New("expected string field for time.Time")
		}
		t, err := time.Parse(time.RFC3339Nano, *d.av.S)
		return true, t, err
	}
	return false, nil, nil
}
<|endoftext|>


<commit_before>package testingtproxy

import (
	"fmt"
	"io"
)

type failFunc func(message string, callerSkip ...int)

func New(writer io.Writer, fail failFunc, offset int) *ginkgoTestingTProxy {
	return &ginkgoTestingTProxy{
		fail:   fail,
		offset: offset,
		writer: writer,
	}
}

type ginkgoTestingTProxy struct {
	fail   failFunc
	offset int
	writer io.Writer
}

func (t *ginkgoTestingTProxy) Error(args ...interface{}) {
	t.fail(fmt.Sprintln(args...), t.offset)
}

func (t *ginkgoTestingTProxy) Errorf(format string, args ...interface{}) {
	t.fail(fmt.Sprintf(format, args...), t.offset)
}

func (t *ginkgoTestingTProxy) Fail() {
	t.fail("failed", t.offset)
}

func (t *ginkgoTestingTProxy) FailNow() {
	t.fail("failed", t.offset)
}

func (t *ginkgoTestingTProxy) Fatal(args ...interface{}) {
	t.fail(fmt.Sprintln(args...), t.offset)
}

func (t *ginkgoTestingTProxy) Fatalf(format string, args ...interface{}) {
	t.fail(fmt.Sprintf(format, args...), t.offset)
}

func (t *ginkgoTestingTProxy) Log(args ...interface{}) {
	fmt.Fprintln(t.writer, args...)
}

func (t *ginkgoTestingTProxy) Logf(format string, args ...interface{}) {
	fmt.Fprintf(t.writer, format, args...)
}

func (t *ginkgoTestingTProxy) Failed() bool {
	return false
}

func (t *ginkgoTestingTProxy) Parallel() {
}

func (t *ginkgoTestingTProxy) Skip(args ...interface{}) {
	fmt.Println(args...)
}

func (t *ginkgoTestingTProxy) Skipf(format string, args ...interface{}) {
	fmt.Printf(format, args...)
}

func (t *ginkgoTestingTProxy) SkipNow() {
}

func (t *ginkgoTestingTProxy) Skipped() bool {
	return false
}
<commit_msg>#287 Ensure Logf/Skipf insert newline characters (#288)<commit_after>package testingtproxy

import (
	"fmt"
	"io"
)

type failFunc func(message string, callerSkip ...int)

func New(writer io.Writer, fail failFunc, offset int) *ginkgoTestingTProxy {
	return &ginkgoTestingTProxy{
		fail:   fail,
		offset: offset,
		writer: writer,
	}
}

type ginkgoTestingTProxy struct {
	fail   failFunc
	offset int
	writer io.Writer
}

func (t *ginkgoTestingTProxy) Error(args ...interface{}) {
	t.fail(fmt.Sprintln(args...), t.offset)
}

func (t *ginkgoTestingTProxy) Errorf(format string, args ...interface{}) {
	t.fail(fmt.Sprintf(format, args...), t.offset)
}

func (t *ginkgoTestingTProxy) Fail() {
	t.fail("failed", t.offset)
}

func (t *ginkgoTestingTProxy) FailNow() {
	t.fail("failed", t.offset)
}

func (t *ginkgoTestingTProxy) Fatal(args ...interface{}) {
	t.fail(fmt.Sprintln(args...), t.offset)
}

func (t *ginkgoTestingTProxy) Fatalf(format string, args ...interface{}) {
	t.fail(fmt.Sprintf(format, args...), t.offset)
}

func (t *ginkgoTestingTProxy) Log(args ...interface{}) {
	fmt.Fprintln(t.writer, args...)
}

func (t *ginkgoTestingTProxy) Logf(format string, args ...interface{}) {
	t.Log(fmt.Sprintf(format, args...))
}

func (t *ginkgoTestingTProxy) Failed() bool {
	return false
}

func (t *ginkgoTestingTProxy) Parallel() {
}

func (t *ginkgoTestingTProxy) Skip(args ...interface{}) {
	fmt.Println(args...)
}

func (t *ginkgoTestingTProxy) Skipf(format string, args ...interface{}) {
	t.Skip(fmt.Sprintf(format, args...))
}

func (t *ginkgoTestingTProxy) SkipNow() {
}

func (t *ginkgoTestingTProxy) Skipped() bool {
	return false
}
<|endoftext|>


<commit_before>package testutil

import (
	"path/filepath"

	"veyron.io/tools/lib/collect"
	"veyron.io/tools/lib/envutil"
	"veyron.io/tools/lib/util"
)

// runJSTest is a harness for executing javascript tests.
func runJSTest(ctx *util.Context, testName, testDir, target string, cleanFn func() error, env map[string]string) (_ *TestResult, e error) {
	// Initialize the test.
	cleanup, err := initTest(ctx, testName, []string{"web"})
	if err != nil {
		return nil, err
	}
	defer collect.Error(func() error { return cleanup() }, &e)

	// Navigate to the target directory.
	if err := ctx.Run().Chdir(testDir); err != nil {
		return nil, err
	}

	// Clean up after previous instances of the test.
	if err := ctx.Run().Command("make", "clean"); err != nil {
		return nil, err
	}
	if cleanFn != nil {
		if err := cleanFn(); err != nil {
			return nil, err
		}
	}

	// Run the test target.
	opts := ctx.Run().Opts()
	osEnv := envutil.NewSnapshotFromOS()
	for key, value := range env {
		osEnv.Set(key, value)
	}
	opts.Env = osEnv.Map()
	if err := ctx.Run().CommandWithOpts(opts, "make", target); err != nil {
		return &TestResult{Status: TestFailed}, nil
	}

	return &TestResult{Status: TestPassed}, nil
}

// VeyronJSBuildExtension tests the veyron javascript build extension.
func VeyronJSBuildExtension(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "extension/veyron.crx"
	return runJSTest(ctx, testName, testDir, target, nil, nil)
}

// VeyronJSDoc (re)generates the content of the veyron javascript
// documentation server.
func VeyronJSDoc(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "docs"
	webDir, jsDocDir := "/var/www/jsdoc", filepath.Join(testDir, "docs")
	cleanFn := func() error {
		if err := ctx.Run().RemoveAll(webDir); err != nil {
			return err
		}
		return nil
	}
	result, err := runJSTest(ctx, testName, testDir, target, cleanFn, nil)
	if err != nil {
		return nil, err
	}
	// Move generated js documentation to the web server directory.
	if err := ctx.Run().Rename(jsDocDir, webDir); err != nil {
		return nil, err
	}
	return result, nil
}

// VeyronJSBrowserIntegrationTest runs the veyron javascript integration test in a browser environment using nacl plugin.
func VeyronJSBrowserIntegrationTest(ctx *util.Context, testName string) (*TestResult, error) {
	// TODO(aghassemi): Re-enable the test when it is fixed.
	return &TestResult{Status: TestPassed}, nil

	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "test-integration-browser"
	env := map[string]string{}
	env["XUNIT"] = "true"
	env["BROWSER_OUTPUT"] = XUnitReportPath(testName)
	return runJSTest(ctx, testName, testDir, target, nil, env)
}

// VeyronJSNodeIntegrationTest runs the veyron javascript integration test in NodeJS environment using wspr.
func VeyronJSNodeIntegrationTest(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "test-integration-node"
	env := map[string]string{}
	env["XUNIT"] = "true"
	env["NODE_OUTPUT"] = XUnitReportPath(testName)
	return runJSTest(ctx, testName, testDir, target, nil, env)
}

// VeyronJSUnitTest runs the veyron javascript unit test.
func VeyronJSUnitTest(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "test-unit"
	env := map[string]string{}
	env["XUNIT"] = "true"
	env["NODE_OUTPUT"] = XUnitReportPath(testName)
	return runJSTest(ctx, testName, testDir, target, nil, env)
}

// VeyronJSVdlTest runs the veyron javascript vdl test.
func VeyronJSVdlTest(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "test-vdl"
	env := map[string]string{}
	env["XUNIT"] = "true"
	env["NODE_OUTPUT"] = XUnitReportPath(testName)
	return runJSTest(ctx, testName, testDir, target, nil, env)
}

// VeyronJSVomTest runs the veyron javascript vom test.
func VeyronJSVomTest(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron", "javascript", "vom")
	target := "test"
	env := map[string]string{}
	env["XUNIT"] = "true"
	env["NODE_OUTPUT"] = XUnitReportPath(testName)
	return runJSTest(ctx, testName, testDir, target, nil, env)
}
<commit_msg>tools: updating the location of the jsdoc (reflecting the switch from Apache to Nginx)<commit_after>package testutil

import (
	"path/filepath"

	"veyron.io/tools/lib/collect"
	"veyron.io/tools/lib/envutil"
	"veyron.io/tools/lib/util"
)

// runJSTest is a harness for executing javascript tests.
func runJSTest(ctx *util.Context, testName, testDir, target string, cleanFn func() error, env map[string]string) (_ *TestResult, e error) {
	// Initialize the test.
	cleanup, err := initTest(ctx, testName, []string{"web"})
	if err != nil {
		return nil, err
	}
	defer collect.Error(func() error { return cleanup() }, &e)

	// Navigate to the target directory.
	if err := ctx.Run().Chdir(testDir); err != nil {
		return nil, err
	}

	// Clean up after previous instances of the test.
	if err := ctx.Run().Command("make", "clean"); err != nil {
		return nil, err
	}
	if cleanFn != nil {
		if err := cleanFn(); err != nil {
			return nil, err
		}
	}

	// Run the test target.
	opts := ctx.Run().Opts()
	osEnv := envutil.NewSnapshotFromOS()
	for key, value := range env {
		osEnv.Set(key, value)
	}
	opts.Env = osEnv.Map()
	if err := ctx.Run().CommandWithOpts(opts, "make", target); err != nil {
		return &TestResult{Status: TestFailed}, nil
	}

	return &TestResult{Status: TestPassed}, nil
}

// VeyronJSBuildExtension tests the veyron javascript build extension.
func VeyronJSBuildExtension(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "extension/veyron.crx"
	return runJSTest(ctx, testName, testDir, target, nil, nil)
}

// VeyronJSDoc (re)generates the content of the veyron javascript
// documentation server.
func VeyronJSDoc(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "docs"
	webDir, jsDocDir := "/usr/share/nginx/www/jsdoc", filepath.Join(testDir, "docs")
	cleanFn := func() error {
		if err := ctx.Run().RemoveAll(webDir); err != nil {
			return err
		}
		return nil
	}
	result, err := runJSTest(ctx, testName, testDir, target, cleanFn, nil)
	if err != nil {
		return nil, err
	}
	// Move generated js documentation to the web server directory.
	if err := ctx.Run().Rename(jsDocDir, webDir); err != nil {
		return nil, err
	}
	return result, nil
}

// VeyronJSBrowserIntegrationTest runs the veyron javascript integration test in a browser environment using nacl plugin.
func VeyronJSBrowserIntegrationTest(ctx *util.Context, testName string) (*TestResult, error) {
	// TODO(aghassemi): Re-enable the test when it is fixed.
	return &TestResult{Status: TestPassed}, nil

	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "test-integration-browser"
	env := map[string]string{}
	env["XUNIT"] = "true"
	env["BROWSER_OUTPUT"] = XUnitReportPath(testName)
	return runJSTest(ctx, testName, testDir, target, nil, env)
}

// VeyronJSNodeIntegrationTest runs the veyron javascript integration test in NodeJS environment using wspr.
func VeyronJSNodeIntegrationTest(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "test-integration-node"
	env := map[string]string{}
	env["XUNIT"] = "true"
	env["NODE_OUTPUT"] = XUnitReportPath(testName)
	return runJSTest(ctx, testName, testDir, target, nil, env)
}

// VeyronJSUnitTest runs the veyron javascript unit test.
func VeyronJSUnitTest(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "test-unit"
	env := map[string]string{}
	env["XUNIT"] = "true"
	env["NODE_OUTPUT"] = XUnitReportPath(testName)
	return runJSTest(ctx, testName, testDir, target, nil, env)
}

// VeyronJSVdlTest runs the veyron javascript vdl test.
func VeyronJSVdlTest(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron.js")
	target := "test-vdl"
	env := map[string]string{}
	env["XUNIT"] = "true"
	env["NODE_OUTPUT"] = XUnitReportPath(testName)
	return runJSTest(ctx, testName, testDir, target, nil, env)
}

// VeyronJSVomTest runs the veyron javascript vom test.
func VeyronJSVomTest(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	testDir := filepath.Join(root, "veyron", "javascript", "vom")
	target := "test"
	env := map[string]string{}
	env["XUNIT"] = "true"
	env["NODE_OUTPUT"] = XUnitReportPath(testName)
	return runJSTest(ctx, testName, testDir, target, nil, env)
}
<|endoftext|>


<commit_before>package doubleratchet

import (
	"github.com/stretchr/testify/require"
	"testing"
)

func TestDefaultCrypto_GenerateDH_Basic(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	pair, err := c.GenerateDH()

	// Assert.
	require.Nil(t, err)

	require.EqualValues(t, 0, pair.PrivateKey[0]&7)
	require.EqualValues(t, 0, pair.PrivateKey[31]&128)
	require.EqualValues(t, 64, pair.PrivateKey[31]&64)

	require.NotEqual(t, [32]byte{}, pair.PrivateKey)
	require.NotEqual(t, [32]byte{}, pair.PublicKey)
	require.Len(t, pair.PrivateKey, 32)
	require.Len(t, pair.PublicKey, 32)
	require.NotEqual(t, pair.PublicKey, pair.PrivateKey)
}

func TestDefaultCrypto_GenerateDH_DifferentKeysEveryTime(t *testing.T) {
	// Arrange.
	var (
		c    = DefaultCrypto{}
		keys = make(map[[32]byte]bool)
	)

	for i := 0; i < 100; i++ {
		t.Run("", func(t *testing.T) {
			// Act.
			pair, err := c.GenerateDH()

			// Assert.
			require.Nil(t, err)
			require.False(t, keys[pair.PrivateKey])
			require.False(t, keys[pair.PublicKey])

			// Preserve.
			keys[pair.PrivateKey] = true
			keys[pair.PublicKey] = true
		})
	}
}

func TestDefaultCrypto_DH(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	var (
		alicePair, err1 = c.GenerateDH()
		bobPair, err2   = c.GenerateDH()
		aliceSK         = c.DH(alicePair, bobPair.PublicKey)
		bobSK           = c.DH(bobPair, alicePair.PublicKey)
	)

	// Assert.
	require.Nil(t, err1)
	require.Nil(t, err2)
	require.NotEqual(t, [32]byte{}, aliceSK)
	require.Equal(t, aliceSK, bobSK)
}

func TestDefaultCrypto_KdfRK(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	newRK, newCK := c.KdfRK(
		[32]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40},
		[32]byte{0x9c, 0x1e, 0x68, 0xab, 0x9d, 0x45, 0xf5, 0x82, 0x35, 0xc4, 0x2, 0xa8, 0x82, 0xa1, 0x46, 0x55, 0x35, 0x41, 0xf1, 0x9d, 0x87, 0x2b, 0x59, 0x24, 0x39, 0x3b, 0x91, 0xf7, 0xda, 0x46, 0x56, 0xf},
	)

	// Assert.
	require.NotEqual(t, [32]byte{}, newRK)
	require.NotEqual(t, [32]byte{}, newCK)
	require.Len(t, newRK, 32)
	require.Len(t, newCK, 32)
	require.NotEqual(t, newRK, newCK)
}
<commit_msg>Wrote TestDefaultCrypto_KdfCK<commit_after>package doubleratchet

import (
	"github.com/stretchr/testify/require"
	"testing"
)

func TestDefaultCrypto_GenerateDH_Basic(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	pair, err := c.GenerateDH()

	// Assert.
	require.Nil(t, err)

	require.EqualValues(t, 0, pair.PrivateKey[0]&7)
	require.EqualValues(t, 0, pair.PrivateKey[31]&128)
	require.EqualValues(t, 64, pair.PrivateKey[31]&64)

	require.NotEqual(t, [32]byte{}, pair.PrivateKey)
	require.NotEqual(t, [32]byte{}, pair.PublicKey)
	require.Len(t, pair.PrivateKey, 32)
	require.Len(t, pair.PublicKey, 32)
	require.NotEqual(t, pair.PublicKey, pair.PrivateKey)
}

func TestDefaultCrypto_GenerateDH_DifferentKeysEveryTime(t *testing.T) {
	// Arrange.
	var (
		c    = DefaultCrypto{}
		keys = make(map[[32]byte]bool)
	)

	for i := 0; i < 100; i++ {
		t.Run("", func(t *testing.T) {
			// Act.
			pair, err := c.GenerateDH()

			// Assert.
			require.Nil(t, err)
			require.False(t, keys[pair.PrivateKey])
			require.False(t, keys[pair.PublicKey])

			// Preserve.
			keys[pair.PrivateKey] = true
			keys[pair.PublicKey] = true
		})
	}
}

func TestDefaultCrypto_DH(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	var (
		alicePair, err1 = c.GenerateDH()
		bobPair, err2   = c.GenerateDH()
		aliceSK         = c.DH(alicePair, bobPair.PublicKey)
		bobSK           = c.DH(bobPair, alicePair.PublicKey)
	)

	// Assert.
	require.Nil(t, err1)
	require.Nil(t, err2)
	require.NotEqual(t, [32]byte{}, aliceSK)
	require.Equal(t, aliceSK, bobSK)
}

func TestDefaultCrypto_KdfRK(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	newRK, newCK := c.KdfRK(
		[32]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40},
		[32]byte{0x9c, 0x1e, 0x68, 0xab, 0x9d, 0x45, 0xf5, 0x82, 0x35, 0xc4, 0x2, 0xa8, 0x82, 0xa1, 0x46, 0x55, 0x35, 0x41, 0xf1, 0x9d, 0x87, 0x2b, 0x59, 0x24, 0x39, 0x3b, 0x91, 0xf7, 0xda, 0x46, 0x56, 0xf},
	)

	// Assert.
	require.NotEqual(t, [32]byte{}, newRK)
	require.NotEqual(t, [32]byte{}, newCK)
	require.Len(t, newRK, 32)
	require.Len(t, newCK, 32)
	require.NotEqual(t, newRK, newCK)
}

func TestDefaultCrypto_KdfCK(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	newCK, mk := c.KdfCK([32]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40})

	// Assert.
	require.NotEqual(t, [32]byte{}, newCK)
	require.NotEqual(t, [32]byte{}, mk)
	require.Len(t, newCK, 32)
	require.Len(t, mk, 32)
	require.NotEqual(t, mk, newCK)
}
<|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 main

import (
	"bytes"
	"io"
	"regexp"
	"testing"
)

//NOTE: This method is for avoiding flake tests instead of using reflect.DeepEqual()
func equalAPIArray(a, b apiArray) bool {
	if a == nil && b == nil {
		return true
	}
	if a == nil || b == nil {
		return false
	}
	if len(a) != len(b) {
		return false
	}
	for _, i := range a {
		found := false
		for _, j := range b {
			if i.Method == j.Method && i.URL == j.URL {
				found = true
				break
			}
		}
		if !found {
			return false
		}
	}
	return true
}

func TestParseOpenAPI(t *testing.T) {
	testCases := []struct {
		Rawdata  []byte
		Expected apiArray
	}{
		{
			Rawdata: []byte(`{"paths": {"/resources": {
				"get": {"description": "get available resources"}}}}`),
			Expected: apiArray{
				{Method: "GET", URL: "/resources"},
			},
		},
		{
			Rawdata: []byte(`{"paths": {"/resources": {
				"get": {"description": "get available resources"},
				"post": {"description": "create resource"}}}}`),
			Expected: apiArray{
				{Method: "GET", URL: "/resources"},
				{Method: "POST", URL: "/resources"},
			},
		},
		{
			Rawdata: []byte(`{"paths": {
			"/resources": {
				"get": {"description": "get available resources"},
				"post": {"description": "create resource"}},
			"/foo": {
				"get": {"description": "get avaiable foo"},
				"post": {"description": "create foo"},
				"parameters": [{"type": "string", "description": "This should be ignored", "name": "bar", "in": "query"}]}}}`),
			Expected: apiArray{
				{Method: "GET", URL: "/resources"},
				{Method: "POST", URL: "/resources"},
				{Method: "GET", URL: "/foo"},
				{Method: "POST", URL: "/foo"},
			},
		},
	}
	for _, test := range testCases {
		res := parseOpenAPI(test.Rawdata)
		if !equalAPIArray(res, test.Expected) {
			t.Errorf("OpenAPI did not match expected for test")
			t.Errorf("%#v", res)
			t.Errorf("%#v", test.Expected)
		}
	}
}

func TestParseAPILog(t *testing.T) {
	testCases := []struct {
		Rawdata  io.Reader
		Expected apiArray
	}{
		{
			Rawdata: bytes.NewReader(
				[]byte(`
I0919 15:34:14.943642    6611 round_trippers.go:414] GET https://k8s-api/api/v1/foo
I0919 15:34:16.943642    6611 round_trippers.go:414] POST https://k8s-api/api/v1/bar
`)),
			Expected: apiArray{
				{Method: "GET", URL: "/api/v1/foo"},
				{Method: "POST", URL: "/api/v1/bar"},
			},
		},
		{
			Rawdata: bytes.NewReader(
				[]byte(`
I0919 15:34:14.943642    6611 round_trippers.go:414] GET https://k8s-api/api/v1/foo?other
`)),
			Expected: apiArray{
				{Method: "GET", URL: "/api/v1/foo"},
			},
		},
	}
	for _, test := range testCases {
		res := parseAPILog(test.Rawdata)
		if !equalAPIArray(res, test.Expected) {
			t.Errorf("APILog did not match expected for test")
			t.Errorf("Actual: %#v", res)
			t.Errorf("Expected: %#v", test.Expected)
		}
	}
}

func TestGetTestedAPIsByLevel(t *testing.T) {
	testCases := []struct {
		Negative       bool
		Reg            *regexp.Regexp
		apisOpenapi    apiArray
		apisTested     apiArray
		ExpectedTested apiArray
		ExpectedAll    apiArray
	}{
		{
			//Test Alpha APIs are returned
			Negative: false,
			Reg:      reAlphaAPI,
			apisOpenapi: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "POST", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "POST", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
				{Method: "POST", URL: "/apis/resources/v1beta1/"},
			},
			apisTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
			},
			ExpectedTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
			},
			ExpectedAll: apiArray{
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "POST", URL: "/apis/resources/v2alpha1/"},
			},
		},
		{
			//Test Beta APIs are returned
			Negative: false,
			Reg:      reBetaAPI,
			apisOpenapi: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "POST", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "POST", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
				{Method: "POST", URL: "/apis/resources/v1beta1/"},
			},
			apisTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
			},
			ExpectedTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
			},
			ExpectedAll: apiArray{
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
				{Method: "POST", URL: "/apis/resources/v1beta1/"},
			},
		},
		{
			//Test Stable APIs are returned
			Negative: true,
			Reg:      reNotStableAPI,
			apisOpenapi: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "POST", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "POST", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
				{Method: "POST", URL: "/apis/resources/v1beta1/"},
			},
			apisTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
			},
			ExpectedTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
			},
			ExpectedAll: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "POST", URL: "/apis/resources/v1/"},
			},
		},
	}
	for _, test := range testCases {
		resTested, resAll := getTestedAPIsByLevel(test.Negative, test.Reg, test.apisOpenapi, test.apisTested)
		if !equalAPIArray(resTested, test.ExpectedTested) {
			t.Errorf("resTested did not match expected for test")
			t.Errorf("Expected: %#v", test.ExpectedTested)
			t.Errorf("Actual: %#v", resTested)
		}
		if !equalAPIArray(resAll, test.ExpectedAll) {
			t.Errorf("resAll did not match expected for test")
			t.Errorf("Expected: %#v", test.ExpectedAll)
			t.Errorf("Actual: %#v", resAll)
		}
	}
}
<commit_msg>Add unit test for getTestedAPIs()<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 main

import (
	"bytes"
	"io"
	"regexp"
	"testing"
)

//NOTE: This method is for avoiding flake tests instead of using reflect.DeepEqual()
func equalAPIArray(a, b apiArray) bool {
	if a == nil && b == nil {
		return true
	}
	if a == nil || b == nil {
		return false
	}
	if len(a) != len(b) {
		return false
	}
	for _, i := range a {
		found := false
		for _, j := range b {
			if i.Method == j.Method && i.URL == j.URL {
				found = true
				break
			}
		}
		if !found {
			return false
		}
	}
	return true
}

func TestParseOpenAPI(t *testing.T) {
	testCases := []struct {
		Rawdata  []byte
		Expected apiArray
	}{
		{
			Rawdata: []byte(`{"paths": {"/resources": {
				"get": {"description": "get available resources"}}}}`),
			Expected: apiArray{
				{Method: "GET", URL: "/resources"},
			},
		},
		{
			Rawdata: []byte(`{"paths": {"/resources": {
				"get": {"description": "get available resources"},
				"post": {"description": "create resource"}}}}`),
			Expected: apiArray{
				{Method: "GET", URL: "/resources"},
				{Method: "POST", URL: "/resources"},
			},
		},
		{
			Rawdata: []byte(`{"paths": {
			"/resources": {
				"get": {"description": "get available resources"},
				"post": {"description": "create resource"}},
			"/foo": {
				"get": {"description": "get avaiable foo"},
				"post": {"description": "create foo"},
				"parameters": [{"type": "string", "description": "This should be ignored", "name": "bar", "in": "query"}]}}}`),
			Expected: apiArray{
				{Method: "GET", URL: "/resources"},
				{Method: "POST", URL: "/resources"},
				{Method: "GET", URL: "/foo"},
				{Method: "POST", URL: "/foo"},
			},
		},
	}
	for _, test := range testCases {
		res := parseOpenAPI(test.Rawdata)
		if !equalAPIArray(res, test.Expected) {
			t.Errorf("OpenAPI did not match expected for test")
			t.Errorf("%#v", res)
			t.Errorf("%#v", test.Expected)
		}
	}
}

func TestParseAPILog(t *testing.T) {
	testCases := []struct {
		Rawdata  io.Reader
		Expected apiArray
	}{
		{
			Rawdata: bytes.NewReader(
				[]byte(`
I0919 15:34:14.943642    6611 round_trippers.go:414] GET https://k8s-api/api/v1/foo
I0919 15:34:16.943642    6611 round_trippers.go:414] POST https://k8s-api/api/v1/bar
`)),
			Expected: apiArray{
				{Method: "GET", URL: "/api/v1/foo"},
				{Method: "POST", URL: "/api/v1/bar"},
			},
		},
		{
			Rawdata: bytes.NewReader(
				[]byte(`
I0919 15:34:14.943642    6611 round_trippers.go:414] GET https://k8s-api/api/v1/foo?other
`)),
			Expected: apiArray{
				{Method: "GET", URL: "/api/v1/foo"},
			},
		},
	}
	for _, test := range testCases {
		res := parseAPILog(test.Rawdata)
		if !equalAPIArray(res, test.Expected) {
			t.Errorf("APILog did not match expected for test")
			t.Errorf("Actual: %#v", res)
			t.Errorf("Expected: %#v", test.Expected)
		}
	}
}

func TestGetTestedAPIs(t *testing.T) {
	testCases := []struct {
		apisOpenapi apiArray
		apisLogs    apiArray
		Expected    apiArray
	}{
		{
			apisOpenapi: apiArray{
				{Method: "GET", URL: "/api/v1/foo"},
				{Method: "POST", URL: "/api/v1/foo"},
				{Method: "GET", URL: "/api/v1/bar"},
				{Method: "POST", URL: "/api/v1/bar"},
			},
			apisLogs: apiArray{
				{Method: "GET", URL: "/api/v1/foo"},
				{Method: "GET", URL: "/api/v1/bar"},
				{Method: "GET", URL: "/api/v1/foo"},
			},
			Expected: apiArray{
				{Method: "GET", URL: "/api/v1/foo"},
				{Method: "GET", URL: "/api/v1/bar"},
			},
		},
	}
	for _, test := range testCases {
		res := getTestedAPIs(test.apisOpenapi, test.apisLogs)
		if !equalAPIArray(res, test.Expected) {
			t.Errorf("APILog did not match expected for test")
			t.Errorf("Actual: %#v", res)
			t.Errorf("Expected: %#v", test.Expected)
		}
	}
}

func TestGetTestedAPIsByLevel(t *testing.T) {
	testCases := []struct {
		Negative       bool
		Reg            *regexp.Regexp
		apisOpenapi    apiArray
		apisTested     apiArray
		ExpectedTested apiArray
		ExpectedAll    apiArray
	}{
		{
			//Test Alpha APIs are returned
			Negative: false,
			Reg:      reAlphaAPI,
			apisOpenapi: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "POST", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "POST", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
				{Method: "POST", URL: "/apis/resources/v1beta1/"},
			},
			apisTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
			},
			ExpectedTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
			},
			ExpectedAll: apiArray{
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "POST", URL: "/apis/resources/v2alpha1/"},
			},
		},
		{
			//Test Beta APIs are returned
			Negative: false,
			Reg:      reBetaAPI,
			apisOpenapi: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "POST", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "POST", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
				{Method: "POST", URL: "/apis/resources/v1beta1/"},
			},
			apisTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
			},
			ExpectedTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
			},
			ExpectedAll: apiArray{
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
				{Method: "POST", URL: "/apis/resources/v1beta1/"},
			},
		},
		{
			//Test Stable APIs are returned
			Negative: true,
			Reg:      reNotStableAPI,
			apisOpenapi: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "POST", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "POST", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
				{Method: "POST", URL: "/apis/resources/v1beta1/"},
			},
			apisTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "GET", URL: "/apis/resources/v2alpha1/"},
				{Method: "GET", URL: "/apis/resources/v1beta1/"},
			},
			ExpectedTested: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
			},
			ExpectedAll: apiArray{
				{Method: "GET", URL: "/apis/resources/v1/"},
				{Method: "POST", URL: "/apis/resources/v1/"},
			},
		},
	}
	for _, test := range testCases {
		resTested, resAll := getTestedAPIsByLevel(test.Negative, test.Reg, test.apisOpenapi, test.apisTested)
		if !equalAPIArray(resTested, test.ExpectedTested) {
			t.Errorf("resTested did not match expected for test")
			t.Errorf("Expected: %#v", test.ExpectedTested)
			t.Errorf("Actual: %#v", resTested)
		}
		if !equalAPIArray(resAll, test.ExpectedAll) {
			t.Errorf("resAll did not match expected for test")
			t.Errorf("Expected: %#v", test.ExpectedAll)
			t.Errorf("Actual: %#v", resAll)
		}
	}
}
<|endoftext|>