<commit_before>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package framework

import (
	"fmt"
	"os"
	"path"
	"strings"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/kubernetes/pkg/api/v1"
	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

func EtcdUpgrade(target_storage, target_version string) error {
	switch TestContext.Provider {
	case "gce":
		return etcdUpgradeGCE(target_storage, target_version)
	default:
		return fmt.Errorf("EtcdUpgrade() is not implemented for provider %s", TestContext.Provider)
	}
}

func MasterUpgrade(v string) error {
	switch TestContext.Provider {
	case "gce":
		return masterUpgradeGCE(v)
	case "gke":
		return masterUpgradeGKE(v)
	default:
		return fmt.Errorf("MasterUpgrade() is not implemented for provider %s", TestContext.Provider)
	}
}

func etcdUpgradeGCE(target_storage, target_version string) error {
	env := append(
		os.Environ(),
		"TEST_ETCD_VERSION="+target_version,
		"STORAGE_BACKEND="+target_storage,
		"TEST_ETCD_IMAGE=3.0.17")

	_, _, err := RunCmdEnv(env, gceUpgradeScript(), "-l", "-M")
	return err
}

func masterUpgradeGCE(rawV string) error {
	env := os.Environ()
	// TODO: Remove these variables when they're no longer needed for downgrades.
	if TestContext.EtcdUpgradeVersion != "" && TestContext.EtcdUpgradeStorage != "" {
		env = append(env,
			"ETCD_VERSION="+TestContext.EtcdUpgradeVersion,
			"STORAGE_BACKEND="+TestContext.EtcdUpgradeStorage,
			"ETCD_IMAGE=3.0.17")
	}

	v := "v" + rawV
	_, _, err := RunCmdEnv(env, gceUpgradeScript(), "-M", v)
	return err
}

func masterUpgradeGKE(v string) error {
	Logf("Upgrading master to %q", v)
	_, _, err := RunCmd("gcloud", "container",
		"clusters",
		fmt.Sprintf("--project=%s", TestContext.CloudConfig.ProjectID),
		fmt.Sprintf("--zone=%s", TestContext.CloudConfig.Zone),
		"upgrade",
		TestContext.CloudConfig.Cluster,
		"--master",
		fmt.Sprintf("--cluster-version=%s", v),
		"--quiet")
	return err
}

func NodeUpgrade(f *Framework, v string, img string) error {
	// Perform the upgrade.
	var err error
	switch TestContext.Provider {
	case "gce":
		err = nodeUpgradeGCE(v, img)
	case "gke":
		err = nodeUpgradeGKE(v, img)
	default:
		err = fmt.Errorf("NodeUpgrade() is not implemented for provider %s", TestContext.Provider)
	}
	if err != nil {
		return err
	}

	// Wait for it to complete and validate nodes are healthy.
	//
	// TODO(ihmccreery) We shouldn't have to wait for nodes to be ready in
	// GKE; the operation shouldn't return until they all are.
	Logf("Waiting up to %v for all nodes to be ready after the upgrade", RestartNodeReadyAgainTimeout)
	if _, err := CheckNodesReady(f.ClientSet, RestartNodeReadyAgainTimeout, TestContext.CloudConfig.NumNodes); err != nil {
		return err
	}
	return nil
}

func nodeUpgradeGCE(rawV, img string) error {
	v := "v" + rawV
	if img != "" {
		env := append(os.Environ(), "KUBE_NODE_OS_DISTRIBUTION="+img)
		_, _, err := RunCmdEnv(env, gceUpgradeScript(), "-N", "-o", v)
		return err
	}
	_, _, err := RunCmd(gceUpgradeScript(), "-N", v)
	return err
}

func cleanupNodeUpgradeGCE(tmplBefore string) {
	Logf("Cleaning up any unused node templates")
	tmplAfter, err := MigTemplate()
	if err != nil {
		Logf("Could not get node template post-upgrade; may have leaked template %s", tmplBefore)
		return
	}
	if tmplBefore == tmplAfter {
		// The node upgrade failed so there's no need to delete
		// anything.
		Logf("Node template %s is still in use; not cleaning up", tmplBefore)
		return
	}
	Logf("Deleting node template %s", tmplBefore)
	if _, _, err := retryCmd("gcloud", "compute", "instance-templates",
		fmt.Sprintf("--project=%s", TestContext.CloudConfig.ProjectID),
		"delete",
		tmplBefore); err != nil {
		Logf("gcloud compute instance-templates delete %s call failed with err: %v", tmplBefore, err)
		Logf("May have leaked instance template %q", tmplBefore)
	}
}

func nodeUpgradeGKE(v string, img string) error {
	Logf("Upgrading nodes to version %q and image %q", v, img)
	args := []string{
		"container",
		"clusters",
		fmt.Sprintf("--project=%s", TestContext.CloudConfig.ProjectID),
		fmt.Sprintf("--zone=%s", TestContext.CloudConfig.Zone),
		"upgrade",
		TestContext.CloudConfig.Cluster,
		fmt.Sprintf("--cluster-version=%s", v),
		"--quiet",
	}
	if len(img) > 0 {
		args = append(args, fmt.Sprintf("--image-type=%s", img))
	}
	_, _, err := RunCmd("gcloud", args...)
	return err
}

// CheckNodesReady waits up to nt for expect nodes accessed by c to be ready,
// returning an error if this doesn't happen in time. It returns the names of
// nodes it finds.
func CheckNodesReady(c clientset.Interface, nt time.Duration, expect int) ([]string, error) {
	// First, keep getting all of the nodes until we get the number we expect.
	var nodeList *v1.NodeList
	var errLast error
	start := time.Now()
	found := wait.Poll(Poll, nt, func() (bool, error) {
		// A rolling-update (GCE/GKE implementation of restart) can complete before the apiserver
		// knows about all of the nodes. Thus, we retry the list nodes call
		// until we get the expected number of nodes.
		nodeList, errLast = c.Core().Nodes().List(metav1.ListOptions{
			FieldSelector: fields.Set{"spec.unschedulable": "false"}.AsSelector().String()})
		if errLast != nil {
			return false, nil
		}
		if len(nodeList.Items) != expect {
			errLast = fmt.Errorf("expected to find %d nodes but found only %d (%v elapsed)",
				expect, len(nodeList.Items), time.Since(start))
			Logf("%v", errLast)
			return false, nil
		}
		return true, nil
	}) == nil
	nodeNames := make([]string, len(nodeList.Items))
	for i, n := range nodeList.Items {
		nodeNames[i] = n.ObjectMeta.Name
	}
	if !found {
		return nodeNames, fmt.Errorf("couldn't find %d nodes within %v; last error: %v",
			expect, nt, errLast)
	}
	Logf("Successfully found %d nodes", expect)

	// Next, ensure in parallel that all the nodes are ready. We subtract the
	// time we spent waiting above.
	timeout := nt - time.Since(start)
	result := make(chan bool, len(nodeList.Items))
	for _, n := range nodeNames {
		n := n
		go func() { result <- WaitForNodeToBeReady(c, n, timeout) }()
	}
	failed := false
	// TODO(mbforbes): Change to `for range` syntax once we support only Go
	// >= 1.4.
	for i := range nodeList.Items {
		_ = i
		if !<-result {
			failed = true
		}
	}
	if failed {
		return nodeNames, fmt.Errorf("at least one node failed to be ready")
	}
	return nodeNames, nil
}

// MigTemplate (GCE-only) returns the name of the MIG template that the
// nodes of the cluster use.
func MigTemplate() (string, error) {
	var errLast error
	var templ string
	key := "instanceTemplate"
	if wait.Poll(Poll, SingleCallTimeout, func() (bool, error) {
		// TODO(mikedanese): make this hit the compute API directly instead of
		// shelling out to gcloud.
		// An `instance-groups managed describe` call outputs what we want to stdout.
		output, _, err := retryCmd("gcloud", "compute", "instance-groups", "managed",
			fmt.Sprintf("--project=%s", TestContext.CloudConfig.ProjectID),
			"describe",
			fmt.Sprintf("--zone=%s", TestContext.CloudConfig.Zone),
			TestContext.CloudConfig.NodeInstanceGroup)
		if err != nil {
			errLast = fmt.Errorf("gcloud compute instance-groups managed describe call failed with err: %v", err)
			return false, nil
		}

		// The 'describe' call probably succeeded; parse the output and try to
		// find the line that looks like "instanceTemplate: url/to/<templ>" and
		// return <templ>.
		if val := ParseKVLines(output, key); len(val) > 0 {
			url := strings.Split(val, "/")
			templ = url[len(url)-1]
			Logf("MIG group %s using template: %s", TestContext.CloudConfig.NodeInstanceGroup, templ)
			return true, nil
		}
		errLast = fmt.Errorf("couldn't find %s in output to get MIG template. Output: %s", key, output)
		return false, nil
	}) != nil {
		return "", fmt.Errorf("MigTemplate() failed with last error: %v", errLast)
	}
	return templ, nil
}

func gceUpgradeScript() string {
	if len(TestContext.GCEUpgradeScript) == 0 {
		return path.Join(TestContext.RepoRoot, "cluster/gce/upgrade.sh")
	}
	return TestContext.GCEUpgradeScript
}
<commit_msg>Revert "Fix the ETCD env vars for downgrade"<commit_after>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package framework

import (
	"fmt"
	"os"
	"path"
	"strings"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/kubernetes/pkg/api/v1"
	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

func EtcdUpgrade(target_storage, target_version string) error {
	switch TestContext.Provider {
	case "gce":
		return etcdUpgradeGCE(target_storage, target_version)
	default:
		return fmt.Errorf("EtcdUpgrade() is not implemented for provider %s", TestContext.Provider)
	}
}

func MasterUpgrade(v string) error {
	switch TestContext.Provider {
	case "gce":
		return masterUpgradeGCE(v)
	case "gke":
		return masterUpgradeGKE(v)
	default:
		return fmt.Errorf("MasterUpgrade() is not implemented for provider %s", TestContext.Provider)
	}
}

func etcdUpgradeGCE(target_storage, target_version string) error {
	env := append(
		os.Environ(),
		"TEST_ETCD_VERSION="+target_version,
		"STORAGE_BACKEND="+target_storage,
		"TEST_ETCD_IMAGE=3.0.17")

	_, _, err := RunCmdEnv(env, gceUpgradeScript(), "-l", "-M")
	return err
}

func masterUpgradeGCE(rawV string) error {
	env := os.Environ()
	// TODO: Remove these variables when they're no longer needed for downgrades.
	if TestContext.EtcdUpgradeVersion != "" && TestContext.EtcdUpgradeStorage != "" {
		env = append(env,
			"TEST_ETCD_VERSION="+TestContext.EtcdUpgradeVersion,
			"STORAGE_BACKEND="+TestContext.EtcdUpgradeStorage,
			"TEST_ETCD_IMAGE=3.0.17")
	}

	v := "v" + rawV
	_, _, err := RunCmdEnv(env, gceUpgradeScript(), "-M", v)
	return err
}

func masterUpgradeGKE(v string) error {
	Logf("Upgrading master to %q", v)
	_, _, err := RunCmd("gcloud", "container",
		"clusters",
		fmt.Sprintf("--project=%s", TestContext.CloudConfig.ProjectID),
		fmt.Sprintf("--zone=%s", TestContext.CloudConfig.Zone),
		"upgrade",
		TestContext.CloudConfig.Cluster,
		"--master",
		fmt.Sprintf("--cluster-version=%s", v),
		"--quiet")
	return err
}

func NodeUpgrade(f *Framework, v string, img string) error {
	// Perform the upgrade.
	var err error
	switch TestContext.Provider {
	case "gce":
		err = nodeUpgradeGCE(v, img)
	case "gke":
		err = nodeUpgradeGKE(v, img)
	default:
		err = fmt.Errorf("NodeUpgrade() is not implemented for provider %s", TestContext.Provider)
	}
	if err != nil {
		return err
	}

	// Wait for it to complete and validate nodes are healthy.
	//
	// TODO(ihmccreery) We shouldn't have to wait for nodes to be ready in
	// GKE; the operation shouldn't return until they all are.
	Logf("Waiting up to %v for all nodes to be ready after the upgrade", RestartNodeReadyAgainTimeout)
	if _, err := CheckNodesReady(f.ClientSet, RestartNodeReadyAgainTimeout, TestContext.CloudConfig.NumNodes); err != nil {
		return err
	}
	return nil
}

func nodeUpgradeGCE(rawV, img string) error {
	v := "v" + rawV
	if img != "" {
		env := append(os.Environ(), "KUBE_NODE_OS_DISTRIBUTION="+img)
		_, _, err := RunCmdEnv(env, gceUpgradeScript(), "-N", "-o", v)
		return err
	}
	_, _, err := RunCmd(gceUpgradeScript(), "-N", v)
	return err
}

func cleanupNodeUpgradeGCE(tmplBefore string) {
	Logf("Cleaning up any unused node templates")
	tmplAfter, err := MigTemplate()
	if err != nil {
		Logf("Could not get node template post-upgrade; may have leaked template %s", tmplBefore)
		return
	}
	if tmplBefore == tmplAfter {
		// The node upgrade failed so there's no need to delete
		// anything.
		Logf("Node template %s is still in use; not cleaning up", tmplBefore)
		return
	}
	Logf("Deleting node template %s", tmplBefore)
	if _, _, err := retryCmd("gcloud", "compute", "instance-templates",
		fmt.Sprintf("--project=%s", TestContext.CloudConfig.ProjectID),
		"delete",
		tmplBefore); err != nil {
		Logf("gcloud compute instance-templates delete %s call failed with err: %v", tmplBefore, err)
		Logf("May have leaked instance template %q", tmplBefore)
	}
}

func nodeUpgradeGKE(v string, img string) error {
	Logf("Upgrading nodes to version %q and image %q", v, img)
	args := []string{
		"container",
		"clusters",
		fmt.Sprintf("--project=%s", TestContext.CloudConfig.ProjectID),
		fmt.Sprintf("--zone=%s", TestContext.CloudConfig.Zone),
		"upgrade",
		TestContext.CloudConfig.Cluster,
		fmt.Sprintf("--cluster-version=%s", v),
		"--quiet",
	}
	if len(img) > 0 {
		args = append(args, fmt.Sprintf("--image-type=%s", img))
	}
	_, _, err := RunCmd("gcloud", args...)
	return err
}

// CheckNodesReady waits up to nt for expect nodes accessed by c to be ready,
// returning an error if this doesn't happen in time. It returns the names of
// nodes it finds.
func CheckNodesReady(c clientset.Interface, nt time.Duration, expect int) ([]string, error) {
	// First, keep getting all of the nodes until we get the number we expect.
	var nodeList *v1.NodeList
	var errLast error
	start := time.Now()
	found := wait.Poll(Poll, nt, func() (bool, error) {
		// A rolling-update (GCE/GKE implementation of restart) can complete before the apiserver
		// knows about all of the nodes. Thus, we retry the list nodes call
		// until we get the expected number of nodes.
		nodeList, errLast = c.Core().Nodes().List(metav1.ListOptions{
			FieldSelector: fields.Set{"spec.unschedulable": "false"}.AsSelector().String()})
		if errLast != nil {
			return false, nil
		}
		if len(nodeList.Items) != expect {
			errLast = fmt.Errorf("expected to find %d nodes but found only %d (%v elapsed)",
				expect, len(nodeList.Items), time.Since(start))
			Logf("%v", errLast)
			return false, nil
		}
		return true, nil
	}) == nil
	nodeNames := make([]string, len(nodeList.Items))
	for i, n := range nodeList.Items {
		nodeNames[i] = n.ObjectMeta.Name
	}
	if !found {
		return nodeNames, fmt.Errorf("couldn't find %d nodes within %v; last error: %v",
			expect, nt, errLast)
	}
	Logf("Successfully found %d nodes", expect)

	// Next, ensure in parallel that all the nodes are ready. We subtract the
	// time we spent waiting above.
	timeout := nt - time.Since(start)
	result := make(chan bool, len(nodeList.Items))
	for _, n := range nodeNames {
		n := n
		go func() { result <- WaitForNodeToBeReady(c, n, timeout) }()
	}
	failed := false
	// TODO(mbforbes): Change to `for range` syntax once we support only Go
	// >= 1.4.
	for i := range nodeList.Items {
		_ = i
		if !<-result {
			failed = true
		}
	}
	if failed {
		return nodeNames, fmt.Errorf("at least one node failed to be ready")
	}
	return nodeNames, nil
}

// MigTemplate (GCE-only) returns the name of the MIG template that the
// nodes of the cluster use.
func MigTemplate() (string, error) {
	var errLast error
	var templ string
	key := "instanceTemplate"
	if wait.Poll(Poll, SingleCallTimeout, func() (bool, error) {
		// TODO(mikedanese): make this hit the compute API directly instead of
		// shelling out to gcloud.
		// An `instance-groups managed describe` call outputs what we want to stdout.
		output, _, err := retryCmd("gcloud", "compute", "instance-groups", "managed",
			fmt.Sprintf("--project=%s", TestContext.CloudConfig.ProjectID),
			"describe",
			fmt.Sprintf("--zone=%s", TestContext.CloudConfig.Zone),
			TestContext.CloudConfig.NodeInstanceGroup)
		if err != nil {
			errLast = fmt.Errorf("gcloud compute instance-groups managed describe call failed with err: %v", err)
			return false, nil
		}

		// The 'describe' call probably succeeded; parse the output and try to
		// find the line that looks like "instanceTemplate: url/to/<templ>" and
		// return <templ>.
		if val := ParseKVLines(output, key); len(val) > 0 {
			url := strings.Split(val, "/")
			templ = url[len(url)-1]
			Logf("MIG group %s using template: %s", TestContext.CloudConfig.NodeInstanceGroup, templ)
			return true, nil
		}
		errLast = fmt.Errorf("couldn't find %s in output to get MIG template. Output: %s", key, output)
		return false, nil
	}) != nil {
		return "", fmt.Errorf("MigTemplate() failed with last error: %v", errLast)
	}
	return templ, nil
}

func gceUpgradeScript() string {
	if len(TestContext.GCEUpgradeScript) == 0 {
		return path.Join(TestContext.RepoRoot, "cluster/gce/upgrade.sh")
	}
	return TestContext.GCEUpgradeScript
}
<|endoftext|>


<commit_before>package sessiongate

import (
	"crypto/rand"
	"errors"
	"reflect"
	"regexp"
	"testing"
	"time"
)

var signKey []byte

func init() {
	signKey = make([]byte, 16)
	rand.Read(signKey)
}

// TestInitializer tests the Sessiongate initializer
func TestInitializer(t *testing.T) {
	t.Run("Should fail with missing SignKey", func(t *testing.T) {
		config := &Config{}

		_, err := NewSessiongate(config)
		if err == nil {
			t.Fail()
		}
	})
}

// TestStart tests the START command for the SessionGate module
func TestStart(t *testing.T) {
	t.Run("Should fail with negative TTL", func(t *testing.T) {
		config := &Config{
			SignKey: signKey,
		}

		sessiongate, err := NewSessiongate(config)
		if err != nil {
			t.Error(err)
		}

		_, err = sessiongate.Start(-1)
		if err == nil {
			t.Error(errors.New("Negative TTL should produce an error"))
		}
	})

	// checkStart checks if the START command does not produce an error and if
	// token is in the expected format
	checkStart := func(config *Config) {
		sessiongate, err := NewSessiongate(config)
		if err != nil {
			t.Error(err)
		}

		token, err := sessiongate.Start(300)
		if err != nil {
			t.Error(err)
		}

		regex := "^v[0-9]\\.[a-zA-Z0-9]+\\.[a-zA-Z0-9]+$"
		match, err := regexp.MatchString(regex, string(token))
		if err != nil {
			t.Error(err)
		}

		if match == false {
			err = errors.New("The response token does not match the expected format")
			t.Error(err)
		}
	}

	t.Run("Should succeed with default configuration", func(t *testing.T) {
		checkStart(&Config{
			SignKey: signKey,
		})
	})

	t.Run("Should succeed with explicit Addr", func(t *testing.T) {
		checkStart(&Config{
			SignKey: signKey,
			Addr:    "localhost:6379",
		})
	})

	t.Run("Should succeed with explicit MaxIdle", func(t *testing.T) {
		checkStart(&Config{
			SignKey: signKey,
			MaxIdle: 15,
		})
	})

	t.Run("Should succeed with explicit IdleTimeout", func(t *testing.T) {
		checkStart(&Config{
			SignKey:     signKey,
			IdleTimeout: 90 * time.Second,
		})
	})
}

func createSession() (*Sessiongate, []byte, error) {
	config := &Config{
		SignKey: signKey,
	}

	sessiongate, err := NewSessiongate(config)
	if err != nil {
		return nil, nil, err
	}

	token, err := sessiongate.Start(300)
	if err != nil {
		return nil, nil, err
	}

	return sessiongate, token, nil
}

// TestExpire tests the EXPIRE command for the SessionGate module
func TestExpire(t *testing.T) {
	sessiongate, token, err := createSession()
	if err != nil {
		t.Error(err)
	}

	t.Run("Should fail with negative TTL", func(t *testing.T) {
		err := sessiongate.Expire(token, -5)
		if err == nil {
			t.Error(errors.New("Negative TTL should produce an error"))
		}
	})

	t.Run("Should succeed with positive TTL", func(t *testing.T) {
		err := sessiongate.Expire(token, 500)
		if err != nil {
			t.Error(err)
		}
	})
}

// TestPSet tests the PSET command for the SessionGate module
func TestPSet(t *testing.T) {
	sessiongate, token, err := createSession()
	if err != nil {
		t.Error(err)
	}

	t.Run("Should fail with an empty name", func(t *testing.T) {
		name := []byte("")
		payload := []byte("{}")
		err := sessiongate.PSet(token, name, payload)
		if err == nil {
			t.Error(errors.New("Empty name should produce an error"))
		}
	})

	t.Run("Should fail with an empty payload", func(t *testing.T) {
		name := []byte("user")
		payload := []byte("")
		err := sessiongate.PSet(token, name, payload)
		if err == nil {
			t.Error(errors.New("Empty payload should produce an error"))
		}
	})

	t.Run("Should succeed with a JSON string as a payload", func(t *testing.T) {
		name := []byte("user")
		payload := []byte("{\"name\":\"John Doe\"}")
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}
	})

	t.Run("Should succeed with random bytes in the name", func(t *testing.T) {
		name := make([]byte, 8)
		rand.Read(name)
		payload := []byte("{\"name\":\"John Doe\"}")
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}
	})

	t.Run("Should succeed with random bytes in the payload", func(t *testing.T) {
		name := []byte("user")
		payload := make([]byte, 128)
		rand.Read(payload)
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}
	})
}

