<commit_before>package lxtypes

import (
	"encoding/json"
	"github.com/gogo/protobuf/proto"
	"github.com/mesos/mesos-go/mesosproto"
	"github.com/mesos/mesos-go/mesosutil"
)

const (
	task_provider_key  = "layerx_mesos_tpi_task_provider_key"
	kill_requested_key = "layerx_mesos_tpi_kill_requested_key"
	launched_key       = "layerx_mesos_tpi_launched_key"
)

type Task struct {
	TaskProvider  *TaskProvider            `json:"task_provider"`
	Launched      bool                     `json:"launched"`
	KillRequested bool                     `json:"kill_requested"`
	Name          string                   `json:"name,omitempty"`
	TaskId        string                   `json:"task_id,omitempty"`
	SlaveId       string                   `json:"slave_id,omitempty"`
	Cpus          float64                  `json:cpus`
	Mem           float64                  `json:mem`
	Disk          float64                  `json:disk`
	Ports         []PortRange              `json:ports`
	Executor      *mesosproto.ExecutorInfo `json:"executor,omitempty"`
	Command       *mesosproto.CommandInfo  `json:"command,omitempty"`
	// Task provided with a container will launch the container as part
	// of this task paired with the task's CommandInfo.
	Container *mesosproto.ContainerInfo `json:"container,omitempty"`
	Data      []byte                    `json:"data,omitempty"`
	// A health check for the task (currently in *alpha* and initial
	// support will only be for TaskInfo's that have a CommandInfo).
	HealthCheck *mesosproto.HealthCheck `json:"health_check,omitempty"`
	// Labels are free-form key value pairs which are exposed through
	// master and slave endpoints. Labels will not be interpreted or
	// acted upon by Mesos itself. As opposed to the data field, labels
	// will be kept in memory on master and slave processes. Therefore,
	// labels should be used to tag tasks with light-weight meta-data.
	Labels map[string]string `json:"labels,omitempty"`
	// Service discovery information for the task. It is not interpreted
	// or acted upon by Mesos. It is up to a service discovery system
	// to use this information as needed and to handle tasks without
	// service discovery information.
	Discovery *mesosproto.DiscoveryInfo `json:"discovery,omitempty"`
}

func (t *Task) ToMesos() *mesosproto.TaskInfo {
	var scalarType = mesosproto.Value_SCALAR
	var rangesType = mesosproto.Value_RANGES
	mesosPortRanges := []*mesosproto.Value_Range{}
	for _, portRange := range t.Ports {
		mesosPort := &mesosproto.Value_Range{
			Begin: proto.Uint64(portRange.Begin),
			End:   proto.Uint64(portRange.End),
		}
		mesosPortRanges = append(mesosPortRanges, mesosPort)
	}
	mesosPorts := &mesosproto.Value_Ranges{
		Range: mesosPortRanges,
	}
	var label_arr []*mesosproto.Label
	for key, val := range t.Labels {
		label := &mesosproto.Label{
			Key:   proto.String(key),
			Value: proto.String(val),
		}
		label_arr = append(label_arr, label)
	}
	taskProviderJson, err := json.Marshal(t.TaskProvider)
	//store current_status as a label
	if err != nil {
		tasks_label := &mesosproto.Label{
			Key:   proto.String(task_provider_key),
			Value: proto.String(string(taskProviderJson)),
		}
		label_arr = append(label_arr, tasks_label)
	}
	//store launched as a label
	if t.Launched {
		tasks_label := &mesosproto.Label{
			Key:   proto.String(launched_key),
			Value: proto.String("true"),
		}
		label_arr = append(label_arr, tasks_label)
	} else {
		tasks_label := &mesosproto.Label{
			Key:   proto.String(launched_key),
			Value: proto.String("false"),
		}
		label_arr = append(label_arr, tasks_label)
	}
	//store kill_requested as a label
	if t.KillRequested {
		tasks_label := &mesosproto.Label{
			Key:   proto.String(kill_requested_key),
			Value: proto.String("true"),
		}
		label_arr = append(label_arr, tasks_label)
	} else {
		tasks_label := &mesosproto.Label{
			Key:   proto.String(kill_requested_key),
			Value: proto.String("false"),
		}
		label_arr = append(label_arr, tasks_label)
	}

	labels := &mesosproto.Labels{
		Labels: label_arr,
	}
	return &mesosproto.TaskInfo{
		Name: proto.String(t.Name),
		TaskId: &mesosproto.TaskID{
			Value: proto.String(t.TaskId),
		},
		SlaveId: &mesosproto.SlaveID{
			Value: proto.String(t.SlaveId),
		},
		Resources: []*mesosproto.Resource{
			&mesosproto.Resource{
				Name: proto.String("cpus"),
				Type: &scalarType,
				Scalar: &mesosproto.Value_Scalar{
					Value: proto.Float64(t.Cpus),
				},
			},
			&mesosproto.Resource{
				Name: proto.String("mem"),
				Type: &scalarType,
				Scalar: &mesosproto.Value_Scalar{
					Value: proto.Float64(t.Mem),
				},
			},
			&mesosproto.Resource{
				Name: proto.String("disk"),
				Type: &scalarType,
				Scalar: &mesosproto.Value_Scalar{
					Value: proto.Float64(t.Disk),
				},
			},
			&mesosproto.Resource{
				Name:   proto.String("ports"),
				Type:   &rangesType,
				Ranges: mesosPorts,
			},
		},
		Executor:    t.Executor,
		Command:     t.Command,
		Container:   t.Container,
		Data:        t.Data,
		HealthCheck: t.HealthCheck,
		Labels:      labels,
		Discovery:   t.Discovery,
	}
}

func NewTaskFromMesos(taskInfo *mesosproto.TaskInfo) *Task {
	ports := []PortRange{}
	for _, resource := range taskInfo.GetResources() {
		if resource.GetName() == "ports" {
			for _, mesosRange := range resource.GetRanges().GetRange() {
				port := PortRange{
					Begin: mesosRange.GetBegin(),
					End:   mesosRange.GetEnd(),
				}
				ports = append(ports, port)
			}
		}
	}
	var taskProvider TaskProvider
	var killRequested bool
	var launched bool
	labels := make(map[string]string)
	for _, label := range taskInfo.GetLabels().GetLabels() {
		//if label is task_provider_key, populate task provider instead
		if label.GetKey() == task_provider_key {
			json.Unmarshal([]byte(label.GetValue()), &taskProvider)
		} else if label.GetKey() == kill_requested_key {
			if label.GetValue() == "true" {
				killRequested = true
			}
		} else if label.GetKey() == launched_key {
			if label.GetValue() == "true" {
				launched = true
			}
		} else {
			labels[label.GetKey()] = label.GetValue()
		}
	}

	task := &Task{
		KillRequested: killRequested,
		Launched:      launched,
		Name:          taskInfo.GetName(),
		TaskId:        taskInfo.GetTaskId().GetValue(),
		SlaveId:       taskInfo.GetSlaveId().GetValue(),
		Cpus:          getResourceScalar(taskInfo.GetResources(), "cpus"),
		Mem:           getResourceScalar(taskInfo.GetResources(), "mem"),
		Disk:          getResourceScalar(taskInfo.GetResources(), "disk"),
		Ports:         ports,
		Executor:      taskInfo.Executor,
		Command:       taskInfo.Command,
		Data:          taskInfo.Data,
		HealthCheck:   taskInfo.HealthCheck,
	}

	if taskProvider.Id != "" {
		task.TaskProvider = &taskProvider
	}

	return task
}

func getResourceScalar(resources []*mesosproto.Resource, name string) float64 {
	resources = mesosutil.FilterResources(resources, func(res *mesosproto.Resource) bool {
		return res.GetName() == name
	})

	value := 0.0
	for _, res := range resources {
		value += res.GetScalar().GetValue()
	}

	return value
}
<commit_msg>add checkpointed flag<commit_after>package lxtypes

import (
	"encoding/json"
	"github.com/gogo/protobuf/proto"
	"github.com/mesos/mesos-go/mesosproto"
	"github.com/mesos/mesos-go/mesosutil"
)

const (
	task_provider_key  = "layerx_mesos_tpi_task_provider_key"
	kill_requested_key = "layerx_mesos_tpi_kill_requested_key"
	checkpointed_key       = "layerx_mesos_tpi_checkpointed_key"
)

type Task struct {
	TaskProvider  *TaskProvider            `json:"task_provider"`
	Checkpointed bool                     `json:"checkpointed"`
	KillRequested bool                     `json:"kill_requested"`
	Name          string                   `json:"name,omitempty"`
	TaskId        string                   `json:"task_id,omitempty"`
	SlaveId       string                   `json:"slave_id,omitempty"`
	Cpus          float64                  `json:cpus`
	Mem           float64                  `json:mem`
	Disk          float64                  `json:disk`
	Ports         []PortRange              `json:ports`
	Executor      *mesosproto.ExecutorInfo `json:"executor,omitempty"`
	Command       *mesosproto.CommandInfo  `json:"command,omitempty"`
	// Task provided with a container will launch the container as part
	// of this task paired with the task's CommandInfo.
	Container *mesosproto.ContainerInfo `json:"container,omitempty"`
	Data      []byte                    `json:"data,omitempty"`
	// A health check for the task (currently in *alpha* and initial
	// support will only be for TaskInfo's that have a CommandInfo).
	HealthCheck *mesosproto.HealthCheck `json:"health_check,omitempty"`
	// Labels are free-form key value pairs which are exposed through
	// master and slave endpoints. Labels will not be interpreted or
	// acted upon by Mesos itself. As opposed to the data field, labels
	// will be kept in memory on master and slave processes. Therefore,
	// labels should be used to tag tasks with light-weight meta-data.
	Labels map[string]string `json:"labels,omitempty"`
	// Service discovery information for the task. It is not interpreted
	// or acted upon by Mesos. It is up to a service discovery system
	// to use this information as needed and to handle tasks without
	// service discovery information.
	Discovery *mesosproto.DiscoveryInfo `json:"discovery,omitempty"`
}

func (t *Task) ToMesos() *mesosproto.TaskInfo {
	var scalarType = mesosproto.Value_SCALAR
	var rangesType = mesosproto.Value_RANGES
	mesosPortRanges := []*mesosproto.Value_Range{}
	for _, portRange := range t.Ports {
		mesosPort := &mesosproto.Value_Range{
			Begin: proto.Uint64(portRange.Begin),
			End:   proto.Uint64(portRange.End),
		}
		mesosPortRanges = append(mesosPortRanges, mesosPort)
	}
	mesosPorts := &mesosproto.Value_Ranges{
		Range: mesosPortRanges,
	}
	var label_arr []*mesosproto.Label
	for key, val := range t.Labels {
		label := &mesosproto.Label{
			Key:   proto.String(key),
			Value: proto.String(val),
		}
		label_arr = append(label_arr, label)
	}
	taskProviderJson, err := json.Marshal(t.TaskProvider)
	//store current_status as a label
	if err != nil {
		tasks_label := &mesosproto.Label{
			Key:   proto.String(task_provider_key),
			Value: proto.String(string(taskProviderJson)),
		}
		label_arr = append(label_arr, tasks_label)
	}
	//store checkpointed as a label
	if t.Checkpointed {
		tasks_label := &mesosproto.Label{
			Key:   proto.String(checkpointed_key),
			Value: proto.String("true"),
		}
		label_arr = append(label_arr, tasks_label)
	} else {
		tasks_label := &mesosproto.Label{
			Key:   proto.String(checkpointed_key),
			Value: proto.String("false"),
		}
		label_arr = append(label_arr, tasks_label)
	}
	//store kill_requested as a label
	if t.KillRequested {
		tasks_label := &mesosproto.Label{
			Key:   proto.String(kill_requested_key),
			Value: proto.String("true"),
		}
		label_arr = append(label_arr, tasks_label)
	} else {
		tasks_label := &mesosproto.Label{
			Key:   proto.String(kill_requested_key),
			Value: proto.String("false"),
		}
		label_arr = append(label_arr, tasks_label)
	}

	labels := &mesosproto.Labels{
		Labels: label_arr,
	}
	return &mesosproto.TaskInfo{
		Name: proto.String(t.Name),
		TaskId: &mesosproto.TaskID{
			Value: proto.String(t.TaskId),
		},
		SlaveId: &mesosproto.SlaveID{
			Value: proto.String(t.SlaveId),
		},
		Resources: []*mesosproto.Resource{
			&mesosproto.Resource{
				Name: proto.String("cpus"),
				Type: &scalarType,
				Scalar: &mesosproto.Value_Scalar{
					Value: proto.Float64(t.Cpus),
				},
			},
			&mesosproto.Resource{
				Name: proto.String("mem"),
				Type: &scalarType,
				Scalar: &mesosproto.Value_Scalar{
					Value: proto.Float64(t.Mem),
				},
			},
			&mesosproto.Resource{
				Name: proto.String("disk"),
				Type: &scalarType,
				Scalar: &mesosproto.Value_Scalar{
					Value: proto.Float64(t.Disk),
				},
			},
			&mesosproto.Resource{
				Name:   proto.String("ports"),
				Type:   &rangesType,
				Ranges: mesosPorts,
			},
		},
		Executor:    t.Executor,
		Command:     t.Command,
		Container:   t.Container,
		Data:        t.Data,
		HealthCheck: t.HealthCheck,
		Labels:      labels,
		Discovery:   t.Discovery,
	}
}

