<commit_before>// +build e2e

/*
Copyright 2019 The Tekton 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 test

import (
	"context"
	"fmt"
	"testing"

	"github.com/tektoncd/pipeline/test/parse"

	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1"
	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
	"github.com/tektoncd/pipeline/pkg/names"
	rbacv1 "k8s.io/api/rbac/v1beta1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	knativetest "knative.dev/pkg/test"
	"knative.dev/pkg/test/helpers"
)

var (
	clusterRoleBindings [1]*rbacv1.ClusterRoleBinding
)

// TestHelmDeployPipelineRun is an integration test that will verify a pipeline build an image
// and then using helm to deploy it
func TestHelmDeployPipelineRun(t *testing.T) {
	repo := ensureDockerRepo(t)
	ctx := context.Background()
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()
	c, namespace := setup(ctx, t)
	setupClusterBindingForHelm(ctx, c, t, namespace)

	var (
		sourceResourceName        = helpers.ObjectNameForTest(t)
		sourceImageName           = helpers.ObjectNameForTest(t)
		createImageTaskName       = helpers.ObjectNameForTest(t)
		helmDeployTaskName        = helpers.ObjectNameForTest(t)
		checkServiceTaskName      = helpers.ObjectNameForTest(t)
		helmDeployPipelineName    = helpers.ObjectNameForTest(t)
		helmDeployPipelineRunName = helpers.ObjectNameForTest(t)
	)

	knativetest.CleanupOnInterrupt(func() { tearDown(ctx, t, c, namespace) }, t.Logf)
	defer tearDown(ctx, t, c, namespace)

	t.Logf("Creating Git PipelineResource %s", sourceResourceName)
	if _, err := c.PipelineResourceClient.Create(ctx, getGoHelloworldGitResource(t, sourceResourceName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Pipeline Resource `%s`: %s", sourceResourceName, err)
	}

	t.Logf("Creating Image PipelineResource %s", sourceImageName)
	if _, err := c.PipelineResourceClient.Create(ctx, getHelmImageResource(t, repo, sourceImageName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Pipeline Resource `%s`: %s", sourceImageName, err)
	}

	t.Logf("Creating Task %s", createImageTaskName)
	if _, err := c.TaskClient.Create(ctx, getCreateImageTask(t, namespace, createImageTaskName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Task `%s`: %s", createImageTaskName, err)
	}

	t.Logf("Creating Task %s", helmDeployTaskName)
	if _, err := c.TaskClient.Create(ctx, getHelmDeployTask(t, namespace, helmDeployTaskName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Task `%s`: %s", helmDeployTaskName, err)
	}

	t.Logf("Creating Task %s", checkServiceTaskName)
	if _, err := c.TaskClient.Create(ctx, getCheckServiceTask(t, namespace, checkServiceTaskName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Task `%s`: %s", checkServiceTaskName, err)
	}

	t.Logf("Creating Pipeline %s", helmDeployPipelineName)
	if _, err := c.PipelineClient.Create(ctx, getHelmDeployPipeline(t, namespace, createImageTaskName, helmDeployTaskName, checkServiceTaskName, helmDeployPipelineName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Pipeline `%s`: %s", helmDeployPipelineName, err)
	}

	t.Logf("Creating PipelineRun %s", helmDeployPipelineRunName)
	if _, err := c.PipelineRunClient.Create(ctx, getHelmDeployPipelineRun(t, namespace, sourceResourceName, sourceImageName, helmDeployPipelineRunName, helmDeployPipelineName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Pipeline `%s`: %s", helmDeployPipelineRunName, err)
	}

	// Verify status of PipelineRun (wait for it)
	if err := WaitForPipelineRunState(ctx, c, helmDeployPipelineRunName, timeout, PipelineRunSucceed(helmDeployPipelineRunName), "PipelineRunCompleted"); err != nil {
		t.Errorf("Error waiting for PipelineRun %s to finish: %s", helmDeployPipelineRunName, err)
		t.Fatalf("PipelineRun execution failed; helm may or may not have been installed :(")
	}

	// cleanup task to remove helm releases from cluster and cluster role bindings, will not fail the test if it fails, just log
	knativetest.CleanupOnInterrupt(func() { helmCleanup(ctx, c, t, namespace) }, t.Logf)
	defer helmCleanup(ctx, c, t, namespace)
}

func getGoHelloworldGitResource(t *testing.T, sourceResourceName string) *v1alpha1.PipelineResource {
	return parse.MustParsePipelineResource(t, fmt.Sprintf(`
metadata:
  name: %s
spec:
  type: git
  params:
  - name: url
    value: https://github.com/tektoncd/pipeline
`, sourceResourceName))
}

func getHelmImageResource(t *testing.T, dockerRepo, sourceImageName string) *v1alpha1.PipelineResource {
	imageName := fmt.Sprintf("%s/%s", dockerRepo, names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(sourceImageName))

	return parse.MustParsePipelineResource(t, fmt.Sprintf(`
metadata:
  name: %s
spec:
  type: image
  params:
  - name: url
    value: %s
`, sourceImageName, imageName))
}

func getCreateImageTask(t *testing.T, namespace, createImageTaskName string) *v1beta1.Task {
	return parse.MustParseTask(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  resources:
    inputs:
    - name: gitsource
      type: git
    outputs:
    - name: builtimage
      type: image
  steps:
  - name: kaniko
    image: %s
    args: ['--dockerfile=/workspace/gitsource/test/gohelloworld/Dockerfile',
	  	   '--context=/workspace/gitsource/',
	  	   '--destination=$(outputs.resources.builtimage.url)']
`, createImageTaskName, namespace, getTestImage(kanikoImage)))
}

func getHelmDeployTask(t *testing.T, namespace, helmDeployTaskName string) *v1beta1.Task {
	return parse.MustParseTask(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  resources:
    inputs:
    - name: gitsource
      type: git
    - name: image
      type: image
  params:
  - name: pathToHelmCharts
    type: string
    description: 'Path to the helm charts'
  - name: chartname
    type: string
    default: ""
  steps:
  - image: alpine/helm:3.5.4
    args: ['upgrade',
		   '--wait',
		   '--debug',
		   '--install',
		   '--namespace',
		   '%s',
		   '$(inputs.params.chartname)',
		   '$(inputs.params.pathToHelmCharts)',
		   '--set',
		   'image.repository=$(inputs.resources.image.url)',
		   '--set',
		   'service.type=ClusterIP']
  - image: lachlanevenson/k8s-kubectl
    command: ['kubectl']
    args: ['get',
		   'all',
		   '--namespace',
		   '%s']
`, helmDeployTaskName, namespace, namespace, namespace))
}

func getCheckServiceTask(t *testing.T, namespace, checkServiceTaskName string) *v1beta1.Task {
	return parse.MustParseTask(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  params:
  - name: serviceUrl
    type: string
    description: 'Service url'
  steps:
  - image: %s
    args: ['-wait', '$(inputs.params.serviceUrl)', '-timeout', '1m']
`, checkServiceTaskName, namespace, getTestImage(dockerizeImage)))
}

func getHelmDeployPipeline(t *testing.T, namespace, createImageTaskName, helmDeployTaskName, checkServiceTaskName, helmDeployPipelineName string) *v1beta1.Pipeline {
	return parse.MustParsePipeline(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  params:
  - name: chartname
    type: string
  resources:
  - name: git-repo
    type: git
  - name: the-image
    type: image
  tasks:
  - name: push-image
    taskRef:
      name: %s
    resources:
      inputs:
      - name: gitsource
        resource: git-repo
      outputs:
      - name: builtimage
        resource: the-image
  - name: helm-deploy
    taskRef:
      name: %s
    resources:
      inputs:
      - name: gitsource
        resource: git-repo
      - name: image
        resource: the-image
    params:
    - name: pathToHelmCharts
      value: /workspace/gitsource/test/gohelloworld/gohelloworld-chart
    - name: chartname
      value: '$(params.chartname)'
  - name: check-service
    taskRef:
      name: %s
    params:
    - name: serviceUrl
      value: http://gohelloworld-chart:8080
    runAfter: ['helm-deploy']
`, helmDeployPipelineName, namespace, createImageTaskName, helmDeployTaskName, checkServiceTaskName))
}

func getHelmDeployPipelineRun(t *testing.T, namespace, sourceResourceName, sourceImageName, helmDeployPipelineRunName, helmDeployPipelineName string) *v1beta1.PipelineRun {
	return parse.MustParsePipelineRun(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  pipelineRef:
    name: %s
  params:
  - name: chartname
    value: gohelloworld
  resources:
  - name: git-repo
    resourceRef:
      name: %s
  - name: the-image
    resourceRef:
      name: %s
`, helmDeployPipelineRunName, namespace, helmDeployPipelineName, sourceResourceName, sourceImageName))
}

func setupClusterBindingForHelm(ctx context.Context, c *clients, t *testing.T, namespace string) {
	clusterRoleBindings[0] = &rbacv1.ClusterRoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name: names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("default-tiller"),
		},
		RoleRef: rbacv1.RoleRef{
			APIGroup: "rbac.authorization.k8s.io",
			Kind:     "ClusterRole",
			Name:     "cluster-admin",
		},
		Subjects: []rbacv1.Subject{{
			Kind:      "ServiceAccount",
			Name:      "default",
			Namespace: namespace,
		}},
	}

	for _, crb := range clusterRoleBindings {
		t.Logf("Creating Cluster Role binding %s for helm", crb.Name)
		if _, err := c.KubeClient.RbacV1beta1().ClusterRoleBindings().Create(ctx, crb, metav1.CreateOptions{}); err != nil {
			t.Fatalf("Failed to create cluster role binding for Helm %s", err)
		}
	}
}

func helmCleanup(ctx context.Context, c *clients, t *testing.T, namespace string) {
	t.Logf("Cleaning up helm from cluster...")

	removeAllHelmReleases(ctx, c, t, namespace)

	for _, crb := range clusterRoleBindings {
		t.Logf("Deleting Cluster Role binding %s for helm", crb.Name)
		if err := c.KubeClient.RbacV1beta1().ClusterRoleBindings().Delete(ctx, crb.Name, metav1.DeleteOptions{}); err != nil {
			t.Fatalf("Failed to delete cluster role binding for Helm %s", err)
		}
	}
}

func removeAllHelmReleases(ctx context.Context, c *clients, t *testing.T, namespace string) {
	helmRemoveAllTaskName := "helm-remove-all-task"
	helmRemoveAllTask := parse.MustParseTask(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  steps:
  - name: helm-remove-all
    image: alpine/helm:3.5.4
    command: ['/bin/sh']
    args: ['-c', 'helm ls --short --all --namespace %s | xargs -n1 helm delete --namespace %s']
`, helmRemoveAllTaskName, namespace, namespace, namespace))

	helmRemoveAllTaskRunName := "helm-remove-all-taskrun"
	helmRemoveAllTaskRun := parse.MustParseTaskRun(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  taskRef:
    name: %s
`, helmRemoveAllTaskRunName, namespace, helmRemoveAllTaskName))

	t.Logf("Creating Task %s", helmRemoveAllTaskName)
	if _, err := c.TaskClient.Create(ctx, helmRemoveAllTask, metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Task `%s`: %s", helmRemoveAllTaskName, err)
	}

	t.Logf("Creating TaskRun %s", helmRemoveAllTaskRunName)
	if _, err := c.TaskRunClient.Create(ctx, helmRemoveAllTaskRun, metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create TaskRun `%s`: %s", helmRemoveAllTaskRunName, err)
	}

	t.Logf("Waiting for TaskRun %s in namespace %s to complete", helmRemoveAllTaskRunName, namespace)
	if err := WaitForTaskRunState(ctx, c, helmRemoveAllTaskRunName, TaskRunSucceed(helmRemoveAllTaskRunName), "TaskRunSuccess"); err != nil {
		t.Logf("TaskRun %s failed to finish: %s", helmRemoveAllTaskRunName, err)
	}
}
<commit_msg>Updates helm task e2e test to use v1 rbac api<commit_after>// +build e2e

/*
Copyright 2019 The Tekton 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 test

import (
	"context"
	"fmt"
	"testing"

	"github.com/tektoncd/pipeline/test/parse"

	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1"
	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
	"github.com/tektoncd/pipeline/pkg/names"
	rbacv1 "k8s.io/api/rbac/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	knativetest "knative.dev/pkg/test"
	"knative.dev/pkg/test/helpers"
)

var (
	clusterRoleBindings [1]*rbacv1.ClusterRoleBinding
)

// TestHelmDeployPipelineRun is an integration test that will verify a pipeline build an image
// and then using helm to deploy it
func TestHelmDeployPipelineRun(t *testing.T) {
	repo := ensureDockerRepo(t)
	ctx := context.Background()
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()
	c, namespace := setup(ctx, t)
	setupClusterBindingForHelm(ctx, c, t, namespace)

	var (
		sourceResourceName        = helpers.ObjectNameForTest(t)
		sourceImageName           = helpers.ObjectNameForTest(t)
		createImageTaskName       = helpers.ObjectNameForTest(t)
		helmDeployTaskName        = helpers.ObjectNameForTest(t)
		checkServiceTaskName      = helpers.ObjectNameForTest(t)
		helmDeployPipelineName    = helpers.ObjectNameForTest(t)
		helmDeployPipelineRunName = helpers.ObjectNameForTest(t)
	)

	knativetest.CleanupOnInterrupt(func() { tearDown(ctx, t, c, namespace) }, t.Logf)
	defer tearDown(ctx, t, c, namespace)

	t.Logf("Creating Git PipelineResource %s", sourceResourceName)
	if _, err := c.PipelineResourceClient.Create(ctx, getGoHelloworldGitResource(t, sourceResourceName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Pipeline Resource `%s`: %s", sourceResourceName, err)
	}

	t.Logf("Creating Image PipelineResource %s", sourceImageName)
	if _, err := c.PipelineResourceClient.Create(ctx, getHelmImageResource(t, repo, sourceImageName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Pipeline Resource `%s`: %s", sourceImageName, err)
	}

	t.Logf("Creating Task %s", createImageTaskName)
	if _, err := c.TaskClient.Create(ctx, getCreateImageTask(t, namespace, createImageTaskName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Task `%s`: %s", createImageTaskName, err)
	}

	t.Logf("Creating Task %s", helmDeployTaskName)
	if _, err := c.TaskClient.Create(ctx, getHelmDeployTask(t, namespace, helmDeployTaskName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Task `%s`: %s", helmDeployTaskName, err)
	}

	t.Logf("Creating Task %s", checkServiceTaskName)
	if _, err := c.TaskClient.Create(ctx, getCheckServiceTask(t, namespace, checkServiceTaskName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Task `%s`: %s", checkServiceTaskName, err)
	}

	t.Logf("Creating Pipeline %s", helmDeployPipelineName)
	if _, err := c.PipelineClient.Create(ctx, getHelmDeployPipeline(t, namespace, createImageTaskName, helmDeployTaskName, checkServiceTaskName, helmDeployPipelineName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Pipeline `%s`: %s", helmDeployPipelineName, err)
	}

	t.Logf("Creating PipelineRun %s", helmDeployPipelineRunName)
	if _, err := c.PipelineRunClient.Create(ctx, getHelmDeployPipelineRun(t, namespace, sourceResourceName, sourceImageName, helmDeployPipelineRunName, helmDeployPipelineName), metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Pipeline `%s`: %s", helmDeployPipelineRunName, err)
	}

	// Verify status of PipelineRun (wait for it)
	if err := WaitForPipelineRunState(ctx, c, helmDeployPipelineRunName, timeout, PipelineRunSucceed(helmDeployPipelineRunName), "PipelineRunCompleted"); err != nil {
		t.Errorf("Error waiting for PipelineRun %s to finish: %s", helmDeployPipelineRunName, err)
		t.Fatalf("PipelineRun execution failed; helm may or may not have been installed :(")
	}

	// cleanup task to remove helm releases from cluster and cluster role bindings, will not fail the test if it fails, just log
	knativetest.CleanupOnInterrupt(func() { helmCleanup(ctx, c, t, namespace) }, t.Logf)
	defer helmCleanup(ctx, c, t, namespace)
}

func getGoHelloworldGitResource(t *testing.T, sourceResourceName string) *v1alpha1.PipelineResource {
	return parse.MustParsePipelineResource(t, fmt.Sprintf(`
metadata:
  name: %s
spec:
  type: git
  params:
  - name: url
    value: https://github.com/tektoncd/pipeline
`, sourceResourceName))
}

func getHelmImageResource(t *testing.T, dockerRepo, sourceImageName string) *v1alpha1.PipelineResource {
	imageName := fmt.Sprintf("%s/%s", dockerRepo, names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(sourceImageName))

	return parse.MustParsePipelineResource(t, fmt.Sprintf(`
metadata:
  name: %s
spec:
  type: image
  params:
  - name: url
    value: %s
`, sourceImageName, imageName))
}

func getCreateImageTask(t *testing.T, namespace, createImageTaskName string) *v1beta1.Task {
	return parse.MustParseTask(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  resources:
    inputs:
    - name: gitsource
      type: git
    outputs:
    - name: builtimage
      type: image
  steps:
  - name: kaniko
    image: %s
    args: ['--dockerfile=/workspace/gitsource/test/gohelloworld/Dockerfile',
	  	   '--context=/workspace/gitsource/',
	  	   '--destination=$(outputs.resources.builtimage.url)']
`, createImageTaskName, namespace, getTestImage(kanikoImage)))
}

func getHelmDeployTask(t *testing.T, namespace, helmDeployTaskName string) *v1beta1.Task {
	return parse.MustParseTask(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  resources:
    inputs:
    - name: gitsource
      type: git
    - name: image
      type: image
  params:
  - name: pathToHelmCharts
    type: string
    description: 'Path to the helm charts'
  - name: chartname
    type: string
    default: ""
  steps:
  - image: alpine/helm:3.5.4
    args: ['upgrade',
		   '--wait',
		   '--debug',
		   '--install',
		   '--namespace',
		   '%s',
		   '$(inputs.params.chartname)',
		   '$(inputs.params.pathToHelmCharts)',
		   '--set',
		   'image.repository=$(inputs.resources.image.url)',
		   '--set',
		   'service.type=ClusterIP']
  - image: lachlanevenson/k8s-kubectl
    command: ['kubectl']
    args: ['get',
		   'all',
		   '--namespace',
		   '%s']
`, helmDeployTaskName, namespace, namespace, namespace))
}

func getCheckServiceTask(t *testing.T, namespace, checkServiceTaskName string) *v1beta1.Task {
	return parse.MustParseTask(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  params:
  - name: serviceUrl
    type: string
    description: 'Service url'
  steps:
  - image: %s
    args: ['-wait', '$(inputs.params.serviceUrl)', '-timeout', '1m']
`, checkServiceTaskName, namespace, getTestImage(dockerizeImage)))
}

func getHelmDeployPipeline(t *testing.T, namespace, createImageTaskName, helmDeployTaskName, checkServiceTaskName, helmDeployPipelineName string) *v1beta1.Pipeline {
	return parse.MustParsePipeline(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  params:
  - name: chartname
    type: string
  resources:
  - name: git-repo
    type: git
  - name: the-image
    type: image
  tasks:
  - name: push-image
    taskRef:
      name: %s
    resources:
      inputs:
      - name: gitsource
        resource: git-repo
      outputs:
      - name: builtimage
        resource: the-image
  - name: helm-deploy
    taskRef:
      name: %s
    resources:
      inputs:
      - name: gitsource
        resource: git-repo
      - name: image
        resource: the-image
    params:
    - name: pathToHelmCharts
      value: /workspace/gitsource/test/gohelloworld/gohelloworld-chart
    - name: chartname
      value: '$(params.chartname)'
  - name: check-service
    taskRef:
      name: %s
    params:
    - name: serviceUrl
      value: http://gohelloworld-chart:8080
    runAfter: ['helm-deploy']
`, helmDeployPipelineName, namespace, createImageTaskName, helmDeployTaskName, checkServiceTaskName))
}

func getHelmDeployPipelineRun(t *testing.T, namespace, sourceResourceName, sourceImageName, helmDeployPipelineRunName, helmDeployPipelineName string) *v1beta1.PipelineRun {
	return parse.MustParsePipelineRun(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  pipelineRef:
    name: %s
  params:
  - name: chartname
    value: gohelloworld
  resources:
  - name: git-repo
    resourceRef:
      name: %s
  - name: the-image
    resourceRef:
      name: %s
`, helmDeployPipelineRunName, namespace, helmDeployPipelineName, sourceResourceName, sourceImageName))
}

func setupClusterBindingForHelm(ctx context.Context, c *clients, t *testing.T, namespace string) {
	clusterRoleBindings[0] = &rbacv1.ClusterRoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name: names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("default-tiller"),
		},
		RoleRef: rbacv1.RoleRef{
			APIGroup: "rbac.authorization.k8s.io",
			Kind:     "ClusterRole",
			Name:     "cluster-admin",
		},
		Subjects: []rbacv1.Subject{{
			Kind:      "ServiceAccount",
			Name:      "default",
			Namespace: namespace,
		}},
	}

	for _, crb := range clusterRoleBindings {
		t.Logf("Creating Cluster Role binding %s for helm", crb.Name)
		if _, err := c.KubeClient.RbacV1().ClusterRoleBindings().Create(ctx, crb, metav1.CreateOptions{}); err != nil {
			t.Fatalf("Failed to create cluster role binding for Helm %s", err)
		}
	}
}

func helmCleanup(ctx context.Context, c *clients, t *testing.T, namespace string) {
	t.Logf("Cleaning up helm from cluster...")

	removeAllHelmReleases(ctx, c, t, namespace)

	for _, crb := range clusterRoleBindings {
		t.Logf("Deleting Cluster Role binding %s for helm", crb.Name)
		if err := c.KubeClient.RbacV1().ClusterRoleBindings().Delete(ctx, crb.Name, metav1.DeleteOptions{}); err != nil {
			t.Fatalf("Failed to delete cluster role binding for Helm %s", err)
		}
	}
}

func removeAllHelmReleases(ctx context.Context, c *clients, t *testing.T, namespace string) {
	helmRemoveAllTaskName := "helm-remove-all-task"
	helmRemoveAllTask := parse.MustParseTask(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  steps:
  - name: helm-remove-all
    image: alpine/helm:3.5.4
    command: ['/bin/sh']
    args: ['-c', 'helm ls --short --all --namespace %s | xargs -n1 helm delete --namespace %s']
`, helmRemoveAllTaskName, namespace, namespace, namespace))

	helmRemoveAllTaskRunName := "helm-remove-all-taskrun"
	helmRemoveAllTaskRun := parse.MustParseTaskRun(t, fmt.Sprintf(`
metadata:
  name: %s
  namespace: %s
spec:
  taskRef:
    name: %s
`, helmRemoveAllTaskRunName, namespace, helmRemoveAllTaskName))

	t.Logf("Creating Task %s", helmRemoveAllTaskName)
	if _, err := c.TaskClient.Create(ctx, helmRemoveAllTask, metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create Task `%s`: %s", helmRemoveAllTaskName, err)
	}

	t.Logf("Creating TaskRun %s", helmRemoveAllTaskRunName)
	if _, err := c.TaskRunClient.Create(ctx, helmRemoveAllTaskRun, metav1.CreateOptions{}); err != nil {
		t.Fatalf("Failed to create TaskRun `%s`: %s", helmRemoveAllTaskRunName, err)
	}

	t.Logf("Waiting for TaskRun %s in namespace %s to complete", helmRemoveAllTaskRunName, namespace)
	if err := WaitForTaskRunState(ctx, c, helmRemoveAllTaskRunName, TaskRunSucceed(helmRemoveAllTaskRunName), "TaskRunSuccess"); err != nil {
		t.Logf("TaskRun %s failed to finish: %s", helmRemoveAllTaskRunName, err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 The ACH Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package ach

import (
	"testing"
)

// TODO make all the mock values cor fields

// mockBatchCORHeader creates a COR BatchHeader
func mockBatchCORHeader() *BatchHeader {
	bh := NewBatchHeader()
	bh.ServiceClassCode = 220
	bh.StandardEntryClassCode = "COR"
	bh.CompanyName = "Your Company, inc"
	bh.CompanyIdentification = "121042882"
	bh.CompanyEntryDescription = "Vendor Pay"
	bh.ODFIIdentification = "121042882"
	return bh
}

// mockCOREntryDetail creates a COR EntryDetail
func mockCOREntryDetail() *EntryDetail {
	entry := NewEntryDetail()
	entry.TransactionCode = 21
	entry.SetRDFI("231380104")
	entry.DFIAccountNumber = "744-5678-99"
	entry.Amount = 0
	entry.IdentificationNumber = "location #23"
	entry.SetReceivingCompany("Best Co. #23")
	entry.SetTraceNumber(mockBatchCORHeader().ODFIIdentification, 1)
	entry.DiscretionaryData = "S"
	return entry
}

//  mockBatchCOR creates a BatchCOR
func mockBatchCOR() *BatchCOR {
	mockBatch := NewBatchCOR(mockBatchCORHeader())
	mockBatch.AddEntry(mockCOREntryDetail())
	mockBatch.GetEntries()[0].AddAddenda(mockAddenda98())
	if err := mockBatch.Create(); err != nil {
		panic(err)
	}
	return mockBatch
}

// testBatchCORHeader creates a COR BatchHeader
func testBatchCORHeader(t testing.TB) {
	batch, _ := NewBatch(mockBatchCORHeader())

	_, ok := batch.(*BatchCOR)
	if !ok {
		t.Error("Expecting BachCOR")
	}
}

// TestBatchCORHeader tests creating a COR BatchHeader
func TestBatchCORHeader(t *testing.T) {
	testBatchCORHeader(t)
}

// BenchmarkBatchCORHeader benchmarks creating a COR BatchHeader
func BenchmarkBatchCORHeader(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORHeader(b)
	}
}

// testBatchCORSEC validates BatchCOR SEC code
func testBatchCORSEC(t testing.TB) {
	mockBatch := mockBatchCOR()
	mockBatch.Header.StandardEntryClassCode = "COR"
	if err := mockBatch.Validate(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "StandardEntryClassCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORSEC tests validating BatchCOR SEC code
func TestBatchCORSEC(t *testing.T) {
	testBatchCORSEC(t)
}

// BenchmarkBatchCORSEC benchmarks validating BatchCOR SEC code
func BenchmarkBatchCORSEC(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORSEC(b)
	}
}

//  testBatchCORAddendumCountTwo validates Addendum count of 2
func testBatchCORAddendumCountTwo(t testing.TB) {
	mockBatch := mockBatchCOR()
	// Adding a second addenda to the mock entry
	mockBatch.GetEntries()[0].AddAddenda(mockAddenda98())
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "Addendum" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORAddendumCountTwo tests validating Addendum count of 2
func TestBatchCORAddendumCountTwo(t *testing.T) {
	testBatchCORAddendumCountTwo(t)
}

// BenchmarkBatchCORAddendumCountTwo benchmarks validating Addendum count of 2
func BenchmarkBatchCORAddendumCountTwo(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORAddendumCountTwo(b)
	}
}

// testBatchCORAddendaCountZero validates Addendum count of 0
func testBatchCORAddendaCountZero(t testing.TB) {
	mockBatch := NewBatchCOR(mockBatchCORHeader())
	mockBatch.AddEntry(mockCOREntryDetail())
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "Addendum" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORAddendaCountZero tests validating Addendum count of 0
func TestBatchCORAddendaCountZero(t *testing.T) {
	testBatchCORAddendaCountZero(t)
}

// BenchmarkBatchCORAddendaCountZero benchmarks validating Addendum count of 0
func BenchmarkBatchCORAddendaCountZero(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORAddendaCountZero(b)
	}
}

// testBatchCORAddendaType validates that Addendum is of type Addenda98
func testBatchCORAddendaType(t testing.TB) {
	mockBatch := NewBatchCOR(mockBatchCORHeader())
	mockBatch.AddEntry(mockCOREntryDetail())
	mockBatch.GetEntries()[0].AddAddenda(mockAddenda05())
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "Addendum" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORAddendaType tests validating that Addendum is of type Addenda98
func TestBatchCORAddendaType(t *testing.T) {
	testBatchCORAddendaType(t)
}

// BenchmarkBatchCORAddendaType benchmarks validating that Addendum is of type Addenda98
func BenchmarkBatchCORAddendaType(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORAddendaType(b)
	}
}

// testBatchCORAddendaTypeCode validates TypeCode
func testBatchCORAddendaTypeCode(t testing.TB) {
	mockBatch := mockBatchCOR()
	mockBatch.GetEntries()[0].Addendum[0].(*Addenda98).typeCode = "07"
	if err := mockBatch.Validate(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "TypeCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORAddendaTypeCode tests validating TypeCode
func TestBatchCORAddendaTypeCode(t *testing.T) {
	testBatchCORAddendaTypeCode(t)
}

// BenchmarkBatchCORAddendaTypeCode benchmarks validating TypeCode
func BenchmarkBatchCORAddendaTypeCode(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORAddendaTypeCode(b)
	}
}

// testBatchCORAmount validates BatchCOR Amount
func testBatchCORAmount(t testing.TB) {
	mockBatch := mockBatchCOR()
	mockBatch.GetEntries()[0].Amount = 9999
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "Amount" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORAmount tests validating BatchCOR Amount
func TestBatchCORAmount(t *testing.T) {
	testBatchCORAmount(t)
}

// BenchmarkBatchCORAmount benchmarks validating BatchCOR Amount
func BenchmarkBatchCORAmount(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORAmount(b)
	}
}

// testBatchCORTransactionCode27 validates BatchCOR TransactionCode 27 returns an error
func testBatchCORTransactionCode27(t testing.TB) {
	mockBatch := mockBatchCOR()
	mockBatch.GetEntries()[0].TransactionCode = 27
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "TransactionCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORTransactionCode27 tests validating BatchCOR TransactionCode 27 returns an error
func TestBatchCORTransactionCode27(t *testing.T) {
	testBatchCORTransactionCode27(t)
}

// BenchmarkBatchCORTransactionCode27 benchmarks validating
// BatchCOR TransactionCode 27 returns an error
func BenchmarkBatchCORTransactionCode27(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORTransactionCode27(b)
	}
}

// testBatchCORTransactionCode21 validates BatchCOR TransactionCode 21
func testBatchCORTransactionCode21(t testing.TB) {
	mockBatch := mockBatchCOR()
	mockBatch.GetEntries()[0].TransactionCode = 21
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "TransactionCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORTransactionCode21 tests validating BatchCOR TransactionCode 21
func TestBatchCORTransactionCode21(t *testing.T) {
	testBatchCORTransactionCode21(t)
}

// BenchmarkBatchCORTransactionCode21 benchmarks validating BatchCOR TransactionCode 21
func BenchmarkBatchCORTransactionCode21(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORTransactionCode21(b)
	}
}

// testBatchCORCreate creates BatchCOR
func testBatchCORCreate(t testing.TB) {
	mockBatch := mockBatchCOR()
	// Must have valid batch header to create a Batch
	mockBatch.GetHeader().ServiceClassCode = 63
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.FieldName != "ServiceClassCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORCreate tests creating BatchCOR
func TestBatchCORCreate(t *testing.T) {
	testBatchCORCreate(t)
}

// BenchmarkBatchCORCreate benchmarks creating BatchCOR
func BenchmarkBatchCORCreate(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORCreate(b)
	}
}
<commit_msg>batchCOR code coverage 100%<commit_after>// Copyright 2018 The ACH Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package ach

import (
	"testing"
)

// TODO make all the mock values cor fields

// mockBatchCORHeader creates a COR BatchHeader
func mockBatchCORHeader() *BatchHeader {
	bh := NewBatchHeader()
	bh.ServiceClassCode = 220
	bh.StandardEntryClassCode = "COR"
	bh.CompanyName = "Your Company, inc"
	bh.CompanyIdentification = "121042882"
	bh.CompanyEntryDescription = "Vendor Pay"
	bh.ODFIIdentification = "121042882"
	return bh
}

// mockCOREntryDetail creates a COR EntryDetail
func mockCOREntryDetail() *EntryDetail {
	entry := NewEntryDetail()
	entry.TransactionCode = 21
	entry.SetRDFI("231380104")
	entry.DFIAccountNumber = "744-5678-99"
	entry.Amount = 0
	entry.IdentificationNumber = "location #23"
	entry.SetReceivingCompany("Best Co. #23")
	entry.SetTraceNumber(mockBatchCORHeader().ODFIIdentification, 1)
	entry.DiscretionaryData = "S"
	return entry
}

//  mockBatchCOR creates a BatchCOR
func mockBatchCOR() *BatchCOR {
	mockBatch := NewBatchCOR(mockBatchCORHeader())
	mockBatch.AddEntry(mockCOREntryDetail())
	mockBatch.GetEntries()[0].AddAddenda(mockAddenda98())
	if err := mockBatch.Create(); err != nil {
		panic(err)
	}
	return mockBatch
}

// testBatchCORHeader creates a COR BatchHeader
func testBatchCORHeader(t testing.TB) {
	batch, _ := NewBatch(mockBatchCORHeader())

	_, ok := batch.(*BatchCOR)
	if !ok {
		t.Error("Expecting BachCOR")
	}
}

// TestBatchCORHeader tests creating a COR BatchHeader
func TestBatchCORHeader(t *testing.T) {
	testBatchCORHeader(t)
}

// BenchmarkBatchCORHeader benchmarks creating a COR BatchHeader
func BenchmarkBatchCORHeader(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORHeader(b)
	}
}

// testBatchCORSEC validates BatchCOR SEC code
func testBatchCORSEC(t testing.TB) {
	mockBatch := mockBatchCOR()
	mockBatch.Header.StandardEntryClassCode = "WEB"
	if err := mockBatch.Validate(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "StandardEntryClassCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORSEC tests validating BatchCOR SEC code
func TestBatchCORSEC(t *testing.T) {
	testBatchCORSEC(t)
}

// BenchmarkBatchCORSEC benchmarks validating BatchCOR SEC code
func BenchmarkBatchCORSEC(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORSEC(b)
	}
}

//  testBatchCORAddendumCountTwo validates Addendum count of 2
func testBatchCORAddendumCountTwo(t testing.TB) {
	mockBatch := mockBatchCOR()
	// Adding a second addenda to the mock entry
	mockBatch.GetEntries()[0].AddAddenda(mockAddenda98())
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "Addendum" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORAddendumCountTwo tests validating Addendum count of 2
func TestBatchCORAddendumCountTwo(t *testing.T) {
	testBatchCORAddendumCountTwo(t)
}

// BenchmarkBatchCORAddendumCountTwo benchmarks validating Addendum count of 2
func BenchmarkBatchCORAddendumCountTwo(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORAddendumCountTwo(b)
	}
}

// testBatchCORAddendaCountZero validates Addendum count of 0
func testBatchCORAddendaCountZero(t testing.TB) {
	mockBatch := NewBatchCOR(mockBatchCORHeader())
	mockBatch.AddEntry(mockCOREntryDetail())
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "Addendum" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORAddendaCountZero tests validating Addendum count of 0
func TestBatchCORAddendaCountZero(t *testing.T) {
	testBatchCORAddendaCountZero(t)
}

// BenchmarkBatchCORAddendaCountZero benchmarks validating Addendum count of 0
func BenchmarkBatchCORAddendaCountZero(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORAddendaCountZero(b)
	}
}

// testBatchCORAddendaType validates that Addendum is of type Addenda98
func testBatchCORAddendaType(t testing.TB) {
	mockBatch := NewBatchCOR(mockBatchCORHeader())
	mockBatch.AddEntry(mockCOREntryDetail())
	mockBatch.GetEntries()[0].AddAddenda(mockAddenda05())
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "Addendum" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORAddendaType tests validating that Addendum is of type Addenda98
func TestBatchCORAddendaType(t *testing.T) {
	testBatchCORAddendaType(t)
}

// BenchmarkBatchCORAddendaType benchmarks validating that Addendum is of type Addenda98
func BenchmarkBatchCORAddendaType(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORAddendaType(b)
	}
}

// testBatchCORAddendaTypeCode validates TypeCode
func testBatchCORAddendaTypeCode(t testing.TB) {
	mockBatch := mockBatchCOR()
	mockBatch.GetEntries()[0].Addendum[0].(*Addenda98).typeCode = "07"
	if err := mockBatch.Validate(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "TypeCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORAddendaTypeCode tests validating TypeCode
func TestBatchCORAddendaTypeCode(t *testing.T) {
	testBatchCORAddendaTypeCode(t)
}

// BenchmarkBatchCORAddendaTypeCode benchmarks validating TypeCode
func BenchmarkBatchCORAddendaTypeCode(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORAddendaTypeCode(b)
	}
}

// testBatchCORAmount validates BatchCOR Amount
func testBatchCORAmount(t testing.TB) {
	mockBatch := mockBatchCOR()
	mockBatch.GetEntries()[0].Amount = 9999
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "Amount" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORAmount tests validating BatchCOR Amount
func TestBatchCORAmount(t *testing.T) {
	testBatchCORAmount(t)
}

// BenchmarkBatchCORAmount benchmarks validating BatchCOR Amount
func BenchmarkBatchCORAmount(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORAmount(b)
	}
}

// testBatchCORTransactionCode27 validates BatchCOR TransactionCode 27 returns an error
func testBatchCORTransactionCode27(t testing.TB) {
	mockBatch := mockBatchCOR()
	mockBatch.GetEntries()[0].TransactionCode = 27
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "TransactionCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORTransactionCode27 tests validating BatchCOR TransactionCode 27 returns an error
func TestBatchCORTransactionCode27(t *testing.T) {
	testBatchCORTransactionCode27(t)
}

// BenchmarkBatchCORTransactionCode27 benchmarks validating
// BatchCOR TransactionCode 27 returns an error
func BenchmarkBatchCORTransactionCode27(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORTransactionCode27(b)
	}
}

// testBatchCORTransactionCode21 validates BatchCOR TransactionCode 21
func testBatchCORTransactionCode21(t testing.TB) {
	mockBatch := mockBatchCOR()
	mockBatch.GetEntries()[0].TransactionCode = 21
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "TransactionCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORTransactionCode21 tests validating BatchCOR TransactionCode 21
func TestBatchCORTransactionCode21(t *testing.T) {
	testBatchCORTransactionCode21(t)
}

// BenchmarkBatchCORTransactionCode21 benchmarks validating BatchCOR TransactionCode 21
func BenchmarkBatchCORTransactionCode21(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORTransactionCode21(b)
	}
}

// testBatchCORCreate creates BatchCOR
func testBatchCORCreate(t testing.TB) {
	mockBatch := mockBatchCOR()
	// Must have valid batch header to create a Batch
	mockBatch.GetHeader().ServiceClassCode = 63
	if err := mockBatch.Create(); err != nil {
		if e, ok := err.(*FieldError); ok {
			if e.FieldName != "ServiceClassCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORCreate tests creating BatchCOR
func TestBatchCORCreate(t *testing.T) {
	testBatchCORCreate(t)
}

// BenchmarkBatchCORCreate benchmarks creating BatchCOR
func BenchmarkBatchCORCreate(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORCreate(b)
	}
}

// testBatchCORServiceClassCodeEquality validates service class code equality
func testBatchCORServiceClassCodeEquality(t testing.TB) {
	mockBatch := mockBatchCOR()
	mockBatch.GetControl().ServiceClassCode = 200
	if err := mockBatch.Validate(); err != nil {
		if e, ok := err.(*BatchError); ok {
			if e.FieldName != "ServiceClassCode" {
				t.Errorf("%T: %s", err, err)
			}
		} else {
			t.Errorf("%T: %s", err, err)
		}
	}
}

// TestBatchCORServiceClassCodeEquality tests validating service class code equality
func TestBatchCORServiceClassCodeEquality(t *testing.T) {
	testBatchCORServiceClassCodeEquality(t)
}

// BenchmarkBatchCORServiceClassCodeEquality benchmarks validating service class code equality
func BenchmarkBatchCORServiceClassCodeEquality(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		testBatchCORServiceClassCodeEquality(b)
	}
}
<|endoftext|>


<commit_before><commit_msg>gosh: Stop special-casing propagate output in BuildGoPkg<commit_after><|endoftext|>


<commit_before><commit_msg>feat: new user function<commit_after><|endoftext|>


<commit_before><commit_msg>Version<commit_after><|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"

	"github.com/prometheus/client_golang/prometheus"
)

func init() {
	RegisterExporter("memory", newExporterMemory)
}

var (
	memoryLabels = []string{"cluster", "node"}

	memoryGaugeVec = map[string]*prometheus.GaugeVec{
		"memory.allocated_unused": newGaugeVec(
			"memory_allocated_unused_bytes",
			"memory preallocated by the runtime (VM allocators) but not yet used",
			memoryLabels,
		),
		"memory.atom": newGaugeVec(
			"memory_atom_bytes",
			"memory used by atoms. Should be fairly constant",
			memoryLabels,
		),
		"memory.binary": newGaugeVec(
			"memory_binary_bytes",
			"memory used by shared binary data in the runtime. Most of this memory is message bodies and metadata.)",
			memoryLabels,
		),
		"memory.code": newGaugeVec(
			"memory_code_bytes",
			"memory used by code (bytecode, module metadata). This section is usually fairly constant and relatively small (unless the node is entirely blank and stores no data).",
			memoryLabels,
		),
		"memory.connection_channels": newGaugeVec(
			"memory_connection_channels_bytes",
			"memory used by client connections - channels",
			memoryLabels,
		),
		"memory.connection_other": newGaugeVec(
			"memory_connection_other_bytes",
			"memory used by client connection - other",
			memoryLabels,
		),
		"memory.connection_readers_bytes": newGaugeVec(
			"memory_connection_readers",
			"memory used by processes responsible for connection parser and most of connection state. Most of their memory attributes to TCP buffers",
			memoryLabels,
		),
		"memory.connection_writers": newGaugeVec(
			"memory_connection_writers_bytes",
			"memory used by processes responsible for serialization of outgoing protocol frames and writing to client connections socktes",
			memoryLabels,
		),
		"memory.metrics": newGaugeVec(
			"memory_metrics_bytes",
			"node-local metrics. The more connections, channels, queues are node hosts, the more stats there are to collect and keep",
			memoryLabels,
		),
		"memory.mgmt_db": newGaugeVec(
			"memory_mgmt_db_bytes",
			"management DB ETS tables + processes",
			memoryLabels,
		),
		"memory.mnesia": newGaugeVec(
			"memory_mnesia_bytes",
			"internal database (Mnesia) tables keep an in-memory copy of all its data (even on disc nodes)",
			memoryLabels,
		),
		"memory.msg_index": newGaugeVec(
			"memory_msg_index_bytes",
			"message index ETS + processes",
			memoryLabels,
		),
		"memory.other_ets": newGaugeVec(
			"memory_other_ets_bytes",
			"other in-memory tables besides those belonging to the stats database and internal database tables",
			memoryLabels,
		),
		"memory.other_proc": newGaugeVec(
			"memory_other_proc_bytes",
			"memory used by all other processes that RabbitMQ cannot categorise",
			memoryLabels,
		),
		"memory.other_system": newGaugeVec(
			"memory_other_system_bytes",
			"memory used by all other system that RabbitMQ cannot categorise",
			memoryLabels,
		),
		"memory.plugins": newGaugeVec(
			"memory_plugins_bytes",
			"memory used by plugins (apart from the Erlang client which is counted under Connections, and the management database which is counted separately). ",
			memoryLabels,
		),
		"memory.queue_procs": newGaugeVec(
			"memory_queue_procs_bytes",
			"memory used by class queue masters, queue indices, queue state",
			memoryLabels,
		),
		"memory.queue_slave_procs": newGaugeVec(
			"memory_queue_slave_procs_bytes",
			"memory used by class queue mirrors, queue indices, queue state",
			memoryLabels,
		),
		"memory.reserved_unallocated": newGaugeVec(
			"memory_reserved_unallocated_bytes",
			"memory preallocated/reserved by the kernel but not the runtime",
			memoryLabels,
		),
		"memory.total": newGaugeVec(
			"memory_total_bytes",
			"total memory",
			memoryLabels,
		),
	}
)

type exporterMemory struct {
	memoryMetricsGauge map[string]*prometheus.GaugeVec
}

func newExporterMemory() Exporter {
	memoryGaugeVecActual := memoryGaugeVec

	if len(config.ExcludeMetrics) > 0 {
		for _, metric := range config.ExcludeMetrics {
			if memoryGaugeVecActual[metric] != nil {
				delete(memoryGaugeVecActual, metric)
			}
		}
	}

	return exporterMemory{
		memoryMetricsGauge: memoryGaugeVecActual,
	}
}

func (e exporterMemory) Collect(ctx context.Context, ch chan<- prometheus.Metric) error {
	for _, gauge := range e.memoryMetricsGauge {
		gauge.Reset()
	}
	selfNode := ""
	if n, ok := ctx.Value(nodeName).(string); ok {
		selfNode = n
	}
	cluster := ""
	if n, ok := ctx.Value(clusterName).(string); ok {
		cluster = n
	}
	rabbitMemoryResponses, err := getMetricMap(config, fmt.Sprintf("nodes/%s/memory", selfNode))
	if err != nil {
		return err
	}
	for key, gauge := range e.memoryMetricsGauge {
		if value, ok := rabbitMemoryResponses[key]; ok {
			gauge.WithLabelValues(cluster, selfNode).Set(value)
		}
	}
	for _, gauge := range e.memoryMetricsGauge {
		gauge.Collect(ch)
	}
	return nil
}

func (e exporterMemory) Describe(ch chan<- *prometheus.Desc) {
	for _, gauge := range e.memoryMetricsGauge {
		gauge.Describe(ch)
	}
}
<commit_msg>Scrape memory breakdown from every nodes in cluster<commit_after>package main

import (
	"context"
	"fmt"

	"github.com/prometheus/client_golang/prometheus"
)

func init() {
	RegisterExporter("memory", newExporterMemory)
}

var (
	memoryLabels = []string{"cluster", "node", "self"}

	memoryGaugeVec = map[string]*prometheus.GaugeVec{
		"memory.allocated_unused": newGaugeVec(
			"memory_allocated_unused_bytes",
			"Memory preallocated by the runtime (VM allocators) but not yet used",
			memoryLabels,
		),
		"memory.atom": newGaugeVec(
			"memory_atom_bytes",
			"Memory used by atoms. Should be fairly constant",
			memoryLabels,
		),
		"memory.binary": newGaugeVec(
			"memory_binary_bytes",
			"Memory used by shared binary data in the runtime. Most of this memory is message bodies and metadata.)",
			memoryLabels,
		),
		"memory.code": newGaugeVec(
			"memory_code_bytes",
			"Memory used by code (bytecode, module metadata). This section is usually fairly constant and relatively small (unless the node is entirely blank and stores no data).",
			memoryLabels,
		),
		"memory.connection_channels": newGaugeVec(
			"memory_connection_channels_bytes",
			"Memory used by client connections - channels",
			memoryLabels,
		),
		"memory.connection_other": newGaugeVec(
			"memory_connection_other_bytes",
			"Memory used by client connection - other",
			memoryLabels,
		),
		"memory.connection_readers_bytes": newGaugeVec(
			"memory_connection_readers",
			"Memory used by processes responsible for connection parser and most of connection state. Most of their memory attributes to TCP buffers",
			memoryLabels,
		),
		"memory.connection_writers": newGaugeVec(
			"memory_connection_writers_bytes",
			"Memory used by processes responsible for serialization of outgoing protocol frames and writing to client connections socktes",
			memoryLabels,
		),
		"memory.metrics": newGaugeVec(
			"memory_metrics_bytes",
			"Node-local metrics. The more connections, channels, queues are node hosts, the more stats there are to collect and keep",
			memoryLabels,
		),
		"memory.mgmt_db": newGaugeVec(
			"memory_mgmt_db_bytes",
			"Management DB ETS tables + processes",
			memoryLabels,
		),
		"memory.mnesia": newGaugeVec(
			"memory_mnesia_bytes",
			"Internal database (Mnesia) tables keep an in-memory copy of all its data (even on disc nodes)",
			memoryLabels,
		),
		"memory.msg_index": newGaugeVec(
			"memory_msg_index_bytes",
			"Message index ETS + processes",
			memoryLabels,
		),
		"memory.other_ets": newGaugeVec(
			"memory_other_ets_bytes",
			"Other in-memory tables besides those belonging to the stats database and internal database tables",
			memoryLabels,
		),
		"memory.other_proc": newGaugeVec(
			"memory_other_proc_bytes",
			"Memory used by all other processes that RabbitMQ cannot categorise",
			memoryLabels,
		),
		"memory.other_system": newGaugeVec(
			"memory_other_system_bytes",
			"Memory used by all other system that RabbitMQ cannot categorise",
			memoryLabels,
		),
		"memory.plugins": newGaugeVec(
			"memory_plugins_bytes",
			"Memory used by plugins (apart from the Erlang client which is counted under Connections, and the management database which is counted separately). ",
			memoryLabels,
		),
		"memory.queue_procs": newGaugeVec(
			"memory_queue_procs_bytes",
			"Memory used by class queue masters, queue indices, queue state",
			memoryLabels,
		),
		"memory.queue_slave_procs": newGaugeVec(
			"memory_queue_slave_procs_bytes",
			"Memory used by class queue mirrors, queue indices, queue state",
			memoryLabels,
		),
		"memory.reserved_unallocated": newGaugeVec(
			"memory_reserved_unallocated_bytes",
			"Memory preallocated/reserved by the kernel but not the runtime",
			memoryLabels,
		),
		"memory.total": newGaugeVec(
			"memory_total_bytes",
			"Node-local total memory",
			memoryLabels,
		),
	}
)

type exporterMemory struct {
	memoryMetricsGauge map[string]*prometheus.GaugeVec
}

func newExporterMemory() Exporter {
	memoryGaugeVecActual := memoryGaugeVec

	if len(config.ExcludeMetrics) > 0 {
		for _, metric := range config.ExcludeMetrics {
			if memoryGaugeVecActual[metric] != nil {
				delete(memoryGaugeVecActual, metric)
			}
		}
	}

	return exporterMemory{
		memoryMetricsGauge: memoryGaugeVecActual,
	}
}

func (e exporterMemory) Collect(ctx context.Context, ch chan<- prometheus.Metric) error {
	for _, gauge := range e.memoryMetricsGauge {
		gauge.Reset()
	}
	selfNode := ""
	if n, ok := ctx.Value(nodeName).(string); ok {
		selfNode = n
	}
	cluster := ""
	if n, ok := ctx.Value(clusterName).(string); ok {
		cluster = n
	}

	nodeData, err := getStatsInfo(config, "nodes", nodeLabelKeys)
	if err != nil {
		return err
	}

	for _, node := range nodeData {
		self := "0"
		if node.labels["name"] == selfNode {
			self = "1"
		}
		rabbitMemoryResponses, err := getMetricMap(config, fmt.Sprintf("nodes/%s/memory", node.labels["name"]))
		if err != nil {
			return err
		}
		for key, gauge := range e.memoryMetricsGauge {
			if value, ok := rabbitMemoryResponses[key]; ok {
				gauge.WithLabelValues(cluster, node.labels["name"], self).Set(value)
			}
		}
	}

	for _, gauge := range e.memoryMetricsGauge {
		gauge.Collect(ch)
	}
	return nil
}

func (e exporterMemory) Describe(ch chan<- *prometheus.Desc) {
	for _, gauge := range e.memoryMetricsGauge {
		gauge.Describe(ch)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Netflix, 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 binprot

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"

	"github.com/netflix/rend/common"
)

var ErrBadMagic = errors.New("Bad magic value")

const (
	MagicRequest  = 0x80
	MagicResponse = 0x81

	// All opcodes as defined in memcached
	// Minus SASL and range ops
	OpcodeGet        = 0x00
	OpcodeSet        = 0x01
	OpcodeAdd        = 0x02
	OpcodeReplace    = 0x03
	OpcodeDelete     = 0x04
	OpcodeIncrement  = 0x05
	OpcodeDecrement  = 0x06
	OpcodeQuit       = 0x07
	OpcodeFlush      = 0x08
	OpcodeGetQ       = 0x09
	OpcodeNoop       = 0x0a
	OpcodeVersion    = 0x0b
	OpcodeGetK       = 0x0c
	OpcodeGetKQ      = 0x0d
	OpcodeAppend     = 0x0e
	OpcodePrepend    = 0x0f
	OpcodeStat       = 0x10
	OpcodeSetQ       = 0x11
	OpcodeAddQ       = 0x12
	OpcodeReplaceQ   = 0x13
	OpcodeDeleteQ    = 0x14
	OpcodeIncrementQ = 0x15
	OpcodeDecrementQ = 0x16
	OpcodeQuitQ      = 0x17
	OpcodeFlushQ     = 0x18
	OpcodeAppendQ    = 0x19
	OpcodePrependQ   = 0x1a
	OpcodeTouch      = 0x1c
	OpcodeGat        = 0x1d
	OpcodeGatQ       = 0x1e
	OpcodeGatK       = 0x23
	OpcodeGatKQ      = 0x24
	OpcodeInvalid    = 0xFF

	StatusSuccess        = uint16(0x00)
	StatusKeyEnoent      = uint16(0x01)
	StatusKeyEexists     = uint16(0x02)
	StatusE2big          = uint16(0x03)
	StatusEinval         = uint16(0x04)
	StatusNotStored      = uint16(0x05)
	StatusDeltaBadval    = uint16(0x06)
	StatusAuthError      = uint16(0x20)
	StatusAuthContinue   = uint16(0x21)
	StatusUnknownCommand = uint16(0x81)
	StatusEnomem         = uint16(0x82)
	StatusNotSupported   = uint16(0x83)
	StatusInternalError  = uint16(0x84)
	StatusBusy           = uint16(0x85)
	StatusTempFailure    = uint16(0x86)
	StatusInvalid        = uint16(0xFFFF)
)

func DecodeError(header ResponseHeader) error {
	switch header.Status {
	case StatusKeyEnoent:
		return common.ErrKeyNotFound
	case StatusKeyEexists:
		return common.ErrKeyExists
	case StatusE2big:
		return common.ErrValueTooBig
	case StatusEinval:
		return common.ErrInvalidArgs
	case StatusNotStored:
		return common.ErrItemNotStored
	case StatusDeltaBadval:
		return common.ErrBadIncDecValue
	case StatusAuthError:
		return common.ErrAuth
	case StatusUnknownCommand:
		return common.ErrUnknownCmd
	case StatusEnomem:
		return common.ErrNoMem
	case StatusNotSupported:
		return common.ErrNotSupported
	case StatusInternalError:
		return common.ErrInternal
	case StatusBusy:
		return common.ErrBusy
	case StatusTempFailure:
		return common.ErrTempFailure
	}
	return nil
}

func errorToCode(err error) uint16 {
	switch err {
	case common.ErrKeyNotFound:
		return StatusKeyEnoent
	case common.ErrKeyExists:
		return StatusKeyEexists
	case common.ErrValueTooBig:
		return StatusE2big
	case common.ErrInvalidArgs:
		return StatusEinval
	case common.ErrItemNotStored:
		return StatusNotStored
	case common.ErrBadIncDecValue:
		return StatusDeltaBadval
	case common.ErrAuth:
		return StatusAuthError
	case common.ErrUnknownCmd:
		return StatusUnknownCommand
	case common.ErrNoMem:
		return StatusEnomem
	case common.ErrNotSupported:
		return StatusNotSupported
	case common.ErrInternal:
		return StatusInternalError
	case common.ErrBusy:
		return StatusBusy
	case common.ErrTempFailure:
		return StatusTempFailure
	}
	return StatusInvalid
}

const ReqHeaderLen = 24

type RequestHeader struct {
	Magic           uint8 // Already known, since we're here
	Opcode          uint8
	KeyLength       uint16
	ExtraLength     uint8
	DataType        uint8  // Always 0
	VBucket         uint16 // Not used
	TotalBodyLength uint32
	OpaqueToken     uint32 // Echoed to the client
	CASToken        uint64 // Unused in current implementation
}

func MakeRequestHeader(opcode, keyLength, extraLength, totalBodyLength int) RequestHeader {
	return RequestHeader{
		Magic:           uint8(MagicRequest),
		Opcode:          uint8(opcode),
		KeyLength:       uint16(keyLength),
		ExtraLength:     uint8(extraLength),
		DataType:        uint8(0),
		VBucket:         uint16(0),
		TotalBodyLength: uint32(totalBodyLength),
		OpaqueToken:     uint32(0),
		CASToken:        uint64(0),
	}
}

func ReadRequestHeader(reader io.Reader) (RequestHeader, error) {
	// read in the full header before any variable length fields
	headerBuf := make([]byte, ReqHeaderLen)
	if _, err := io.ReadFull(reader, headerBuf); err != nil {
		return RequestHeader{}, err
	}

	var reqHeader RequestHeader
	binary.Read(bytes.NewBuffer(headerBuf), binary.BigEndian, &reqHeader)

	if reqHeader.Magic != MagicResponse {
		return RequestHeader{}, ErrBadMagic
	}

	return reqHeader, nil
}

const resHeaderLen = 24

type ResponseHeader struct {
	Magic           uint8 // always 0x81
	Opcode          uint8
	KeyLength       uint16
	ExtraLength     uint8
	DataType        uint8 // unused, always 0
	Status          uint16
	TotalBodyLength uint32
	OpaqueToken     uint32 // same as the user passed in
	CASToken        uint64
}

func makeSuccessResponseHeader(opcode, keyLength, extraLength, totalBodyLength, opaqueToken int) ResponseHeader {
	return ResponseHeader{
		Magic:           MagicResponse,
		Opcode:          uint8(opcode),
		KeyLength:       uint16(keyLength),
		ExtraLength:     uint8(extraLength),
		DataType:        uint8(0),
		Status:          uint16(StatusSuccess),
		TotalBodyLength: uint32(totalBodyLength),
		OpaqueToken:     uint32(opaqueToken),
		CASToken:        uint64(0),
	}
}

func makeErrorResponseHeader(opcode, status, opaqueToken int) ResponseHeader {
	return ResponseHeader{
		Magic:           MagicResponse,
		Opcode:          uint8(opcode),
		KeyLength:       uint16(0),
		ExtraLength:     uint8(0),
		DataType:        uint8(0),
		Status:          uint16(status),
		TotalBodyLength: uint32(0),
		OpaqueToken:     uint32(opaqueToken),
		CASToken:        uint64(0),
	}
}

func ReadResponseHeader(reader io.Reader) (ResponseHeader, error) {
	// read in the full header before any variable length fields
	headerBuf := make([]byte, resHeaderLen)
	if _, err := io.ReadFull(reader, headerBuf); err != nil {
		return ResponseHeader{}, err
	}

	var resHeader ResponseHeader
	binary.Read(bytes.NewBuffer(headerBuf), binary.BigEndian, &resHeader)

	if resHeader.Magic != MagicResponse {
		return ResponseHeader{}, ErrBadMagic
	}

	return resHeader, nil
}
<commit_msg>Fixing error checking in binprot.ReadRequestHeader<commit_after>// Copyright 2015 Netflix, 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 binprot

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"

	"github.com/netflix/rend/common"
)

var ErrBadMagic = errors.New("Bad magic value")

const (
	MagicRequest  = 0x80
	MagicResponse = 0x81

	// All opcodes as defined in memcached
	// Minus SASL and range ops
	OpcodeGet        = 0x00
	OpcodeSet        = 0x01
	OpcodeAdd        = 0x02
	OpcodeReplace    = 0x03
	OpcodeDelete     = 0x04
	OpcodeIncrement  = 0x05
	OpcodeDecrement  = 0x06
	OpcodeQuit       = 0x07
	OpcodeFlush      = 0x08
	OpcodeGetQ       = 0x09
	OpcodeNoop       = 0x0a
	OpcodeVersion    = 0x0b
	OpcodeGetK       = 0x0c
	OpcodeGetKQ      = 0x0d
	OpcodeAppend     = 0x0e
	OpcodePrepend    = 0x0f
	OpcodeStat       = 0x10
	OpcodeSetQ       = 0x11
	OpcodeAddQ       = 0x12
	OpcodeReplaceQ   = 0x13
	OpcodeDeleteQ    = 0x14
	OpcodeIncrementQ = 0x15
	OpcodeDecrementQ = 0x16
	OpcodeQuitQ      = 0x17
	OpcodeFlushQ     = 0x18
	OpcodeAppendQ    = 0x19
	OpcodePrependQ   = 0x1a
	OpcodeTouch      = 0x1c
	OpcodeGat        = 0x1d
	OpcodeGatQ       = 0x1e
	OpcodeGatK       = 0x23
	OpcodeGatKQ      = 0x24
	OpcodeInvalid    = 0xFF

	StatusSuccess        = uint16(0x00)
	StatusKeyEnoent      = uint16(0x01)
	StatusKeyEexists     = uint16(0x02)
	StatusE2big          = uint16(0x03)
	StatusEinval         = uint16(0x04)
	StatusNotStored      = uint16(0x05)
	StatusDeltaBadval    = uint16(0x06)
	StatusAuthError      = uint16(0x20)
	StatusAuthContinue   = uint16(0x21)
	StatusUnknownCommand = uint16(0x81)
	StatusEnomem         = uint16(0x82)
	StatusNotSupported   = uint16(0x83)
	StatusInternalError  = uint16(0x84)
	StatusBusy           = uint16(0x85)
	StatusTempFailure    = uint16(0x86)
	StatusInvalid        = uint16(0xFFFF)
)

func DecodeError(header ResponseHeader) error {
	switch header.Status {
	case StatusKeyEnoent:
		return common.ErrKeyNotFound
	case StatusKeyEexists:
		return common.ErrKeyExists
	case StatusE2big:
		return common.ErrValueTooBig
	case StatusEinval:
		return common.ErrInvalidArgs
	case StatusNotStored:
		return common.ErrItemNotStored
	case StatusDeltaBadval:
		return common.ErrBadIncDecValue
	case StatusAuthError:
		return common.ErrAuth
	case StatusUnknownCommand:
		return common.ErrUnknownCmd
	case StatusEnomem:
		return common.ErrNoMem
	case StatusNotSupported:
		return common.ErrNotSupported
	case StatusInternalError:
		return common.ErrInternal
	case StatusBusy:
		return common.ErrBusy
	case StatusTempFailure:
		return common.ErrTempFailure
	}
	return nil
}

func errorToCode(err error) uint16 {
	switch err {
	case common.ErrKeyNotFound:
		return StatusKeyEnoent
	case common.ErrKeyExists:
		return StatusKeyEexists
	case common.ErrValueTooBig:
		return StatusE2big
	case common.ErrInvalidArgs:
		return StatusEinval
	case common.ErrItemNotStored:
		return StatusNotStored
	case common.ErrBadIncDecValue:
		return StatusDeltaBadval
	case common.ErrAuth:
		return StatusAuthError
	case common.ErrUnknownCmd:
		return StatusUnknownCommand
	case common.ErrNoMem:
		return StatusEnomem
	case common.ErrNotSupported:
		return StatusNotSupported
	case common.ErrInternal:
		return StatusInternalError
	case common.ErrBusy:
		return StatusBusy
	case common.ErrTempFailure:
		return StatusTempFailure
	}
	return StatusInvalid
}

const ReqHeaderLen = 24

type RequestHeader struct {
	Magic           uint8 // Already known, since we're here
	Opcode          uint8
	KeyLength       uint16
	ExtraLength     uint8
	DataType        uint8  // Always 0
	VBucket         uint16 // Not used
	TotalBodyLength uint32
	OpaqueToken     uint32 // Echoed to the client
	CASToken        uint64 // Unused in current implementation
}

func MakeRequestHeader(opcode, keyLength, extraLength, totalBodyLength int) RequestHeader {
	return RequestHeader{
		Magic:           uint8(MagicRequest),
		Opcode:          uint8(opcode),
		KeyLength:       uint16(keyLength),
		ExtraLength:     uint8(extraLength),
		DataType:        uint8(0),
		VBucket:         uint16(0),
		TotalBodyLength: uint32(totalBodyLength),
		OpaqueToken:     uint32(0),
		CASToken:        uint64(0),
	}
}

func ReadRequestHeader(reader io.Reader) (RequestHeader, error) {
	// read in the full header before any variable length fields
	headerBuf := make([]byte, ReqHeaderLen)
	if _, err := io.ReadFull(reader, headerBuf); err != nil {
		return RequestHeader{}, err
	}

	var reqHeader RequestHeader
	binary.Read(bytes.NewBuffer(headerBuf), binary.BigEndian, &reqHeader)

	if reqHeader.Magic != MagicRequest {
		return RequestHeader{}, ErrBadMagic
	}

	return reqHeader, nil
}

const resHeaderLen = 24

type ResponseHeader struct {
	Magic           uint8 // always 0x81
	Opcode          uint8
	KeyLength       uint16
	ExtraLength     uint8
	DataType        uint8 // unused, always 0
	Status          uint16
	TotalBodyLength uint32
	OpaqueToken     uint32 // same as the user passed in
	CASToken        uint64
}

func makeSuccessResponseHeader(opcode, keyLength, extraLength, totalBodyLength, opaqueToken int) ResponseHeader {
	return ResponseHeader{
		Magic:           MagicResponse,
		Opcode:          uint8(opcode),
		KeyLength:       uint16(keyLength),
		ExtraLength:     uint8(extraLength),
		DataType:        uint8(0),
		Status:          uint16(StatusSuccess),
		TotalBodyLength: uint32(totalBodyLength),
		OpaqueToken:     uint32(opaqueToken),
		CASToken:        uint64(0),
	}
}

func makeErrorResponseHeader(opcode, status, opaqueToken int) ResponseHeader {
	return ResponseHeader{
		Magic:           MagicResponse,
		Opcode:          uint8(opcode),
		KeyLength:       uint16(0),
		ExtraLength:     uint8(0),
		DataType:        uint8(0),
		Status:          uint16(status),
		TotalBodyLength: uint32(0),
		OpaqueToken:     uint32(opaqueToken),
		CASToken:        uint64(0),
	}
}

func ReadResponseHeader(reader io.Reader) (ResponseHeader, error) {
	// read in the full header before any variable length fields
	headerBuf := make([]byte, resHeaderLen)
	if _, err := io.ReadFull(reader, headerBuf); err != nil {
		return ResponseHeader{}, err
	}

	var resHeader ResponseHeader
	binary.Read(bytes.NewBuffer(headerBuf), binary.BigEndian, &resHeader)

	if resHeader.Magic != MagicResponse {
		return ResponseHeader{}, ErrBadMagic
	}

	return resHeader, nil
}
<|endoftext|>


<commit_before>package raft

import (
	"fmt"
	"testing"
	"time"
)

func setupTestFollower(t *testing.T, logTerms []TermNo) *ConsensusModule {
	cm, _ := setupTestFollowerR2(t, logTerms)
	return cm
}

func setupTestFollowerR2(
	t *testing.T,
	logTerms []TermNo,
) (*ConsensusModule, *mockRpcSender) {
	ps := newIMPSWithCurrentTerm(testCurrentTerm)
	imle := newIMLEWithDummyCommands(logTerms)
	mrs := newMockRpcSender()
	ts := TimeSettings{testTickerDuration, testElectionTimeoutLow}
	cm := NewConsensusModule(ps, imle, mrs, testServerId, testPeerIds, ts)
	if cm == nil {
		t.Fatal()
	}
	return cm, mrs
}

func (cm *ConsensusModule) stopAsyncWithRecover() (e interface{}) {
	defer func() {
		e = recover()
	}()
	cm.StopAsync()
	return nil
}

func (cm *ConsensusModule) stopAndCheckError() {
	var callersError, stopAsyncError, stopStatusError, stopError interface{}

	callersError = recover()

	stopAsyncError = cm.stopAsyncWithRecover()

	time.Sleep(testSleepToLetGoroutineRun)
	if !cm.IsStopped() {
		stopStatusError = "Timeout waiting for stop!"
	}

	stopError = cm.GetStopError()

	if stopAsyncError == nil && stopStatusError == nil && stopError == nil {
		if callersError != nil {
			panic(callersError)
		} else {
			return
		}
	} else {
		errs := [...]interface{}{
			callersError,
			stopAsyncError,
			stopStatusError,
			stopError,
		}
		panic(fmt.Sprintf("%v", errs))
	}
}

func TestCMStop(t *testing.T) {
	cm := setupTestFollower(t, nil)

	if cm.IsStopped() {
		t.Error()
	}

	cm.StopAsync()
	time.Sleep(testSleepToLetGoroutineRun)

	if !cm.IsStopped() {
		t.Error()
	}
	if cm.GetStopError() != nil {
		t.Error()
	}
}

func TestCMUnknownRpcTypeStopsCM(t *testing.T) {
	cm := setupTestFollower(t, nil)

	if cm.IsStopped() {
		t.Error()
	}

	cm.ProcessRpcAsync("s2", &struct{ int }{42})
	time.Sleep(testSleepToLetGoroutineRun)

	if !cm.IsStopped() {
		cm.StopAsync()
		t.Fatal()
	}

	e := cm.GetStopError()
	if e != "FATAL: unknown rpc type: *struct { int }" {
		t.Error(e)
	}
}
<commit_msg>Tweaks to blackbox test and improve blackbox coverage<commit_after>package raft

import (
	"fmt"
	"testing"
	"time"
)

func setupConsensusModule(t *testing.T, logTerms []TermNo) *ConsensusModule {
	cm, _ := setupConsensusModuleR2(t, logTerms)
	return cm
}

func setupConsensusModuleR2(
	t *testing.T,
	logTerms []TermNo,
) (*ConsensusModule, *mockRpcSender) {
	ps := newIMPSWithCurrentTerm(testCurrentTerm)
	imle := newIMLEWithDummyCommands(logTerms)
	mrs := newMockRpcSender()
	ts := TimeSettings{testTickerDuration, testElectionTimeoutLow}
	cm := NewConsensusModule(ps, imle, mrs, testServerId, testPeerIds, ts)
	if cm == nil {
		t.Fatal()
	}
	return cm, mrs
}

func (cm *ConsensusModule) stopAsyncWithRecover() (e interface{}) {
	defer func() {
		e = recover()
	}()
	cm.StopAsync()
	return nil
}

func (cm *ConsensusModule) stopAndCheckError() {
	var callersError, stopAsyncError, stopStatusError, stopError interface{}

	callersError = recover()

	stopAsyncError = cm.stopAsyncWithRecover()

	time.Sleep(testSleepToLetGoroutineRun)
	if !cm.IsStopped() {
		stopStatusError = "Timeout waiting for stop!"
	}

	stopError = cm.GetStopError()

	if stopAsyncError == nil && stopStatusError == nil && stopError == nil {
		if callersError != nil {
			panic(callersError)
		} else {
			return
		}
	} else {
		errs := [...]interface{}{
			callersError,
			stopAsyncError,
			stopStatusError,
			stopError,
		}
		panic(fmt.Sprintf("%v", errs))
	}
}

func TestCMStartStateAndStop(t *testing.T) {
	cm := setupConsensusModule(t, nil)

	// #5.2-p1s2: When servers start up, they begin as followers
	if cm.GetServerState() != FOLLOWER {
		t.Fatal()
	}

	time.Sleep(testSleepJustMoreThanATick)

	if cm.IsStopped() {
		t.Error()
	}

	cm.StopAsync()
	time.Sleep(testSleepToLetGoroutineRun)

	if !cm.IsStopped() {
		t.Error()
	}
	if cm.GetStopError() != nil {
		t.Error()
	}
}

func TestCMUnknownRpcTypeStopsCM(t *testing.T) {
	cm := setupConsensusModule(t, nil)

	if cm.IsStopped() {
		t.Error()
	}

	cm.ProcessRpcAsync("s2", &struct{ int }{42})
	time.Sleep(testSleepToLetGoroutineRun)

	if !cm.IsStopped() {
		cm.StopAsync()
		t.Fatal()
	}

	e := cm.GetStopError()
	if e != "FATAL: unknown rpc type: *struct { int }" {
		t.Error(e)
	}
}
<|endoftext|>


<commit_before>// Package read implements reading of Erlang external terms.
package read

import (
	"bytes"
	"encoding/binary"
	"fmt"
	t "github.com/goerlang/etf/types"
	"io"
	"math"
	"math/big"
)

type ErrUnknownTerm struct {
	termType byte
}

var (
	ErrFloatScan = fmt.Errorf("read: failed to sscanf float")
	be           = binary.BigEndian
	bTrue        = []byte("true")
	bFalse       = []byte("false")
)

func (e *ErrUnknownTerm) Error() string {
	return fmt.Sprintf("read: unknown term type %d", e.termType)
}

func atom(b []byte) interface{} {
	if bytes.Compare(b, bTrue) == 0 {
		return true
	} else if bytes.Compare(b, bFalse) == 0 {
		return false
	}
	return t.Atom(b)
}

func bigInt(r io.Reader, b []byte, sign byte) (interface{}, error) {
	if _, err := io.ReadFull(r, b); err != nil {
		return nil, err
	}

	size := len(b)
	hsize := size >> 1
	for i := 0; i < hsize; i++ {
		b[i], b[size-i-1] = b[size-i-1], b[i]
	}

	v := new(big.Int).SetBytes(b)
	if sign != 0 {
		v = v.Neg(v)
	}

	// try int and int64
	v64 := v.Int64()
	if x := int(v64); v.Cmp(big.NewInt(int64(x))) == 0 {
		return x, nil
	} else if v.Cmp(big.NewInt(v64)) == 0 {
		return v64, nil
	}

	return v, nil
}

func Term(r io.Reader) (term t.Term, err error) {
	var etype byte
	if etype, err = ruint8(r); err != nil {
		return nil, err
	}
	var b []byte

	switch etype {
	case t.EttAtom, t.EttAtomUTF8:
		// $dLL… | $vLL…
		if b, err = buint16(r); err == nil {
			_, err = io.ReadFull(r, b)
			term = atom(b)
		}

	case t.EttSmallAtom, t.EttSmallAtomUTF8:
		// $sL…, $wL…
		if b, err = buint8(r); err == nil {
			_, err = io.ReadFull(r, b)
			term = atom(b)
		}

	case t.EttBinary:
		// $mLLLL…
		if b, err = buint32(r); err == nil {
			_, err = io.ReadFull(r, b)
			term = b
		}

	case t.EttString:
		// $kLL…
		if b, err = buint16(r); err == nil {
			_, err = io.ReadFull(r, b)
			term = string(b)
		}

	case t.EttFloat:
		// $cFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
		b = make([]byte, 31)
		if _, err = io.ReadFull(r, b); err != nil {
			return
		}
		var r int
		var f float64
		if r, err = fmt.Sscanf(string(b), "%f", &f); r != 1 && err == nil {
			err = ErrFloatScan
		}
		term = f

	case t.EttNewFloat:
		// $FFFFFFFFF
		b = make([]byte, 8)
		if _, err = io.ReadFull(r, b); err == nil {
			term = math.Float64frombits(be.Uint64(b))
		}

	case t.EttSmallInteger:
		// $aI
		var x uint8
		x, err = ruint8(r)
		term = int(x)

	case t.EttInteger:
		// $bIIII
		var x int32
		err = binary.Read(r, be, &x)
		term = int(x)

	case t.EttSmallBig:
		// $nAS…
		b = make([]byte, 2)
		if _, err = io.ReadFull(r, b); err != nil {
			break
		}
		sign := b[1]
		b = make([]byte, b[0])
		term, err = bigInt(r, b, sign)

	case t.EttLargeBig:
		// $oAAAAS…
		b = make([]byte, 5)
		if _, err = io.ReadFull(r, b); err != nil {
			break
		}
		sign := b[4]
		b = make([]byte, be.Uint32(b[:4]))
		term, err = bigInt(r, b, sign)

	case t.EttNil:
		// $j
		term = t.List{}

	case t.EttPid:
		var node interface{}
		var pid t.Pid
		b = make([]byte, 9)
		if node, err = Term(r); err != nil {
			return
		} else if _, err = io.ReadFull(r, b); err != nil {
			return
		}
		pid.Node = node.(t.Atom)
		pid.Id = be.Uint32(b[:4])
		pid.Serial = be.Uint32(b[4:8])
		pid.Creation = b[8]
		term = pid

	case t.EttNewReference:
		// $rLL…
		var ref t.Ref
		var node interface{}
		var nid uint16
		if nid, err = ruint16(r); err != nil {
			return
		} else if node, err = Term(r); err != nil {
			return
		} else if ref.Creation, err = ruint8(r); err != nil {
			return
		}
		ref.Node = node.(t.Atom)
		ref.Id = make([]uint32, nid)
		for i := 0; i < cap(ref.Id); i++ {
			if ref.Id[i], err = ruint32(r); err != nil {
				return
			}
		}
		term = ref

	case t.EttReference:
		// $e…LLLLB
		var ref t.Ref
		var node interface{}
		if node, err = Term(r); err != nil {
			return
		}
		ref.Node = node.(t.Atom)
		ref.Id = make([]uint32, 1)
		if ref.Id[0], err = ruint32(r); err != nil {
			return
		} else if _, err = io.ReadFull(r, b); err != nil {
			return
		}
		ref.Creation = b[0]
		term = ref

	case t.EttSmallTuple:
		// $hA…
		var arity uint8
		if arity, err = ruint8(r); err != nil {
			break
		}
		tuple := make(t.Tuple, arity)
		for i := 0; i < cap(tuple); i++ {
			if tuple[i], err = Term(r); err != nil {
				break
			}
		}
		term = tuple

	case t.EttLargeTuple:
		// $iAAAA…
		var arity uint32
		if arity, err = ruint32(r); err != nil {
			break
		}
		tuple := make(t.Tuple, arity)
		for i := 0; i < cap(tuple); i++ {
			if tuple[i], err = Term(r); err != nil {
				break
			}
		}
		term = tuple

	case t.EttList:
		// $lLLLL…$j
		var n uint32
		if n, err = ruint32(r); err != nil {
			return
		}

		list := make(t.List, n+1)
		for i := 0; i < cap(list); i++ {
			if list[i], err = Term(r); err != nil {
				return
			}
		}

		switch list[n].(type) {
		case t.List:
			// proper list, remove nil element
			list = list[:n]
		}
		term = list

	case t.EttBitBinary:
		// $MLLLLB…
		var length uint32
		var bits uint8
		if length, err = ruint32(r); err != nil {
			break
		} else if bits, err = ruint8(r); err != nil {
			break
		}
		b := make([]byte, length)
		_, err = io.ReadFull(r, b)
		b[len(b)-1] = b[len(b)-1] >> (8 - bits)
		term = b

	case t.EttExport:
		// $qM…F…A
		var m, f interface{}
		var a uint8
		if m, err = Term(r); err != nil {
			break
		} else if f, err = Term(r); err != nil {
			break
		} else if a, err = ruint8(r); err != nil {
			break
		}

		term = t.Export{m.(t.Atom), f.(t.Atom), a}

	case t.EttNewFun:
		// $pSSSSAUUUUUUUUUUUUUUUUIIIIFFFFM…i…u…P…[V…]
		var f t.Function
		ruint32(r)
		f.Arity, _ = ruint8(r)
		io.ReadFull(r, f.Unique[:])
		f.Index, _ = ruint32(r)
		f.Free, _ = ruint32(r)
		m, _ := Term(r)
		oldi, _ := Term(r)
		oldu, _ := Term(r)
		pid, _ := Term(r)

		f.FreeVars = make([]t.Term, f.Free)
		for i := 0; i < cap(f.FreeVars); i++ {
			if f.FreeVars[i], err = Term(r); err != nil {
				break
			}
		}

		f.Module = m.(t.Atom)
		f.OldIndex = uint32(oldi.(int))
		f.OldUnique = uint32(oldu.(int))
		f.Pid = pid.(t.Pid)

		/*
			case t.EttCachedAtom:
			case t.EttFun:
			case t.EttNewCache:
			case t.EttNewFun:
			case t.EttPort:
		*/
	default:
		err = &ErrUnknownTerm{etype}
	}

	return
}