// TestPGet tests the PGET command for the SessionGate module
func TestPGet(t *testing.T) {
	sessiongate, token, err := createSession()
	if err != nil {
		t.Error(err)
	}

	t.Run("Should fail with an empty name", func(t *testing.T) {
		name := []byte("")
		_, err := sessiongate.PGet(token, name)
		if err == nil {
			t.Error(errors.New("Empty name should produce an error"))
		}
	})

	t.Run("Should fail for a name not set", func(t *testing.T) {
		name := []byte("user")
		_, err := sessiongate.PGet(token, name)
		if err == nil {
			t.Error(errors.New("Name not set should produce an error"))
		}
	})

	t.Run("Should fail for expired sessions", func(t *testing.T) {
		sessiongate2, token2, err := createSession()
		if err != nil {
			t.Error(err)
		}

		name := []byte("user")
		payload := []byte("{\"name\":\"John Doe\"}")
		err = sessiongate2.PSet(token2, name, payload)
		if err != nil {
			t.Error(err)
		}

		_, err = sessiongate2.PGet(token2, name)
		if err != nil {
			t.Error(err)
		}

		err = sessiongate2.Expire(token2, 1)
		if err != nil {
			t.Error(err)
		}

		time.Sleep(time.Millisecond * 1050)

		_, err = sessiongate2.PGet(token2, name)
		if err == nil {
			t.Error(errors.New("Expired session should produce an error"))
		}
	})

	t.Run("Should succeed with a JSON string as a payload", func(t *testing.T) {
		name := []byte("user")
		payload := []byte("{\"name\":\"John Doe\"}")
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}

		payloadPGet, err := sessiongate.PGet(token, name)
		if err != nil {
			t.Error(err)
		}

		if reflect.DeepEqual(payload, payloadPGet) == false {
			t.Error(errors.New("The payloads should be equal"))
		}
	})

	t.Run("Should succeed with random bytes in the payload", func(t *testing.T) {
		name := []byte("user")
		payload := make([]byte, 128)
		rand.Read(payload)
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}

		payloadPGet, err := sessiongate.PGet(token, name)
		if err != nil {
			t.Error(err)
		}

		if reflect.DeepEqual(payload, payloadPGet) == false {
			t.Error(errors.New("The payloads should be equal"))
		}
	})

	t.Run("Should succeed with random bytes in the name", func(t *testing.T) {
		name := make([]byte, 8)
		rand.Read(name)
		payload := []byte("{\"name\":\"John Doe\"}")
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}

		payloadPGet, err := sessiongate.PGet(token, name)
		if err != nil {
			t.Error(err)
		}

		if reflect.DeepEqual(payload, payloadPGet) == false {
			t.Error(errors.New("The payloads should be equal"))
		}
	})
}
<commit_msg>Added test cases for the PDel command<commit_after>package sessiongate