func NewTaskFromMesos(taskInfo *mesosproto.TaskInfo) *Task {
	ports := []PortRange{}
	for _, resource := range taskInfo.GetResources() {
		if resource.GetName() == "ports" {
			for _, mesosRange := range resource.GetRanges().GetRange() {
				port := PortRange{
					Begin: mesosRange.GetBegin(),
					End:   mesosRange.GetEnd(),
				}
				ports = append(ports, port)
			}
		}
	}
	var taskProvider TaskProvider
	var killRequested bool
	var checkpointed bool
	labels := make(map[string]string)
	for _, label := range taskInfo.GetLabels().GetLabels() {
		//if label is task_provider_key, populate task provider instead
		if label.GetKey() == task_provider_key {
			json.Unmarshal([]byte(label.GetValue()), &taskProvider)
		} else if label.GetKey() == kill_requested_key {
			if label.GetValue() == "true" {
				killRequested = true
			}
		} else if label.GetKey() == checkpointed_key {
			if label.GetValue() == "true" {
				checkpointed = true
			}
		} else {
			labels[label.GetKey()] = label.GetValue()
		}
	}

	task := &Task{
		KillRequested: killRequested,
		Checkpointed:      checkpointed,
		Name:          taskInfo.GetName(),
		TaskId:        taskInfo.GetTaskId().GetValue(),
		SlaveId:       taskInfo.GetSlaveId().GetValue(),
		Cpus:          getResourceScalar(taskInfo.GetResources(), "cpus"),
		Mem:           getResourceScalar(taskInfo.GetResources(), "mem"),
		Disk:          getResourceScalar(taskInfo.GetResources(), "disk"),
		Ports:         ports,
		Executor:      taskInfo.Executor,
		Command:       taskInfo.Command,
		Data:          taskInfo.Data,
		HealthCheck:   taskInfo.HealthCheck,
	}

	if taskProvider.Id != "" {
		task.TaskProvider = &taskProvider
	}

	return task
}

func getResourceScalar(resources []*mesosproto.Resource, name string) float64 {
	resources = mesosutil.FilterResources(resources, func(res *mesosproto.Resource) bool {
		return res.GetName() == name
	})

	value := 0.0
	for _, res := range resources {
		value += res.GetScalar().GetValue()
	}

	return value
}
<|endoftext|>


<commit_before>package main_test

import (
	"bufio"
	"os"
	"os/exec"
	"path/filepath"
	"time"

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

var _ = Describe("main", func() {
	var (
		old_PLUGINS_HOME string
	)

	BeforeEach(func() {
		old_PLUGINS_HOME = os.Getenv("CF_PLUGIN_HOME")

		dir, err := os.Getwd()
		Expect(err).NotTo(HaveOccurred())

		fullDir := filepath.Join(dir, "..", "fixtures", "config", "main-plugin-test-config")
		err = os.Setenv("CF_PLUGIN_HOME", fullDir)
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		err := os.Setenv("CF_PLUGIN_HOME", old_PLUGINS_HOME)
		Expect(err).NotTo(HaveOccurred())
	})

	Describe("Help menu with -h/--help", func() {
		It("prints the help output with our custom template when run with 'cf -h'", func() {
			output := Cf("-h").Wait(1 * time.Second)
			Eventually(output.Out.Contents).Should(ContainSubstring("A command line tool to interact with Cloud Foundry"))
			Eventually(output.Out.Contents).Should(ContainSubstring("CF_TRACE=true"))
		})

		It("prints the help output with our custom template when run with 'cf --help'", func() {
			output := Cf("--help").Wait(1 * time.Second)
			Eventually(output.Out.Contents).Should(ContainSubstring("A command line tool to interact with Cloud Foundry"))
			Eventually(output.Out.Contents).Should(ContainSubstring("CF_TRACE=true"))
		})

		It("accepts -h and --h flags for all commands", func() {
			result := Cf("push", "-h")
			Consistently(result.Out).ShouldNot(Say("Incorrect Usage"))
			Eventually(result.Out.Contents).Should(ContainSubstring("USAGE"))

			result = Cf("target", "--h")
			Consistently(result.Out).ShouldNot(Say("Incorrect Usage"))
			Eventually(result.Out.Contents).Should(ContainSubstring("USAGE"))
		})

	})

	Describe("Shows version with -v or --version", func() {
		It("prints the cf version if '-v' flag is provided", func() {
			output := Cf("-v").Wait(1 * time.Second)
			Eventually(output.Out.Contents).Should(ContainSubstring("version"))
			Ω(output.ExitCode()).To(Equal(0))
		})

		It("prints the cf version if '--version' flag is provided", func() {
			output := Cf("-v").Wait(1 * time.Second)
			Eventually(output.Out.Contents).Should(ContainSubstring("version"))
			Ω(output.ExitCode()).To(Equal(0))
		})
	})

	Describe("Commands /w new non-codegangsta structure", func() {
		It("prints usage help for all non-codegangsta commands by providing `help` flag", func() {
			output := Cf("api", "-h").Wait(1 * time.Second)
			Eventually(output.Out.Contents).Should(ContainSubstring("USAGE"))
			Eventually(output.Out.Contents).Should(ContainSubstring("OPTIONS"))
		})

		It("accepts -h and --h flags for non-codegangsta commands", func() {
			result := Cf("api", "-h")
			Consistently(result.Out).ShouldNot(Say("Invalid flag: -h"))
			Eventually(result.Out.Contents).Should(ContainSubstring("api - Set or view target api url"))

			result = Cf("api", "--h")
			Consistently(result.Out).ShouldNot(Say("Invalid flag: --h"))
			Eventually(result.Out.Contents).Should(ContainSubstring("api - Set or view target api url"))
		})

		It("runs requirement of the non-codegangsta command", func() {
			dir, err := os.Getwd()
			Expect(err).ToNot(HaveOccurred())
			fullDir := filepath.Join(dir, "..", "fixtures") //set home to a config w/o targeted api
			result := CfWith_CF_HOME(fullDir, "app", "app-should-never-exist-blah-blah")

			Eventually(result.Out).Should(Say("No API endpoint set."))
		})
	})

	Describe("exit codes", func() {
		It("exits non-zero when an unknown command is invoked", func() {
			result := Cf("some-command-that-should-never-actually-be-a-real-thing-i-can-use")

			Eventually(result, 3*time.Second).Should(Say("not a registered command"))
			Eventually(result).Should(Exit(1))
		})

		It("exits non-zero when known command is invoked with invalid option", func() {
			result := Cf("push", "--crazy")
			Eventually(result).Should(Exit(1))
		})
	})

	It("can print help menu by executing only the command `cf`", func() {
		output := Cf().Wait(3 * time.Second)
		Eventually(output.Out.Contents).Should(ContainSubstring("A command line tool to interact with Cloud Foundry"))
	})

	Describe("Plugins", func() {
		It("Can call a plugin command from the Plugins configuration if it does not exist as a cf command", func() {
			output := Cf("test_1_cmd1").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("You called cmd1 in test_1"))
		})

		It("Can call a plugin command via alias if it does not exist as a cf command", func() {
			output := Cf("test_1_cmd1_alias").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("You called cmd1 in test_1"))
		})

		It("Can call another plugin command when more than one plugin is installed", func() {
			output := Cf("test_2_cmd1").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("You called cmd1 in test_2"))
		})

		It("informs user for any invalid commands", func() {
			output := Cf("foo-bar")
			Eventually(output.Out, 3*time.Second).Should(Say("'foo-bar' is not a registered command"))
		})

		It("Calls help if the plugin shares the same name", func() {
			output := Cf("help")
			Consistently(output.Out, 1).ShouldNot(Say("You called help in test_with_help"))
		})

		It("shows help with a '-h' or '--help' flag in plugin command", func() {
			output := Cf("test_1_cmd1", "-h").Wait(3 * time.Second)
			Eventually(output.Out).ShouldNot(Say("You called cmd1 in test_1"))
			Eventually(output.Out.Contents).Should(ContainSubstring("USAGE:"))
			Eventually(output.Out.Contents).Should(ContainSubstring("OPTIONS:"))
		})

		It("Calls the core push command if the plugin shares the same name", func() {
			output := Cf("push")
			Consistently(output.Out, 1).ShouldNot(Say("You called push in test_with_push"))
		})

		It("Calls the core short name if a plugin shares the same name", func() {
			output := Cf("p")
			Consistently(output.Out, 1).ShouldNot(Say("You called p within the plugin"))
		})

		It("Passes all arguments to a plugin", func() {
			output := Cf("my-say", "foo").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("foo"))
		})

		It("Passes all arguments and flags to a plugin", func() {
			output := Cf("my-say", "foo", "--loud").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("FOO"))
		})

		It("Calls a plugin that calls core commands", func() {
			output := Cf("awesomeness").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("my-say")) //look for another plugin
		})

		It("Sends stdoutput to the plugin to echo", func() {
			output := Cf("core-command", "plugins").Wait(3 * time.Second)
			Eventually(output.Out.Contents).Should(MatchRegexp("Command output from the plugin(.*\\W)*awesomeness(.*\\W)*FIN"))
		})

		It("Can call a core commmand from a plugin without terminal output", func() {
			output := Cf("core-command-quiet", "plugins").Wait(3 * time.Second)
			Eventually(output.Out.Contents).Should(MatchRegexp("^\n---------- Command output from the plugin"))
		})

		It("Can call a plugin that requires stdin (interactive)", func() {
			session := CfWithIo("input", "silly\n").Wait(5 * time.Second)
			Eventually(session.Out).Should(Say("silly"))
		})

		It("exits 1 when a plugin panics", func() {
			session := Cf("panic").Wait(5 * time.Second)
			Eventually(session).Should(Exit(1))
		})

		It("exits 1 when a plugin exits 1", func() {
			session := Cf("exit1").Wait(5 * time.Second)
			Eventually(session).Should(Exit(1))
		})
	})

})

func Cf(args ...string) *Session {
	path, err := Build("github.com/cloudfoundry/cli/main")
	Expect(err).NotTo(HaveOccurred())

	session, err := Start(exec.Command(path, args...), GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())

	return session
}
func CfWithIo(command string, args string) *Session {
	path, err := Build("github.com/cloudfoundry/cli/main")
	Expect(err).NotTo(HaveOccurred())

	cmd := exec.Command(path, command)

	stdin, err := cmd.StdinPipe()
	Expect(err).ToNot(HaveOccurred())

	buffer := bufio.NewWriter(stdin)
	buffer.WriteString(args)
	buffer.Flush()

	session, err := Start(cmd, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())

	return session
}
func CfWith_CF_HOME(cfHome string, args ...string) *Session {
	path, err := Build("github.com/cloudfoundry/cli/main")
	Expect(err).NotTo(HaveOccurred())

	cmd := exec.Command(path, args...)
	cmd.Env = append(cmd.Env, "CF_HOME="+cfHome)
	session, err := Start(cmd, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())

	return session
}