func ruint8(r io.Reader) (uint8, error) {
	b := []byte{0}
	_, err := io.ReadFull(r, b)
	return b[0], err
}

func ruint16(r io.Reader) (uint16, error) {
	b := []byte{0, 0}
	_, err := io.ReadFull(r, b)
	return be.Uint16(b), err
}

func ruint32(r io.Reader) (uint32, error) {
	b := []byte{0, 0, 0, 0}
	_, err := io.ReadFull(r, b)
	return be.Uint32(b), err
}

func buint8(r io.Reader) ([]byte, error) {
	size, err := ruint8(r)
	return make([]byte, size), err
}

func buint16(r io.Reader) ([]byte, error) {
	size, err := ruint16(r)
	return make([]byte, size), err
}

func buint32(r io.Reader) ([]byte, error) {
	size, err := ruint32(r)
	return make([]byte, size), err
}
<commit_msg>read: Fun support<commit_after>// Package read implements reading of Erlang external terms.
package read

import (
	"bytes"
	"encoding/binary"
	"fmt"
	t "github.com/goerlang/etf/types"
	"io"
	"math"
	"math/big"
)

type ErrUnknownTerm struct {
	termType byte
}

var (
	ErrFloatScan = fmt.Errorf("read: failed to sscanf float")
	be           = binary.BigEndian
	bTrue        = []byte("true")
	bFalse       = []byte("false")
)