import (
	"crypto/rand"
	"errors"
	"reflect"
	"regexp"
	"testing"
	"time"
)

var signKey []byte

func init() {
	signKey = make([]byte, 16)
	rand.Read(signKey)
}

// TestInitializer tests the Sessiongate initializer
func TestInitializer(t *testing.T) {
	t.Run("Should fail with missing SignKey", func(t *testing.T) {
		config := &Config{}

		_, err := NewSessiongate(config)
		if err == nil {
			t.Fail()
		}
	})
}

// TestStart tests the START command for the SessionGate module
func TestStart(t *testing.T) {
	t.Run("Should fail with negative TTL", func(t *testing.T) {
		config := &Config{
			SignKey: signKey,
		}

		sessiongate, err := NewSessiongate(config)
		if err != nil {
			t.Error(err)
		}

		_, err = sessiongate.Start(-1)
		if err == nil {
			t.Error(errors.New("Negative TTL should produce an error"))
		}
	})

	// checkStart checks if the START command does not produce an error and if
	// token is in the expected format
	checkStart := func(config *Config) {
		sessiongate, err := NewSessiongate(config)
		if err != nil {
			t.Error(err)
		}

		token, err := sessiongate.Start(300)
		if err != nil {
			t.Error(err)
		}

		regex := "^v[0-9]\\.[a-zA-Z0-9]+\\.[a-zA-Z0-9]+$"
		match, err := regexp.MatchString(regex, string(token))
		if err != nil {
			t.Error(err)
		}

		if match == false {
			err = errors.New("The response token does not match the expected format")
			t.Error(err)
		}
	}

	t.Run("Should succeed with default configuration", func(t *testing.T) {
		checkStart(&Config{
			SignKey: signKey,
		})
	})

	t.Run("Should succeed with explicit Addr", func(t *testing.T) {
		checkStart(&Config{
			SignKey: signKey,
			Addr:    "localhost:6379",
		})
	})

	t.Run("Should succeed with explicit MaxIdle", func(t *testing.T) {
		checkStart(&Config{
			SignKey: signKey,
			MaxIdle: 15,
		})
	})

	t.Run("Should succeed with explicit IdleTimeout", func(t *testing.T) {
		checkStart(&Config{
			SignKey:     signKey,
			IdleTimeout: 90 * time.Second,
		})
	})
}

func createSession() (*Sessiongate, []byte, error) {
	config := &Config{
		SignKey: signKey,
	}

	sessiongate, err := NewSessiongate(config)
	if err != nil {
		return nil, nil, err
	}

	token, err := sessiongate.Start(300)
	if err != nil {
		return nil, nil, err
	}

	return sessiongate, token, nil
}

// TestExpire tests the EXPIRE command for the SessionGate module
func TestExpire(t *testing.T) {
	sessiongate, token, err := createSession()
	if err != nil {
		t.Error(err)
	}

	t.Run("Should fail with negative TTL", func(t *testing.T) {
		err := sessiongate.Expire(token, -5)
		if err == nil {
			t.Error(errors.New("Negative TTL should produce an error"))
		}
	})

	t.Run("Should succeed with positive TTL", func(t *testing.T) {
		err := sessiongate.Expire(token, 500)
		if err != nil {
			t.Error(err)
		}
	})
}

// TestPSet tests the PSET command for the SessionGate module
func TestPSet(t *testing.T) {
	sessiongate, token, err := createSession()
	if err != nil {
		t.Error(err)
	}

	t.Run("Should fail with an empty name", func(t *testing.T) {
		name := []byte("")
		payload := []byte("{}")
		err := sessiongate.PSet(token, name, payload)
		if err == nil {
			t.Error(errors.New("Empty name should produce an error"))
		}
	})

	t.Run("Should fail with an empty payload", func(t *testing.T) {
		name := []byte("user")
		payload := []byte("")
		err := sessiongate.PSet(token, name, payload)
		if err == nil {
			t.Error(errors.New("Empty payload should produce an error"))
		}
	})

	t.Run("Should succeed with a JSON string as a payload", func(t *testing.T) {
		name := []byte("user")
		payload := []byte("{\"name\":\"John Doe\"}")
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}
	})

	t.Run("Should succeed with random bytes in the name", func(t *testing.T) {
		name := make([]byte, 8)
		rand.Read(name)
		payload := []byte("{\"name\":\"John Doe\"}")
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}
	})

	t.Run("Should succeed with random bytes in the payload", func(t *testing.T) {
		name := []byte("user")
		payload := make([]byte, 128)
		rand.Read(payload)
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}
	})
}

// TestPGet tests the PGET command for the SessionGate module
func TestPGet(t *testing.T) {
	sessiongate, token, err := createSession()
	if err != nil {
		t.Error(err)
	}

	t.Run("Should fail with an empty name", func(t *testing.T) {
		name := []byte("")
		_, err := sessiongate.PGet(token, name)
		if err == nil {
			t.Error(errors.New("Empty name should produce an error"))
		}
	})

	t.Run("Should fail for a name not set", func(t *testing.T) {
		name := []byte("user")
		_, err := sessiongate.PGet(token, name)
		if err == nil {
			t.Error(errors.New("Name not set should produce an error"))
		}
	})

	t.Run("Should fail for expired sessions", func(t *testing.T) {
		sessiongate2, token2, err := createSession()
		if err != nil {
			t.Error(err)
		}

		name := []byte("user")
		payload := []byte("{\"name\":\"John Doe\"}")
		err = sessiongate2.PSet(token2, name, payload)
		if err != nil {
			t.Error(err)
		}

		_, err = sessiongate2.PGet(token2, name)
		if err != nil {
			t.Error(err)
		}

		err = sessiongate2.Expire(token2, 1)
		if err != nil {
			t.Error(err)
		}

		time.Sleep(time.Millisecond * 1050)

		_, err = sessiongate2.PGet(token2, name)
		if err == nil {
			t.Error(errors.New("Expired session should produce an error"))
		}
	})

	t.Run("Should succeed with a JSON string as a payload", func(t *testing.T) {
		name := []byte("user")
		payload := []byte("{\"name\":\"John Doe\"}")
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}

		payloadPGet, err := sessiongate.PGet(token, name)
		if err != nil {
			t.Error(err)
		}

		if reflect.DeepEqual(payload, payloadPGet) == false {
			t.Error(errors.New("The payloads should be equal"))
		}
	})

	t.Run("Should succeed with random bytes in the payload", func(t *testing.T) {
		name := []byte("user")
		payload := make([]byte, 128)
		rand.Read(payload)
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}

		payloadPGet, err := sessiongate.PGet(token, name)
		if err != nil {
			t.Error(err)
		}

		if reflect.DeepEqual(payload, payloadPGet) == false {
			t.Error(errors.New("The payloads should be equal"))
		}
	})

	t.Run("Should succeed with random bytes in the name", func(t *testing.T) {
		name := make([]byte, 8)
		rand.Read(name)
		payload := []byte("{\"name\":\"John Doe\"}")
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}

		payloadPGet, err := sessiongate.PGet(token, name)
		if err != nil {
			t.Error(err)
		}

		if reflect.DeepEqual(payload, payloadPGet) == false {
			t.Error(errors.New("The payloads should be equal"))
		}
	})
}

// TestPDel tests the PDEL command for the SessionGate module
func TestPDel(t *testing.T) {
	sessiongate, token, err := createSession()
	if err != nil {
		t.Error(err)
	}

	t.Run("Should fail with an empty name", func(t *testing.T) {
		name := []byte("")
		err := sessiongate.PDel(token, name)
		if err == nil {
			t.Error(errors.New("Empty name should produce an error"))
		}
	})

	t.Run("Should fail for a name not set", func(t *testing.T) {
		name := []byte("user")
		err := sessiongate.PDel(token, name)
		if err == nil {
			t.Error(errors.New("Name not set should produce an error"))
		}
	})

	t.Run("Should fail for expired sessions", func(t *testing.T) {
		sessiongate2, token2, err := createSession()
		if err != nil {
			t.Error(err)
		}

		name := []byte("user")
		payload := []byte("{\"name\":\"John Doe\"}")
		err = sessiongate2.PSet(token2, name, payload)
		if err != nil {
			t.Error(err)
		}

		_, err = sessiongate2.PGet(token2, name)
		if err != nil {
			t.Error(err)
		}

		err = sessiongate2.Expire(token2, 1)
		if err != nil {
			t.Error(err)
		}

		time.Sleep(time.Millisecond * 1050)

		err = sessiongate2.PDel(token2, name)
		if err == nil {
			t.Error(errors.New("Expired session should produce an error"))
		}
	})

	t.Run("Should succeed with a UTF-8 name", func(t *testing.T) {
		name := []byte("user")
		payload := []byte("{\"name\":\"John Doe\"}")
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}

		err = sessiongate.PDel(token, name)
		if err != nil {
			t.Error(err)
		}
	})

	t.Run("Should succeed with random bytes in the name", func(t *testing.T) {
		name := make([]byte, 8)
		rand.Read(name)
		payload := []byte("{\"name\":\"John Doe\"}")
		err := sessiongate.PSet(token, name, payload)
		if err != nil {
			t.Error(err)
		}

		err = sessiongate.PDel(token, name)
		if err != nil {
			t.Error(err)
		}
	})
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2017 BitGo
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package wire

import (
	"bytes"
	"encoding/hex"
	"io"
	"time"
	// "log"
	"github.com/bitgo/prova/btcec"
	"github.com/bitgo/prova/chaincfg/chainhash"
)

// BlockValidatingPubKeySize is the number of bytes for a compressed pubkey.
const BlockValidatingPubKeySize = 33

// BlockValidatingPubKey defines the block validating public key.
// TODO(prova): replace this with a struct
type BlockValidatingPubKey [BlockValidatingPubKeySize]byte

// String returns a hexadecimal string of the public key
func (p BlockValidatingPubKey) String() string {
	return hex.EncodeToString(p[:])
}

// BlockSignatureSize is the number of bytes for a signature
const BlockSignatureSize = 80

// BlockSignature defines the block validating signature.
// TODO(prova): replace this with a struct
type BlockSignature [BlockSignatureSize]byte

// String returns a hexadecimal string of the signature
func (s BlockSignature) String() string {
	return hex.EncodeToString(s[:])
}

// BlockVersion is the current latest supported block version.
// TODO(prova): change this
const BlockVersion = 4

// MaxBlockHeaderPayload is the maximum number of bytes a block header can be.
const MaxBlockHeaderPayload = 32 + (chainhash.HashSize * 2) + BlockValidatingPubKeySize + BlockSignatureSize

// BlockHeader defines information about a block and is used in the bitcoin
// block (MsgBlock) and headers (MsgHeaders) messages.
type BlockHeader struct {
	// Version of the block.  This is not the same as the protocol version.
	Version uint32

	// Hash of the previous block in the block chain.
	PrevBlock chainhash.Hash

	// Merkle tree reference to hash of all transactions for the block.
	MerkleRoot chainhash.Hash

	// Time the block was created. Encoded as int64 on the wire.
	Timestamp time.Time

	// Difficulty target for the block.
	Bits uint32

	// Height is the block height in the block chain.
	Height uint32

	// Size is the size of the serialized block in its entirety.
	Size uint32

	// Nonce used to generate the block (64 bits, to avoid extraNonce)
	Nonce uint64

	// Public key of the validating key used to sign the block
	ValidatingPubKey BlockValidatingPubKey

	// Signature of (PrevBlock|Merkle root) by block validating key
	Signature BlockSignature
}