// gexec.Build leaves a compiled binary behind in /tmp.
var _ = AfterSuite(func() {
	CleanupBuildArtifacts()
})
<commit_msg>fix test for cf --version [#103506518]<commit_after>package main_test

import (
	"bufio"
	"os"
	"os/exec"
	"path/filepath"
	"time"

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

var _ = Describe("main", func() {
	var (
		old_PLUGINS_HOME string
	)

	BeforeEach(func() {
		old_PLUGINS_HOME = os.Getenv("CF_PLUGIN_HOME")

		dir, err := os.Getwd()
		Expect(err).NotTo(HaveOccurred())

		fullDir := filepath.Join(dir, "..", "fixtures", "config", "main-plugin-test-config")
		err = os.Setenv("CF_PLUGIN_HOME", fullDir)
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		err := os.Setenv("CF_PLUGIN_HOME", old_PLUGINS_HOME)
		Expect(err).NotTo(HaveOccurred())
	})

	Describe("Help menu with -h/--help", func() {
		It("prints the help output with our custom template when run with 'cf -h'", func() {
			output := Cf("-h").Wait(1 * time.Second)
			Eventually(output.Out.Contents).Should(ContainSubstring("A command line tool to interact with Cloud Foundry"))
			Eventually(output.Out.Contents).Should(ContainSubstring("CF_TRACE=true"))
		})

		It("prints the help output with our custom template when run with 'cf --help'", func() {
			output := Cf("--help").Wait(1 * time.Second)
			Eventually(output.Out.Contents).Should(ContainSubstring("A command line tool to interact with Cloud Foundry"))
			Eventually(output.Out.Contents).Should(ContainSubstring("CF_TRACE=true"))
		})

		It("accepts -h and --h flags for all commands", func() {
			result := Cf("push", "-h")
			Consistently(result.Out).ShouldNot(Say("Incorrect Usage"))
			Eventually(result.Out.Contents).Should(ContainSubstring("USAGE"))

			result = Cf("target", "--h")
			Consistently(result.Out).ShouldNot(Say("Incorrect Usage"))
			Eventually(result.Out.Contents).Should(ContainSubstring("USAGE"))
		})

	})

	Describe("Shows version with -v or --version", func() {
		It("prints the cf version if '-v' flag is provided", func() {
			output := Cf("-v").Wait(1 * time.Second)
			Eventually(output.Out.Contents).Should(ContainSubstring("version"))
			Ω(output.ExitCode()).To(Equal(0))
		})

		It("prints the cf version if '--version' flag is provided", func() {
			output := Cf("--version").Wait(1 * time.Second)
			Eventually(output.Out.Contents).Should(ContainSubstring("version"))
			Ω(output.ExitCode()).To(Equal(0))
		})
	})

	Describe("Commands /w new non-codegangsta structure", func() {
		It("prints usage help for all non-codegangsta commands by providing `help` flag", func() {
			output := Cf("api", "-h").Wait(1 * time.Second)
			Eventually(output.Out.Contents).Should(ContainSubstring("USAGE"))
			Eventually(output.Out.Contents).Should(ContainSubstring("OPTIONS"))
		})

		It("accepts -h and --h flags for non-codegangsta commands", func() {
			result := Cf("api", "-h")
			Consistently(result.Out).ShouldNot(Say("Invalid flag: -h"))
			Eventually(result.Out.Contents).Should(ContainSubstring("api - Set or view target api url"))

			result = Cf("api", "--h")
			Consistently(result.Out).ShouldNot(Say("Invalid flag: --h"))
			Eventually(result.Out.Contents).Should(ContainSubstring("api - Set or view target api url"))
		})

		It("runs requirement of the non-codegangsta command", func() {
			dir, err := os.Getwd()
			Expect(err).ToNot(HaveOccurred())
			fullDir := filepath.Join(dir, "..", "fixtures") //set home to a config w/o targeted api
			result := CfWith_CF_HOME(fullDir, "app", "app-should-never-exist-blah-blah")

			Eventually(result.Out).Should(Say("No API endpoint set."))
		})
	})

	Describe("exit codes", func() {
		It("exits non-zero when an unknown command is invoked", func() {
			result := Cf("some-command-that-should-never-actually-be-a-real-thing-i-can-use")

			Eventually(result, 3*time.Second).Should(Say("not a registered command"))
			Eventually(result).Should(Exit(1))
		})

		It("exits non-zero when known command is invoked with invalid option", func() {
			result := Cf("push", "--crazy")
			Eventually(result).Should(Exit(1))
		})
	})

	It("can print help menu by executing only the command `cf`", func() {
		output := Cf().Wait(3 * time.Second)
		Eventually(output.Out.Contents).Should(ContainSubstring("A command line tool to interact with Cloud Foundry"))
	})

	Describe("Plugins", func() {
		It("Can call a plugin command from the Plugins configuration if it does not exist as a cf command", func() {
			output := Cf("test_1_cmd1").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("You called cmd1 in test_1"))
		})

		It("Can call a plugin command via alias if it does not exist as a cf command", func() {
			output := Cf("test_1_cmd1_alias").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("You called cmd1 in test_1"))
		})

		It("Can call another plugin command when more than one plugin is installed", func() {
			output := Cf("test_2_cmd1").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("You called cmd1 in test_2"))
		})

		It("informs user for any invalid commands", func() {
			output := Cf("foo-bar")
			Eventually(output.Out, 3*time.Second).Should(Say("'foo-bar' is not a registered command"))
		})

		It("Calls help if the plugin shares the same name", func() {
			output := Cf("help")
			Consistently(output.Out, 1).ShouldNot(Say("You called help in test_with_help"))
		})

		It("shows help with a '-h' or '--help' flag in plugin command", func() {
			output := Cf("test_1_cmd1", "-h").Wait(3 * time.Second)
			Eventually(output.Out).ShouldNot(Say("You called cmd1 in test_1"))
			Eventually(output.Out.Contents).Should(ContainSubstring("USAGE:"))
			Eventually(output.Out.Contents).Should(ContainSubstring("OPTIONS:"))
		})

		It("Calls the core push command if the plugin shares the same name", func() {
			output := Cf("push")
			Consistently(output.Out, 1).ShouldNot(Say("You called push in test_with_push"))
		})

		It("Calls the core short name if a plugin shares the same name", func() {
			output := Cf("p")
			Consistently(output.Out, 1).ShouldNot(Say("You called p within the plugin"))
		})

		It("Passes all arguments to a plugin", func() {
			output := Cf("my-say", "foo").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("foo"))
		})

		It("Passes all arguments and flags to a plugin", func() {
			output := Cf("my-say", "foo", "--loud").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("FOO"))
		})

		It("Calls a plugin that calls core commands", func() {
			output := Cf("awesomeness").Wait(3 * time.Second)
			Eventually(output.Out).Should(Say("my-say")) //look for another plugin
		})

		It("Sends stdoutput to the plugin to echo", func() {
			output := Cf("core-command", "plugins").Wait(3 * time.Second)
			Eventually(output.Out.Contents).Should(MatchRegexp("Command output from the plugin(.*\\W)*awesomeness(.*\\W)*FIN"))
		})

		It("Can call a core commmand from a plugin without terminal output", func() {
			output := Cf("core-command-quiet", "plugins").Wait(3 * time.Second)
			Eventually(output.Out.Contents).Should(MatchRegexp("^\n---------- Command output from the plugin"))
		})

		It("Can call a plugin that requires stdin (interactive)", func() {
			session := CfWithIo("input", "silly\n").Wait(5 * time.Second)
			Eventually(session.Out).Should(Say("silly"))
		})

		It("exits 1 when a plugin panics", func() {
			session := Cf("panic").Wait(5 * time.Second)
			Eventually(session).Should(Exit(1))
		})

		It("exits 1 when a plugin exits 1", func() {
			session := Cf("exit1").Wait(5 * time.Second)
			Eventually(session).Should(Exit(1))
		})
	})

})

func Cf(args ...string) *Session {
	path, err := Build("github.com/cloudfoundry/cli/main")
	Expect(err).NotTo(HaveOccurred())

	session, err := Start(exec.Command(path, args...), GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())

	return session
}
func CfWithIo(command string, args string) *Session {
	path, err := Build("github.com/cloudfoundry/cli/main")
	Expect(err).NotTo(HaveOccurred())

	cmd := exec.Command(path, command)

	stdin, err := cmd.StdinPipe()
	Expect(err).ToNot(HaveOccurred())

	buffer := bufio.NewWriter(stdin)
	buffer.WriteString(args)
	buffer.Flush()

	session, err := Start(cmd, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())

	return session
}
func CfWith_CF_HOME(cfHome string, args ...string) *Session {
	path, err := Build("github.com/cloudfoundry/cli/main")
	Expect(err).NotTo(HaveOccurred())

	cmd := exec.Command(path, args...)
	cmd.Env = append(cmd.Env, "CF_HOME="+cfHome)
	session, err := Start(cmd, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())

	return session
}

// gexec.Build leaves a compiled binary behind in /tmp.
var _ = AfterSuite(func() {
	CleanupBuildArtifacts()
})
<|endoftext|>


<commit_before>// Copyright ©2013 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package mat64

import (
	"math"

	"gopkg.in/check.v1"
)