func (e *ErrUnknownTerm) Error() string {
	return fmt.Sprintf("read: unknown term type %d", e.termType)
}

func atom(b []byte) interface{} {
	if bytes.Compare(b, bTrue) == 0 {
		return true
	} else if bytes.Compare(b, bFalse) == 0 {
		return false
	}
	return t.Atom(b)
}

func bigInt(r io.Reader, b []byte, sign byte) (interface{}, error) {
	if _, err := io.ReadFull(r, b); err != nil {
		return nil, err
	}

	size := len(b)
	hsize := size >> 1
	for i := 0; i < hsize; i++ {
		b[i], b[size-i-1] = b[size-i-1], b[i]
	}

	v := new(big.Int).SetBytes(b)
	if sign != 0 {
		v = v.Neg(v)
	}

	// try int and int64
	v64 := v.Int64()
	if x := int(v64); v.Cmp(big.NewInt(int64(x))) == 0 {
		return x, nil
	} else if v.Cmp(big.NewInt(v64)) == 0 {
		return v64, nil
	}

	return v, nil
}

func Term(r io.Reader) (term t.Term, err error) {
	var etype byte
	if etype, err = ruint8(r); err != nil {
		return nil, err
	}
	var b []byte

	switch etype {
	case t.EttAtom, t.EttAtomUTF8:
		// $dLL… | $vLL…
		if b, err = buint16(r); err == nil {
			_, err = io.ReadFull(r, b)
			term = atom(b)
		}

	case t.EttSmallAtom, t.EttSmallAtomUTF8:
		// $sL…, $wL…
		if b, err = buint8(r); err == nil {
			_, err = io.ReadFull(r, b)
			term = atom(b)
		}

	case t.EttBinary:
		// $mLLLL…
		if b, err = buint32(r); err == nil {
			_, err = io.ReadFull(r, b)
			term = b
		}

	case t.EttString:
		// $kLL…
		if b, err = buint16(r); err == nil {
			_, err = io.ReadFull(r, b)
			term = string(b)
		}

	case t.EttFloat:
		// $cFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
		b = make([]byte, 31)
		if _, err = io.ReadFull(r, b); err != nil {
			return
		}
		var r int
		var f float64
		if r, err = fmt.Sscanf(string(b), "%f", &f); r != 1 && err == nil {
			err = ErrFloatScan
		}
		term = f

	case t.EttNewFloat:
		// $FFFFFFFFF
		b = make([]byte, 8)
		if _, err = io.ReadFull(r, b); err == nil {
			term = math.Float64frombits(be.Uint64(b))
		}

	case t.EttSmallInteger:
		// $aI
		var x uint8
		x, err = ruint8(r)
		term = int(x)

	case t.EttInteger:
		// $bIIII
		var x int32
		err = binary.Read(r, be, &x)
		term = int(x)

	case t.EttSmallBig:
		// $nAS…
		b = make([]byte, 2)
		if _, err = io.ReadFull(r, b); err != nil {
			break
		}
		sign := b[1]
		b = make([]byte, b[0])
		term, err = bigInt(r, b, sign)

	case t.EttLargeBig:
		// $oAAAAS…
		b = make([]byte, 5)
		if _, err = io.ReadFull(r, b); err != nil {
			break
		}
		sign := b[4]
		b = make([]byte, be.Uint32(b[:4]))
		term, err = bigInt(r, b, sign)

	case t.EttNil:
		// $j
		term = t.List{}

	case t.EttPid:
		var node interface{}
		var pid t.Pid
		b = make([]byte, 9)
		if node, err = Term(r); err != nil {
			return
		} else if _, err = io.ReadFull(r, b); err != nil {
			return
		}
		pid.Node = node.(t.Atom)
		pid.Id = be.Uint32(b[:4])
		pid.Serial = be.Uint32(b[4:8])
		pid.Creation = b[8]
		term = pid

	case t.EttNewReference:
		// $rLL…
		var ref t.Ref
		var node interface{}
		var nid uint16
		if nid, err = ruint16(r); err != nil {
			return
		} else if node, err = Term(r); err != nil {
			return
		} else if ref.Creation, err = ruint8(r); err != nil {
			return
		}
		ref.Node = node.(t.Atom)
		ref.Id = make([]uint32, nid)
		for i := 0; i < cap(ref.Id); i++ {
			if ref.Id[i], err = ruint32(r); err != nil {
				return
			}
		}
		term = ref

	case t.EttReference:
		// $e…LLLLB
		var ref t.Ref
		var node interface{}
		if node, err = Term(r); err != nil {
			return
		}
		ref.Node = node.(t.Atom)
		ref.Id = make([]uint32, 1)
		if ref.Id[0], err = ruint32(r); err != nil {
			return
		} else if _, err = io.ReadFull(r, b); err != nil {
			return
		}
		ref.Creation = b[0]
		term = ref

	case t.EttSmallTuple:
		// $hA…
		var arity uint8
		if arity, err = ruint8(r); err != nil {
			break
		}
		tuple := make(t.Tuple, arity)
		for i := 0; i < cap(tuple); i++ {
			if tuple[i], err = Term(r); err != nil {
				break
			}
		}
		term = tuple

	case t.EttLargeTuple:
		// $iAAAA…
		var arity uint32
		if arity, err = ruint32(r); err != nil {
			break
		}
		tuple := make(t.Tuple, arity)
		for i := 0; i < cap(tuple); i++ {
			if tuple[i], err = Term(r); err != nil {
				break
			}
		}
		term = tuple

	case t.EttList:
		// $lLLLL…$j
		var n uint32
		if n, err = ruint32(r); err != nil {
			return
		}

		list := make(t.List, n+1)
		for i := 0; i < cap(list); i++ {
			if list[i], err = Term(r); err != nil {
				return
			}
		}

		switch list[n].(type) {
		case t.List:
			// proper list, remove nil element
			list = list[:n]
		}
		term = list

	case t.EttBitBinary:
		// $MLLLLB…
		var length uint32
		var bits uint8
		if length, err = ruint32(r); err != nil {
			break
		} else if bits, err = ruint8(r); err != nil {
			break
		}
		b := make([]byte, length)
		_, err = io.ReadFull(r, b)
		b[len(b)-1] = b[len(b)-1] >> (8 - bits)
		term = b

	case t.EttExport:
		// $qM…F…A
		var m, f interface{}
		var a uint8
		if m, err = Term(r); err != nil {
			break
		} else if f, err = Term(r); err != nil {
			break
		} else if a, err = ruint8(r); err != nil {
			break
		}

		term = t.Export{m.(t.Atom), f.(t.Atom), a}

	case t.EttNewFun:
		// $pSSSSAUUUUUUUUUUUUUUUUIIIIFFFFM…i…u…P…[V…]
		var f t.Function
		ruint32(r)
		f.Arity, _ = ruint8(r)
		io.ReadFull(r, f.Unique[:])
		f.Index, _ = ruint32(r)
		f.Free, _ = ruint32(r)
		m, _ := Term(r)
		oldi, _ := Term(r)
		oldu, _ := Term(r)
		pid, _ := Term(r)

		f.FreeVars = make([]t.Term, f.Free)
		for i := 0; i < cap(f.FreeVars); i++ {
			if f.FreeVars[i], err = Term(r); err != nil {
				break
			}
		}

		f.Module = m.(t.Atom)
		f.OldIndex = uint32(oldi.(int))
		f.OldUnique = uint32(oldu.(int))
		f.Pid = pid.(t.Pid)

	case t.EttFun:
		// $uFFFFP…M…i…u…[V…]
		var f t.Function
		f.Free, _ = ruint32(r)
		pid, _ := Term(r)
		m, _ := Term(r)
		oldi, _ := Term(r)
		oldu, _ := Term(r)

		f.FreeVars = make([]t.Term, f.Free)
		for i := 0; i < cap(f.FreeVars); i++ {
			if f.FreeVars[i], err = Term(r); err != nil {
				break
			}
		}

		f.Module = m.(t.Atom)
		f.OldIndex = uint32(oldi.(int))
		f.OldUnique = uint32(oldu.(int))
		f.Pid = pid.(t.Pid)

		/*
			case t.EttCachedAtom:
			case t.EttNewCache:
			case t.EttPort:
		*/
	default:
		err = &ErrUnknownTerm{etype}
	}

	return
}