// blockHeaderLen is a constant that represents the number of bytes for a block
// header.
const blockHeaderLen = MaxBlockHeaderPayload

// BlockHash computes the block identifier hash for the given block header.
func (h *BlockHeader) BlockHash() chainhash.Hash {
	// Encode the header and double sha256 everything prior to the number of
	// transactions.  Ignore the error returns since there is no way the
	// encode could fail except being out of memory which would cause a
	// run-time panic.
	var buf bytes.Buffer
	_ = writeBlockHeader(&buf, 0, h)

	return chainhash.PowHashH(buf.Bytes())
}

// BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
// This is part of the Message interface implementation.
// See Deserialize for decoding block headers stored to disk, such as in a
// database, as opposed to decoding block headers from the wire.
func (h *BlockHeader) BtcDecode(r io.Reader, pver uint32) error {
	return readBlockHeader(r, pver, h)
}

// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
// This is part of the Message interface implementation.
// See Serialize for encoding block headers to be stored to disk, such as in a
// database, as opposed to encoding block headers for the wire.
func (h *BlockHeader) BtcEncode(w io.Writer, pver uint32) error {
	return writeBlockHeader(w, pver, h)
}

// Deserialize decodes a block header from r into the receiver using a format
// that is suitable for long-term storage such as a database while respecting
// the Version field.
func (h *BlockHeader) Deserialize(r io.Reader) error {
	// At the current time, there is no difference between the wire encoding
	// at protocol version 0 and the stable long-term storage format.  As
	// a result, make use of readBlockHeader.
	return readBlockHeader(r, 0, h)
}

// Serialize encodes a block header from r into the receiver using a format
// that is suitable for long-term storage such as a database while respecting
// the Version field.
func (h *BlockHeader) Serialize(w io.Writer) error {
	// At the current time, there is no difference between the wire encoding
	// at protocol version 0 and the stable long-term storage format.  As
	// a result, make use of writeBlockHeader.
	return writeBlockHeader(w, 0, h)
}

// hashForSigning gets the double SHA256 hash of (Version|Timestamp|PrevBlock|MerkleRoot)
// which is used for the validator's signature.
func (h *BlockHeader) hashForSigning() []byte {
	buf := bytes.NewBuffer(make([]byte, 0, 12+2*chainhash.HashSize))
	err := writeElements(buf, h.Version, h.Timestamp.Unix(), &h.PrevBlock, &h.MerkleRoot)
	if err != nil {
		return nil
	}
	return chainhash.PowHashB(buf.Bytes())
}

// Sign uses the supplied private key to sign the signing-hash of the block
// header, and sets it in the Signature field.
func (h *BlockHeader) Sign(key *btcec.PrivateKey) error {
	hash := h.hashForSigning()
	signature, err := key.Sign(hash)
	if err != nil {
		return err
	}
	serialized := signature.Serialize()
	// TODO(prova): Remove commented code.
	// log.Printf("SIGNED hash=%v sig=%v prevblock=%v merkle=%v ",
	// 	hex.EncodeToString(hash),
	// 	hex.EncodeToString(serialized),
	// 	hex.EncodeToString(h.PrevBlock[:]),
	// 	hex.EncodeToString(h.MerkleRoot[:]),
	// )

	// Mark the public key used to sign the block.
	pubKey := key.PubKey().SerializeCompressed()[:BlockValidatingPubKeySize]
	copy(h.ValidatingPubKey[:BlockValidatingPubKeySize], pubKey[:BlockValidatingPubKeySize])

	copy(h.Signature[:], serialized)
	return nil
}

// Verify checks the signature on the block using the supplied public key.
func (h *BlockHeader) Verify(pubKey *btcec.PublicKey) bool {
	sig, err := btcec.ParseDERSignature(h.Signature[:], btcec.S256())
	if err != nil {
		return false
	}
	hash := h.hashForSigning()
	ret := sig.Verify(hash, pubKey)
	// log.Printf("VERIFY result=%v, hash=%v sig=%v prevblock=%v merkle=%v, ",
	// 	ret,
	// 	hex.EncodeToString(hash),
	// 	hex.EncodeToString(sig.Serialize()),
	// 	hex.EncodeToString(h.PrevBlock[:]),
	// 	hex.EncodeToString(h.MerkleRoot[:]),
	// )
	return ret
}

// NewBlockHeader returns a new BlockHeader using the provided previous block
// hash, merkle root hash, difficulty bits, and nonce used to generate the
// block with defaults for the remaining fields.
func NewBlockHeader(prevHash *chainhash.Hash, merkleRootHash *chainhash.Hash,
	bits uint32, nonce uint64) *BlockHeader {

	// Limit the timestamp to one second precision since the protocol
	// doesn't support better.
	return &BlockHeader{
		Version:    BlockVersion,
		PrevBlock:  *prevHash,
		MerkleRoot: *merkleRootHash,
		Timestamp:  time.Unix(time.Now().Unix(), 0),
		Bits:       bits,
		Nonce:      nonce,
	}
}

// readBlockHeader reads a bitcoin block header from r.  See Deserialize for
// decoding block headers stored to disk, such as in a database, as opposed to
// decoding from the wire.
func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error {
	return readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
		(*int64Time)(&bh.Timestamp), &bh.Bits, &bh.Height, &bh.Size, &bh.Nonce, &bh.ValidatingPubKey, &bh.Signature)
}

// writeBlockHeader writes a bitcoin block header to w.  See Serialize for
// encoding block headers to be stored to disk, such as in a database, as
// opposed to encoding for the wire.
func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error {
	return writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
		bh.Timestamp.Unix(), bh.Bits, bh.Height, bh.Size, bh.Nonce, bh.ValidatingPubKey, bh.Signature)
}
<commit_msg>Patch commit 187355448a21cb3c644091a716892888c54845c7 from btcd Author: David Hill <dhill@mindcry.org> Date:   Wed Nov 16 11:04:47 2016 -0500<commit_after>// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2017 BitGo
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package wire

import (
	"bytes"
	"encoding/hex"
	"io"
	"time"
	// "log"
	"github.com/bitgo/prova/btcec"
	"github.com/bitgo/prova/chaincfg/chainhash"
)

// BlockValidatingPubKeySize is the number of bytes for a compressed pubkey.
const BlockValidatingPubKeySize = 33

// BlockValidatingPubKey defines the block validating public key.
// TODO(prova): replace this with a struct
type BlockValidatingPubKey [BlockValidatingPubKeySize]byte

// String returns a hexadecimal string of the public key
func (p BlockValidatingPubKey) String() string {
	return hex.EncodeToString(p[:])
}

// BlockSignatureSize is the number of bytes for a signature
const BlockSignatureSize = 80

// BlockSignature defines the block validating signature.
// TODO(prova): replace this with a struct
type BlockSignature [BlockSignatureSize]byte

// String returns a hexadecimal string of the signature
func (s BlockSignature) String() string {
	return hex.EncodeToString(s[:])
}

// BlockVersion is the current latest supported block version.
// TODO(prova): change this
const BlockVersion = 4

// MaxBlockHeaderPayload is the maximum number of bytes a block header can be.
const MaxBlockHeaderPayload = 32 + (chainhash.HashSize * 2) + BlockValidatingPubKeySize + BlockSignatureSize

// BlockHeader defines information about a block and is used in the bitcoin
// block (MsgBlock) and headers (MsgHeaders) messages.
type BlockHeader struct {
	// Version of the block.  This is not the same as the protocol version.
	Version uint32

	// Hash of the previous block in the block chain.
	PrevBlock chainhash.Hash

	// Merkle tree reference to hash of all transactions for the block.
	MerkleRoot chainhash.Hash

	// Time the block was created. Encoded as int64 on the wire.
	Timestamp time.Time

	// Difficulty target for the block.
	Bits uint32

	// Height is the block height in the block chain.
	Height uint32

	// Size is the size of the serialized block in its entirety.
	Size uint32

	// Nonce used to generate the block (64 bits, to avoid extraNonce)
	Nonce uint64

	// Public key of the validating key used to sign the block
	ValidatingPubKey BlockValidatingPubKey

	// Signature of (PrevBlock|Merkle root) by block validating key
	Signature BlockSignature
}

// blockHeaderLen is a constant that represents the number of bytes for a block
// header.
const blockHeaderLen = MaxBlockHeaderPayload

// BlockHash computes the block identifier hash for the given block header.
func (h *BlockHeader) BlockHash() chainhash.Hash {
	// Encode the header and double sha256 everything prior to the number of
	// transactions.  Ignore the error returns since there is no way the
	// encode could fail except being out of memory which would cause a
	// run-time panic.
	buf := bytes.NewBuffer(make([]byte, 0, MaxBlockHeaderPayload))
	_ = writeBlockHeader(buf, 0, h)

	return chainhash.PowHashH(buf.Bytes())
}

// BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
// This is part of the Message interface implementation.
// See Deserialize for decoding block headers stored to disk, such as in a
// database, as opposed to decoding block headers from the wire.
func (h *BlockHeader) BtcDecode(r io.Reader, pver uint32) error {
	return readBlockHeader(r, pver, h)
}

// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
// This is part of the Message interface implementation.
// See Serialize for encoding block headers to be stored to disk, such as in a
// database, as opposed to encoding block headers for the wire.
func (h *BlockHeader) BtcEncode(w io.Writer, pver uint32) error {
	return writeBlockHeader(w, pver, h)
}

// Deserialize decodes a block header from r into the receiver using a format
// that is suitable for long-term storage such as a database while respecting
// the Version field.
func (h *BlockHeader) Deserialize(r io.Reader) error {
	// At the current time, there is no difference between the wire encoding
	// at protocol version 0 and the stable long-term storage format.  As
	// a result, make use of readBlockHeader.
	return readBlockHeader(r, 0, h)
}

// Serialize encodes a block header from r into the receiver using a format
// that is suitable for long-term storage such as a database while respecting
// the Version field.
func (h *BlockHeader) Serialize(w io.Writer) error {
	// At the current time, there is no difference between the wire encoding
	// at protocol version 0 and the stable long-term storage format.  As
	// a result, make use of writeBlockHeader.
	return writeBlockHeader(w, 0, h)
}

// hashForSigning gets the double SHA256 hash of (Version|Timestamp|PrevBlock|MerkleRoot)
// which is used for the validator's signature.
func (h *BlockHeader) hashForSigning() []byte {
	buf := bytes.NewBuffer(make([]byte, 0, 12+2*chainhash.HashSize))
	err := writeElements(buf, h.Version, h.Timestamp.Unix(), &h.PrevBlock, &h.MerkleRoot)
	if err != nil {
		return nil
	}
	return chainhash.PowHashB(buf.Bytes())
}

// Sign uses the supplied private key to sign the signing-hash of the block
// header, and sets it in the Signature field.
func (h *BlockHeader) Sign(key *btcec.PrivateKey) error {
	hash := h.hashForSigning()
	signature, err := key.Sign(hash)
	if err != nil {
		return err
	}
	serialized := signature.Serialize()
	// TODO(prova): Remove commented code.
	// log.Printf("SIGNED hash=%v sig=%v prevblock=%v merkle=%v ",
	// 	hex.EncodeToString(hash),
	// 	hex.EncodeToString(serialized),
	// 	hex.EncodeToString(h.PrevBlock[:]),
	// 	hex.EncodeToString(h.MerkleRoot[:]),
	// )

	// Mark the public key used to sign the block.
	pubKey := key.PubKey().SerializeCompressed()[:BlockValidatingPubKeySize]
	copy(h.ValidatingPubKey[:BlockValidatingPubKeySize], pubKey[:BlockValidatingPubKeySize])

	copy(h.Signature[:], serialized)
	return nil
}

// Verify checks the signature on the block using the supplied public key.
func (h *BlockHeader) Verify(pubKey *btcec.PublicKey) bool {
	sig, err := btcec.ParseDERSignature(h.Signature[:], btcec.S256())
	if err != nil {
		return false
	}
	hash := h.hashForSigning()
	ret := sig.Verify(hash, pubKey)
	// log.Printf("VERIFY result=%v, hash=%v sig=%v prevblock=%v merkle=%v, ",
	// 	ret,
	// 	hex.EncodeToString(hash),
	// 	hex.EncodeToString(sig.Serialize()),
	// 	hex.EncodeToString(h.PrevBlock[:]),
	// 	hex.EncodeToString(h.MerkleRoot[:]),
	// )
	return ret
}