func (s *S) TestSVD(c *check.C) {
	for _, t := range []struct {
		a *Dense

		epsilon float64
		small   float64

		wantu bool
		u     *Dense

		sigma []float64

		wantv bool
		v     *Dense
	}{
		{
			a: NewDense(4, 2, []float64{2, 4, 1, 3, 0, 0, 0, 0}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			wantu: true,
			u: NewDense(4, 2, []float64{
				0.8174155604703632, -0.5760484367663209,
				0.5760484367663209, 0.8174155604703633,
				0, 0,
				0, 0,
			}),

			sigma: []float64{5.464985704219041, 0.365966190626258},

			wantv: true,
			v: NewDense(2, 2, []float64{
				0.4045535848337571, -0.9145142956773044,
				0.9145142956773044, 0.4045535848337571,
			}),
		},
		{
			a: NewDense(4, 2, []float64{2, 4, 1, 3, 0, 0, 0, 0}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			wantu: true,
			u: NewDense(4, 2, []float64{
				0.8174155604703632, -0.5760484367663209,
				0.5760484367663209, 0.8174155604703633,
				0, 0,
				0, 0,
			}),

			sigma: []float64{5.464985704219041, 0.365966190626258},

			wantv: false,
		},
		{
			a: NewDense(4, 2, []float64{2, 4, 1, 3, 0, 0, 0, 0}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			wantu: false,

			sigma: []float64{5.464985704219041, 0.365966190626258},

			wantv: true,
			v: NewDense(2, 2, []float64{
				0.4045535848337571, -0.9145142956773044,
				0.9145142956773044, 0.4045535848337571,
			}),
		},
		{
			a: NewDense(4, 2, []float64{2, 4, 1, 3, 0, 0, 0, 0}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			sigma: []float64{5.464985704219041, 0.365966190626258},
		},
		{ // Issue #5.
			a: NewDense(3, 11, []float64{
				1, 1, 0, 1, 0, 0, 0, 0, 0, 11, 1,
				1, 0, 0, 0, 0, 0, 1, 0, 0, 12, 2,
				1, 1, 0, 0, 0, 0, 0, 0, 1, 13, 3,
			}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			sigma: []float64{21.259500881097434, 1.5415021616856566, 1.2873979074613628},

			wantu: true,
			u: NewDense(3, 3, []float64{
				0.5224167862273765, -0.7864430360363114, 0.3295270133658976,
				0.5739526766688285, 0.03852203026050301, -0.8179818935216693,
				0.6306021141833781, 0.6164603833618163, 0.4715056408282468,
			}),

			wantv: true,
			v: NewDense(11, 3, []float64{
				0.08123293141915189, -0.08528085505260324, -0.013165501690885152,
				0.05423546426886932, -0.1102707844980355, 0.622210623111631,
				0, 0, 0,
				0.0245733326078166, -0.510179651760153, 0.25596360803140994,
				0, 0, 0,
				0, 0, 0,
				0.026997467150282436, 0.024989929445430496, -0.6353761248025164,
				0, 0, 0,
				0.029662131661052707, 0.3999088672621176, 0.3662470150802212,
				0.9798839760830571, -0.11328174160898856, -0.047702613241813366,
				0.16755466189153964, 0.7395268089170608, 0.08395240366704032,
			}),
		},
		{ // Issue #5: test that correct matrices are constructed.
			a: NewDense(3, 11, []float64{
				1, 1, 0, 1, 0, 0, 0, 0, 0, 11, 1,
				1, 0, 0, 0, 0, 0, 1, 0, 0, 12, 2,
				1, 1, 0, 0, 0, 0, 0, 0, 1, 13, 3,
			}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			sigma: []float64{21.259500881097434, 1.5415021616856566, 1.2873979074613628},

			wantu: true,
			u: NewDense(3, 3, []float64{
				0.5224167862273765, -0.7864430360363114, 0.3295270133658976,
				0.5739526766688285, 0.03852203026050301, -0.8179818935216693,
				0.6306021141833781, 0.6164603833618163, 0.4715056408282468,
			}),
		},
		{ // Issue #5: test that correct matrices are constructed.
			a: NewDense(3, 11, []float64{
				1, 1, 0, 1, 0, 0, 0, 0, 0, 11, 1,
				1, 0, 0, 0, 0, 0, 1, 0, 0, 12, 2,
				1, 1, 0, 0, 0, 0, 0, 0, 1, 13, 3,
			}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			sigma: []float64{21.259500881097434, 1.5415021616856566, 1.2873979074613628},

			wantv: true,
			v: NewDense(11, 3, []float64{
				0.08123293141915189, -0.08528085505260324, -0.013165501690885152,
				0.05423546426886932, -0.1102707844980355, 0.622210623111631,
				0, 0, 0,
				0.0245733326078166, -0.510179651760153, 0.25596360803140994,
				0, 0, 0,
				0, 0, 0,
				0.026997467150282436, 0.024989929445430496, -0.6353761248025164,
				0, 0, 0,
				0.029662131661052707, 0.3999088672621176, 0.3662470150802212,
				0.9798839760830571, -0.11328174160898856, -0.047702613241813366,
				0.16755466189153964, 0.7395268089170608, 0.08395240366704032,
			}),
		},
	} {
		svd := SVD(DenseCopyOf(t.a), t.epsilon, t.small, t.wantu, t.wantv)
		if t.sigma != nil {
			c.Check(svd.Sigma, check.DeepEquals, t.sigma)
		}
		s := svd.S()

		if svd.U != nil {
			c.Check(Equal(svd.U, t.u), check.Equals, true)
		} else {
			c.Check(t.wantu, check.Equals, false)
			c.Check(t.u, check.IsNil)
		}
		if svd.V != nil {
			c.Check(Equal(svd.V, t.v), check.Equals, true)
		} else {
			c.Check(t.wantv, check.Equals, false)
			c.Check(t.v, check.IsNil)
		}

		if t.wantu && t.wantv {
			c.Assert(svd.U, check.NotNil)
			c.Assert(svd.V, check.NotNil)
			var tmp, got Dense
			tmp.Mul(svd.U, s)
			got.Mul(&tmp, svd.V.T())
			c.Check(EqualApprox(&got, t.a, 1e-12), check.Equals, true)
		}
	}
}
<commit_msg>mat64: refactor SVD tests<commit_after>// Copyright ©2013 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package mat64

import (
	"math"
	"reflect"

	"gopkg.in/check.v1"
)

func (s *S) TestSVD(c *check.C) {
	for i, test := range []struct {
		a *Dense

		epsilon float64
		small   float64

		wantu bool
		u     *Dense

		sigma []float64

		wantv bool
		v     *Dense
	}{
		{
			a: NewDense(4, 2, []float64{2, 4, 1, 3, 0, 0, 0, 0}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			wantu: true,
			u: NewDense(4, 2, []float64{
				0.8174155604703632, -0.5760484367663209,
				0.5760484367663209, 0.8174155604703633,
				0, 0,
				0, 0,
			}),

			sigma: []float64{5.464985704219041, 0.365966190626258},

			wantv: true,
			v: NewDense(2, 2, []float64{
				0.4045535848337571, -0.9145142956773044,
				0.9145142956773044, 0.4045535848337571,
			}),
		},
		{
			a: NewDense(4, 2, []float64{2, 4, 1, 3, 0, 0, 0, 0}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			wantu: true,
			u: NewDense(4, 2, []float64{
				0.8174155604703632, -0.5760484367663209,
				0.5760484367663209, 0.8174155604703633,
				0, 0,
				0, 0,
			}),

			sigma: []float64{5.464985704219041, 0.365966190626258},

			wantv: false,
		},
		{
			a: NewDense(4, 2, []float64{2, 4, 1, 3, 0, 0, 0, 0}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			wantu: false,

			sigma: []float64{5.464985704219041, 0.365966190626258},

			wantv: true,
			v: NewDense(2, 2, []float64{
				0.4045535848337571, -0.9145142956773044,
				0.9145142956773044, 0.4045535848337571,
			}),
		},
		{
			a: NewDense(4, 2, []float64{2, 4, 1, 3, 0, 0, 0, 0}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			sigma: []float64{5.464985704219041, 0.365966190626258},
		},
		{ // Issue #5.
			a: NewDense(3, 11, []float64{
				1, 1, 0, 1, 0, 0, 0, 0, 0, 11, 1,
				1, 0, 0, 0, 0, 0, 1, 0, 0, 12, 2,
				1, 1, 0, 0, 0, 0, 0, 0, 1, 13, 3,
			}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			sigma: []float64{21.259500881097434, 1.5415021616856566, 1.2873979074613628},

			wantu: true,
			u: NewDense(3, 3, []float64{
				0.5224167862273765, -0.7864430360363114, 0.3295270133658976,
				0.5739526766688285, 0.03852203026050301, -0.8179818935216693,
				0.6306021141833781, 0.6164603833618163, 0.4715056408282468,
			}),

			wantv: true,
			v: NewDense(11, 3, []float64{
				0.08123293141915189, -0.08528085505260324, -0.013165501690885152,
				0.05423546426886932, -0.1102707844980355, 0.622210623111631,
				0, 0, 0,
				0.0245733326078166, -0.510179651760153, 0.25596360803140994,
				0, 0, 0,
				0, 0, 0,
				0.026997467150282436, 0.024989929445430496, -0.6353761248025164,
				0, 0, 0,
				0.029662131661052707, 0.3999088672621176, 0.3662470150802212,
				0.9798839760830571, -0.11328174160898856, -0.047702613241813366,
				0.16755466189153964, 0.7395268089170608, 0.08395240366704032,
			}),
		},
		{ // Issue #5: test that correct matrices are constructed.
			a: NewDense(3, 11, []float64{
				1, 1, 0, 1, 0, 0, 0, 0, 0, 11, 1,
				1, 0, 0, 0, 0, 0, 1, 0, 0, 12, 2,
				1, 1, 0, 0, 0, 0, 0, 0, 1, 13, 3,
			}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			sigma: []float64{21.259500881097434, 1.5415021616856566, 1.2873979074613628},

			wantu: true,
			u: NewDense(3, 3, []float64{
				0.5224167862273765, -0.7864430360363114, 0.3295270133658976,
				0.5739526766688285, 0.03852203026050301, -0.8179818935216693,
				0.6306021141833781, 0.6164603833618163, 0.4715056408282468,
			}),
		},
		{ // Issue #5: test that correct matrices are constructed.
			a: NewDense(3, 11, []float64{
				1, 1, 0, 1, 0, 0, 0, 0, 0, 11, 1,
				1, 0, 0, 0, 0, 0, 1, 0, 0, 12, 2,
				1, 1, 0, 0, 0, 0, 0, 0, 1, 13, 3,
			}),

			epsilon: math.Pow(2, -52.0),
			small:   math.Pow(2, -966.0),

			sigma: []float64{21.259500881097434, 1.5415021616856566, 1.2873979074613628},

			wantv: true,
			v: NewDense(11, 3, []float64{
				0.08123293141915189, -0.08528085505260324, -0.013165501690885152,
				0.05423546426886932, -0.1102707844980355, 0.622210623111631,
				0, 0, 0,
				0.0245733326078166, -0.510179651760153, 0.25596360803140994,
				0, 0, 0,
				0, 0, 0,
				0.026997467150282436, 0.024989929445430496, -0.6353761248025164,
				0, 0, 0,
				0.029662131661052707, 0.3999088672621176, 0.3662470150802212,
				0.9798839760830571, -0.11328174160898856, -0.047702613241813366,
				0.16755466189153964, 0.7395268089170608, 0.08395240366704032,
			}),
		},
	} {
		svd := SVD(DenseCopyOf(test.a), test.epsilon, test.small, test.wantu, test.wantv)
		if test.sigma != nil {
			if !reflect.DeepEqual(svd.Sigma, test.sigma) {
				c.Errorf("unexpected sigma for test %d: got: %v want: %v", i, svd.Sigma, test.sigma)
			}
		}
		s := svd.S()

		if svd.U != nil {
			if !Equal(svd.U, test.u) {
				c.Errorf("unexpected U value for test %d", i)
			}
		} else if test.wantu || test.u != nil {
			c.Errorf("unexpectedly did not get U for test %d", i)
		}
		if svd.V != nil {
			if !Equal(svd.V, test.v) {
				c.Error("unexpected V value")
			}
		} else if test.wantv || test.v != nil {
			c.Errorf("unexpectedly did not get V for test %d", i)
		}

		if test.wantu && test.wantv {
			if svd.U == nil {
				c.Fatalf("unexpect nil U for test %d", i)
			}
			if svd.V == nil {
				c.Fatalf("unexpect nil V for test %d", i)
			}
			var tmp, got Dense
			tmp.Mul(svd.U, s)
			got.Mul(&tmp, svd.V.T())
			if !EqualApprox(&got, test.a, 1e-12) {
				c.Errorf("incorrect SVD factor product for test %d", i)
			}
		}
	}
}
<|endoftext|>


<commit_before>/*package rand provides implementations of various types of pseudo random
number generators. Due to the similarity in form, it also provides an
implementation of Sobol sequences.

Here are some usage examples for these generators.

	// Generate a single value
    gen := New(Xorshift, 1337)
    x := gen.Uniform(3, 7)

	// Multiple random floats (faster)
	xs := make([]float64, 100)
	gen.UniformAt(3, 7, xs)

    // Random int
    y := gen.UniformInt(3, 7)

    // Use the time as a seed
    gen2 := NewTimeSeed(Xorshift)

Currently three types of generators are provided. The first is Xorshift, which
is very fast, the second is Tausworthe which is slower (especially at start
up), but which is a better generator, and the last is Goland, which is a
wrapper around Go's standard library generator.
*/
package rand

import (
	"math"
	"time"
)

// generatorBackend is an interface which is used by the generators to supply
// the functionality needed for top-level functions like Uniform().
type generatorBackend interface {
	Init(seed uint64)
	Next() float64
	NextSequence(target []float64)
}

// Generator is a random number generator.
type Generator struct {
	backend        generatorBackend
}

// Generator type is a flag used to indicate the desired algorithm
// for a random number generator.
type GeneratorType uint8

const (
	Xorshift GeneratorType = iota
	Golang
	Tausworthe
)

// NewTimeSeed returns a new random number generator that uses the current
// time as the seed.
func NewTimeSeed(gt GeneratorType) *Generator {
	return New(gt, uint64(time.Now().UnixNano()))
}

// New returns a new random number generator.
func New(gt GeneratorType, seed uint64) *Generator {
	var backend generatorBackend

	switch gt {
	case Xorshift:
		backend = new(xorshiftGenerator)
	case Golang:
		backend = new(golangGenerator)
	case Tausworthe:
		backend = new(tauswortheGenerator)
	default:
		panic("Unrecognized GeneratorType")
	}

	backend.Init(seed)
	gen := &Generator{backend}
	return gen
}

// UniformInt returns an integer uniformly at random within in the
// range [low, high).
func (gen *Generator) UniformInt(low, high int) int {
	f := gen.backend.Next()
	return int(math.Floor(float64(high-low)*f + float64(low)))

}

// Uniform returns a float uniformly at random within the range [low, high).
func (gen *Generator) Uniform(low, high float64) float64 {
	if low == 0.0 && high == 1.0 {
		return gen.backend.Next()
	}
	return (gen.backend.Next() * (high - low)) + low
}

// UniformAt writes floats generated uniformly at random in the range
// [low, high) to every element in a target slice. This is generally faster
// than calling Uniform the corresponding number of times.
func (gen *Generator) UniformAt(low, high float64, target []float64) {
	gen.backend.NextSequence(target)
	if low == 0.0 && high == 1.0 {
		return
	}
	for i := range target {
		target[i] = target[i]*(high-low) + low
	}
}
<commit_msg>Rand go fmt on math/rand.<commit_after>/*package rand provides implementations of various types of pseudo random
number generators. Due to the similarity in form, it also provides an
implementation of Sobol sequences.

Here are some usage examples for these generators.

	// Generate a single value
    gen := New(Xorshift, 1337)
    x := gen.Uniform(3, 7)

	// Multiple random floats (faster)
	xs := make([]float64, 100)
	gen.UniformAt(3, 7, xs)

    // Random int
    y := gen.UniformInt(3, 7)

    // Use the time as a seed
    gen2 := NewTimeSeed(Xorshift)

Currently three types of generators are provided. The first is Xorshift, which
is very fast, the second is Tausworthe which is slower (especially at start
up), but which is a better generator, and the last is Goland, which is a
wrapper around Go's standard library generator.
*/
package rand

import (
	"math"
	"time"
)

// generatorBackend is an interface which is used by the generators to supply
// the functionality needed for top-level functions like Uniform().
type generatorBackend interface {
	Init(seed uint64)
	Next() float64
	NextSequence(target []float64)
}

// Generator is a random number generator.
type Generator struct {
	backend generatorBackend
}

// Generator type is a flag used to indicate the desired algorithm
// for a random number generator.
type GeneratorType uint8

const (
	Xorshift GeneratorType = iota
	Golang
	Tausworthe
)

// NewTimeSeed returns a new random number generator that uses the current
// time as the seed.
func NewTimeSeed(gt GeneratorType) *Generator {
	return New(gt, uint64(time.Now().UnixNano()))
}

// New returns a new random number generator.
func New(gt GeneratorType, seed uint64) *Generator {
	var backend generatorBackend

	switch gt {
	case Xorshift:
		backend = new(xorshiftGenerator)
	case Golang:
		backend = new(golangGenerator)
	case Tausworthe:
		backend = new(tauswortheGenerator)
	default:
		panic("Unrecognized GeneratorType")
	}

	backend.Init(seed)
	gen := &Generator{backend}
	return gen
}

// UniformInt returns an integer uniformly at random within in the
// range [low, high).
func (gen *Generator) UniformInt(low, high int) int {
	f := gen.backend.Next()
	return int(math.Floor(float64(high-low)*f + float64(low)))

}

// Uniform returns a float uniformly at random within the range [low, high).
func (gen *Generator) Uniform(low, high float64) float64 {
	if low == 0.0 && high == 1.0 {
		return gen.backend.Next()
	}
	return (gen.backend.Next() * (high - low)) + low
}

// UniformAt writes floats generated uniformly at random in the range
// [low, high) to every element in a target slice. This is generally faster
// than calling Uniform the corresponding number of times.
func (gen *Generator) UniformAt(low, high float64, target []float64) {
	gen.backend.NextSequence(target)
	if low == 0.0 && high == 1.0 {
		return
	}
	for i := range target {
		target[i] = target[i]*(high-low) + low
	}
}
<|endoftext|>


<commit_before>// Package chacha20 provides a pure Go implementation of ChaCha20, a fast, secure
// stream cipher.
//
// From Bernstein, Daniel J. "ChaCha, a variant of Salsa20." Workshop Record of
// SASC. 2008. (http://cr.yp.to/chacha/chacha-20080128.pdf):
//
//	ChaCha8 is a 256-bit stream cipher based on the 8-round cipher Salsa20/8.
//	The changes from Salsa20/8 to ChaCha8 are designed to improve diffusion per
//	round, conjecturally increasing resistance to cryptanalysis, while
//	preserving—and often improving—time per round. ChaCha12 and ChaCha20 are
//	analogous modiﬁcations of the 12-round and 20-round ciphers Salsa20/12 and
//	Salsa20/20. This paper presents the ChaCha family and explains the
//	differences between Salsa20 and ChaCha.
//
// For more information, see http://cr.yp.to/chacha.html
package chacha20

import (
	"encoding/binary"
	"errors"
	"unsafe"
)

const (
	// KeySize is the length of ChaCha20 keys, in bytes.
	KeySize = 32

	// NonceSize is the length of ChaCha20 nonces, in bytes.
	NonceSize = 8

	stateSize = 16            // the size of ChaCha20's state, in words
	blockSize = stateSize * 4 // the size of ChaCha20's block, in bytes
)

var (
	// ErrInvalidKey is returned when the provided key is not 256 bits long.
	ErrInvalidKey = errors.New("chacha20: Invalid key length (must be 256 bits)")
	// ErrInvalidNonce is returned when the provided nonce is not 64 bits long.
	ErrInvalidNonce = errors.New("chacha20: Invalid nonce length (must be 64 bits)")

	bigEndian bool // we're running on a bigEndian CPU
)

// Do some up-front bookkeeping on what sort of CPU we're using. ChaCha20 treats
// its state as a little-endian byte array when it comes to generating the
// keystream, which allows for a zero-copy approach to the core transform. On
// big-endian architectures, we have to take a hit to reverse the bytes.
func init() {
	x := uint32(0x04030201)
	y := [4]byte{0x1, 0x2, 0x3, 0x4}
	bigEndian = *(*[4]byte)(unsafe.Pointer(&x)) != y
}

// A Cipher is an instance of ChaCha20 using a particular key and nonce.
type Cipher struct {
	state  [stateSize]uint32 // the state as an array of 16 32-bit words
	block  [blockSize]byte   // the keystream as an array of 64 bytes
	offset int               // the offset of used bytes in block
}

// NewCipher creates and returns a new Cipher.  The key argument must be 256
// bits long, and the nonce argument must be 64 bits long. The nonce must be
// randomly generated or used only once. This Cipher instance must not be used
// to encrypt more than 2^70 bytes (~1 zettabyte).
func NewCipher(key []byte, nonce []byte) (*Cipher, error) {
	if len(key) != KeySize {
		return nil, ErrInvalidKey
	}

	if len(nonce) != NonceSize {
		return nil, ErrInvalidNonce
	}

	c := new(Cipher)

	// the magic constants for 256-bit keys
	c.state[0] = 0x61707865
	c.state[1] = 0x3320646e
	c.state[2] = 0x79622d32
	c.state[3] = 0x6b206574

	c.state[4] = binary.LittleEndian.Uint32(key[0:])
	c.state[5] = binary.LittleEndian.Uint32(key[4:])
	c.state[6] = binary.LittleEndian.Uint32(key[8:])
	c.state[7] = binary.LittleEndian.Uint32(key[12:])
	c.state[8] = binary.LittleEndian.Uint32(key[16:])
	c.state[9] = binary.LittleEndian.Uint32(key[20:])
	c.state[10] = binary.LittleEndian.Uint32(key[24:])
	c.state[11] = binary.LittleEndian.Uint32(key[28:])

	c.state[12] = 0
	c.state[13] = 0
	c.state[14] = binary.LittleEndian.Uint32(nonce[0:])
	c.state[15] = binary.LittleEndian.Uint32(nonce[4:])

	c.advance()

	return c, nil
}

// XORKeyStream sets dst to the result of XORing src with the key stream.
// Dst and src may be the same slice but otherwise should not overlap. You
// should not encrypt more than 2^70 bytes (~1 zettabyte) without re-keying and
// using a new nonce.
func (c *Cipher) XORKeyStream(dst, src []byte) {
	// Stride over the input in 64-byte blocks, minus the amount of keystream
	// previously used. This will produce best results when processing blocks
	// of a size evenly divisible by 64.
	i := 0
	max := len(src)
	for i < max {
		gap := blockSize - c.offset

		limit := i + gap
		if limit > max {
			limit = max
		}

		o := c.offset
		for j := i; j < limit; j++ {
			dst[j] = src[j] ^ c.block[o]
			o++
		}

		i += gap
		c.offset = o

		if o == blockSize {
			c.advance()
		}
	}
}

// Reset zeros the key data so that it will no longer appear in the process's
// memory.
func (c *Cipher) Reset() {
	for i := range c.state {
		c.state[i] = 0
	}
	for i := range c.block {
		c.block[i] = 0
	}
	c.offset = 0
}

// BUG(codahale): Totally untested on big-endian CPUs. Would very much
// appreciate someone with an ARM device giving this a swing.

// advances the keystream
func (c *Cipher) advance() {
	core(&c.state, (*[stateSize]uint32)(unsafe.Pointer(&c.block)))

	if bigEndian {
		j := blockSize - 1
		for i := 0; i < blockSize/2; i++ {
			c.block[j], c.block[i] = c.block[i], c.block[j]
			j--
		}
	}

	c.offset = 0
	i := c.state[12] + 1
	c.state[12] = i
	if i == 0 {
		c.state[13]++
	}
}
<commit_msg>Small formatting change.<commit_after>// Package chacha20 provides a pure Go implementation of ChaCha20, a fast, secure
// stream cipher.
//
// From Bernstein, Daniel J. "ChaCha, a variant of Salsa20." Workshop Record of
// SASC. 2008. (http://cr.yp.to/chacha/chacha-20080128.pdf):
//
//	ChaCha8 is a 256-bit stream cipher based on the 8-round cipher Salsa20/8.
//	The changes from Salsa20/8 to ChaCha8 are designed to improve diffusion per
//	round, conjecturally increasing resistance to cryptanalysis, while
//	preserving—and often improving—time per round. ChaCha12 and ChaCha20 are
//	analogous modiﬁcations of the 12-round and 20-round ciphers Salsa20/12 and
//	Salsa20/20. This paper presents the ChaCha family and explains the
//	differences between Salsa20 and ChaCha.
//
// For more information, see http://cr.yp.to/chacha.html
package chacha20

import (
	"encoding/binary"
	"errors"
	"unsafe"
)

const (
	KeySize   = 32 // KeySize is the length of ChaCha20 keys, in bytes.
	NonceSize = 8  // NonceSize is the length of ChaCha20 nonces, in bytes.

	stateSize = 16            // the size of ChaCha20's state, in words
	blockSize = stateSize * 4 // the size of ChaCha20's block, in bytes
)

var (
	// ErrInvalidKey is returned when the provided key is not 256 bits long.
	ErrInvalidKey = errors.New("chacha20: Invalid key length (must be 256 bits)")
	// ErrInvalidNonce is returned when the provided nonce is not 64 bits long.
	ErrInvalidNonce = errors.New("chacha20: Invalid nonce length (must be 64 bits)")

	bigEndian bool // we're running on a bigEndian CPU
)

// Do some up-front bookkeeping on what sort of CPU we're using. ChaCha20 treats
// its state as a little-endian byte array when it comes to generating the
// keystream, which allows for a zero-copy approach to the core transform. On
// big-endian architectures, we have to take a hit to reverse the bytes.
func init() {
	x := uint32(0x04030201)
	y := [4]byte{0x1, 0x2, 0x3, 0x4}
	bigEndian = *(*[4]byte)(unsafe.Pointer(&x)) != y
}

// A Cipher is an instance of ChaCha20 using a particular key and nonce.
type Cipher struct {
	state  [stateSize]uint32 // the state as an array of 16 32-bit words
	block  [blockSize]byte   // the keystream as an array of 64 bytes
	offset int               // the offset of used bytes in block
}

// NewCipher creates and returns a new Cipher.  The key argument must be 256
// bits long, and the nonce argument must be 64 bits long. The nonce must be
// randomly generated or used only once. This Cipher instance must not be used
// to encrypt more than 2^70 bytes (~1 zettabyte).
func NewCipher(key []byte, nonce []byte) (*Cipher, error) {
	if len(key) != KeySize {
		return nil, ErrInvalidKey
	}

	if len(nonce) != NonceSize {
		return nil, ErrInvalidNonce
	}

	c := new(Cipher)

	// the magic constants for 256-bit keys
	c.state[0] = 0x61707865
	c.state[1] = 0x3320646e
	c.state[2] = 0x79622d32
	c.state[3] = 0x6b206574

	c.state[4] = binary.LittleEndian.Uint32(key[0:])
	c.state[5] = binary.LittleEndian.Uint32(key[4:])
	c.state[6] = binary.LittleEndian.Uint32(key[8:])
	c.state[7] = binary.LittleEndian.Uint32(key[12:])
	c.state[8] = binary.LittleEndian.Uint32(key[16:])
	c.state[9] = binary.LittleEndian.Uint32(key[20:])
	c.state[10] = binary.LittleEndian.Uint32(key[24:])
	c.state[11] = binary.LittleEndian.Uint32(key[28:])

	c.state[12] = 0
	c.state[13] = 0
	c.state[14] = binary.LittleEndian.Uint32(nonce[0:])
	c.state[15] = binary.LittleEndian.Uint32(nonce[4:])

	c.advance()

	return c, nil
}

// XORKeyStream sets dst to the result of XORing src with the key stream.
// Dst and src may be the same slice but otherwise should not overlap. You
// should not encrypt more than 2^70 bytes (~1 zettabyte) without re-keying and
// using a new nonce.
func (c *Cipher) XORKeyStream(dst, src []byte) {
	// Stride over the input in 64-byte blocks, minus the amount of keystream
	// previously used. This will produce best results when processing blocks
	// of a size evenly divisible by 64.
	i := 0
	max := len(src)
	for i < max {
		gap := blockSize - c.offset

		limit := i + gap
		if limit > max {
			limit = max
		}

		o := c.offset
		for j := i; j < limit; j++ {
			dst[j] = src[j] ^ c.block[o]
			o++
		}

		i += gap
		c.offset = o

		if o == blockSize {
			c.advance()
		}
	}
}

// Reset zeros the key data so that it will no longer appear in the process's
// memory.
func (c *Cipher) Reset() {
	for i := range c.state {
		c.state[i] = 0
	}
	for i := range c.block {
		c.block[i] = 0
	}
	c.offset = 0
}

// BUG(codahale): Totally untested on big-endian CPUs. Would very much
// appreciate someone with an ARM device giving this a swing.

// advances the keystream
func (c *Cipher) advance() {
	core(&c.state, (*[stateSize]uint32)(unsafe.Pointer(&c.block)))

	if bigEndian {
		j := blockSize - 1
		for i := 0; i < blockSize/2; i++ {
			c.block[j], c.block[i] = c.block[i], c.block[j]
			j--
		}
	}

	c.offset = 0
	i := c.state[12] + 1
	c.state[12] = i
	if i == 0 {
		c.state[13]++
	}
}
<|endoftext|>


<commit_before>// Copyright The OpenTelemetry 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 defaultcomponents

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.uber.org/zap"

	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/component/componenttest"
	"go.opentelemetry.io/collector/config/configmodels"
)

func TestDefaultExtensions(t *testing.T) {
	allFactories, err := Components()
	require.NoError(t, err)

	extFactories := allFactories.Extensions

	tests := []struct {
		extension   configmodels.Type
		getConfigFn getExtensionConfigFn
	}{
		{
			extension: "health_check",
		},
		{
			extension: "pprof",
		},
		{
			extension: "zpages",
		},
		{
			extension: "fluentbit",
		},
	}

	assert.Equal(t, len(tests), len(extFactories))
	for _, tt := range tests {
		t.Run(string(tt.extension), func(t *testing.T) {
			factory, ok := extFactories[tt.extension]
			require.True(t, ok)
			assert.Equal(t, tt.extension, factory.Type())
			assert.Equal(t, tt.extension, factory.CreateDefaultConfig().Type())

			verifyExtensionLifecycle(t, factory, nil)
		})
	}
}

// getExtensionConfigFn is used customize the configuration passed to the verification.
// This is used to change ports or provide values required but not provided by the
// default configuration.
type getExtensionConfigFn func() configmodels.Extension

// verifyExtensionLifecycle is used to test if an extension type can handle the typical
// lifecycle of a component. The getConfigFn parameter only need to be specified if
// the test can't be done with the default configuration for the component.
func verifyExtensionLifecycle(t *testing.T, factory component.ExtensionFactory, getConfigFn getExtensionConfigFn) {
	ctx := context.Background()
	host := newAssertNoErrorHost(t)
	extCreateParams := component.ExtensionCreateParams{
		Logger:               zap.NewNop(),
		ApplicationStartInfo: component.DefaultApplicationStartInfo(),
	}

	if getConfigFn == nil {
		getConfigFn = factory.CreateDefaultConfig
	}

	firstExt, err := factory.CreateExtension(ctx, extCreateParams, getConfigFn())
	require.NoError(t, err)
	require.NoError(t, firstExt.Start(ctx, host))
	require.NoError(t, firstExt.Shutdown(ctx))

	secondExt, err := factory.CreateExtension(ctx, extCreateParams, getConfigFn())
	require.NoError(t, err)
	require.NoError(t, secondExt.Start(ctx, host))
	require.NoError(t, secondExt.Shutdown(ctx))
}

// assertNoErrorHost implements a component.Host that asserts that there were no errors.
type assertNoErrorHost struct {
	component.Host
	*testing.T
}

var _ component.Host = (*assertNoErrorHost)(nil)

// newAssertNoErrorHost returns a new instance of assertNoErrorHost.
func newAssertNoErrorHost(t *testing.T) component.Host {
	return &assertNoErrorHost{
		componenttest.NewNopHost(),
		t,
	}
}

func (aneh *assertNoErrorHost) ReportFatalError(err error) {
	assert.NoError(aneh, err)
}
<commit_msg>Make default extensions test more resilient (#2763)<commit_after>// Copyright The OpenTelemetry 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 defaultcomponents

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.uber.org/zap"

	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/component/componenttest"
	"go.opentelemetry.io/collector/config/configmodels"
	"go.opentelemetry.io/collector/extension/healthcheckextension"
	"go.opentelemetry.io/collector/extension/pprofextension"
	"go.opentelemetry.io/collector/extension/zpagesextension"
	"go.opentelemetry.io/collector/testutil"
)

func TestDefaultExtensions(t *testing.T) {
	allFactories, err := Components()
	require.NoError(t, err)

	extFactories := allFactories.Extensions
	endpoint := testutil.GetAvailableLocalAddress(t)
	port := testutil.GetAvailablePort(t)

	tests := []struct {
		extension   configmodels.Type
		getConfigFn getExtensionConfigFn
	}{
		{
			extension: "health_check",
			getConfigFn: func() configmodels.Extension {
				cfg := extFactories["health_check"].CreateDefaultConfig().(*healthcheckextension.Config)
				cfg.Port = port
				return cfg
			},
		},
		{
			extension: "pprof",
			getConfigFn: func() configmodels.Extension {
				cfg := extFactories["pprof"].CreateDefaultConfig().(*pprofextension.Config)
				cfg.Endpoint = endpoint
				return cfg
			},
		},
		{
			extension: "zpages",
			getConfigFn: func() configmodels.Extension {
				cfg := extFactories["zpages"].CreateDefaultConfig().(*zpagesextension.Config)
				cfg.Endpoint = endpoint
				return cfg
			},
		},
		{
			extension: "fluentbit",
		},
	}

	assert.Equal(t, len(tests), len(extFactories))
	for _, tt := range tests {
		t.Run(string(tt.extension), func(t *testing.T) {
			factory, ok := extFactories[tt.extension]
			require.True(t, ok)
			assert.Equal(t, tt.extension, factory.Type())
			assert.Equal(t, tt.extension, factory.CreateDefaultConfig().Type())

			verifyExtensionLifecycle(t, factory, nil)
		})
	}
}

// getExtensionConfigFn is used customize the configuration passed to the verification.
// This is used to change ports or provide values required but not provided by the
// default configuration.
type getExtensionConfigFn func() configmodels.Extension

// verifyExtensionLifecycle is used to test if an extension type can handle the typical
// lifecycle of a component. The getConfigFn parameter only need to be specified if
// the test can't be done with the default configuration for the component.
func verifyExtensionLifecycle(t *testing.T, factory component.ExtensionFactory, getConfigFn getExtensionConfigFn) {
	ctx := context.Background()
	host := newAssertNoErrorHost(t)
	extCreateParams := component.ExtensionCreateParams{
		Logger:               zap.NewNop(),
		ApplicationStartInfo: component.DefaultApplicationStartInfo(),
	}

	if getConfigFn == nil {
		getConfigFn = factory.CreateDefaultConfig
	}

	firstExt, err := factory.CreateExtension(ctx, extCreateParams, getConfigFn())
	require.NoError(t, err)
	require.NoError(t, firstExt.Start(ctx, host))
	require.NoError(t, firstExt.Shutdown(ctx))

	secondExt, err := factory.CreateExtension(ctx, extCreateParams, getConfigFn())
	require.NoError(t, err)
	require.NoError(t, secondExt.Start(ctx, host))
	require.NoError(t, secondExt.Shutdown(ctx))
}

// assertNoErrorHost implements a component.Host that asserts that there were no errors.
type assertNoErrorHost struct {
	component.Host
	*testing.T
}

var _ component.Host = (*assertNoErrorHost)(nil)

// newAssertNoErrorHost returns a new instance of assertNoErrorHost.
func newAssertNoErrorHost(t *testing.T) component.Host {
	return &assertNoErrorHost{
		componenttest.NewNopHost(),
		t,
	}
}

func (aneh *assertNoErrorHost) ReportFatalError(err error) {
	assert.NoError(aneh, err)
}
<|endoftext|>


<commit_before>package spawn

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"testing"
	"time"
)

func TestMain(m *testing.M) {
	switch os.Getenv("TEST_MAIN") {
	case "app":
		appMain()
	default:
		os.Exit(m.Run())
	}
}

func appMain() {
	if len(os.Args) < 2 {
		fmt.Fprintln(os.Stderr, "no command provided")
		os.Exit(1)
	}
	switch cmd := os.Args[1]; cmd {
	case "echo":
		fmt.Println(strings.Join(os.Args[2:], " "))
	case "sleep":
		if len(os.Args) != 3 {
			fmt.Fprintln(os.Stderr, "expected 3 args")
			os.Exit(1)
		}
		dur, err := time.ParseDuration(os.Args[2])
		if err != nil {
			fmt.Fprintf(os.Stderr, "could not parse sleep time: %v", err)
			os.Exit(1)
		}
		time.Sleep(dur)
	default:
		fmt.Fprintln(os.Stderr, "unknown command:", cmd)
		os.Exit(1)
	}
}

func TestSpawn_NoCmd(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	if err := spawn.Spawn(nil); err == nil {
		t.Fatalf("Spawn() with no user command should fail")
	}
}

func TestSpawn_InvalidCmd(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(exec.Command("foo")) // non-existent command
	if err := spawn.Spawn(nil); err == nil {
		t.Fatalf("Spawn() with an invalid command should fail")
	}
}

func TestSpawn_SetsLogs(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	exp := "foo"
	spawn.SetCommand(testCommand("echo", exp))

	// Create file for stdout.
	stdout := tempFileName(t)
	defer os.Remove(stdout)
	spawn.SetLogs(&Logs{Stdout: stdout})

	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed: %v", err)
	}

	if res := spawn.Wait(); res.ExitCode != 0 && res.Err != nil {
		t.Fatalf("Wait() returned %v, %v; want 0, nil", res.ExitCode, res.Err)
	}

	stdout2, err := os.Open(stdout)
	if err != nil {
		t.Fatalf("Open() failed: %v", err)
	}

	data, err := ioutil.ReadAll(stdout2)
	if err != nil {
		t.Fatalf("ReadAll() failed: %v", err)
	}

	act := strings.TrimSpace(string(data))
	if act != exp {
		t.Fatalf("Unexpected data written to stdout; got %v; want %v", act, exp)
	}
}

func TestSpawn_Callback(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "1s"))

	called := false
	cbErr := fmt.Errorf("ERROR CB")
	cb := func(_ int) error {
		called = true
		return cbErr
	}

	if err := spawn.Spawn(cb); err == nil {
		t.Fatalf("Spawn(%#v) should have errored; want %v", cb, cbErr)
	}

	if !called {
		t.Fatalf("Spawn(%#v) didn't call callback", cb)
	}
}

func TestSpawn_ParentWaitExited(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("echo", "foo"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	time.Sleep(1 * time.Second)

	if res := spawn.Wait(); res.ExitCode != 0 && res.Err != nil {
		t.Fatalf("Wait() returned %v, %v; want 0, nil", res.ExitCode, res.Err)
	}
}

func TestSpawn_ParentWait(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "2s"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	if res := spawn.Wait(); res.ExitCode != 0 && res.Err != nil {
		t.Fatalf("Wait() returned %v, %v; want 0, nil", res.ExitCode, res.Err)
	}
}

func TestSpawn_NonParentWaitExited(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("echo", "foo"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	time.Sleep(1 * time.Second)

	// Force the wait to assume non-parent.
	spawn.SpawnPpid = 0
	if res := spawn.Wait(); res.ExitCode != 0 && res.Err != nil {
		t.Fatalf("Wait() returned %v, %v; want 0, nil", res.ExitCode, res.Err)
	}
}

func TestSpawn_NonParentWait(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "2s"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	// Need to wait on the spawner, otherwise it becomes a zombie and the test
	// only finishes after the init process cleans it. This speeds that up.
	go func() {
		time.Sleep(3 * time.Second)
		if _, err := spawn.spawn.Wait(); err != nil {
			t.FailNow()
		}
	}()

	// Force the wait to assume non-parent.
	spawn.SpawnPpid = 0
	if res := spawn.Wait(); res.ExitCode != 0 && res.Err != nil {
		t.Fatalf("Wait() returned %v, %v; want 0, nil", res.ExitCode, res.Err)
	}
}

func TestSpawn_DeadSpawnDaemon_Parent(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	var spawnPid int
	cb := func(pid int) error {
		spawnPid = pid
		return nil
	}

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "5s"))
	if err := spawn.Spawn(cb); err != nil {
		t.Fatalf("Spawn() errored: %v", err)
	}

	proc, err := os.FindProcess(spawnPid)
	if err != nil {
		t.FailNow()
	}

	if err := proc.Kill(); err != nil {
		t.FailNow()
	}

	if _, err := proc.Wait(); err != nil {
		t.FailNow()
	}

	if res := spawn.Wait(); res.Err == nil {
		t.Fatalf("Wait() should have failed: %v", res.Err)
	}
}

func TestSpawn_DeadSpawnDaemon_NonParent(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	var spawnPid int
	cb := func(pid int) error {
		spawnPid = pid
		return nil
	}

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "2s"))
	if err := spawn.Spawn(cb); err != nil {
		t.Fatalf("Spawn() errored: %v", err)
	}

	proc, err := os.FindProcess(spawnPid)
	if err != nil {
		t.FailNow()
	}

	if err := proc.Kill(); err != nil {
		t.FailNow()
	}

	if _, err := proc.Wait(); err != nil {
		t.FailNow()
	}

	// Force the wait to assume non-parent.
	spawn.SpawnPpid = 0
	if res := spawn.Wait(); res.Err == nil {
		t.Fatalf("Wait() should have failed: %v", res.Err)
	}
}

func TestSpawn_Valid_TaskRunning(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "2s"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	if err := spawn.Valid(); err != nil {
		t.Fatalf("Valid() failed: %v", err)
	}

	if res := spawn.Wait(); res.Err != nil {
		t.Fatalf("Wait() failed: %v", res.Err)
	}
}

func TestSpawn_Valid_TaskExit_ExitCode(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("echo", "foo"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	if res := spawn.Wait(); res.Err != nil {
		t.Fatalf("Wait() failed: %v", res.Err)
	}

	if err := spawn.Valid(); err != nil {
		t.Fatalf("Valid() failed: %v", err)
	}
}

func TestSpawn_Valid_TaskExit_NoExitCode(t *testing.T) {
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("echo", "foo"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	if res := spawn.Wait(); res.Err != nil {
		t.Fatalf("Wait() failed: %v", res.Err)
	}

	// Delete the file so that it can't find the exit code.
	os.Remove(tempFile)

	if err := spawn.Valid(); err == nil {
		t.Fatalf("Valid() should have failed")
	}
}

func tempFileName(t *testing.T) string {
	f, err := ioutil.TempFile("", "")
	if err != nil {
		t.Fatalf("TempFile() failed")
	}
	defer f.Close()
	return f.Name()
}

func testCommand(args ...string) *exec.Cmd {
	cmd := exec.Command(os.Args[0], args...)
	cmd.Env = append(os.Environ(), "TEST_MAIN=app")
	return cmd
}
<commit_msg>Speed up tests by allowing parallel execution.<commit_after>package spawn

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"testing"
	"time"
)

func TestMain(m *testing.M) {
	switch os.Getenv("TEST_MAIN") {
	case "app":
		appMain()
	default:
		os.Exit(m.Run())
	}
}

func appMain() {
	if len(os.Args) < 2 {
		fmt.Fprintln(os.Stderr, "no command provided")
		os.Exit(1)
	}
	switch cmd := os.Args[1]; cmd {
	case "echo":
		fmt.Println(strings.Join(os.Args[2:], " "))
	case "sleep":
		if len(os.Args) != 3 {
			fmt.Fprintln(os.Stderr, "expected 3 args")
			os.Exit(1)
		}
		dur, err := time.ParseDuration(os.Args[2])
		if err != nil {
			fmt.Fprintf(os.Stderr, "could not parse sleep time: %v", err)
			os.Exit(1)
		}
		time.Sleep(dur)
	default:
		fmt.Fprintln(os.Stderr, "unknown command:", cmd)
		os.Exit(1)
	}
}

func TestSpawn_NoCmd(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	if err := spawn.Spawn(nil); err == nil {
		t.Fatalf("Spawn() with no user command should fail")
	}
}

func TestSpawn_InvalidCmd(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(exec.Command("foo")) // non-existent command
	if err := spawn.Spawn(nil); err == nil {
		t.Fatalf("Spawn() with an invalid command should fail")
	}
}

func TestSpawn_SetsLogs(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	exp := "foo"
	spawn.SetCommand(testCommand("echo", exp))

	// Create file for stdout.
	stdout := tempFileName(t)
	defer os.Remove(stdout)
	spawn.SetLogs(&Logs{Stdout: stdout})

	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed: %v", err)
	}

	if res := spawn.Wait(); res.ExitCode != 0 && res.Err != nil {
		t.Fatalf("Wait() returned %v, %v; want 0, nil", res.ExitCode, res.Err)
	}

	stdout2, err := os.Open(stdout)
	if err != nil {
		t.Fatalf("Open() failed: %v", err)
	}

	data, err := ioutil.ReadAll(stdout2)
	if err != nil {
		t.Fatalf("ReadAll() failed: %v", err)
	}

	act := strings.TrimSpace(string(data))
	if act != exp {
		t.Fatalf("Unexpected data written to stdout; got %v; want %v", act, exp)
	}
}

func TestSpawn_Callback(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "1s"))

	called := false
	cbErr := fmt.Errorf("ERROR CB")
	cb := func(_ int) error {
		called = true
		return cbErr
	}

	if err := spawn.Spawn(cb); err == nil {
		t.Fatalf("Spawn(%#v) should have errored; want %v", cb, cbErr)
	}

	if !called {
		t.Fatalf("Spawn(%#v) didn't call callback", cb)
	}
}

func TestSpawn_ParentWaitExited(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("echo", "foo"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	time.Sleep(1 * time.Second)

	if res := spawn.Wait(); res.ExitCode != 0 && res.Err != nil {
		t.Fatalf("Wait() returned %v, %v; want 0, nil", res.ExitCode, res.Err)
	}
}

func TestSpawn_ParentWait(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "2s"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	if res := spawn.Wait(); res.ExitCode != 0 && res.Err != nil {
		t.Fatalf("Wait() returned %v, %v; want 0, nil", res.ExitCode, res.Err)
	}
}

func TestSpawn_NonParentWaitExited(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("echo", "foo"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	time.Sleep(1 * time.Second)

	// Force the wait to assume non-parent.
	spawn.SpawnPpid = 0
	if res := spawn.Wait(); res.ExitCode != 0 && res.Err != nil {
		t.Fatalf("Wait() returned %v, %v; want 0, nil", res.ExitCode, res.Err)
	}
}

func TestSpawn_NonParentWait(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "2s"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	// Need to wait on the spawner, otherwise it becomes a zombie and the test
	// only finishes after the init process cleans it. This speeds that up.
	go func() {
		time.Sleep(3 * time.Second)
		if _, err := spawn.spawn.Wait(); err != nil {
			t.FailNow()
		}
	}()

	// Force the wait to assume non-parent.
	spawn.SpawnPpid = 0
	if res := spawn.Wait(); res.ExitCode != 0 && res.Err != nil {
		t.Fatalf("Wait() returned %v, %v; want 0, nil", res.ExitCode, res.Err)
	}
}

func TestSpawn_DeadSpawnDaemon_Parent(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	var spawnPid int
	cb := func(pid int) error {
		spawnPid = pid
		return nil
	}

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "5s"))
	if err := spawn.Spawn(cb); err != nil {
		t.Fatalf("Spawn() errored: %v", err)
	}

	proc, err := os.FindProcess(spawnPid)
	if err != nil {
		t.FailNow()
	}

	if err := proc.Kill(); err != nil {
		t.FailNow()
	}

	if _, err := proc.Wait(); err != nil {
		t.FailNow()
	}

	if res := spawn.Wait(); res.Err == nil {
		t.Fatalf("Wait() should have failed: %v", res.Err)
	}
}

func TestSpawn_DeadSpawnDaemon_NonParent(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	var spawnPid int
	cb := func(pid int) error {
		spawnPid = pid
		return nil
	}

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "2s"))
	if err := spawn.Spawn(cb); err != nil {
		t.Fatalf("Spawn() errored: %v", err)
	}

	proc, err := os.FindProcess(spawnPid)
	if err != nil {
		t.FailNow()
	}

	if err := proc.Kill(); err != nil {
		t.FailNow()
	}

	if _, err := proc.Wait(); err != nil {
		t.FailNow()
	}

	// Force the wait to assume non-parent.
	spawn.SpawnPpid = 0
	if res := spawn.Wait(); res.Err == nil {
		t.Fatalf("Wait() should have failed: %v", res.Err)
	}
}

func TestSpawn_Valid_TaskRunning(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("sleep", "2s"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	if err := spawn.Valid(); err != nil {
		t.Fatalf("Valid() failed: %v", err)
	}

	if res := spawn.Wait(); res.Err != nil {
		t.Fatalf("Wait() failed: %v", res.Err)
	}
}

func TestSpawn_Valid_TaskExit_ExitCode(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("echo", "foo"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	if res := spawn.Wait(); res.Err != nil {
		t.Fatalf("Wait() failed: %v", res.Err)
	}

	if err := spawn.Valid(); err != nil {
		t.Fatalf("Valid() failed: %v", err)
	}
}

func TestSpawn_Valid_TaskExit_NoExitCode(t *testing.T) {
	t.Parallel()
	tempFile := tempFileName(t)
	defer os.Remove(tempFile)

	spawn := NewSpawner(tempFile)
	spawn.SetCommand(testCommand("echo", "foo"))
	if err := spawn.Spawn(nil); err != nil {
		t.Fatalf("Spawn() failed %v", err)
	}

	if res := spawn.Wait(); res.Err != nil {
		t.Fatalf("Wait() failed: %v", res.Err)
	}

	// Delete the file so that it can't find the exit code.
	os.Remove(tempFile)

	if err := spawn.Valid(); err == nil {
		t.Fatalf("Valid() should have failed")
	}
}

func tempFileName(t *testing.T) string {
	f, err := ioutil.TempFile("", "")
	if err != nil {
		t.Fatalf("TempFile() failed")
	}
	defer f.Close()
	return f.Name()
}

func testCommand(args ...string) *exec.Cmd {
	cmd := exec.Command(os.Args[0], args...)
	cmd.Env = append(os.Environ(), "TEST_MAIN=app")
	return cmd
}
<|endoftext|>


<commit_before>// Copyright 2017 The etcd 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 integration

import (
	"context"
	"strconv"
	"testing"
	"time"

	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
	"github.com/coreos/etcd/pkg/testutil"
)

// TestMetricDbSizeBoot checks that the db size metric is set on boot.
func TestMetricDbSizeBoot(t *testing.T) {
	defer testutil.AfterTest(t)
	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
	defer clus.Terminate(t)

	v, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_bytes")
	if err != nil {
		t.Fatal(err)
	}

	if v == "0" {
		t.Fatalf("expected non-zero, got %q", v)
	}
}

// TestMetricDbSizeDefrag checks that the db size metric is set after defrag.
func TestMetricDbSizeDefrag(t *testing.T) {
	defer testutil.AfterTest(t)
	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
	defer clus.Terminate(t)

	kvc := toGRPC(clus.Client(0)).KV
	mc := toGRPC(clus.Client(0)).Maintenance

	// expand the db size
	numPuts := 25 // large enough to write more than 1 page
	putreq := &pb.PutRequest{Key: []byte("k"), Value: make([]byte, 4096)}
	for i := 0; i < numPuts; i++ {
		if _, err := kvc.Put(context.TODO(), putreq); err != nil {
			t.Fatal(err)
		}
	}

	// wait for backend txn sync
	time.Sleep(500 * time.Millisecond)

	beforeDefrag, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_bytes")
	if err != nil {
		t.Fatal(err)
	}
	bv, err := strconv.Atoi(beforeDefrag)
	if err != nil {
		t.Fatal(err)
	}
	if expected := numPuts * len(putreq.Value); bv < expected {
		t.Fatalf("expected db size greater than %d, got %d", expected, bv)
	}
	beforeDefragInUse, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_use_in_bytes")
	if err != nil {
		t.Fatal(err)
	}
	biu, err := strconv.Atoi(beforeDefragInUse)
	if err != nil {
		t.Fatal(err)
	}
	if biu != bv {
		t.Fatalf("when db size is growing, db size (%d) and db size in use (%d) is expected to be equal", bv, biu)
	}

	// clear out historical keys, in use bytes should free pages
	creq := &pb.CompactionRequest{Revision: int64(numPuts), Physical: true}
	if _, kerr := kvc.Compact(context.TODO(), creq); kerr != nil {
		t.Fatal(kerr)
	}

	// Put to move PendingPages to FreePages
	if _, err := kvc.Put(context.TODO(), putreq); err != nil {
		t.Fatal(err)
	}
	time.Sleep(500 * time.Millisecond)

	afterCompactionInUse, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_use_in_bytes")
	if err != nil {
		t.Fatal(err)
	}
	aciu, err := strconv.Atoi(afterCompactionInUse)
	if err != nil {
		t.Fatal(err)
	}
	if biu <= aciu {
		t.Fatalf("expected less than %d, got %d after compaction", biu, aciu)
	}

	// defrag should give freed space back to fs
	mc.Defragment(context.TODO(), &pb.DefragmentRequest{})

	afterDefrag, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_bytes")
	if err != nil {
		t.Fatal(err)
	}
	av, err := strconv.Atoi(afterDefrag)
	if err != nil {
		t.Fatal(err)
	}
	if bv <= av {
		t.Fatalf("expected less than %d, got %d after defrag", bv, av)
	}

	afterDefragInUse, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_use_in_bytes")
	if err != nil {
		t.Fatal(err)
	}
	adiu, err := strconv.Atoi(afterDefragInUse)
	if err != nil {
		t.Fatal(err)
	}
	if adiu > av {
		t.Fatalf("db size in use (%d) is expected less than db size (%d) after defrag", adiu, av)
	}
}
<commit_msg>integration: fix govet error in Go tip<commit_after>// Copyright 2017 The etcd 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 integration

import (
	"context"
	"strconv"
	"testing"
	"time"

	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
	"github.com/coreos/etcd/pkg/testutil"
)

// TestMetricDbSizeBoot checks that the db size metric is set on boot.
func TestMetricDbSizeBoot(t *testing.T) {
	defer testutil.AfterTest(t)
	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
	defer clus.Terminate(t)

	v, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_bytes")
	if err != nil {
		t.Fatal(err)
	}

	if v == "0" {
		t.Fatalf("expected non-zero, got %q", v)
	}
}

// TestMetricDbSizeDefrag checks that the db size metric is set after defrag.
func TestMetricDbSizeDefrag(t *testing.T) {
	defer testutil.AfterTest(t)
	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
	defer clus.Terminate(t)

	kvc := toGRPC(clus.Client(0)).KV
	mc := toGRPC(clus.Client(0)).Maintenance

	// expand the db size
	numPuts := 25 // large enough to write more than 1 page
	putreq := &pb.PutRequest{Key: []byte("k"), Value: make([]byte, 4096)}
	for i := 0; i < numPuts; i++ {
		if _, err := kvc.Put(context.TODO(), putreq); err != nil {
			t.Fatal(err)
		}
	}

	// wait for backend txn sync
	time.Sleep(500 * time.Millisecond)

	beforeDefrag, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_bytes")
	if err != nil {
		t.Fatal(err)
	}
	bv, err := strconv.Atoi(beforeDefrag)
	if err != nil {
		t.Fatal(err)
	}
	if expected := numPuts * len(putreq.Value); bv < expected {
		t.Fatalf("expected db size greater than %d, got %d", expected, bv)
	}
	beforeDefragInUse, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_use_in_bytes")
	if err != nil {
		t.Fatal(err)
	}
	biu, err := strconv.Atoi(beforeDefragInUse)
	if err != nil {
		t.Fatal(err)
	}
	if biu != bv {
		t.Fatalf("when db size is growing, db size (%d) and db size in use (%d) is expected to be equal", bv, biu)
	}

	// clear out historical keys, in use bytes should free pages
	creq := &pb.CompactionRequest{Revision: int64(numPuts), Physical: true}
	if _, kerr := kvc.Compact(context.TODO(), creq); kerr != nil {
		t.Fatal(kerr)
	}

	// Put to move PendingPages to FreePages
	if _, err = kvc.Put(context.TODO(), putreq); err != nil {
		t.Fatal(err)
	}
	time.Sleep(500 * time.Millisecond)

	afterCompactionInUse, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_use_in_bytes")
	if err != nil {
		t.Fatal(err)
	}
	aciu, err := strconv.Atoi(afterCompactionInUse)
	if err != nil {
		t.Fatal(err)
	}
	if biu <= aciu {
		t.Fatalf("expected less than %d, got %d after compaction", biu, aciu)
	}

	// defrag should give freed space back to fs
	mc.Defragment(context.TODO(), &pb.DefragmentRequest{})

	afterDefrag, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_bytes")
	if err != nil {
		t.Fatal(err)
	}
	av, err := strconv.Atoi(afterDefrag)
	if err != nil {
		t.Fatal(err)
	}
	if bv <= av {
		t.Fatalf("expected less than %d, got %d after defrag", bv, av)
	}

	afterDefragInUse, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_use_in_bytes")
	if err != nil {
		t.Fatal(err)
	}
	adiu, err := strconv.Atoi(afterDefragInUse)
	if err != nil {
		t.Fatal(err)
	}
	if adiu > av {
		t.Fatalf("db size in use (%d) is expected less than db size (%d) after defrag", adiu, av)
	}
}
<|endoftext|>


<commit_before>package integration_test

import (
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/concourse/fly/ui"
	"github.com/fatih/color"
	"github.com/onsi/gomega/gexec"

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

var _ = Describe("Fly CLI", func() {
	var (
		flyCmd *exec.Cmd
		flyrc  string
	)

	BeforeEach(func() {
		flyrc = filepath.Join(userHomeDir(), ".flyrc")

		flyFixtureFile, err := os.OpenFile("./fixtures/flyrc.yml", os.O_RDONLY, 0600)
		Expect(err).NotTo(HaveOccurred())

		flyFixtureData, err := ioutil.ReadAll(flyFixtureFile)
		Expect(err).NotTo(HaveOccurred())

		err = ioutil.WriteFile(flyrc, flyFixtureData, 0600)
		Expect(err).NotTo(HaveOccurred())

		flyCmd = exec.Command(flyPath, "targets")
	})

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

	Describe("targets", func() {
		Context("when there are targets in the .flyrc", func() {
			It("displays all the targets with their token expiration", func() {
				sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())

				Eventually(sess).Should(gexec.Exit(0))

				Expect(sess.Out).To(PrintTable(ui.Table{
					Headers: ui.TableRow{
						{Contents: "name", Color: color.New(color.Bold)},
						{Contents: "url", Color: color.New(color.Bold)},
						{Contents: "expiry", Color: color.New(color.Bold)},
					},
					Data: []ui.TableRow{
						{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
						{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "n/a"}},
						{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "Mon, 21 Mar 2016 01:54:30 UTC"}},
						{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "Fri, 25 Mar 2016 23:29:57 UTC"}},
					},
				}))
			})
		})

		Context("when no targets are available", func() {
			BeforeEach(func() {
				os.RemoveAll(flyrc)
			})

			It("prints an empty table", func() {
				sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())

				Eventually(sess).Should(gexec.Exit(0))
				Expect(sess.Out).To(PrintTable(ui.Table{
					Headers: ui.TableRow{
						{Contents: "name", Color: color.New(color.Bold)},
						{Contents: "url", Color: color.New(color.Bold)},
						{Contents: "expiry", Color: color.New(color.Bold)},
					},
					Data: []ui.TableRow{}}))
			})
		})
	})
})
<commit_msg>make flyrc location portable to windows<commit_after>package integration_test

import (
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"

	"github.com/concourse/fly/ui"
	"github.com/fatih/color"
	"github.com/onsi/gomega/gexec"

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

var _ = Describe("Fly CLI", func() {
	var (
		flyCmd *exec.Cmd
		flyrc  string
		tmpDir string
	)

	BeforeEach(func() {
		var err error
		tmpDir, err = ioutil.TempDir("", "fly-test")
		Expect(err).NotTo(HaveOccurred())

		if runtime.GOOS == "windows" {
			os.Setenv("USERPROFILE", tmpDir)
		} else {
			os.Setenv("HOME", tmpDir)
		}

		flyrc = filepath.Join(userHomeDir(), ".flyrc")

		flyFixtureFile, err := os.OpenFile("./fixtures/flyrc.yml", os.O_RDONLY, 0600)
		Expect(err).NotTo(HaveOccurred())

		flyFixtureData, err := ioutil.ReadAll(flyFixtureFile)
		Expect(err).NotTo(HaveOccurred())

		err = ioutil.WriteFile(flyrc, flyFixtureData, 0600)
		Expect(err).NotTo(HaveOccurred())

		flyCmd = exec.Command(flyPath, "targets")
	})

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

	Describe("targets", func() {
		Context("when there are targets in the .flyrc", func() {
			It("displays all the targets with their token expiration", func() {
				sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())

				Eventually(sess).Should(gexec.Exit(0))

				Expect(sess.Out).To(PrintTable(ui.Table{
					Headers: ui.TableRow{
						{Contents: "name", Color: color.New(color.Bold)},
						{Contents: "url", Color: color.New(color.Bold)},
						{Contents: "expiry", Color: color.New(color.Bold)},
					},
					Data: []ui.TableRow{
						{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
						{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "n/a"}},
						{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "Mon, 21 Mar 2016 01:54:30 UTC"}},
						{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "Fri, 25 Mar 2016 23:29:57 UTC"}},
					},
				}))
			})
		})

		Context("when no targets are available", func() {
			BeforeEach(func() {
				os.RemoveAll(flyrc)
			})

			It("prints an empty table", func() {
				sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())

				Eventually(sess).Should(gexec.Exit(0))
				Expect(sess.Out).To(PrintTable(ui.Table{
					Headers: ui.TableRow{
						{Contents: "name", Color: color.New(color.Bold)},
						{Contents: "url", Color: color.New(color.Bold)},
						{Contents: "expiry", Color: color.New(color.Bold)},
					},
					Data: []ui.TableRow{}}))
			})
		})
	})
})
<|endoftext|>