func ruint8(r io.Reader) (uint8, error) {
	b := []byte{0}
	_, err := io.ReadFull(r, b)
	return b[0], err
}

func ruint16(r io.Reader) (uint16, error) {
	b := []byte{0, 0}
	_, err := io.ReadFull(r, b)
	return be.Uint16(b), err
}

func ruint32(r io.Reader) (uint32, error) {
	b := []byte{0, 0, 0, 0}
	_, err := io.ReadFull(r, b)
	return be.Uint32(b), err
}

func buint8(r io.Reader) ([]byte, error) {
	size, err := ruint8(r)
	return make([]byte, size), err
}

func buint16(r io.Reader) ([]byte, error) {
	size, err := ruint16(r)
	return make([]byte, size), err
}

func buint32(r io.Reader) ([]byte, error) {
	size, err := ruint32(r)
	return make([]byte, size), err
}
<|endoftext|>


<commit_before>// Example buildhhm shows how to construct an HHM using HHblits and HHmake
// from a single sequence FASTA file.
package main

import (
	"flag"

	"github.com/BurntSushi/bcbgo/apps/hhsuite"
	"github.com/BurntSushi/bcbgo/cmd/util"
	"github.com/TuftsBCB/io/hhm"
)

var (
	flagQuiet = false
)