// NewBlockHeader returns a new BlockHeader using the provided previous block
// hash, merkle root hash, difficulty bits, and nonce used to generate the
// block with defaults for the remaining fields.
func NewBlockHeader(prevHash *chainhash.Hash, merkleRootHash *chainhash.Hash,
	bits uint32, nonce uint64) *BlockHeader {

	// Limit the timestamp to one second precision since the protocol
	// doesn't support better.
	return &BlockHeader{
		Version:    BlockVersion,
		PrevBlock:  *prevHash,
		MerkleRoot: *merkleRootHash,
		Timestamp:  time.Unix(time.Now().Unix(), 0),
		Bits:       bits,
		Nonce:      nonce,
	}
}

// readBlockHeader reads a bitcoin block header from r.  See Deserialize for
// decoding block headers stored to disk, such as in a database, as opposed to
// decoding from the wire.
func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error {
	return readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
		(*int64Time)(&bh.Timestamp), &bh.Bits, &bh.Height, &bh.Size, &bh.Nonce, &bh.ValidatingPubKey, &bh.Signature)
}

// writeBlockHeader writes a bitcoin block header to w.  See Serialize for
// encoding block headers to be stored to disk, such as in a database, as
// opposed to encoding for the wire.
func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error {
	return writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
		bh.Timestamp.Unix(), bh.Bits, bh.Height, bh.Size, bh.Nonce, bh.ValidatingPubKey, bh.Signature)
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package tchannel