func init() {
	flag.BoolVar(&flagQuiet, "quiet", flagQuiet,
		"When set, hhblits/hhmake output will be hidden.")

	util.FlagUse("seq-db")
	util.FlagParse("in-fasta-file out-hhm-file", "")
	util.AssertNArg(2)
}

func main() {
	inFasta := util.Arg(0)
	outHHM := util.Arg(1)

	hhblits := hhsuite.HHBlitsDefault
	hhmake := hhsuite.HHMakePseudo
	hhblits.Verbose = !flagQuiet
	hhmake.Verbose = !flagQuiet

	HHM, err := hhsuite.BuildHHM(
		hhblits, hhmake, util.FlagSeqDB, inFasta)
	util.Assert(err, "Error building HHM")

	util.Assert(hhm.Write(util.CreateFile(outHHM), HHM),
		"Error writing HHM '%s'", outHHM)
}
<commit_msg>Moved the "apps" package into its own repository.<commit_after>// Example buildhhm shows how to construct an HHM using HHblits and HHmake
// from a single sequence FASTA file.
package main

import (
	"flag"

	"github.com/BurntSushi/bcbgo/cmd/util"
	"github.com/TuftsBCB/apps/hhsuite"
	"github.com/TuftsBCB/io/hhm"
)

var (
	flagQuiet = false
)

func init() {
	flag.BoolVar(&flagQuiet, "quiet", flagQuiet,
		"When set, hhblits/hhmake output will be hidden.")

	util.FlagUse("seq-db")
	util.FlagParse("in-fasta-file out-hhm-file", "")
	util.AssertNArg(2)
}

func main() {
	inFasta := util.Arg(0)
	outHHM := util.Arg(1)

	hhblits := hhsuite.HHBlitsDefault
	hhmake := hhsuite.HHMakePseudo
	hhblits.Verbose = !flagQuiet
	hhmake.Verbose = !flagQuiet

	HHM, err := hhsuite.BuildHHM(
		hhblits, hhmake, util.FlagSeqDB, inFasta)
	util.Assert(err, "Error building HHM")

	util.Assert(hhm.Write(util.CreateFile(outHHM), HHM),
		"Error writing HHM '%s'", outHHM)
}
<|endoftext|>


<commit_before>package runtime_test

import (
	"runtime"
	"testing"
)

func TestGcSys(t *testing.T) {
	runtime.GC()
	runtime.UpdateMemStats()
	sys := runtime.MemStats.Sys

	for i := 0; i < 1000000; i++ {
		workthegc()
	}

	// Should only be using a few MB.
	runtime.UpdateMemStats()
	if sys > runtime.MemStats.Sys {
		sys = 0
	} else {
		sys = runtime.MemStats.Sys - sys
	}
	t.Logf("used %d extra bytes", sys)
	if sys > 2<<20 {
		t.Fatalf("using too much memory: %d bytes", sys)
	}
}