import (
	"io/ioutil"
	"os"
	"testing"

	"golang.org/x/net/context"

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

func toMap(fields LogFields) map[string]interface{} {
	m := make(map[string]interface{})
	for _, f := range fields {
		m[f.Key] = f.Value
	}
	return m
}

func TestLoggers(t *testing.T) {
	ch, err := NewChannel("svc", &ChannelOptions{
		Logger: NewLogger(ioutil.Discard),
	})
	require.NoError(t, err, "NewChannel failed")

	peerInfo := ch.PeerInfo()
	fields := toMap(ch.Logger().Fields())
	assert.Equal(t, peerInfo.ServiceName, fields["service"])

	sc := ch.GetSubChannel("subch")
	fields = toMap(sc.Logger().Fields())
	assert.Equal(t, peerInfo.ServiceName, fields["service"])
	assert.Equal(t, "subch", fields["subchannel"])
}

func TestStats(t *testing.T) {
	ch, err := NewChannel("svc", &ChannelOptions{
		Logger: NewLogger(ioutil.Discard),
	})
	require.NoError(t, err, "NewChannel failed")

	hostname, err := os.Hostname()
	require.NoError(t, err, "Hostname failed")

	peerInfo := ch.PeerInfo()
	tags := ch.StatsTags()
	assert.NotNil(t, ch.StatsReporter(), "StatsReporter missing")
	assert.NotNil(t, ch.TraceReporter(), "TraceReporter missing")
	assert.Equal(t, peerInfo.ProcessName, tags["app"], "app tag")
	assert.Equal(t, peerInfo.ServiceName, tags["service"], "service tag")
	assert.Equal(t, hostname, tags["host"], "hostname tag")

	sc := ch.GetSubChannel("subch")
	subTags := sc.StatsTags()
	assert.NotNil(t, sc.StatsReporter(), "StatsReporter missing")
	for k, v := range tags {
		assert.Equal(t, v, subTags[k], "subchannel missing tag %v", k)
	}
	assert.Equal(t, "subch", subTags["subchannel"], "subchannel tag missing")
}

func TestIsolatedSubChannelsDontSharePeers(t *testing.T) {
	ch, err := NewChannel("svc", &ChannelOptions{
		Logger: NewLogger(ioutil.Discard),
	})
	require.NoError(t, err, "NewChannel failed")

	sub := ch.GetSubChannel("svc-ringpop")
	if ch.peers != sub.peers {
		t.Log("Channel and subchannel don't share the same peer list.")
		t.Fail()
	}

	isolatedSub := ch.GetSubChannel("svc-shy-ringpop", Isolated)
	if ch.peers == isolatedSub.peers {
		t.Log("Channel and isolated subchannel share the same peer list.")
		t.Fail()
	}

	// Nobody knows about the peer.
	assert.Nil(t, ch.peers.peersByHostPort["127.0.0.1:3000"])
	assert.Nil(t, sub.peers.peersByHostPort["127.0.0.1:3000"])
	assert.Nil(t, isolatedSub.peers.peersByHostPort["127.0.0.1:3000"])

	// Uses of the parent channel should be reflected in the subchannel, but
	// not the isolated subchannel.
	ch.BeginCall(context.Background(), "127.0.0.1:3000", "foo", "Bar::baz", nil)
	assert.NotNil(t, ch.peers.peersByHostPort["127.0.0.1:3000"])
	assert.NotNil(t, sub.peers.peersByHostPort["127.0.0.1:3000"])
	assert.Nil(t, isolatedSub.peers.peersByHostPort["127.0.0.1:3000"])
}
<commit_msg>Order imports alphabetically<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package tchannel

import (
	"io/ioutil"
	"os"
	"testing"

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

	"golang.org/x/net/context"
)

func toMap(fields LogFields) map[string]interface{} {
	m := make(map[string]interface{})
	for _, f := range fields {
		m[f.Key] = f.Value
	}
	return m
}

func TestLoggers(t *testing.T) {
	ch, err := NewChannel("svc", &ChannelOptions{
		Logger: NewLogger(ioutil.Discard),
	})
	require.NoError(t, err, "NewChannel failed")

	peerInfo := ch.PeerInfo()
	fields := toMap(ch.Logger().Fields())
	assert.Equal(t, peerInfo.ServiceName, fields["service"])

	sc := ch.GetSubChannel("subch")
	fields = toMap(sc.Logger().Fields())
	assert.Equal(t, peerInfo.ServiceName, fields["service"])
	assert.Equal(t, "subch", fields["subchannel"])
}

func TestStats(t *testing.T) {
	ch, err := NewChannel("svc", &ChannelOptions{
		Logger: NewLogger(ioutil.Discard),
	})
	require.NoError(t, err, "NewChannel failed")

	hostname, err := os.Hostname()
	require.NoError(t, err, "Hostname failed")

	peerInfo := ch.PeerInfo()
	tags := ch.StatsTags()
	assert.NotNil(t, ch.StatsReporter(), "StatsReporter missing")
	assert.NotNil(t, ch.TraceReporter(), "TraceReporter missing")
	assert.Equal(t, peerInfo.ProcessName, tags["app"], "app tag")
	assert.Equal(t, peerInfo.ServiceName, tags["service"], "service tag")
	assert.Equal(t, hostname, tags["host"], "hostname tag")

	sc := ch.GetSubChannel("subch")
	subTags := sc.StatsTags()
	assert.NotNil(t, sc.StatsReporter(), "StatsReporter missing")
	for k, v := range tags {
		assert.Equal(t, v, subTags[k], "subchannel missing tag %v", k)
	}
	assert.Equal(t, "subch", subTags["subchannel"], "subchannel tag missing")
}

func TestIsolatedSubChannelsDontSharePeers(t *testing.T) {
	ch, err := NewChannel("svc", &ChannelOptions{
		Logger: NewLogger(ioutil.Discard),
	})
	require.NoError(t, err, "NewChannel failed")

	sub := ch.GetSubChannel("svc-ringpop")
	if ch.peers != sub.peers {
		t.Log("Channel and subchannel don't share the same peer list.")
		t.Fail()
	}

	isolatedSub := ch.GetSubChannel("svc-shy-ringpop", Isolated)
	if ch.peers == isolatedSub.peers {
		t.Log("Channel and isolated subchannel share the same peer list.")
		t.Fail()
	}

	// Nobody knows about the peer.
	assert.Nil(t, ch.peers.peersByHostPort["127.0.0.1:3000"])
	assert.Nil(t, sub.peers.peersByHostPort["127.0.0.1:3000"])
	assert.Nil(t, isolatedSub.peers.peersByHostPort["127.0.0.1:3000"])

	// Uses of the parent channel should be reflected in the subchannel, but
	// not the isolated subchannel.
	ch.BeginCall(context.Background(), "127.0.0.1:3000", "foo", "Bar::baz", nil)
	assert.NotNil(t, ch.peers.peersByHostPort["127.0.0.1:3000"])
	assert.NotNil(t, sub.peers.peersByHostPort["127.0.0.1:3000"])
	assert.Nil(t, isolatedSub.peers.peersByHostPort["127.0.0.1:3000"])
}
<|endoftext|>


<commit_before>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// 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 workflow

import (
	"encoding/json"

	"github.com/venicegeo/pz-gocommon/elasticsearch"
	"github.com/venicegeo/pz-gocommon/gocommon"
)

type EventDB struct {
	*ResourceDB
}

func NewEventDB(service *WorkflowService, esi elasticsearch.IIndex) (*EventDB, error) {
	rdb, err := NewResourceDB(service, esi, EventIndexSettings)
	if err != nil {
		return nil, err
	}
	erdb := EventDB{ResourceDB: rdb}
	return &erdb, nil
}

func (db *EventDB) PostData(mapping string, obj interface{}, id piazza.Ident) (piazza.Ident, error) {
	indexResult, err := db.Esi.PostData(mapping, id.String(), obj)
	if err != nil {
		return piazza.NoIdent, LoggedError("EventDB.PostData failed: %s", err)
	}
	if !indexResult.Created {
		return piazza.NoIdent, LoggedError("EventDB.PostData failed: not created")
	}

	return id, nil
}

func (db *EventDB) GetAll(mapping string, format *piazza.JsonPagination) ([]Event, int64, error) {
	events := []Event{}

	exists := true
	if mapping != "" {
		exists = db.Esi.TypeExists(mapping)
	}
	if !exists {
		return nil, 0, LoggedError("Type %s does not exist", mapping)
	}

	searchResult, err := db.Esi.FilterByMatchAll(mapping, format)
	if err != nil {
		return nil, 0, LoggedError("EventDB.GetAll failed: %s", err)
	}
	if searchResult == nil {
		return nil, 0, LoggedError("EventDB.GetAll failed: no searchResult")
	}

	if searchResult != nil && searchResult.GetHits() != nil {
		for _, hit := range *searchResult.GetHits() {
			var event Event
			err := json.Unmarshal(*hit.Source, &event)
			if err != nil {
				return nil, 0, err
			}
			events = append(events, event)
		}
	}

	return events, searchResult.TotalHits(), nil
}

func (db *EventDB) lookupEventTypeNameByEventID(id piazza.Ident) (string, error) {
	var mapping string = ""

	types, err := db.Esi.GetTypes()
	if err != nil {
		return "", err
	}
	for _, typ := range types {
		if db.Esi.ItemExists(typ, id.String()) {
			mapping = typ
			break
		}
	}

	return mapping, nil
}

// Function to check if an EventType name exists
// This is easier to check in EventDB, as the mappings use the EventType.Name
func (db *EventDB) NameExists(name string) bool {
	return db.Esi.TypeExists(name)
}

func (db *EventDB) GetOne(mapping string, id piazza.Ident) (*Event, error) {
	getResult, err := db.Esi.GetByID(mapping, id.String())
	if err != nil {
		return nil, LoggedError("EventDB.GetOne failed: %s", err)
	}
	if getResult == nil {
		return nil, LoggedError("EventDB.GetOne failed: no getResult")
	}

	if !getResult.Found {
		return nil, nil
	}

	src := getResult.Source
	var event Event
	err = json.Unmarshal(*src, &event)
	if err != nil {
		return nil, err
	}

	return &event, nil
}

func (db *EventDB) DeleteByID(mapping string, id piazza.Ident) (bool, error) {
	deleteResult, err := db.Esi.DeleteByID(mapping, string(id))
	if err != nil {
		return false, LoggedError("EventDB.DeleteById failed: %s", err)
	}
	if deleteResult == nil {
		return false, LoggedError("EventDB.DeleteById failed: no deleteResult")
	}

	return deleteResult.Found, nil
}

func (db *EventDB) AddMapping(name string, mapping map[string]elasticsearch.MappingElementTypeName) error {
	jsn, err := elasticsearch.ConstructMappingSchema(name, mapping)
	if err != nil {
		return LoggedError("EventDB.AddMapping failed: %s", err)
	}

	err = db.Esi.SetMapping(name, jsn)
	if err != nil {
		return LoggedError("EventDB.AddMapping SetMapping failed: %s", err)
	}

	return nil
}

func (db *EventDB) PercolateEventData(eventType string, data map[string]interface{}, id piazza.Ident) (*[]piazza.Ident, error) {
	percolateResponse, err := db.Esi.AddPercolationDocument(eventType, data)

	if err != nil {
		return nil, LoggedError("EventDB.PercolateEventData failed: %s", err)
	}
	if percolateResponse == nil {
		return nil, LoggedError("EventDB.PercolateEventData failed: no percolateResult")
	}

	// add the triggers to the alert queue
	ids := make([]piazza.Ident, len(percolateResponse.Matches))
	for i, v := range percolateResponse.Matches {
		ids[i] = piazza.Ident(v.Id)
	}

	return &ids, nil
}
<commit_msg>Update comments<commit_after>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// 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 workflow

import (
	"encoding/json"

	"github.com/venicegeo/pz-gocommon/elasticsearch"
	"github.com/venicegeo/pz-gocommon/gocommon"
)

type EventDB struct {
	*ResourceDB
}

func NewEventDB(service *WorkflowService, esi elasticsearch.IIndex) (*EventDB, error) {
	rdb, err := NewResourceDB(service, esi, EventIndexSettings)
	if err != nil {
		return nil, err
	}
	erdb := EventDB{ResourceDB: rdb}
	return &erdb, nil
}

func (db *EventDB) PostData(mapping string, obj interface{}, id piazza.Ident) (piazza.Ident, error) {
	indexResult, err := db.Esi.PostData(mapping, id.String(), obj)
	if err != nil {
		return piazza.NoIdent, LoggedError("EventDB.PostData failed: %s", err)
	}
	if !indexResult.Created {
		return piazza.NoIdent, LoggedError("EventDB.PostData failed: not created")
	}

	return id, nil
}

func (db *EventDB) GetAll(mapping string, format *piazza.JsonPagination) ([]Event, int64, error) {
	events := []Event{}

	exists := true
	if mapping != "" {
		exists = db.Esi.TypeExists(mapping)
	}
	if !exists {
		return nil, 0, LoggedError("Type %s does not exist", mapping)
	}

	searchResult, err := db.Esi.FilterByMatchAll(mapping, format)
	if err != nil {
		return nil, 0, LoggedError("EventDB.GetAll failed: %s", err)
	}
	if searchResult == nil {
		return nil, 0, LoggedError("EventDB.GetAll failed: no searchResult")
	}

	if searchResult != nil && searchResult.GetHits() != nil {
		for _, hit := range *searchResult.GetHits() {
			var event Event
			err := json.Unmarshal(*hit.Source, &event)
			if err != nil {
				return nil, 0, err
			}
			events = append(events, event)
		}
	}

	return events, searchResult.TotalHits(), nil
}

func (db *EventDB) lookupEventTypeNameByEventID(id piazza.Ident) (string, error) {
	var mapping string = ""

	types, err := db.Esi.GetTypes()
	if err != nil {
		return "", err
	}
	for _, typ := range types {
		if db.Esi.ItemExists(typ, id.String()) {
			mapping = typ
			break
		}
	}

	return mapping, nil
}

// NameExists checks if an EventType name exists.
// This is easier to check in EventDB, as the mappings use the EventType.Name.
func (db *EventDB) NameExists(name string) bool {
	return db.Esi.TypeExists(name)
}

func (db *EventDB) GetOne(mapping string, id piazza.Ident) (*Event, error) {
	getResult, err := db.Esi.GetByID(mapping, id.String())
	if err != nil {
		return nil, LoggedError("EventDB.GetOne failed: %s", err)
	}
	if getResult == nil {
		return nil, LoggedError("EventDB.GetOne failed: no getResult")
	}

	if !getResult.Found {
		return nil, nil
	}

	src := getResult.Source
	var event Event
	err = json.Unmarshal(*src, &event)
	if err != nil {
		return nil, err
	}

	return &event, nil
}

func (db *EventDB) DeleteByID(mapping string, id piazza.Ident) (bool, error) {
	deleteResult, err := db.Esi.DeleteByID(mapping, string(id))
	if err != nil {
		return false, LoggedError("EventDB.DeleteById failed: %s", err)
	}
	if deleteResult == nil {
		return false, LoggedError("EventDB.DeleteById failed: no deleteResult")
	}

	return deleteResult.Found, nil
}

func (db *EventDB) AddMapping(name string, mapping map[string]elasticsearch.MappingElementTypeName) error {
	jsn, err := elasticsearch.ConstructMappingSchema(name, mapping)
	if err != nil {
		return LoggedError("EventDB.AddMapping failed: %s", err)
	}

	err = db.Esi.SetMapping(name, jsn)
	if err != nil {
		return LoggedError("EventDB.AddMapping SetMapping failed: %s", err)
	}

	return nil
}

func (db *EventDB) PercolateEventData(eventType string, data map[string]interface{}, id piazza.Ident) (*[]piazza.Ident, error) {
	percolateResponse, err := db.Esi.AddPercolationDocument(eventType, data)

	if err != nil {
		return nil, LoggedError("EventDB.PercolateEventData failed: %s", err)
	}
	if percolateResponse == nil {
		return nil, LoggedError("EventDB.PercolateEventData failed: no percolateResult")
	}

	// add the triggers to the alert queue
	ids := make([]piazza.Ident, len(percolateResponse.Matches))
	for i, v := range percolateResponse.Matches {
		ids[i] = piazza.Ident(v.Id)
	}

	return &ids, nil
}
<|endoftext|>


<commit_before>package osxkeychain

import (
	"testing"
)

func TestInternetPassword(t *testing.T) {
	passwordVal := "longfakepassword with emoji 🍻 and \000 embedded nuls \000"
	accountNameVal := "bgentry"
	serverNameVal := "go-osxkeychain-test.example.com"
	securityDomainVal := ""
	portVal := 886
	pathVal := "/fake"
	pass := InternetPassword{
		ServerName:     serverNameVal,
		SecurityDomain: securityDomainVal,
		AccountName:    accountNameVal,
		Port:           portVal,
		Path:           pathVal,
		Protocol:       ProtocolHTTPS,
		AuthType:       AuthenticationHTTPBasic,
		Password:       passwordVal,
	}
	// Add the password
	err := AddInternetPassword(&pass)
	if err != nil {
		t.Error(err)
	}
	// Try adding again, expect it to fail as a duplicate
	err = AddInternetPassword(&pass)
	if err != ErrDuplicateItem {
		t.Errorf("expected ErrDuplicateItem on 2nd save, got %s", err)
	}
	// Find the password
	pass2 := InternetPassword{
		ServerName: serverNameVal,
		Path:       pathVal,
		Protocol:   ProtocolHTTPS,
		AuthType:   AuthenticationHTTPBasic,
	}
	resp, err := FindInternetPassword(&pass2)
	if err != nil {
		t.Error(err)
	}
	if resp.Password != passwordVal {
		t.Errorf("FindInternetPassword expected Password=%s, got %s", passwordVal, resp.Password)
	}
	if resp.AccountName != accountNameVal {
		t.Errorf("FindInternetPassword expected AccountName=%q, got %q", accountNameVal, resp.AccountName)
	}
	if resp.ServerName != serverNameVal {
		t.Errorf("FindInternetPassword expected ServerName=%q, got %q", serverNameVal, resp.ServerName)
	}
	if resp.SecurityDomain != securityDomainVal {
		t.Errorf("FindInternetPassword expected SecurityDomain=%q, got %q", securityDomainVal, resp.SecurityDomain)
	}
	if resp.Protocol != ProtocolHTTPS {
		t.Errorf("FindInternetPassword expected Protocol=https, got %q", resp.Protocol)
	}
	if resp.Port != portVal {
		t.Errorf("FindInternetPassword expected Port=%d, got %d", portVal, resp.Port)
	}
	if resp.AuthType != AuthenticationHTTPBasic {
		t.Errorf("FindInternetPassword expected AuthType=HTTPBasic, got %q", resp.AuthType)
	}
	if resp.Path != pathVal {
		t.Errorf("FindInternetPassword expected Path=%q, got %q", pathVal, resp.Path)
	}
}
<commit_msg>Replace emoji with invalid UTF-8<commit_after>package osxkeychain

import (
	"testing"
)

func TestInternetPassword(t *testing.T) {
	passwordVal := "longfakepassword with invalid UTF-8 \xc3\x28 and \000 embedded nuls \000"
	accountNameVal := "bgentry"
	serverNameVal := "go-osxkeychain-test.example.com"
	securityDomainVal := ""
	portVal := 886
	pathVal := "/fake"
	pass := InternetPassword{
		ServerName:     serverNameVal,
		SecurityDomain: securityDomainVal,
		AccountName:    accountNameVal,
		Port:           portVal,
		Path:           pathVal,
		Protocol:       ProtocolHTTPS,
		AuthType:       AuthenticationHTTPBasic,
		Password:       passwordVal,
	}
	// Add the password
	err := AddInternetPassword(&pass)
	if err != nil {
		t.Error(err)
	}
	// Try adding again, expect it to fail as a duplicate
	err = AddInternetPassword(&pass)
	if err != ErrDuplicateItem {
		t.Errorf("expected ErrDuplicateItem on 2nd save, got %s", err)
	}
	// Find the password
	pass2 := InternetPassword{
		ServerName: serverNameVal,
		Path:       pathVal,
		Protocol:   ProtocolHTTPS,
		AuthType:   AuthenticationHTTPBasic,
	}
	resp, err := FindInternetPassword(&pass2)
	if err != nil {
		t.Error(err)
	}
	if resp.Password != passwordVal {
		t.Errorf("FindInternetPassword expected Password=%s, got %s", passwordVal, resp.Password)
	}
	if resp.AccountName != accountNameVal {
		t.Errorf("FindInternetPassword expected AccountName=%q, got %q", accountNameVal, resp.AccountName)
	}
	if resp.ServerName != serverNameVal {
		t.Errorf("FindInternetPassword expected ServerName=%q, got %q", serverNameVal, resp.ServerName)
	}
	if resp.SecurityDomain != securityDomainVal {
		t.Errorf("FindInternetPassword expected SecurityDomain=%q, got %q", securityDomainVal, resp.SecurityDomain)
	}
	if resp.Protocol != ProtocolHTTPS {
		t.Errorf("FindInternetPassword expected Protocol=https, got %q", resp.Protocol)
	}
	if resp.Port != portVal {
		t.Errorf("FindInternetPassword expected Port=%d, got %d", portVal, resp.Port)
	}
	if resp.AuthType != AuthenticationHTTPBasic {
		t.Errorf("FindInternetPassword expected AuthType=HTTPBasic, got %q", resp.AuthType)
	}
	if resp.Path != pathVal {
		t.Errorf("FindInternetPassword expected Path=%q, got %q", pathVal, resp.Path)
	}
}
<|endoftext|>


<commit_before>package image

import (
	"io"
	"io/ioutil"
	"strings"
	"testing"

	"github.com/docker/cli/internal/test"
	"github.com/docker/docker/api/types"
	"github.com/pkg/errors"
	"gotest.tools/v3/assert"
	is "gotest.tools/v3/assert/cmp"
)

func TestNewImportCommandErrors(t *testing.T) {
	testCases := []struct {
		name            string
		args            []string
		expectedError   string
		imageImportFunc func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
	}{
		{
			name:          "wrong-args",
			args:          []string{},
			expectedError: "requires at least 1 argument.",
		},
		{
			name:          "import-failed",
			args:          []string{"testdata/import-command-success.input.txt"},
			expectedError: "something went wrong",
			imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
				return nil, errors.Errorf("something went wrong")
			},
		},
	}
	for _, tc := range testCases {
		cmd := NewImportCommand(test.NewFakeCli(&fakeClient{imageImportFunc: tc.imageImportFunc}))
		cmd.SetOut(ioutil.Discard)
		cmd.SetArgs(tc.args)
		assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
	}
}