func workthegc() []byte {
	return make([]byte, 1029)
}
<commit_msg>runtime: bump gc 'extra bytes' check<commit_after>package runtime_test

import (
	"runtime"
	"testing"
)

func TestGcSys(t *testing.T) {
	runtime.GC()
	runtime.UpdateMemStats()
	sys := runtime.MemStats.Sys

	for i := 0; i < 1000000; i++ {
		workthegc()
	}

	// Should only be using a few MB.
	runtime.UpdateMemStats()
	if sys > runtime.MemStats.Sys {
		sys = 0
	} else {
		sys = runtime.MemStats.Sys - sys
	}
	t.Logf("used %d extra bytes", sys)
	if sys > 4<<20 {
		t.Fatalf("using too much memory: %d bytes", sys)
	}
}

func workthegc() []byte {
	return make([]byte, 1029)
}
<|endoftext|>


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

package time_test

import (
	"errors"
	"fmt"
	"runtime"
	"sort"
	"sync/atomic"
	"testing"
	. "time"
)

func TestSleep(t *testing.T) {
	const delay = 100 * Millisecond
	go func() {
		Sleep(delay / 2)
		Interrupt()
	}()
	start := Now()
	Sleep(delay)
	duration := Now().Sub(start)
	if duration < delay {
		t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
	}
}