func TestNewImportCommandInvalidFile(t *testing.T) {
	cmd := NewImportCommand(test.NewFakeCli(&fakeClient{}))
	cmd.SetOut(ioutil.Discard)
	cmd.SetArgs([]string{"testdata/import-command-success.unexistent-file"})
	assert.ErrorContains(t, cmd.Execute(), "testdata/import-command-success.unexistent-file")
}

func TestNewImportCommandSuccess(t *testing.T) {
	testCases := []struct {
		name            string
		args            []string
		imageImportFunc func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
	}{
		{
			name: "simple",
			args: []string{"testdata/import-command-success.input.txt"},
		},
		{
			name: "terminal-source",
			args: []string{"-"},
		},
		{
			name: "double",
			args: []string{"-", "image:local"},
			imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
				assert.Check(t, is.Equal("image:local", ref))
				return ioutil.NopCloser(strings.NewReader("")), nil
			},
		},
		{
			name: "message",
			args: []string{"--message", "test message", "-"},
			imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
				assert.Check(t, is.Equal("test message", options.Message))
				return ioutil.NopCloser(strings.NewReader("")), nil
			},
		},
		{
			name: "change",
			args: []string{"--change", "ENV DEBUG true", "-"},
			imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
				assert.Check(t, is.Equal("ENV DEBUG true", options.Changes[0]))
				return ioutil.NopCloser(strings.NewReader("")), nil
			},
		},
	}
	for _, tc := range testCases {
		cmd := NewImportCommand(test.NewFakeCli(&fakeClient{imageImportFunc: tc.imageImportFunc}))
		cmd.SetOut(ioutil.Discard)
		cmd.SetArgs(tc.args)
		assert.NilError(t, cmd.Execute())
	}
}
<commit_msg>Add test-case for env with, and without =<commit_after>package image

import (
	"io"
	"io/ioutil"
	"strings"
	"testing"

	"github.com/docker/cli/internal/test"
	"github.com/docker/docker/api/types"
	"github.com/pkg/errors"
	"gotest.tools/v3/assert"
	is "gotest.tools/v3/assert/cmp"
)

func TestNewImportCommandErrors(t *testing.T) {
	testCases := []struct {
		name            string
		args            []string
		expectedError   string
		imageImportFunc func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
	}{
		{
			name:          "wrong-args",
			args:          []string{},
			expectedError: "requires at least 1 argument.",
		},
		{
			name:          "import-failed",
			args:          []string{"testdata/import-command-success.input.txt"},
			expectedError: "something went wrong",
			imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
				return nil, errors.Errorf("something went wrong")
			},
		},
	}
	for _, tc := range testCases {
		cmd := NewImportCommand(test.NewFakeCli(&fakeClient{imageImportFunc: tc.imageImportFunc}))
		cmd.SetOut(ioutil.Discard)
		cmd.SetArgs(tc.args)
		assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
	}
}

func TestNewImportCommandInvalidFile(t *testing.T) {
	cmd := NewImportCommand(test.NewFakeCli(&fakeClient{}))
	cmd.SetOut(ioutil.Discard)
	cmd.SetArgs([]string{"testdata/import-command-success.unexistent-file"})
	assert.ErrorContains(t, cmd.Execute(), "testdata/import-command-success.unexistent-file")
}

func TestNewImportCommandSuccess(t *testing.T) {
	testCases := []struct {
		name            string
		args            []string
		imageImportFunc func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
	}{
		{
			name: "simple",
			args: []string{"testdata/import-command-success.input.txt"},
		},
		{
			name: "terminal-source",
			args: []string{"-"},
		},
		{
			name: "double",
			args: []string{"-", "image:local"},
			imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
				assert.Check(t, is.Equal("image:local", ref))
				return ioutil.NopCloser(strings.NewReader("")), nil
			},
		},
		{
			name: "message",
			args: []string{"--message", "test message", "-"},
			imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
				assert.Check(t, is.Equal("test message", options.Message))
				return ioutil.NopCloser(strings.NewReader("")), nil
			},
		},
		{
			name: "change",
			args: []string{"--change", "ENV DEBUG=true", "-"},
			imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
				assert.Check(t, is.Equal("ENV DEBUG=true", options.Changes[0]))
				return ioutil.NopCloser(strings.NewReader("")), nil
			},
		},
		{
			name: "change legacy syntax",
			args: []string{"--change", "ENV DEBUG true", "-"},
			imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
				assert.Check(t, is.Equal("ENV DEBUG true", options.Changes[0]))
				return ioutil.NopCloser(strings.NewReader("")), nil
			},
		},
	}
	for _, tc := range testCases {
		cmd := NewImportCommand(test.NewFakeCli(&fakeClient{imageImportFunc: tc.imageImportFunc}))
		cmd.SetOut(ioutil.Discard)
		cmd.SetArgs(tc.args)
		assert.NilError(t, cmd.Execute())
	}
}
<|endoftext|>


<commit_before>package sigmon

import (
	"syscall"
	"testing"
	"time"
)

var (
	sigs = []syscall.Signal{
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGUSR1,
		syscall.SIGUSR2,
	}
)

type checkable struct {
	id  int
	val int
}

func (c *checkable) handler(sm *SignalMonitor) {
	c.val = c.id
}

func TestUnitSignalJunctionConnect(t *testing.T) {
	j := newSignalJunction()
	j.connect()

	for _, s := range sigs {
		if err := callOSSignal(s); err != nil {
			t.Errorf("unexpected error when calling %s: %s", s, err)
		}
	}

	if !receiveOnAll(j) {
		t.Fatal("should not wait forever")
	}
}

func TestUnitSignalJunctionDisconnect(t *testing.T) {
	j := newSignalJunction()
	j.connect()
	j.disconnect()

	if receiveOnAll(j) {
		t.Fatal("should wait forever")
	}
}

func TestUnitSignalHandlerRegister(t *testing.T) {
	c1 := &checkable{id: 123}
	c2 := &checkable{id: 234}

	h := newSignalHandler(nil)
	h.register(c1.handler)
	h.register(c2.handler)

	select {
	case fn := <-h.registry:
		if fn == nil {
			t.Error("want function, got nil")
		}

		fn(&SignalMonitor{})
	case <-time.After(time.Millisecond):
		t.Error("should not wait forever")
	}

	if 0 != c1.val {
		t.Errorf("want %d, got %d", 0, c1.val)
	}
	if c2.id != c2.val {
		t.Errorf("want %d, got %d", c2.id, c2.val)
	}
}

func TestUnitSignalHandlerSet(t *testing.T) {
	c := &checkable{id: 123}
	h := newSignalHandler(nil)
	h.set(c.handler)

	h.handler(&SignalMonitor{})

	if c.id != c.val {
		t.Errorf("want %d, got %d", c.id, c.val)
	}
}

func TestUnitSignalHandlerHandle(t *testing.T) {
	c := &checkable{id: 123}
	h := newSignalHandler(c.handler)

	h.handle(&SignalMonitor{})

	if c.id != c.val {
		t.Errorf("want %d, got %d", c.id, c.val)
	}
}

func TestUnitSignalMonitorSet(t *testing.T) {
	c := &checkable{id: 123}
	m := New(nil)
	m.Set(c.handler)

	select {
	case fn := <-m.handler.registry:
		if fn == nil {
			t.Error("want function, got nil")
		}
	case <-time.After(time.Millisecond):
		t.Error("should not wait forever")
	}
}

func receiveOnAll(j *signalJunction) bool {
	for i := 0; i < 5; i++ {
		select {
		case <-j.sighup:
		case <-j.sigint:
		case <-j.sigterm:
		case <-j.sigusr1:
		case <-j.sigusr2:
		case <-time.After(time.Millisecond):
			return false
		}
	}

	return true
}

func callOSSignal(s syscall.Signal) error {
	return syscall.Kill(syscall.Getpid(), s)
}
<commit_msg>Fix checkable data race, and add wait time for os signal propagation.<commit_after>package sigmon

import (
	"sync"
	"syscall"
	"testing"
	"time"
)

var (
	sigs = []syscall.Signal{
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGUSR1,
		syscall.SIGUSR2,
	}
)

type checkable struct {
	sync.Mutex
	id  int
	val int
	ct  int
}

func (c *checkable) handler(sm *SignalMonitor) {
	c.Lock()
	defer c.Unlock()

	c.val = c.id
	c.ct++
}

func (c *checkable) info() (id, val, ct int) {
	c.Lock()
	defer c.Unlock()

	return c.id, c.val, c.ct
}

func TestUnitSignalJunctionConnect(t *testing.T) {
	j := newSignalJunction()
	j.connect()

	for _, s := range sigs {
		if err := callOSSignal(s); err != nil {
			t.Errorf("unexpected error when calling %s: %s", s, err)
		}
	}

	if !receiveOnAll(j) {
		t.Fatal("should not wait forever")
	}
}

func TestUnitSignalJunctionDisconnect(t *testing.T) {
	j := newSignalJunction()
	j.connect()
	j.disconnect()

	if receiveOnAll(j) {
		t.Fatal("should wait forever")
	}
}

func TestUnitSignalHandlerRegister(t *testing.T) {
	c1 := &checkable{id: 123}
	c2 := &checkable{id: 234}

	h := newSignalHandler(nil)
	h.register(c1.handler)
	h.register(c2.handler)

	select {
	case fn := <-h.registry:
		if fn == nil {
			t.Error("want function, got nil")
		}

		fn(&SignalMonitor{})
	case <-time.After(time.Millisecond):
		t.Error("should not wait forever")
	}

	_, c1Val, _ := c1.info()
	if 0 != c1Val {
		t.Errorf("want %d, got %d", 0, c1Val)
	}
	c2ID, c2Val, _ := c2.info()
	if c2ID != c2Val {
		t.Errorf("want %d, got %d", c2ID, c2Val)
	}
}

func TestUnitSignalHandlerSet(t *testing.T) {
	c := &checkable{id: 123}
	h := newSignalHandler(nil)
	h.set(c.handler)

	h.handler(&SignalMonitor{})

	id, val, _ := c.info()
	if id != val {
		t.Errorf("want %d, got %d", id, val)
	}
}

func TestUnitSignalHandlerHandle(t *testing.T) {
	c := &checkable{id: 123}
	h := newSignalHandler(c.handler)

	h.handle(&SignalMonitor{})

	id, val, _ := c.info()
	if id != val {
		t.Errorf("want %d, got %d", id, val)
	}
}

func TestUnitSignalMonitorSet(t *testing.T) {
	c := &checkable{id: 123}
	m := New(nil)
	m.Set(c.handler)

	select {
	case fn := <-m.handler.registry:
		if fn == nil {
			t.Error("want function, got nil")
		}
	case <-time.After(time.Millisecond):
		t.Error("should not wait forever")
	}
}

func receiveOnAll(j *signalJunction) bool {
	for i := 0; i < 5; i++ {
		select {
		case <-j.sighup:
		case <-j.sigint:
		case <-j.sigterm:
		case <-j.sigusr1:
		case <-j.sigusr2:
		case <-time.After(time.Millisecond):
			return false
		}
	}

	return true
}

func callOSSignal(s syscall.Signal) error {
	if err := syscall.Kill(syscall.Getpid(), s); err != nil {
		return err
	}

	// delay for requested signal propagation
	for i := 1 << 13; i > 0; i-- {
		syscall.Getpid()
	}

	return nil
}
<|endoftext|>


<commit_before>package tm

import (
	"flag"
)

// configure the tfcat command utility / DisplayFrame function
type TfcatConfig struct {
	PrettyPrint bool
	SkipPayload bool
	Follow      bool
}

// call DefineFlags before myflags.Parse()
func (c *TfcatConfig) DefineFlags(fs *flag.FlagSet) {
	fs.BoolVar(&c.PrettyPrint, "p", false, "pretty print output.")
	fs.BoolVar(&c.SkipPayload, "s", false, "short display. skip printing any data payload.")
	fs.BoolVar(&c.Follow, "f", false, "follow the file, only printing any new additions.")
}

// call c.ValidateConfig() after myflags.Parse()
func (c *TfcatConfig) ValidateConfig() error {
	return nil
}
<commit_msg>atg. doc++<commit_after>package tm

import (
	"flag"
)

// configure the tfcat command utility
type TfcatConfig struct {
	PrettyPrint bool
	SkipPayload bool
	Follow      bool
}