// Test the basic function calling behavior. Correct queueing
// behavior is tested elsewhere, since After and AfterFunc share
// the same code.
func TestAfterFunc(t *testing.T) {
	i := 10
	c := make(chan bool)
	var f func()
	f = func() {
		i--
		if i >= 0 {
			AfterFunc(0, f)
			Sleep(1 * Second)
		} else {
			c <- true
		}
	}

	AfterFunc(0, f)
	<-c
}

func TestAfterStress(t *testing.T) {
	stop := uint32(0)
	go func() {
		for atomic.LoadUint32(&stop) == 0 {
			runtime.GC()
			// Need to yield, because otherwise
			// the main goroutine will never set the stop flag.
			runtime.Gosched()
		}
	}()
	c := Tick(1)
	for i := 0; i < 100; i++ {
		<-c
	}
	atomic.StoreUint32(&stop, 1)
}

func BenchmarkAfterFunc(b *testing.B) {
	i := b.N
	c := make(chan bool)
	var f func()
	f = func() {
		i--
		if i >= 0 {
			AfterFunc(0, f)
		} else {
			c <- true
		}
	}

	AfterFunc(0, f)
	<-c
}

func BenchmarkAfter(b *testing.B) {
	for i := 0; i < b.N; i++ {
		<-After(1)
	}
}

func BenchmarkStop(b *testing.B) {
	for i := 0; i < b.N; i++ {
		NewTimer(1 * Second).Stop()
	}
}

func TestAfter(t *testing.T) {
	const delay = 100 * Millisecond
	start := Now()
	end := <-After(delay)
	if duration := Now().Sub(start); duration < delay {
		t.Fatalf("After(%s) slept for only %d ns", delay, duration)
	}
	if min := start.Add(delay); end.Before(min) {
		t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
	}
}

func TestAfterTick(t *testing.T) {
	const (
		Delta = 100 * Millisecond
		Count = 10
	)
	t0 := Now()
	for i := 0; i < Count; i++ {
		<-After(Delta)
	}
	t1 := Now()
	d := t1.Sub(t0)
	target := Delta * Count
	slop := target * 2 / 10
	if d < target-slop || d > target+slop {
		t.Fatalf("%d ticks of %s took %s, expected %s", Count, Delta, d, target)
	}
}

func TestAfterStop(t *testing.T) {
	AfterFunc(100*Millisecond, func() {})
	t0 := NewTimer(50 * Millisecond)
	c1 := make(chan bool, 1)
	t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
	c2 := After(200 * Millisecond)
	if !t0.Stop() {
		t.Fatalf("failed to stop event 0")
	}
	if !t1.Stop() {
		t.Fatalf("failed to stop event 1")
	}
	<-c2
	select {
	case <-t0.C:
		t.Fatalf("event 0 was not stopped")
	case <-c1:
		t.Fatalf("event 1 was not stopped")
	default:
	}
	if t1.Stop() {
		t.Fatalf("Stop returned true twice")
	}
}

func TestAfterQueuing(t *testing.T) {
	// This test flakes out on some systems,
	// so we'll try it a few times before declaring it a failure.
	const attempts = 3
	err := errors.New("!=nil")
	for i := 0; i < attempts && err != nil; i++ {
		if err = testAfterQueuing(t); err != nil {
			t.Logf("attempt %v failed: %v", i, err)
		}
	}
	if err != nil {
		t.Fatal(err)
	}
}

var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}

type afterResult struct {
	slot int
	t    Time
}

func await(slot int, result chan<- afterResult, ac <-chan Time) {
	result <- afterResult{slot, <-ac}
}

func testAfterQueuing(t *testing.T) error {
	const (
		Delta = 100 * Millisecond
	)
	// make the result channel buffered because we don't want
	// to depend on channel queueing semantics that might
	// possibly change in the future.
	result := make(chan afterResult, len(slots))

	t0 := Now()
	for _, slot := range slots {
		go await(slot, result, After(Duration(slot)*Delta))
	}
	sort.Ints(slots)
	for _, slot := range slots {
		r := <-result
		if r.slot != slot {
			return fmt.Errorf("after slot %d, expected %d", r.slot, slot)
		}
		dt := r.t.Sub(t0)
		target := Duration(slot) * Delta
		slop := Delta / 4
		if dt < target-slop || dt > target+slop {
			return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-slop, target+slop)
		}
	}
	return nil
}

func TestTimerStopStress(t *testing.T) {
	if testing.Short() {
		return
	}
	for i := 0; i < 100; i++ {
		go func(i int) {
			timer := AfterFunc(2*Second, func() {
				t.Fatalf("timer %d was not stopped", i)
			})
			Sleep(1 * Second)
			timer.Stop()
		}(i)
	}
	Sleep(3 * Second)
}
<commit_msg>time: allow sleep tests to run for 200% too long<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package time_test

import (
	"errors"
	"fmt"
	"runtime"
	"sort"
	"sync/atomic"
	"testing"
	. "time"
)

func TestSleep(t *testing.T) {
	const delay = 100 * Millisecond
	go func() {
		Sleep(delay / 2)
		Interrupt()
	}()
	start := Now()
	Sleep(delay)
	duration := Now().Sub(start)
	if duration < delay {
		t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
	}
}

// Test the basic function calling behavior. Correct queueing
// behavior is tested elsewhere, since After and AfterFunc share
// the same code.
func TestAfterFunc(t *testing.T) {
	i := 10
	c := make(chan bool)
	var f func()
	f = func() {
		i--
		if i >= 0 {
			AfterFunc(0, f)
			Sleep(1 * Second)
		} else {
			c <- true
		}
	}

	AfterFunc(0, f)
	<-c
}

func TestAfterStress(t *testing.T) {
	stop := uint32(0)
	go func() {
		for atomic.LoadUint32(&stop) == 0 {
			runtime.GC()
			// Need to yield, because otherwise
			// the main goroutine will never set the stop flag.
			runtime.Gosched()
		}
	}()
	c := Tick(1)
	for i := 0; i < 100; i++ {
		<-c
	}
	atomic.StoreUint32(&stop, 1)
}

func BenchmarkAfterFunc(b *testing.B) {
	i := b.N
	c := make(chan bool)
	var f func()
	f = func() {
		i--
		if i >= 0 {
			AfterFunc(0, f)
		} else {
			c <- true
		}
	}

	AfterFunc(0, f)
	<-c
}

func BenchmarkAfter(b *testing.B) {
	for i := 0; i < b.N; i++ {
		<-After(1)
	}
}

func BenchmarkStop(b *testing.B) {
	for i := 0; i < b.N; i++ {
		NewTimer(1 * Second).Stop()
	}
}

func TestAfter(t *testing.T) {
	const delay = 100 * Millisecond
	start := Now()
	end := <-After(delay)
	if duration := Now().Sub(start); duration < delay {
		t.Fatalf("After(%s) slept for only %d ns", delay, duration)
	}
	if min := start.Add(delay); end.Before(min) {
		t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
	}
}

func TestAfterTick(t *testing.T) {
	const (
		Delta = 100 * Millisecond
		Count = 10
	)
	t0 := Now()
	for i := 0; i < Count; i++ {
		<-After(Delta)
	}
	t1 := Now()
	d := t1.Sub(t0)
	target := Delta * Count
	if d < target*9/10 || d > target*30/10 {
		t.Fatalf("%d ticks of %s took %s, expected %s", Count, Delta, d, target)
	}
}

func TestAfterStop(t *testing.T) {
	AfterFunc(100*Millisecond, func() {})
	t0 := NewTimer(50 * Millisecond)
	c1 := make(chan bool, 1)
	t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
	c2 := After(200 * Millisecond)
	if !t0.Stop() {
		t.Fatalf("failed to stop event 0")
	}
	if !t1.Stop() {
		t.Fatalf("failed to stop event 1")
	}
	<-c2
	select {
	case <-t0.C:
		t.Fatalf("event 0 was not stopped")
	case <-c1:
		t.Fatalf("event 1 was not stopped")
	default:
	}
	if t1.Stop() {
		t.Fatalf("Stop returned true twice")
	}
}

func TestAfterQueuing(t *testing.T) {
	// This test flakes out on some systems,
	// so we'll try it a few times before declaring it a failure.
	const attempts = 3
	err := errors.New("!=nil")
	for i := 0; i < attempts && err != nil; i++ {
		if err = testAfterQueuing(t); err != nil {
			t.Logf("attempt %v failed: %v", i, err)
		}
	}
	if err != nil {
		t.Fatal(err)
	}
}

var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}

type afterResult struct {
	slot int
	t    Time
}

func await(slot int, result chan<- afterResult, ac <-chan Time) {
	result <- afterResult{slot, <-ac}
}

func testAfterQueuing(t *testing.T) error {
	const (
		Delta = 100 * Millisecond
	)
	// make the result channel buffered because we don't want
	// to depend on channel queueing semantics that might
	// possibly change in the future.
	result := make(chan afterResult, len(slots))

	t0 := Now()
	for _, slot := range slots {
		go await(slot, result, After(Duration(slot)*Delta))
	}
	sort.Ints(slots)
	for _, slot := range slots {
		r := <-result
		if r.slot != slot {
			return fmt.Errorf("after slot %d, expected %d", r.slot, slot)
		}
		dt := r.t.Sub(t0)
		target := Duration(slot) * Delta
		if dt < target-Delta/2 || dt > target+Delta*10 {
			return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-Delta/2, target+Delta*10)
		}
	}
	return nil
}

func TestTimerStopStress(t *testing.T) {
	if testing.Short() {
		return
	}
	for i := 0; i < 100; i++ {
		go func(i int) {
			timer := AfterFunc(2*Second, func() {
				t.Fatalf("timer %d was not stopped", i)
			})
			Sleep(1 * Second)
			timer.Stop()
		}(i)
	}
	Sleep(3 * Second)
}
<|endoftext|>