// call DefineFlags before myflags.Parse()
func (c *TfcatConfig) DefineFlags(fs *flag.FlagSet) {
	fs.BoolVar(&c.PrettyPrint, "p", false, "pretty print output.")
	fs.BoolVar(&c.SkipPayload, "s", false, "short display. skip printing any data payload.")
	fs.BoolVar(&c.Follow, "f", false, "follow the file, only printing any new additions.")
}

// call c.ValidateConfig() after myflags.Parse()
func (c *TfcatConfig) ValidateConfig() error {
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/codegangsta/cli"
	"github.com/mikebeyer/clc-cli/aa"
	"github.com/mikebeyer/clc-cli/alert"
	"github.com/mikebeyer/clc-cli/group"
	"github.com/mikebeyer/clc-cli/lb"
	"github.com/mikebeyer/clc-cli/server"
	"github.com/mikebeyer/clc-cli/status"
	"github.com/mikebeyer/clc-sdk"
	"github.com/mikebeyer/clc-sdk/api"
)

func main() {

	app := cli.NewApp()
	app.Name = "clc"
	app.Usage = "clc v2 api cli"
	app.Version = "0.0.1"
	app.Authors = []cli.Author{
		cli.Author{
			Name:  "Mike Beyer",
			Email: "michael.beyer@ctl.io",
		},
	}
	app.Flags = []cli.Flag{
		cli.BoolFlag{Name: "default-config", Usage: "create template configuration file"},
	}
	var config api.Config
	var configErr error
	app.Action = func(c *cli.Context) {
		fmt.Println("here")
		if c.Bool("default-config") {

			conf := api.NewConfig("USERNAME", "PASSWORD", "DEFAULT-ALIAS")
			b, err := json.MarshalIndent(conf, "", "  ")
			if err != nil {
				fmt.Printf("unable to generate config template.")
			}

			err = ioutil.WriteFile("./config.json", b, 0666)
			if err != nil {
				fmt.Printf("unable to generate config template.")
			}
			fmt.Printf("config template written to config.json")
			return
		} else if c.String("config") != "" {
			config, configErr = api.FileConfig(c.String("config"))
			if configErr != nil {
				fmt.Printf("unable to find/parse config: %s\n", c.String("config"))
				return
			}
		} else if !c.Args().Present() {
			cli.ShowAppHelp(c)
		}
	}
	if !config.Valid() {
		config, configErr = api.EnvConfig()
		if configErr != nil {
			config, configErr = api.FileConfig("./config.json")
			if configErr != nil {
				fmt.Printf("failed to find necessary environment variables or default config location (./config.json)\n")
				return
			}
		}
	}

	client := clc.New(config)
	app.Commands = []cli.Command{
		server.Commands(client),
		status.Commands(client),
		aa.Commands(client),
		alert.Commands(client),
		lb.Commands(client),
		group.Commands(client),
	}
	app.Run(os.Args)
}
<commit_msg>removed extra return<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/codegangsta/cli"
	"github.com/mikebeyer/clc-cli/aa"
	"github.com/mikebeyer/clc-cli/alert"
	"github.com/mikebeyer/clc-cli/group"
	"github.com/mikebeyer/clc-cli/lb"
	"github.com/mikebeyer/clc-cli/server"
	"github.com/mikebeyer/clc-cli/status"
	"github.com/mikebeyer/clc-sdk"
	"github.com/mikebeyer/clc-sdk/api"
)

func main() {

	app := cli.NewApp()
	app.Name = "clc"
	app.Usage = "clc v2 api cli"
	app.Version = "0.0.1"
	app.Authors = []cli.Author{
		cli.Author{
			Name:  "Mike Beyer",
			Email: "michael.beyer@ctl.io",
		},
	}
	app.Flags = []cli.Flag{
		cli.BoolFlag{Name: "default-config", Usage: "create template configuration file"},
	}
	var config api.Config
	var configErr error
	app.Action = func(c *cli.Context) {
		fmt.Println("here")
		if c.Bool("default-config") {

			conf := api.NewConfig("USERNAME", "PASSWORD", "DEFAULT-ALIAS")
			b, err := json.MarshalIndent(conf, "", "  ")
			if err != nil {
				fmt.Printf("unable to generate config template.")
			}

			err = ioutil.WriteFile("./config.json", b, 0666)
			if err != nil {
				fmt.Printf("unable to generate config template.")
			}
			fmt.Printf("config template written to config.json")
			return
		} else if c.String("config") != "" {
			config, configErr = api.FileConfig(c.String("config"))
			if configErr != nil {
				fmt.Printf("unable to find/parse config: %s\n", c.String("config"))
			}
		} else if !c.Args().Present() {
			cli.ShowAppHelp(c)
		}
	}
	if !config.Valid() {
		config, configErr = api.EnvConfig()
		if configErr != nil {
			config, configErr = api.FileConfig("./config.json")
			if configErr != nil {
				fmt.Printf("failed to find necessary environment variables or default config location (./config.json)\n")
				return
			}
		}
	}

	client := clc.New(config)
	app.Commands = []cli.Command{
		server.Commands(client),
		status.Commands(client),
		aa.Commands(client),
		alert.Commands(client),
		lb.Commands(client),
		group.Commands(client),
	}
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"golang.org/x/net/context"
)

func main() {
	ctx := context.Background()

	configPath := "./config.json"
	config, err := LoadProcessConfig(configPath)
	if err != nil {
		fmt.Printf("Error to load %v cause of %v\n", configPath, err)
		os.Exit(1)
	}
	config.setup(os.Args[1:])

	p := &Process{config: config}
	err = p.setup(ctx)
	if err != nil {
		fmt.Printf("Error to setup Process cause of %v\n", err)
		os.Exit(1)
	}

	err = p.run()
	if err != nil {
		fmt.Printf("Error to run cause of %v\n", err)
		os.Exit(1)
	}
}
<commit_msg>:+1: Use cli in main function<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/urfave/cli"
	"golang.org/x/net/context"
)

func main() {
	app := cli.NewApp()
	app.Name = "blocks-gcs-proxy"
	app.Usage = "github.com/groovenauts/blocks-gcs-proxy"
	app.Version = VERSION

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "config, c",
			Usage: "Load configuration from `FILE`",
		},
	}

	app.Action = run

	app.Run(os.Args)
}

func run(c *cli.Context) error {
	ctx := context.Background()

	configPath := c.String("config")
	if configPath == "" {
		configPath = "./config.json"
	}
	config, err := LoadProcessConfig(configPath)
	if err != nil {
		fmt.Printf("Error to load %v cause of %v\n", configPath, err)
		os.Exit(1)
	}
	config.setup(os.Args[1:])

	p := &Process{config: config}
	err = p.setup(ctx)
	if err != nil {
		fmt.Printf("Error to setup Process cause of %v\n", err)
		os.Exit(1)
	}

	err = p.run()
	if err != nil {
		fmt.Printf("Error to run cause of %v\n", err)
		os.Exit(1)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/urfave/cli"
	"os"
)

// settings for the server
type Settings struct {
	Directory          string
	ManagerAddress     string
	ManagerCredentials string
	ManagerEnabled     bool
	Address            string
	Name               string
	BootstrapAddress   string
}

var globalSettings Settings = Settings{
	Directory:          "",
	ManagerAddress:     "localhost:8080",
	ManagerCredentials: "replicat:isthecat",
	Address:            ":8001",
	Name:               "",
}

func SetupCli() {

	app := cli.NewApp()
	app.Name = "Replicat"
	app.Usage = "rsync for the cloud"
	app.Action = func(c *cli.Context) error {
		globalSettings.Directory = c.GlobalString("directory")
		globalSettings.ManagerAddress = c.GlobalString("manager")
		globalSettings.ManagerCredentials = c.GlobalString("manager_credentials")
		globalSettings.Address = c.GlobalString("address")
		globalSettings.Name = c.GlobalString("name")
		globalSettings.BootstrapAddress = c.GlobalString("bootstrap_address")

		if globalSettings.Directory == "" {
			panic("directory is required to serve files\n")
		}

		if globalSettings.Name == "" {
			panic("Name is currently a required parameter. Name has to be one of the predefined names (e.g. NodeA, NodeB). This will improve.\n")
		}

		return nil
	}

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "directory, d",
			Value:  globalSettings.Directory,
			Usage:  "Specify a directory where the files to share are located.",
			EnvVar: "directory, d",
		},
		cli.StringFlag{
			Name:   "manager, m",
			Value:  globalSettings.ManagerAddress,
			Usage:  "Specify a host and port for reaching the manager",
			EnvVar: "manager, m",
		},
		cli.StringFlag{
			Name:   "manager_credentials, mc",
			Value:  globalSettings.ManagerCredentials,
			Usage:  "Specify a usernmae:password for login to the manager",
			EnvVar: "manager_credentials, mc",
		},
		cli.StringFlag{
			Name:   "address, a",
			Value:  globalSettings.Address,
			Usage:  "Specify a listen address for this node. e.g. '127.0.0.1:8000' or ':8000' for where updates are accepted from",
			EnvVar: "address, a",
		},
		cli.StringFlag{
			Name:   "name, n",
			Value:  globalSettings.Name,
			Usage:  "Specify a name for this node. e.g. 'NodeA' or 'NodeB'",
			EnvVar: "name, n",
		},
		cli.StringFlag{
			Name:   "bootstrap_address, ba",
			Value:  globalSettings.BootstrapAddress,
			Usage:  "Specify a bootstrap address. e.g. '10.10.10.10:12345'",
			EnvVar: "bootstrap_address, ba",
		},
	}

	app.Run(os.Args)
}
<commit_msg>Default point to localhost 8080 for webcat<commit_after>package main

import (
	"github.com/urfave/cli"
	"os"
)

// settings for the server
type Settings struct {
	Directory          string
	ManagerAddress     string
	ManagerCredentials string
	ManagerEnabled     bool
	Address            string
	Name               string
	BootstrapAddress   string
}

var globalSettings Settings = Settings{
	Directory:          "",
	ManagerAddress:     "localhost:8080",
	ManagerCredentials: "replicat:isthecat",
	Address:            ":8001",
	Name:               "",
	BootstrapAddress:   ":8080",
}

func SetupCli() {

	app := cli.NewApp()
	app.Name = "Replicat"
	app.Usage = "rsync for the cloud"
	app.Action = func(c *cli.Context) error {
		globalSettings.Directory = c.GlobalString("directory")
		globalSettings.ManagerAddress = c.GlobalString("manager")
		globalSettings.ManagerCredentials = c.GlobalString("manager_credentials")
		globalSettings.Address = c.GlobalString("address")
		globalSettings.Name = c.GlobalString("name")
		globalSettings.BootstrapAddress = c.GlobalString("bootstrap_address")

		if globalSettings.Directory == "" {
			panic("directory is required to serve files\n")
		}

		if globalSettings.Name == "" {
			panic("Name is currently a required parameter. Name has to be one of the predefined names (e.g. NodeA, NodeB). This will improve.\n")
		}

		return nil
	}

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "directory, d",
			Value:  globalSettings.Directory,
			Usage:  "Specify a directory where the files to share are located.",
			EnvVar: "directory, d",
		},
		cli.StringFlag{
			Name:   "manager, m",
			Value:  globalSettings.ManagerAddress,
			Usage:  "Specify a host and port for reaching the manager",
			EnvVar: "manager, m",
		},
		cli.StringFlag{
			Name:   "manager_credentials, mc",
			Value:  globalSettings.ManagerCredentials,
			Usage:  "Specify a usernmae:password for login to the manager",
			EnvVar: "manager_credentials, mc",
		},
		cli.StringFlag{
			Name:   "address, a",
			Value:  globalSettings.Address,
			Usage:  "Specify a listen address for this node. e.g. '127.0.0.1:8000' or ':8000' for where updates are accepted from",
			EnvVar: "address, a",
		},
		cli.StringFlag{
			Name:   "name, n",
			Value:  globalSettings.Name,
			Usage:  "Specify a name for this node. e.g. 'NodeA' or 'NodeB'",
			EnvVar: "name, n",
		},
		cli.StringFlag{
			Name:   "bootstrap_address, ba",
			Value:  globalSettings.BootstrapAddress,
			Usage:  "Specify a bootstrap address. e.g. '10.10.10.10:12345'",
			EnvVar: "bootstrap_address, ba",
		},
	}

	app.Run(os.Args)
}
<|endoftext|>