<commit_before>// Copyright 2016 NDP Systèmes. All Rights Reserved.
//
// 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 models

import (
	"testing"

	"github.com/npiganeau/yep/yep/models/security"
	. "github.com/smartystreets/goconvey/convey"
)

func TestConditions(t *testing.T) {
	Convey("Testing SQL building for queries", t, func() {
		if dbArgs.Driver == "postgres" {
			SimulateInNewEnvironment(security.SuperUserID, func(env Environment) {
				rs := env.Pool("User")
				rs = rs.Search(rs.Model().FilteredOn("Profile", env.Pool("Profile").Model().FilteredOn("BestPost", env.Pool("Post").Model().Field("Title").Equals("foo"))))
				fields := []string{"name", "profile_id.best_post_id.title"}
				Convey("Simple query with database field names", func() {
					rs = env.Pool("User").Search(rs.Model().FilteredOn("profile_id", env.Pool("Profile").Model().Field("best_post_id.title").Equals("foo")))
					sql, args := rs.query.selectQuery(fields)
					So(sql, ShouldEqual, `SELECT DISTINCT "user".name AS name, "user__profile__post".title AS profile_id__best_post_id__title FROM "user" "user" LEFT JOIN "profile" "user__profile" ON "user".profile_id="user__profile".id LEFT JOIN "post" "user__profile__post" ON "user__profile".best_post_id="user__profile__post".id  WHERE ("user__profile__post".title = ? ) `)
					So(args, ShouldContain, "foo")
				})
				Convey("Simple query with struct field names", func() {
					fields := []string{"Name", "Profile.BestPost.Title"}
					sql, args := rs.query.selectQuery(fields)
					So(sql, ShouldEqual, `SELECT DISTINCT "user".name AS name, "user__profile__post".title AS profile_id__best_post_id__title FROM "user" "user" LEFT JOIN "profile" "user__profile" ON "user".profile_id="user__profile".id LEFT JOIN "post" "user__profile__post" ON "user__profile".best_post_id="user__profile__post".id  WHERE ("user__profile__post".title = ? ) `)
					So(args, ShouldContain, "foo")
				})
				Convey("Simple query with args inflation", func() {
					getUserID := func(rc RecordCollection) int64 {
						return rc.Env().Uid()
					}
					rs2 := env.Pool("User").Search(rs.Model().Field("Nums").Equals(getUserID))
					fields := []string{"Name"}
					sql, args := rs2.query.selectQuery(fields)
					So(sql, ShouldEqual, `SELECT DISTINCT "user".name AS name FROM "user" "user"  WHERE ("user".nums = ? ) `)
					So(len(args), ShouldEqual, 1)
					So(args, ShouldContain, security.SuperUserID)
				})
				Convey("Check WHERE clause with additionnal filter", func() {
					rs = rs.Search(rs.Model().Field("Profile.Age").GreaterOrEqual(12))
					sql, args := rs.query.sqlWhereClause()
					So(sql, ShouldEqual, `WHERE ("user__profile__post".title = ? ) AND ("user__profile".age >= ? ) `)
					So(args, ShouldContain, 12)
					So(args, ShouldContain, "foo")
				})
				Convey("Check full query with all conditions", func() {
					rs = rs.Search(rs.Model().Field("Profile.Age").GreaterOrEqual(12))
					c2 := rs.Model().Field("name").Like("jane").Or().Field("Profile.Money").Lower(1234.56)
					rs = rs.Search(c2)
					sql, args := rs.query.sqlWhereClause()
					So(sql, ShouldEqual, `WHERE ("user__profile__post".title = ? ) AND ("user__profile".age >= ? ) AND ("user".name LIKE ? OR "user__profile".money < ? ) `)
					So(args, ShouldContain, "%jane%")
					So(args, ShouldContain, 1234.56)
					sql, _ = rs.query.selectQuery(fields)
					So(sql, ShouldEqual, `SELECT DISTINCT "user".name AS name, "user__profile__post".title AS profile_id__best_post_id__title FROM "user" "user" LEFT JOIN "profile" "user__profile" ON "user".profile_id="user__profile".id LEFT JOIN "post" "user__profile__post" ON "user__profile".best_post_id="user__profile__post".id  WHERE ("user__profile__post".title = ? ) AND ("user__profile".age >= ? ) AND ("user".name LIKE ? OR "user__profile".money < ? ) `)
				})
				Convey("Testing query without WHERE clause", func() {
					rs = env.Pool("User").Load()
					fields := []string{"name"}
					sql, _ := rs.query.selectQuery(fields)
					So(sql, ShouldEqual, `SELECT DISTINCT "user".name AS name FROM "user" "user"  `)
				})
			})
		}
	})
}
<commit_msg>Fix tests<commit_after>// Copyright 2016 NDP Systèmes. All Rights Reserved.
//
// 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 models

import (
	"testing"

	"github.com/npiganeau/yep/yep/models/security"
	. "github.com/smartystreets/goconvey/convey"
)

func TestConditions(t *testing.T) {
	Convey("Testing SQL building for queries", t, func() {
		if dbArgs.Driver == "postgres" {
			SimulateInNewEnvironment(security.SuperUserID, func(env Environment) {
				rs := env.Pool("User")
				rs = rs.Search(rs.Model().FilteredOn("Profile", env.Pool("Profile").Model().FilteredOn("BestPost", env.Pool("Post").Model().Field("Title").Equals("foo"))))
				fields := []string{"name", "profile_id.best_post_id.title"}
				Convey("Simple query with database field names", func() {
					rs = env.Pool("User").Search(rs.Model().FilteredOn("profile_id", env.Pool("Profile").Model().Field("best_post_id.title").Equals("foo")))
					sql, args := rs.query.selectQuery(fields)
					So(sql, ShouldEqual, `SELECT DISTINCT "user".name AS name, "user__profile__post".title AS profile_id__best_post_id__title FROM "user" "user" LEFT JOIN "profile" "user__profile" ON "user".profile_id="user__profile".id LEFT JOIN "post" "user__profile__post" ON "user__profile".best_post_id="user__profile__post".id  WHERE ("user__profile__post".title = ? ) ORDER BY id `)
					So(args, ShouldContain, "foo")
				})
				Convey("Simple query with struct field names", func() {
					fields := []string{"Name", "Profile.BestPost.Title"}
					sql, args := rs.query.selectQuery(fields)
					So(sql, ShouldEqual, `SELECT DISTINCT "user".name AS name, "user__profile__post".title AS profile_id__best_post_id__title FROM "user" "user" LEFT JOIN "profile" "user__profile" ON "user".profile_id="user__profile".id LEFT JOIN "post" "user__profile__post" ON "user__profile".best_post_id="user__profile__post".id  WHERE ("user__profile__post".title = ? ) ORDER BY id `)
					So(args, ShouldContain, "foo")
				})
				Convey("Simple query with args inflation", func() {
					getUserID := func(rc RecordCollection) int64 {
						return rc.Env().Uid()
					}
					rs2 := env.Pool("User").Search(rs.Model().Field("Nums").Equals(getUserID))
					fields := []string{"Name"}
					sql, args := rs2.query.selectQuery(fields)
					So(sql, ShouldEqual, `SELECT DISTINCT "user".name AS name FROM "user" "user"  WHERE ("user".nums = ? ) ORDER BY id `)
					So(len(args), ShouldEqual, 1)
					So(args, ShouldContain, security.SuperUserID)
				})
				Convey("Check WHERE clause with additionnal filter", func() {
					rs = rs.Search(rs.Model().Field("Profile.Age").GreaterOrEqual(12))
					sql, args := rs.query.sqlWhereClause()
					So(sql, ShouldEqual, `WHERE ("user__profile__post".title = ? ) AND ("user__profile".age >= ? ) `)
					So(args, ShouldContain, 12)
					So(args, ShouldContain, "foo")
				})
				Convey("Check full query with all conditions", func() {
					rs = rs.Search(rs.Model().Field("Profile.Age").GreaterOrEqual(12))
					c2 := rs.Model().Field("name").Like("jane").Or().Field("Profile.Money").Lower(1234.56)
					rs = rs.Search(c2)
					sql, args := rs.query.sqlWhereClause()
					So(sql, ShouldEqual, `WHERE ("user__profile__post".title = ? ) AND ("user__profile".age >= ? ) AND ("user".name LIKE ? OR "user__profile".money < ? ) `)
					So(args, ShouldContain, "%jane%")
					So(args, ShouldContain, 1234.56)
					sql, _ = rs.query.selectQuery(fields)
					So(sql, ShouldEqual, `SELECT DISTINCT "user".name AS name, "user__profile__post".title AS profile_id__best_post_id__title FROM "user" "user" LEFT JOIN "profile" "user__profile" ON "user".profile_id="user__profile".id LEFT JOIN "post" "user__profile__post" ON "user__profile".best_post_id="user__profile__post".id  WHERE ("user__profile__post".title = ? ) AND ("user__profile".age >= ? ) AND ("user".name LIKE ? OR "user__profile".money < ? ) ORDER BY id `)
				})
				Convey("Testing query without WHERE clause", func() {
					rs = env.Pool("User").Load()
					fields := []string{"name"}
					sql, _ := rs.query.selectQuery(fields)
					So(sql, ShouldEqual, `SELECT DISTINCT "user".name AS name FROM "user" "user"  ORDER BY id `)
				})
			})
		}
	})
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors.

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

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

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

/* This test check that SecurityContext parameters specified at the
 * pod or the container level work as intended. These tests cannot be
 * run when the 'SecurityContextDeny' admission controller is not used
 * so they are skipped by default.
 */

package node

import (
	"fmt"

	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/kubernetes/test/e2e/framework"
	imageutils "k8s.io/kubernetes/test/utils/image"

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

func scTestPod(hostIPC bool, hostPID bool) *v1.Pod {
	podName := "security-context-" + string(uuid.NewUUID())
	pod := &v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:        podName,
			Labels:      map[string]string{"name": podName},
			Annotations: map[string]string{},
		},
		Spec: v1.PodSpec{
			HostIPC:         hostIPC,
			HostPID:         hostPID,
			SecurityContext: &v1.PodSecurityContext{},
			Containers: []v1.Container{
				{
					Name:  "test-container",
					Image: imageutils.GetE2EImage(imageutils.BusyBox),
				},
			},
			RestartPolicy: v1.RestartPolicyNever,
		},
	}

	return pod
}

var _ = SIGDescribe("Security Context [Feature:SecurityContext]", func() {
	f := framework.NewDefaultFramework("security-context")

	It("should support pod.Spec.SecurityContext.SupplementalGroups", func() {
		pod := scTestPod(false, false)
		pod.Spec.Containers[0].Command = []string{"id", "-G"}
		pod.Spec.SecurityContext.SupplementalGroups = []int64{1234, 5678}
		groups := []string{"1234", "5678"}
		f.TestContainerOutput("pod.Spec.SecurityContext.SupplementalGroups", pod, 0, groups)
	})

	It("should support pod.Spec.SecurityContext.RunAsUser", func() {
		pod := scTestPod(false, false)
		userID := int64(1001)
		pod.Spec.SecurityContext.RunAsUser = &userID
		pod.Spec.Containers[0].Command = []string{"sh", "-c", "id -u"}

		f.TestContainerOutput("pod.Spec.SecurityContext.RunAsUser", pod, 0, []string{
			fmt.Sprintf("%v", userID),
		})
	})

	It("should support pod.Spec.SecurityContext.RunAsUser And pod.Spec.SecurityContext.RunAsGroup [Feature:RunAsGroup]", func() {
		pod := scTestPod(false, false)
		userID := int64(1001)
		groupID := int64(2002)
		pod.Spec.SecurityContext.RunAsUser = &userID
		pod.Spec.SecurityContext.RunAsGroup = &groupID
		pod.Spec.Containers[0].Command = []string{"sh", "-c", "id"}

		f.TestContainerOutput("pod.Spec.SecurityContext.RunAsUser", pod, 0, []string{
			fmt.Sprintf("uid=%v", userID),
			fmt.Sprintf("gid=%v", groupID),
		})
	})

	It("should support container.SecurityContext.RunAsUser", func() {
		pod := scTestPod(false, false)
		userID := int64(1001)
		overrideUserID := int64(1002)
		pod.Spec.SecurityContext.RunAsUser = &userID
		pod.Spec.Containers[0].SecurityContext = new(v1.SecurityContext)
		pod.Spec.Containers[0].SecurityContext.RunAsUser = &overrideUserID
		pod.Spec.Containers[0].Command = []string{"sh", "-c", "id -u"}

		f.TestContainerOutput("pod.Spec.SecurityContext.RunAsUser", pod, 0, []string{
			fmt.Sprintf("%v", overrideUserID),
		})
	})

	It("should support container.SecurityContext.RunAsUser And container.SecurityContext.RunAsGroup [Feature:RunAsGroup]", func() {
		pod := scTestPod(false, false)
		userID := int64(1001)
		groupID := int64(2001)
		overrideUserID := int64(1002)
		overrideGroupID := int64(2002)
		pod.Spec.SecurityContext.RunAsUser = &userID
		pod.Spec.SecurityContext.RunAsGroup = &groupID
		pod.Spec.Containers[0].SecurityContext = new(v1.SecurityContext)
		pod.Spec.Containers[0].SecurityContext.RunAsUser = &overrideUserID
		pod.Spec.Containers[0].SecurityContext.RunAsGroup = &overrideGroupID
		pod.Spec.Containers[0].Command = []string{"sh", "-c", "id"}

		f.TestContainerOutput("pod.Spec.SecurityContext.RunAsUser", pod, 0, []string{
			fmt.Sprintf("uid=%v", overrideUserID),
			fmt.Sprintf("gid=%v", overrideGroupID),
		})
	})

	It("should support volume SELinux relabeling", func() {
		testPodSELinuxLabeling(f, false, false)
	})

	It("should support volume SELinux relabeling when using hostIPC", func() {
		testPodSELinuxLabeling(f, true, false)
	})

	It("should support volume SELinux relabeling when using hostPID", func() {
		testPodSELinuxLabeling(f, false, true)
	})

	It("should support seccomp alpha unconfined annotation on the container [Feature:Seccomp]", func() {
		// TODO: port to SecurityContext as soon as seccomp is out of alpha
		pod := scTestPod(false, false)
		pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+"test-container"] = "unconfined"
		pod.Annotations[v1.SeccompPodAnnotationKey] = v1.SeccompProfileRuntimeDefault
		pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
		f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"0"}) // seccomp disabled
	})

	It("should support seccomp alpha unconfined annotation on the pod [Feature:Seccomp]", func() {
		// TODO: port to SecurityContext as soon as seccomp is out of alpha
		pod := scTestPod(false, false)
		pod.Annotations[v1.SeccompPodAnnotationKey] = "unconfined"
		pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
		f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"0"}) // seccomp disabled
	})

	It("should support seccomp alpha runtime/default annotation [Feature:Seccomp]", func() {
		// TODO: port to SecurityContext as soon as seccomp is out of alpha
		pod := scTestPod(false, false)
		pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+"test-container"] = v1.SeccompProfileRuntimeDefault
		pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
		f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"2"}) // seccomp filtered
	})

	It("should support seccomp default which is unconfined [Feature:Seccomp]", func() {
		// TODO: port to SecurityContext as soon as seccomp is out of alpha
		pod := scTestPod(false, false)
		pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
		f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"0"}) // seccomp disabled
	})
})

func testPodSELinuxLabeling(f *framework.Framework, hostIPC bool, hostPID bool) {
	// Write and read a file with an empty_dir volume
	// with a pod with the MCS label s0:c0,c1
	pod := scTestPod(hostIPC, hostPID)
	volumeName := "test-volume"
	mountPath := "/mounted_volume"
	pod.Spec.Containers[0].VolumeMounts = []v1.VolumeMount{
		{
			Name:      volumeName,
			MountPath: mountPath,
		},
	}
	pod.Spec.Volumes = []v1.Volume{
		{
			Name: volumeName,
			VolumeSource: v1.VolumeSource{
				EmptyDir: &v1.EmptyDirVolumeSource{
					Medium: v1.StorageMediumDefault,
				},
			},
		},
	}
	pod.Spec.SecurityContext.SELinuxOptions = &v1.SELinuxOptions{
		Level: "s0:c0,c1",
	}
	pod.Spec.Containers[0].Command = []string{"sleep", "6000"}

	client := f.ClientSet.CoreV1().Pods(f.Namespace.Name)
	pod, err := client.Create(pod)

	framework.ExpectNoError(err, "Error creating pod %v", pod)
	framework.ExpectNoError(framework.WaitForPodRunningInNamespace(f.ClientSet, pod))

	testContent := "hello"
	testFilePath := mountPath + "/TEST"
	err = f.WriteFileViaContainer(pod.Name, pod.Spec.Containers[0].Name, testFilePath, testContent)
	Expect(err).To(BeNil())
	content, err := f.ReadFileViaContainer(pod.Name, pod.Spec.Containers[0].Name, testFilePath)
	Expect(err).To(BeNil())
	Expect(content).To(ContainSubstring(testContent))

	foundPod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(pod.Name, metav1.GetOptions{})
	Expect(err).NotTo(HaveOccurred())

	// Confirm that the file can be accessed from a second
	// pod using host_path with the same MCS label
	volumeHostPath := fmt.Sprintf("%s/pods/%s/volumes/kubernetes.io~empty-dir/%s", framework.TestContext.KubeVolumeDir, foundPod.UID, volumeName)
	By(fmt.Sprintf("confirming a container with the same label can read the file under --volume-dir=%s", framework.TestContext.KubeVolumeDir))
	pod = scTestPod(hostIPC, hostPID)
	pod.Spec.NodeName = foundPod.Spec.NodeName
	volumeMounts := []v1.VolumeMount{
		{
			Name:      volumeName,
			MountPath: mountPath,
		},
	}
	volumes := []v1.Volume{
		{
			Name: volumeName,
			VolumeSource: v1.VolumeSource{
				HostPath: &v1.HostPathVolumeSource{
					Path: volumeHostPath,
				},
			},
		},
	}
	pod.Spec.Containers[0].VolumeMounts = volumeMounts
	pod.Spec.Volumes = volumes
	pod.Spec.Containers[0].Command = []string{"cat", testFilePath}
	pod.Spec.SecurityContext.SELinuxOptions = &v1.SELinuxOptions{
		Level: "s0:c0,c1",
	}

	f.TestContainerOutput("Pod with same MCS label reading test file", pod, 0, []string{testContent})
	// Confirm that the same pod with a different MCS
	// label cannot access the volume
	pod = scTestPod(hostIPC, hostPID)
	pod.Spec.Volumes = volumes
	pod.Spec.Containers[0].VolumeMounts = volumeMounts
	pod.Spec.Containers[0].Command = []string{"sleep", "6000"}
	pod.Spec.SecurityContext.SELinuxOptions = &v1.SELinuxOptions{
		Level: "s0:c2,c3",
	}
	_, err = client.Create(pod)
	framework.ExpectNoError(err, "Error creating pod %v", pod)

	err = f.WaitForPodRunning(pod.Name)
	framework.ExpectNoError(err, "Error waiting for pod to run %v", pod)

	content, err = f.ReadFileViaContainer(pod.Name, "test-container", testFilePath)
	Expect(content).NotTo(ContainSubstring(testContent))
}
<commit_msg>verify gid in runasuser tests<commit_after>/*
Copyright 2015 The Kubernetes Authors.

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

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

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

/* This test check that SecurityContext parameters specified at the
 * pod or the container level work as intended. These tests cannot be
 * run when the 'SecurityContextDeny' admission controller is not used
 * so they are skipped by default.
 */

package node

import (
	"fmt"

	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/kubernetes/test/e2e/framework"
	imageutils "k8s.io/kubernetes/test/utils/image"

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

func scTestPod(hostIPC bool, hostPID bool) *v1.Pod {
	podName := "security-context-" + string(uuid.NewUUID())
	pod := &v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:        podName,
			Labels:      map[string]string{"name": podName},
			Annotations: map[string]string{},
		},
		Spec: v1.PodSpec{
			HostIPC:         hostIPC,
			HostPID:         hostPID,
			SecurityContext: &v1.PodSecurityContext{},
			Containers: []v1.Container{
				{
					Name:  "test-container",
					Image: imageutils.GetE2EImage(imageutils.BusyBox),
				},
			},
			RestartPolicy: v1.RestartPolicyNever,
		},
	}

	return pod
}

var _ = SIGDescribe("Security Context [Feature:SecurityContext]", func() {
	f := framework.NewDefaultFramework("security-context")

	It("should support pod.Spec.SecurityContext.SupplementalGroups", func() {
		pod := scTestPod(false, false)
		pod.Spec.Containers[0].Command = []string{"id", "-G"}
		pod.Spec.SecurityContext.SupplementalGroups = []int64{1234, 5678}
		groups := []string{"1234", "5678"}
		f.TestContainerOutput("pod.Spec.SecurityContext.SupplementalGroups", pod, 0, groups)
	})

	It("should support pod.Spec.SecurityContext.RunAsUser", func() {
		pod := scTestPod(false, false)
		userID := int64(1001)
		pod.Spec.SecurityContext.RunAsUser = &userID
		pod.Spec.Containers[0].Command = []string{"sh", "-c", "id"}

		f.TestContainerOutput("pod.Spec.SecurityContext.RunAsUser", pod, 0, []string{
			fmt.Sprintf("uid=%v", userID),
			fmt.Sprintf("gid=%v", 0),
		})
	})

	It("should support pod.Spec.SecurityContext.RunAsUser And pod.Spec.SecurityContext.RunAsGroup [Feature:RunAsGroup]", func() {
		pod := scTestPod(false, false)
		userID := int64(1001)
		groupID := int64(2002)
		pod.Spec.SecurityContext.RunAsUser = &userID
		pod.Spec.SecurityContext.RunAsGroup = &groupID
		pod.Spec.Containers[0].Command = []string{"sh", "-c", "id"}

		f.TestContainerOutput("pod.Spec.SecurityContext.RunAsUser", pod, 0, []string{
			fmt.Sprintf("uid=%v", userID),
			fmt.Sprintf("gid=%v", groupID),
		})
	})

	It("should support container.SecurityContext.RunAsUser", func() {
		pod := scTestPod(false, false)
		userID := int64(1001)
		overrideUserID := int64(1002)
		pod.Spec.SecurityContext.RunAsUser = &userID
		pod.Spec.Containers[0].SecurityContext = new(v1.SecurityContext)
		pod.Spec.Containers[0].SecurityContext.RunAsUser = &overrideUserID
		pod.Spec.Containers[0].Command = []string{"sh", "-c", "id"}

		f.TestContainerOutput("pod.Spec.SecurityContext.RunAsUser", pod, 0, []string{
			fmt.Sprintf("uid=%v", overrideUserID),
			fmt.Sprintf("gid=%v", 0),
		})
	})

	It("should support container.SecurityContext.RunAsUser And container.SecurityContext.RunAsGroup [Feature:RunAsGroup]", func() {
		pod := scTestPod(false, false)
		userID := int64(1001)
		groupID := int64(2001)
		overrideUserID := int64(1002)
		overrideGroupID := int64(2002)
		pod.Spec.SecurityContext.RunAsUser = &userID
		pod.Spec.SecurityContext.RunAsGroup = &groupID
		pod.Spec.Containers[0].SecurityContext = new(v1.SecurityContext)
		pod.Spec.Containers[0].SecurityContext.RunAsUser = &overrideUserID
		pod.Spec.Containers[0].SecurityContext.RunAsGroup = &overrideGroupID
		pod.Spec.Containers[0].Command = []string{"sh", "-c", "id"}

		f.TestContainerOutput("pod.Spec.SecurityContext.RunAsUser", pod, 0, []string{
			fmt.Sprintf("uid=%v", overrideUserID),
			fmt.Sprintf("gid=%v", overrideGroupID),
		})
	})

	It("should support volume SELinux relabeling", func() {
		testPodSELinuxLabeling(f, false, false)
	})

	It("should support volume SELinux relabeling when using hostIPC", func() {
		testPodSELinuxLabeling(f, true, false)
	})

	It("should support volume SELinux relabeling when using hostPID", func() {
		testPodSELinuxLabeling(f, false, true)
	})

	It("should support seccomp alpha unconfined annotation on the container [Feature:Seccomp]", func() {
		// TODO: port to SecurityContext as soon as seccomp is out of alpha
		pod := scTestPod(false, false)
		pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+"test-container"] = "unconfined"
		pod.Annotations[v1.SeccompPodAnnotationKey] = v1.SeccompProfileRuntimeDefault
		pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
		f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"0"}) // seccomp disabled
	})

	It("should support seccomp alpha unconfined annotation on the pod [Feature:Seccomp]", func() {
		// TODO: port to SecurityContext as soon as seccomp is out of alpha
		pod := scTestPod(false, false)
		pod.Annotations[v1.SeccompPodAnnotationKey] = "unconfined"
		pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
		f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"0"}) // seccomp disabled
	})

	It("should support seccomp alpha runtime/default annotation [Feature:Seccomp]", func() {
		// TODO: port to SecurityContext as soon as seccomp is out of alpha
		pod := scTestPod(false, false)
		pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+"test-container"] = v1.SeccompProfileRuntimeDefault
		pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
		f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"2"}) // seccomp filtered
	})

	It("should support seccomp default which is unconfined [Feature:Seccomp]", func() {
		// TODO: port to SecurityContext as soon as seccomp is out of alpha
		pod := scTestPod(false, false)
		pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
		f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"0"}) // seccomp disabled
	})
})

func testPodSELinuxLabeling(f *framework.Framework, hostIPC bool, hostPID bool) {
	// Write and read a file with an empty_dir volume
	// with a pod with the MCS label s0:c0,c1
	pod := scTestPod(hostIPC, hostPID)
	volumeName := "test-volume"
	mountPath := "/mounted_volume"
	pod.Spec.Containers[0].VolumeMounts = []v1.VolumeMount{
		{
			Name:      volumeName,
			MountPath: mountPath,
		},
	}
	pod.Spec.Volumes = []v1.Volume{
		{
			Name: volumeName,
			VolumeSource: v1.VolumeSource{
				EmptyDir: &v1.EmptyDirVolumeSource{
					Medium: v1.StorageMediumDefault,
				},
			},
		},
	}
	pod.Spec.SecurityContext.SELinuxOptions = &v1.SELinuxOptions{
		Level: "s0:c0,c1",
	}
	pod.Spec.Containers[0].Command = []string{"sleep", "6000"}

	client := f.ClientSet.CoreV1().Pods(f.Namespace.Name)
	pod, err := client.Create(pod)

	framework.ExpectNoError(err, "Error creating pod %v", pod)
	framework.ExpectNoError(framework.WaitForPodRunningInNamespace(f.ClientSet, pod))

	testContent := "hello"
	testFilePath := mountPath + "/TEST"
	err = f.WriteFileViaContainer(pod.Name, pod.Spec.Containers[0].Name, testFilePath, testContent)
	Expect(err).To(BeNil())
	content, err := f.ReadFileViaContainer(pod.Name, pod.Spec.Containers[0].Name, testFilePath)
	Expect(err).To(BeNil())
	Expect(content).To(ContainSubstring(testContent))

	foundPod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(pod.Name, metav1.GetOptions{})
	Expect(err).NotTo(HaveOccurred())

	// Confirm that the file can be accessed from a second
	// pod using host_path with the same MCS label
	volumeHostPath := fmt.Sprintf("%s/pods/%s/volumes/kubernetes.io~empty-dir/%s", framework.TestContext.KubeVolumeDir, foundPod.UID, volumeName)
	By(fmt.Sprintf("confirming a container with the same label can read the file under --volume-dir=%s", framework.TestContext.KubeVolumeDir))
	pod = scTestPod(hostIPC, hostPID)
	pod.Spec.NodeName = foundPod.Spec.NodeName
	volumeMounts := []v1.VolumeMount{
		{
			Name:      volumeName,
			MountPath: mountPath,
		},
	}
	volumes := []v1.Volume{
		{
			Name: volumeName,
			VolumeSource: v1.VolumeSource{
				HostPath: &v1.HostPathVolumeSource{
					Path: volumeHostPath,
				},
			},
		},
	}
	pod.Spec.Containers[0].VolumeMounts = volumeMounts
	pod.Spec.Volumes = volumes
	pod.Spec.Containers[0].Command = []string{"cat", testFilePath}
	pod.Spec.SecurityContext.SELinuxOptions = &v1.SELinuxOptions{
		Level: "s0:c0,c1",
	}

	f.TestContainerOutput("Pod with same MCS label reading test file", pod, 0, []string{testContent})
	// Confirm that the same pod with a different MCS
	// label cannot access the volume
	pod = scTestPod(hostIPC, hostPID)
	pod.Spec.Volumes = volumes
	pod.Spec.Containers[0].VolumeMounts = volumeMounts
	pod.Spec.Containers[0].Command = []string{"sleep", "6000"}
	pod.Spec.SecurityContext.SELinuxOptions = &v1.SELinuxOptions{
		Level: "s0:c2,c3",
	}
	_, err = client.Create(pod)
	framework.ExpectNoError(err, "Error creating pod %v", pod)

	err = f.WaitForPodRunning(pod.Name)
	framework.ExpectNoError(err, "Error waiting for pod to run %v", pod)

	content, err = f.ReadFileViaContainer(pod.Name, "test-container", testFilePath)
	Expect(content).NotTo(ContainSubstring(testContent))
}
<|endoftext|>


<commit_before>package gpio

import (
	"strings"
	"testing"

	"gobot.io/x/gobot"
	"gobot.io/x/gobot/gobottest"
)

var _ gobot.Driver = (*BuzzerDriver)(nil)

func initTestBuzzerDriver(conn DigitalWriter) *BuzzerDriver {
	testAdaptorDigitalWrite = func() (err error) {
		return nil
	}
	testAdaptorPwmWrite = func() (err error) {
		return nil
	}
	return NewBuzzerDriver(conn, "1")
}

func TestBuzzerDriverDefaultName(t *testing.T) {
	g := initTestBuzzerDriver(newGpioTestAdaptor())
	gobottest.Assert(t, strings.HasPrefix(g.Name(), "Buzzer"), true)
}

func TestBuzzerDriverSetName(t *testing.T) {
	g := initTestBuzzerDriver(newGpioTestAdaptor())
	g.SetName("mybot")
	gobottest.Assert(t, g.Name(), "mybot")
}

func TestBuzzerDriverStart(t *testing.T) {
	d := initTestBuzzerDriver(newGpioTestAdaptor())
	gobottest.Assert(t, d.Start(), nil)
}

func TestBuzzerDriverHalt(t *testing.T) {
	d := initTestBuzzerDriver(newGpioTestAdaptor())
	gobottest.Assert(t, d.Halt(), nil)
}

func TestBuzzerDriverToggle(t *testing.T) {
	d := initTestBuzzerDriver(newGpioTestAdaptor())
	d.Off()
	d.Toggle()
	gobottest.Assert(t, d.State(), true)
	d.Toggle()
	gobottest.Assert(t, d.State(), false)
}
<commit_msg>gpio: increase test coverage for buzzer driver<commit_after>package gpio

import (
	"strings"
	"testing"

	"gobot.io/x/gobot"
	"gobot.io/x/gobot/gobottest"
)

var _ gobot.Driver = (*BuzzerDriver)(nil)

func initTestBuzzerDriver(conn DigitalWriter) *BuzzerDriver {
	testAdaptorDigitalWrite = func() (err error) {
		return nil
	}
	testAdaptorPwmWrite = func() (err error) {
		return nil
	}
	return NewBuzzerDriver(conn, "1")
}

func TestBuzzerDriverDefaultName(t *testing.T) {
	g := initTestBuzzerDriver(newGpioTestAdaptor())
	gobottest.Assert(t, strings.HasPrefix(g.Name(), "Buzzer"), true)
}

func TestBuzzerDriverSetName(t *testing.T) {
	g := initTestBuzzerDriver(newGpioTestAdaptor())
	g.SetName("mybot")
	gobottest.Assert(t, g.Name(), "mybot")
}

func TestBuzzerDriverStart(t *testing.T) {
	d := initTestBuzzerDriver(newGpioTestAdaptor())
	gobottest.Assert(t, d.Start(), nil)
}

func TestBuzzerDriverHalt(t *testing.T) {
	d := initTestBuzzerDriver(newGpioTestAdaptor())
	gobottest.Assert(t, d.Halt(), nil)
}

func TestBuzzerDriverToggle(t *testing.T) {
	d := initTestBuzzerDriver(newGpioTestAdaptor())
	d.Off()
	d.Toggle()
	gobottest.Assert(t, d.State(), true)
	d.Toggle()
	gobottest.Assert(t, d.State(), false)
}

func TestBuzzerDriverTone(t *testing.T) {
	d := initTestBuzzerDriver(newGpioTestAdaptor())
	gobottest.Assert(t, d.Tone(100, 0.01), nil)
}
<|endoftext|>


<commit_before>// Copyright 2010 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 main

import (
	"exec"
	"flag"
	"http"
	"io"
	"io/ioutil"
	"log"
	"os"
	"runtime"
	"strconv"
	"template"
)

var (
	httpListen = flag.String("http", "127.0.0.1:3999", "host:port to listen on")
	htmlOutput = flag.Bool("html", false, "render program output as HTML")
)

var (
	// a source of numbers, for naming temporary files
	uniq = make(chan int)
	// the architecture-identifying character of the tool chain, 5, 6, or 8
	archChar string
)

func main() {
	flag.Parse()

	// set archChar
	switch runtime.GOARCH {
	case "arm":
		archChar = "5"
	case "amd64":
		archChar = "6"
	case "386":
		archChar = "8"
	default:
		log.Fatalln("unrecognized GOARCH:", runtime.GOARCH)
	}

	// source of unique numbers
	go func() {
		for i := 0; ; i++ {
			uniq <- i
		}
	}()

	http.HandleFunc("/", FrontPage)
	http.HandleFunc("/compile", Compile)
	log.Fatal(http.ListenAndServe(*httpListen, nil))
}

// FrontPage is an HTTP handler that renders the goplay interface.
// If a filename is supplied in the path component of the URI,
// its contents will be put in the interface's text area.
// Otherwise, the default "hello, world" program is displayed.
func FrontPage(w http.ResponseWriter, req *http.Request) {
	data, err := ioutil.ReadFile(req.URL.Path[1:])
	if err != nil {
		data = helloWorld
	}
	frontPage.Execute(w, data)
}

// Compile is an HTTP handler that reads Go source code from the request,
// compiles and links the code (returning any errors), runs the program,
// and sends the program's output as the HTTP response.
func Compile(w http.ResponseWriter, req *http.Request) {
	// x is the base name for .go, .6, executable files
	x := os.TempDir() + "/compile" + strconv.Itoa(<-uniq)
	src := x + ".go"
	obj := x + "." + archChar
	bin := x
	if runtime.GOOS == "windows" {
		bin += ".exe"
	}

	// write request Body to x.go
	f, err := os.Create(src)
	if err != nil {
		error(w, nil, err)
		return
	}
	defer os.Remove(src)
	defer f.Close()
	_, err = io.Copy(f, req.Body)
	if err != nil {
		error(w, nil, err)
		return
	}
	f.Close()

	// build x.go, creating x.6
	out, err := run(archChar+"g", "-o", obj, src)
	defer os.Remove(obj)
	if err != nil {
		error(w, out, err)
		return
	}

	// link x.6, creating x (the program binary)
	out, err = run(archChar+"l", "-o", bin, obj)
	defer os.Remove(bin)
	if err != nil {
		error(w, out, err)
		return
	}

	// run x
	out, err = run(bin)
	if err != nil {
		error(w, out, err)
	}

	// write the output of x as the http response
	if *htmlOutput {
		w.Write(out)
	} else {
		output.Execute(w, out)
	}
}

// error writes compile, link, or runtime errors to the HTTP connection.
// The JavaScript interface uses the 404 status code to identify the error.
func error(w http.ResponseWriter, out []byte, err os.Error) {
	w.WriteHeader(404)
	if out != nil {
		output.Execute(w, out)
	} else {
		output.Execute(w, err.String())
	}
}

// run executes the specified command and returns its output and an error.
func run(cmd ...string) ([]byte, os.Error) {
	return exec.Command(cmd[0], cmd[1:]...).CombinedOutput()
}

var frontPage = template.Must(template.New("frontPage").Parse(frontPageText)) // HTML template
var output = template.Must(template.New("output").Parse(outputText))          // HTML template

var outputText = `<pre>{{html .}}</pre>`

var frontPageText = `<!doctype html>

<textarea autofocus="true" id="edit" spellcheck="false" onkeydown="keyHandler(event);" onkeyup="autocompile();">{{html .}}</textarea>

(Shift-Enter to compile and run.)
<input type="checkbox" id="autocompile" value="checked" /> Compile and run after each keystroke

`

var helloWorld = []byte(`package main

import "fmt"

func main() {
	fmt.Println("hello, world")
}
`)
<commit_msg>misc/goplay: Fix template output<commit_after>// Copyright 2010 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 main

import (
	"exec"
	"flag"
	"http"
	"io"
	"io/ioutil"
	"log"
	"os"
	"runtime"
	"strconv"
	"template"
)

var (
	httpListen = flag.String("http", "127.0.0.1:3999", "host:port to listen on")
	htmlOutput = flag.Bool("html", false, "render program output as HTML")
)

var (
	// a source of numbers, for naming temporary files
	uniq = make(chan int)
	// the architecture-identifying character of the tool chain, 5, 6, or 8
	archChar string
)

func main() {
	flag.Parse()

	// set archChar
	switch runtime.GOARCH {
	case "arm":
		archChar = "5"
	case "amd64":
		archChar = "6"
	case "386":
		archChar = "8"
	default:
		log.Fatalln("unrecognized GOARCH:", runtime.GOARCH)
	}

	// source of unique numbers
	go func() {
		for i := 0; ; i++ {
			uniq <- i
		}
	}()

	http.HandleFunc("/", FrontPage)
	http.HandleFunc("/compile", Compile)
	log.Fatal(http.ListenAndServe(*httpListen, nil))
}

// FrontPage is an HTTP handler that renders the goplay interface.
// If a filename is supplied in the path component of the URI,
// its contents will be put in the interface's text area.
// Otherwise, the default "hello, world" program is displayed.
func FrontPage(w http.ResponseWriter, req *http.Request) {
	data, err := ioutil.ReadFile(req.URL.Path[1:])
	if err != nil {
		data = helloWorld
	}
	frontPage.Execute(w, data)
}

// Compile is an HTTP handler that reads Go source code from the request,
// compiles and links the code (returning any errors), runs the program,
// and sends the program's output as the HTTP response.
func Compile(w http.ResponseWriter, req *http.Request) {
	// x is the base name for .go, .6, executable files
	x := os.TempDir() + "/compile" + strconv.Itoa(<-uniq)
	src := x + ".go"
	obj := x + "." + archChar
	bin := x
	if runtime.GOOS == "windows" {
		bin += ".exe"
	}

	// write request Body to x.go
	f, err := os.Create(src)
	if err != nil {
		error(w, nil, err)
		return
	}
	defer os.Remove(src)
	defer f.Close()
	_, err = io.Copy(f, req.Body)
	if err != nil {
		error(w, nil, err)
		return
	}
	f.Close()

	// build x.go, creating x.6
	out, err := run(archChar+"g", "-o", obj, src)
	defer os.Remove(obj)
	if err != nil {
		error(w, out, err)
		return
	}

	// link x.6, creating x (the program binary)
	out, err = run(archChar+"l", "-o", bin, obj)
	defer os.Remove(bin)
	if err != nil {
		error(w, out, err)
		return
	}

	// run x
	out, err = run(bin)
	if err != nil {
		error(w, out, err)
	}

	// write the output of x as the http response
	if *htmlOutput {
		w.Write(out)
	} else {
		output.Execute(w, out)
	}
}

// error writes compile, link, or runtime errors to the HTTP connection.
// The JavaScript interface uses the 404 status code to identify the error.
func error(w http.ResponseWriter, out []byte, err os.Error) {
	w.WriteHeader(404)
	if out != nil {
		output.Execute(w, out)
	} else {
		output.Execute(w, err.String())
	}
}

// run executes the specified command and returns its output and an error.
func run(cmd ...string) ([]byte, os.Error) {
	return exec.Command(cmd[0], cmd[1:]...).CombinedOutput()
}

var frontPage = template.Must(template.New("frontPage").Parse(frontPageText)) // HTML template
var output = template.Must(template.New("output").Parse(outputText))          // HTML template

var outputText = `<pre>{{html .}}</pre>`

var frontPageText = `<!doctype html>

<textarea autofocus="true" id="edit" spellcheck="false" onkeydown="keyHandler(event);" onkeyup="autocompile();">{{printf "%s" . |html}}</textarea>

(Shift-Enter to compile and run.)
<input type="checkbox" id="autocompile" value="checked" /> Compile and run after each keystroke

`

var helloWorld = []byte(`package main

import "fmt"

func main() {
	fmt.Println("hello, world")
}
`)
<|endoftext|>


<commit_before>package mettbot

import (
	a "./answers"
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	irc "github.com/fluffle/goirc/client"
	"html"
	"io"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"syscall"
	"time"
)

var Host *string = flag.String("host", "irc.ps0ke.de:2342", "IRC server")
var Channel *string = flag.String("channel", "#metttest", "IRC channel")
var Nick *string = flag.String("nick", "rohmett", "IRC nick")
var Longnick *string = flag.String("longnick", "Le MettBot", "IRC fullname")
var Timeformat *string = flag.String("timeformat", "2006-01-02T15:04", "Time format string (standard date: 2006-01-02T15:04:05)")
var Quotes *string = flag.String("quotes", "mett_quotes.txt", "Quote database file")
var Metts *string = flag.String("metts", "mett_metts.txt", "Metts database file")
var Offtime *int = flag.Int("offtime", 4, "Number of hours of offtopic content befor posting mett content")
var Offmessages *int = flag.Int("offmessages", 100, "Number of messages of offtopic content befor posting mett content")
var Probability *float64 = flag.Float64("probability", 0.1, "Probability that the bot ignores a command")
var MumbleServer *string = flag.String("mumbleserver", "avidrain.de:64738", "Mumble server")
var MumbleTopicregex *string = flag.String("mumbletopicregex", "((?:^|\\|)[^|]*)audiomett:[^|]*?(\\s*(?:$|\\|))", "The regex to match Mumble topic snippet")
var Twitterregex *string = flag.String("twitterregex", "\\S*twitter\\.com\\/\\S+\\/status(es)?\\/(\\d+)\\S*", "The regex to match Twitter URLs")
var Firebird *float64 = flag.Float64("firebird", 0.05, "Probability firebird gets a question")

func init() {
	flag.Parse()
	rand.Seed(time.Now().Unix())
}

type Mettbot struct {
	*irc.Conn
	MumblePing *_mumbleping
	Quitted         chan bool
	QuotesPrnt      chan string
	MettsPrnt       chan string
	QuotesLinesPrnt chan int
	MettsLinesPrnt  chan int
	Input           chan string
	IsMett          chan bool
	ReallyQuit      bool
	Topics          map[string]string
	MsgSinceMett    int
}

func NewMettbot(nick string, args ...string) *Mettbot {
	bot := &Mettbot{
		irc.SimpleClient(nick, args...), // *irc.Conn
		new(_mumbleping), // MumblePing
		make(chan bool),                 // Quitted
		make(chan string),               // QuotesPrnt
		make(chan string),               // MettsPrnt
		make(chan int),                  // QuotesLinesPrnt
		make(chan int),                  // MettsLinesPrnt
		make(chan string, 4),            // Input
		make(chan bool),                 // IsMett
		false,                           // ReallyQuit
		make(map[string]string), // Topics
		0,                       // MsgSinceMett
	}
	bot.EnableStateTracking()
	bot.MumblePing.InitMumblePing(bot)
	return bot
}

func (bot *Mettbot) Syntax(channel string) {
	bot.Notice(channel, a.RandStr(a.Syntax))
}

func (bot *Mettbot) Mentioned(channel string) {
	bot.Privmsg(channel, a.RandStr(a.Mention))
}

func (bot *Mettbot) Mett() {
	bot.MsgSinceMett = 0
	bot.IsMett <- true
}

func (bot *Mettbot) CheckMett() {
	for {
		select {
		case <-bot.IsMett:
		case <-time.After(time.Duration(*Offtime) * time.Hour):
			hour := time.Now().Hour()
			if hour < 1 || hour >= 8 {
				bot.Notice(*Channel, fmt.Sprintf(a.RandStr(a.MettTime), bot.GetMett(*Channel)))
			}
		}
	}
}

func (bot *Mettbot) GetMett(channel string) string {
	fi, err := os.Open(*Metts)
	if err != nil {
		log.Println(err)
		bot.Notice(channel, "Failed to open mett database")
		return "Error"
	}
	defer fi.Close()

	reader := bufio.NewReader(fi)
	lines := 0
	for {
		_, err = reader.ReadString('\n')
		if err != nil {
			break
		}
		lines++
	}

	num := rand.Intn(lines)
	mett := ""

	_, err = fi.Seek(0, 0)
	if err != nil {
		log.Println(err)
	}
	for ; num >= 0; num-- {
		mett, err = reader.ReadString('\n')
		if err == io.EOF {
			log.Println("PostMett: reached EOF")
			return "Error"
		}
		if err != nil {
			log.Println(err)
			bot.Notice(channel, "Failed to read from mett database")
			return "Error"
		}
	}
	return mett
}

func (bot *Mettbot) diffTopic(oldTopic, newTopic string) string {
	oldFile, err := ioutil.TempFile("", ".mettbotWdiffOld")
	if err != nil {
		log.Println(err)
		return ""
	}

	n, err := oldFile.WriteString(oldTopic)
	if n != len(oldTopic) || err != nil {
		log.Println(err)
		return ""
	}
	oldFile.Close()

	newFile, err := ioutil.TempFile("", ".mettbotWdiffNew")
	if err != nil {
		log.Println(err)
		return ""
	}

	n, err = newFile.WriteString(newTopic)
	if n != len(newTopic) || err != nil {
		log.Println(err)
		return ""
	}

	newFile.Close()
	defer func() {
		os.Remove(oldFile.Name())
		os.Remove(newFile.Name())
	}()

	db := "❣" // DeletionBegin
	de := "❢" // DeletionEnd
	ib := "¶" // InsertionBegin
	ie := "⁋" // InsertionEnd

	for {
		rdb := rune(rand.Intn(255-32) + 32)
		rde := rune(rand.Intn(255-32) + 32)
		rib := rune(rand.Intn(255-32) + 32)
		rie := rune(rand.Intn(255-32) + 32)

		contains := strings.ContainsRune(oldTopic, rdb)
		contains = contains || strings.ContainsRune(oldTopic, rde)
		contains = contains || strings.ContainsRune(oldTopic, rib)
		contains = contains || strings.ContainsRune(oldTopic, rie)

		contains = contains || strings.ContainsRune(newTopic, rdb)
		contains = contains || strings.ContainsRune(newTopic, rde)
		contains = contains || strings.ContainsRune(newTopic, rib)
		contains = contains || strings.ContainsRune(newTopic, rie)

		if contains == false {
			db = fmt.Sprintf("%c", rdb)
			de = fmt.Sprintf("%c", rde)
			ib = fmt.Sprintf("%c", rib)
			ie = fmt.Sprintf("%c", rie)
			break
		}
	}

	coloring := map[string]string{ // http://oreilly.com/pub/h/1953
		db: "\x035\x1F\x02",
		de: "\x0F\x0315",
		ib: "\x033\x02",
		ie: "\x0F\x0315",
	}

	cmd := exec.Command("wdiff", "-w"+db, "-x"+de, "-y"+ib, "-z"+ie, oldFile.Name(), newFile.Name())
	out, _ := cmd.Output()
	outStr := string(out)

	for n, v := range coloring {
		outStr = strings.Replace(outStr, n, v, -1)
	}

	return outStr
}

func (bot *Mettbot) GetTweet(channel, url string) {
	regex, err := regexp.Compile(*Twitterregex)
	if err != nil {
		log.Println(err)
		return
	}
	sub := regex.FindStringSubmatch(url)
	tweetUrl := fmt.Sprintf("https://api.twitter.com/1/statuses/show.json?id=%v&trim_user=false&include_entities=no", sub[2])

	resp, err := http.Get(tweetUrl)
	if err != nil {
		log.Println(err)
		return
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
		return
	}

	type usr struct {
		Screen_name string
	}
	type tweet struct {
		Text string
		User usr
	}

	var twt tweet
	err = json.Unmarshal(body, &twt)
	if err != nil {
		log.Println(err)
		return
	}

	tweetText := html.UnescapeString(twt.Text)

	tweetText = strings.Map(func(r rune) rune {
		if r < ' ' {
			return ' '
		}
		return r
	}, tweetText)

	bot.Notice(channel, "@"+twt.User.Screen_name+": "+tweetText)
}

func (bot *Mettbot) firebird(channel string) {
	time.Sleep(time.Duration(rand.Intn(3)+3) * time.Second)
	bot.Notice(channel, "\x034" + a.RandStr(a.Firebird))
}

func (bot *Mettbot) DongDong(channel, msg string) {
	count := strings.Count(msg, "\\a")
	str := a.RandStr(a.Dong)
	notice := ""

	for i := 0; i < count; i++ {
		notice += str + " "
	}

	if len(notice) > 400 {
		notice = notice[:400]
	}
	bot.Notice(channel, notice)
}

func (bot *Mettbot) WriteQuote(filename string, prnt <-chan string, linesPrnt chan<- int) {
	for message := range prnt {
		fo, err := os.OpenFile(filename, syscall.O_RDWR+syscall.O_CREAT, 0644)
		if err != nil {
			log.Println(err)
			bot.Notice(*Channel, "Couldn't open quote database")
			continue
		}
		defer fo.Close()

		foReader := bufio.NewReader(fo)
		lines := 0 //last quote has no newline

		for {
			_, err = foReader.ReadString('\n')
			if err != nil {
				break
			}
			lines++
		}
		linesPrnt <- lines

		_, err = fo.WriteString(message)
		if err != nil {
			log.Println(err)
			bot.Notice(*Channel, "Couldn't write to quote database")
		}
		fo.Close()
	}
}

func (bot *Mettbot) ReadStdin() {
	con := bufio.NewReader(os.Stdin)
	for {
		s, err := con.ReadString('\n')
		if err != nil {
			// wha?, maybe ctrl-D...
			close(bot.Input)
			break
		}
		// no point in sending empty lines down the channel
		if len(s) > 2 {
			bot.Input <- s[0 : len(s)-1]
		}
	}
}

func (bot *Mettbot) ParseStdin() {
	for cmd := range bot.Input {
		if cmd[0] == ':' {
			idx := strings.Index(cmd, " ")
			msg := cmd[idx+1:]

			switch {
			case cmd[1] == 'd':
				fmt.Printf(bot.String())
			case cmd[1] == 'f':
				if len(cmd) > 2 && cmd[2] == 'e' {
					// enable flooding
					bot.Flood = true
				} else if len(cmd) > 2 && cmd[2] == 'd' {
					// disable flooding
					bot.Flood = false
				}
				for i := 0; i < 20; i++ {
					bot.Privmsg(*Channel, "salami!1!")
				}
			case idx == -1:
				continue
			case cmd[1] == 'q':
				bot.ReallyQuit = true
				bot.Quit(msg)
			case cmd[1] == 'j':
				bot.Join(msg)
			case cmd[1] == 'p':
				bot.Part(msg)
			case cmd[1] == 'm':
				bot.Privmsg(*Channel, msg)
			case cmd[1] == 'a':
				bot.Action(*Channel, msg)
			case cmd[1] == 'n':
				bot.Notice(*Channel, msg)
			case cmd[1] == 's':
				midx := strings.Index(msg, " ")
				if midx == -1 {
					fmt.Println("Wrong Syntax")
					continue
				}
				val := msg[midx+1:]
				switch msg[:midx] {
				case "channel":
					bot.Join(val)
					*Channel = val
				case "nick":
					bot.Nick(val)
					*Nick = val
				case "quotes":
					*Quotes = val
				case "metts":
					*Metts = val
				case "offtime":
					num, err := strconv.Atoi(val)
					if err != nil {
						fmt.Println("No Number")
						continue
					}
					*Offtime = num
				case "offmessages":
					num, err := strconv.Atoi(val)
					if err != nil {
						fmt.Println("No Number")
						continue
					}
					*Offmessages = num
				case "probability":
					num, err := strconv.ParseFloat(val, 64)
					if err != nil {
						fmt.Println("No Flaot")
						continue
					}
					*Probability = num
				case "firebird":
					num, err := strconv.ParseFloat(val, 64)
					if err != nil {
						fmt.Println("No Flaot")
						continue
					}
					*Firebird = num
				default:
					fmt.Println("Unknown variable")
				}
			}
		} else {
			bot.Raw(cmd)
		}
	}
}
<commit_msg>removed the posting loop after flooding state toggeling<commit_after>package mettbot

import (
	a "./answers"
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	irc "github.com/fluffle/goirc/client"
	"html"
	"io"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"syscall"
	"time"
)

var Host *string = flag.String("host", "irc.ps0ke.de:2342", "IRC server")
var Channel *string = flag.String("channel", "#metttest", "IRC channel")
var Nick *string = flag.String("nick", "rohmett", "IRC nick")
var Longnick *string = flag.String("longnick", "Le MettBot", "IRC fullname")
var Timeformat *string = flag.String("timeformat", "2006-01-02T15:04", "Time format string (standard date: 2006-01-02T15:04:05)")
var Quotes *string = flag.String("quotes", "mett_quotes.txt", "Quote database file")
var Metts *string = flag.String("metts", "mett_metts.txt", "Metts database file")
var Offtime *int = flag.Int("offtime", 4, "Number of hours of offtopic content befor posting mett content")
var Offmessages *int = flag.Int("offmessages", 100, "Number of messages of offtopic content befor posting mett content")
var Probability *float64 = flag.Float64("probability", 0.1, "Probability that the bot ignores a command")
var MumbleServer *string = flag.String("mumbleserver", "avidrain.de:64738", "Mumble server")
var MumbleTopicregex *string = flag.String("mumbletopicregex", "((?:^|\\|)[^|]*)audiomett:[^|]*?(\\s*(?:$|\\|))", "The regex to match Mumble topic snippet")
var Twitterregex *string = flag.String("twitterregex", "\\S*twitter\\.com\\/\\S+\\/status(es)?\\/(\\d+)\\S*", "The regex to match Twitter URLs")
var Firebird *float64 = flag.Float64("firebird", 0.05, "Probability firebird gets a question")

func init() {
	flag.Parse()
	rand.Seed(time.Now().Unix())
}

type Mettbot struct {
	*irc.Conn
	MumblePing *_mumbleping
	Quitted         chan bool
	QuotesPrnt      chan string
	MettsPrnt       chan string
	QuotesLinesPrnt chan int
	MettsLinesPrnt  chan int
	Input           chan string
	IsMett          chan bool
	ReallyQuit      bool
	Topics          map[string]string
	MsgSinceMett    int
}

func NewMettbot(nick string, args ...string) *Mettbot {
	bot := &Mettbot{
		irc.SimpleClient(nick, args...), // *irc.Conn
		new(_mumbleping), // MumblePing
		make(chan bool),                 // Quitted
		make(chan string),               // QuotesPrnt
		make(chan string),               // MettsPrnt
		make(chan int),                  // QuotesLinesPrnt
		make(chan int),                  // MettsLinesPrnt
		make(chan string, 4),            // Input
		make(chan bool),                 // IsMett
		false,                           // ReallyQuit
		make(map[string]string), // Topics
		0,                       // MsgSinceMett
	}
	bot.EnableStateTracking()
	bot.MumblePing.InitMumblePing(bot)
	return bot
}

func (bot *Mettbot) Syntax(channel string) {
	bot.Notice(channel, a.RandStr(a.Syntax))
}

func (bot *Mettbot) Mentioned(channel string) {
	bot.Privmsg(channel, a.RandStr(a.Mention))
}

func (bot *Mettbot) Mett() {
	bot.MsgSinceMett = 0
	bot.IsMett <- true
}

func (bot *Mettbot) CheckMett() {
	for {
		select {
		case <-bot.IsMett:
		case <-time.After(time.Duration(*Offtime) * time.Hour):
			hour := time.Now().Hour()
			if hour < 1 || hour >= 8 {
				bot.Notice(*Channel, fmt.Sprintf(a.RandStr(a.MettTime), bot.GetMett(*Channel)))
			}
		}
	}
}

func (bot *Mettbot) GetMett(channel string) string {
	fi, err := os.Open(*Metts)
	if err != nil {
		log.Println(err)
		bot.Notice(channel, "Failed to open mett database")
		return "Error"
	}
	defer fi.Close()

	reader := bufio.NewReader(fi)
	lines := 0
	for {
		_, err = reader.ReadString('\n')
		if err != nil {
			break
		}
		lines++
	}

	num := rand.Intn(lines)
	mett := ""

	_, err = fi.Seek(0, 0)
	if err != nil {
		log.Println(err)
	}
	for ; num >= 0; num-- {
		mett, err = reader.ReadString('\n')
		if err == io.EOF {
			log.Println("PostMett: reached EOF")
			return "Error"
		}
		if err != nil {
			log.Println(err)
			bot.Notice(channel, "Failed to read from mett database")
			return "Error"
		}
	}
	return mett
}

func (bot *Mettbot) diffTopic(oldTopic, newTopic string) string {
	oldFile, err := ioutil.TempFile("", ".mettbotWdiffOld")
	if err != nil {
		log.Println(err)
		return ""
	}

	n, err := oldFile.WriteString(oldTopic)
	if n != len(oldTopic) || err != nil {
		log.Println(err)
		return ""
	}
	oldFile.Close()

	newFile, err := ioutil.TempFile("", ".mettbotWdiffNew")
	if err != nil {
		log.Println(err)
		return ""
	}

	n, err = newFile.WriteString(newTopic)
	if n != len(newTopic) || err != nil {
		log.Println(err)
		return ""
	}

	newFile.Close()
	defer func() {
		os.Remove(oldFile.Name())
		os.Remove(newFile.Name())
	}()

	db := "❣" // DeletionBegin
	de := "❢" // DeletionEnd
	ib := "¶" // InsertionBegin
	ie := "⁋" // InsertionEnd

	for {
		rdb := rune(rand.Intn(255-32) + 32)
		rde := rune(rand.Intn(255-32) + 32)
		rib := rune(rand.Intn(255-32) + 32)
		rie := rune(rand.Intn(255-32) + 32)

		contains := strings.ContainsRune(oldTopic, rdb)
		contains = contains || strings.ContainsRune(oldTopic, rde)
		contains = contains || strings.ContainsRune(oldTopic, rib)
		contains = contains || strings.ContainsRune(oldTopic, rie)

		contains = contains || strings.ContainsRune(newTopic, rdb)
		contains = contains || strings.ContainsRune(newTopic, rde)
		contains = contains || strings.ContainsRune(newTopic, rib)
		contains = contains || strings.ContainsRune(newTopic, rie)

		if contains == false {
			db = fmt.Sprintf("%c", rdb)
			de = fmt.Sprintf("%c", rde)
			ib = fmt.Sprintf("%c", rib)
			ie = fmt.Sprintf("%c", rie)
			break
		}
	}

	coloring := map[string]string{ // http://oreilly.com/pub/h/1953
		db: "\x035\x1F\x02",
		de: "\x0F\x0315",
		ib: "\x033\x02",
		ie: "\x0F\x0315",
	}

	cmd := exec.Command("wdiff", "-w"+db, "-x"+de, "-y"+ib, "-z"+ie, oldFile.Name(), newFile.Name())
	out, _ := cmd.Output()
	outStr := string(out)

	for n, v := range coloring {
		outStr = strings.Replace(outStr, n, v, -1)
	}

	return outStr
}

func (bot *Mettbot) GetTweet(channel, url string) {
	regex, err := regexp.Compile(*Twitterregex)
	if err != nil {
		log.Println(err)
		return
	}
	sub := regex.FindStringSubmatch(url)
	tweetUrl := fmt.Sprintf("https://api.twitter.com/1/statuses/show.json?id=%v&trim_user=false&include_entities=no", sub[2])

	resp, err := http.Get(tweetUrl)
	if err != nil {
		log.Println(err)
		return
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
		return
	}

	type usr struct {
		Screen_name string
	}
	type tweet struct {
		Text string
		User usr
	}

	var twt tweet
	err = json.Unmarshal(body, &twt)
	if err != nil {
		log.Println(err)
		return
	}

	tweetText := html.UnescapeString(twt.Text)

	tweetText = strings.Map(func(r rune) rune {
		if r < ' ' {
			return ' '
		}
		return r
	}, tweetText)

	bot.Notice(channel, "@"+twt.User.Screen_name+": "+tweetText)
}

func (bot *Mettbot) firebird(channel string) {
	time.Sleep(time.Duration(rand.Intn(3)+3) * time.Second)
	bot.Notice(channel, "\x034" + a.RandStr(a.Firebird))
}

func (bot *Mettbot) DongDong(channel, msg string) {
	count := strings.Count(msg, "\\a")
	str := a.RandStr(a.Dong)
	notice := ""

	for i := 0; i < count; i++ {
		notice += str + " "
	}

	if len(notice) > 400 {
		notice = notice[:400]
	}
	bot.Notice(channel, notice)
}

func (bot *Mettbot) WriteQuote(filename string, prnt <-chan string, linesPrnt chan<- int) {
	for message := range prnt {
		fo, err := os.OpenFile(filename, syscall.O_RDWR+syscall.O_CREAT, 0644)
		if err != nil {
			log.Println(err)
			bot.Notice(*Channel, "Couldn't open quote database")
			continue
		}
		defer fo.Close()

		foReader := bufio.NewReader(fo)
		lines := 0 //last quote has no newline

		for {
			_, err = foReader.ReadString('\n')
			if err != nil {
				break
			}
			lines++
		}
		linesPrnt <- lines

		_, err = fo.WriteString(message)
		if err != nil {
			log.Println(err)
			bot.Notice(*Channel, "Couldn't write to quote database")
		}
		fo.Close()
	}
}

func (bot *Mettbot) ReadStdin() {
	con := bufio.NewReader(os.Stdin)
	for {
		s, err := con.ReadString('\n')
		if err != nil {
			// wha?, maybe ctrl-D...
			close(bot.Input)
			break
		}
		// no point in sending empty lines down the channel
		if len(s) > 2 {
			bot.Input <- s[0 : len(s)-1]
		}
	}
}

func (bot *Mettbot) ParseStdin() {
	for cmd := range bot.Input {
		if cmd[0] == ':' {
			idx := strings.Index(cmd, " ")
			msg := cmd[idx+1:]

			switch {
			case cmd[1] == 'd':
				fmt.Printf(bot.String())
			case cmd[1] == 'f':
				if len(cmd) > 2 && cmd[2] == 'e' {
					// enable flooding
					bot.Flood = true
				} else if len(cmd) > 2 && cmd[2] == 'd' {
					// disable flooding
					bot.Flood = false
				}
			case idx == -1:
				continue
			case cmd[1] == 'q':
				bot.ReallyQuit = true
				bot.Quit(msg)
			case cmd[1] == 'j':
				bot.Join(msg)
			case cmd[1] == 'p':
				bot.Part(msg)
			case cmd[1] == 'm':
				bot.Privmsg(*Channel, msg)
			case cmd[1] == 'a':
				bot.Action(*Channel, msg)
			case cmd[1] == 'n':
				bot.Notice(*Channel, msg)
			case cmd[1] == 's':
				midx := strings.Index(msg, " ")
				if midx == -1 {
					fmt.Println("Wrong Syntax")
					continue
				}
				val := msg[midx+1:]
				switch msg[:midx] {
				case "channel":
					bot.Join(val)
					*Channel = val
				case "nick":
					bot.Nick(val)
					*Nick = val
				case "quotes":
					*Quotes = val
				case "metts":
					*Metts = val
				case "offtime":
					num, err := strconv.Atoi(val)
					if err != nil {
						fmt.Println("No Number")
						continue
					}
					*Offtime = num
				case "offmessages":
					num, err := strconv.Atoi(val)
					if err != nil {
						fmt.Println("No Number")
						continue
					}
					*Offmessages = num
				case "probability":
					num, err := strconv.ParseFloat(val, 64)
					if err != nil {
						fmt.Println("No Flaot")
						continue
					}
					*Probability = num
				case "firebird":
					num, err := strconv.ParseFloat(val, 64)
					if err != nil {
						fmt.Println("No Flaot")
						continue
					}
					*Firebird = num
				default:
					fmt.Println("Unknown variable")
				}
			}
		} else {
			bot.Raw(cmd)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// 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 v1beta1

import (
	"fmt"
	"strings"
	"testing"
	"time"

	habv1beta1 "github.com/habitat-sh/habitat-operator/pkg/apis/habitat/v1beta1"
	utils "github.com/habitat-sh/habitat-operator/test/e2e/v1beta1/framework"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
)

const (
	serviceStartupWaitTime = 1 * time.Minute
	secretUpdateTimeout    = 2 * time.Minute
	secretUpdateQueryTime  = 10 * time.Second

	configMapName = "peer-watch-file"
)

// TestBind tests that the operator correctly created two Habitat Services and bound them together.
func TestBind(t *testing.T) {
	// Get Habitat object from Habitat go example.
	web, err := utils.ConvertHabitat("resources/bind-config/webapp.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(web); err != nil {
		t.Fatal(err)
	}

	// Get Habitat object from Habitat db example.
	db, err := utils.ConvertHabitat("resources/bind-config/db.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(db); err != nil {
		t.Fatal(err)
	}

	// Get Service object from example file.
	svc, err := utils.ConvertService("resources/bind-config/service.yml")
	if err != nil {
		t.Fatal(err)
	}

	// Create Service.
	_, err = framework.KubeClient.CoreV1().Services(utils.TestNs).Create(svc)
	if err != nil {
		t.Fatal(err)
	}
	// Delete Service so it doesn't interfere with other tests.
	defer (func(name string) {
		if err := framework.DeleteService(name); err != nil {
			t.Fatal(err)
		}
	})(svc.Name)

	// Get Secret object from example file.
	sec, err := utils.ConvertSecret("resources/bind-config/secret.yml")
	if err != nil {
		t.Fatal(err)
	}

	// Create Secret.
	sec, err = framework.KubeClient.CoreV1().Secrets(utils.TestNs).Create(sec)
	if err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be ready.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, web.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, db.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Wait until endpoints are ready.
	if err := framework.WaitForEndpoints(svc.ObjectMeta.Name); err != nil {
		t.Fatal(err)
	}

	time.Sleep(serviceStartupWaitTime)

	// Get response from Habitat Service.
	url := fmt.Sprintf("http://%s:30001/", framework.ExternalIP)

	body, err := utils.QueryService(url)
	if err != nil {
		t.Fatal(err)
	}

	// This msg is set in the config of the habitat/bindgo-hab Go Habitat Service.
	expectedMsg := "hello from port: 4444"
	actualMsg := body
	// actualMsg can contain whitespace and newlines or different formatting,
	// the only thing we need to check is it contains the expectedMsg.
	if !strings.Contains(actualMsg, expectedMsg) {
		t.Fatalf("Habitat Service msg does not match one in default.toml. Expected: \"%s\", got: \"%s\"", expectedMsg, actualMsg)
	}

	// Test `user.toml` updates.

	// Update secret.
	newPort := "port = 6333"

	sec.Data["user.toml"] = []byte(newPort)
	if _, err = framework.KubeClient.CoreV1().Secrets(utils.TestNs).Update(sec); err != nil {
		t.Fatalf("Could not update Secret: \"%s\"", err)
	}

	// Wait for SecretVolume to be updated.
	ticker := time.NewTicker(secretUpdateQueryTime)
	defer ticker.Stop()
	timer := time.NewTimer(secretUpdateTimeout)
	defer timer.Stop()

	// Update the message set in the config of the habitat/bindgo-hab Go Habitat Service.
	expectedMsg = fmt.Sprintf("hello from port: %v", 6333)
	for {
		// Check that the port differs after the update.
		actualMsg, err := utils.QueryService(url)
		if err != nil {
			t.Fatal(err)
		}

		// actualMsg can contain whitespace and newlines or different formatting,
		// the only thing we need to check is it contains the expectedMsg.
		if strings.Contains(actualMsg, expectedMsg) {
			break
		}

		fail := func() {
			t.Fatalf("Configuration update did not go through. Expected: \"%s\", got: \"%s\"", expectedMsg, actualMsg)
		}

		select {
		case <-timer.C:
			fail()
		case <-ticker.C:
			// This is to avoid infinite loops when go
			// decides to always pick the ticker channel,
			// even when timer channel is ready too.
			select {
			case <-timer.C:
				fail()
			default:
			}
		}
	}
}

// TestHabitatDelete tests Habitat deletion.
func TestHabitatDelete(t *testing.T) {
	// Get Habitat object from Habitat go example.
	habitat, err := utils.ConvertHabitat("resources/standalone/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(habitat); err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be ready.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, habitat.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Delete Habitat.
	if err := framework.DeleteHabitat(habitat.ObjectMeta.Name); err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be deleted.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, habitat.ObjectMeta.Name, 0); err != nil {
		t.Fatal(err)
	}

	// Check if all the resources the operator creates are deleted.
	// We do not care about secrets being deleted, as the user needs to delete those manually.
	d, err := framework.KubeClient.AppsV1beta1().Deployments(utils.TestNs).Get(habitat.ObjectMeta.Name, metav1.GetOptions{})
	if err == nil && d != nil {
		t.Fatal("Deployment was not deleted.")
	}

	// The CM with the peer IP should still be alive, despite the Habitat being deleted as it was created outside of the scope of a Habitat.
	_, err = framework.KubeClient.CoreV1().ConfigMaps(utils.TestNs).Get(configMapName, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}
}

func TestPersistentStorage(t *testing.T) {
	// We run minikube in a VM on Travis. In that environment, we cannot create PersistentVolumes.
	t.Skip("This test cannot be run successfully in our current testing setup")

	ephemeral, err := utils.ConvertHabitat("resources/standalone/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	persisted, err := utils.ConvertHabitat("resources/persisted/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(ephemeral); err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(persisted); err != nil {
		t.Fatal(err)
	}

	// Delete all PVCs at the end of the test.
	// For dynamically provisioned PVs (as is the case on minikube), this will
	// also delete the PVs.
	defer (func(name string) {
		ls := labels.SelectorFromSet(labels.Set(map[string]string{
			habv1beta1.HabitatNameLabel: name,
		}))

		lo := metav1.ListOptions{
			LabelSelector: ls.String(),
		}

		err := framework.KubeClient.CoreV1().PersistentVolumeClaims(utils.TestNs).DeleteCollection(&metav1.DeleteOptions{}, lo)
		if err != nil {
			t.Fatal(err)
		}
	})(persisted.Name)

	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, persisted.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Test that persistence is only enabled if requested
	ephemeralSTS, err := framework.KubeClient.AppsV1beta1().StatefulSets(utils.TestNs).Get(ephemeral.Name, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}

	if len(ephemeralSTS.Spec.VolumeClaimTemplates) != 0 {
		t.Fatal("PersistentVolumeClaims created for ephemeral StatefulSet")
	}

	persistedSTS, err := framework.KubeClient.AppsV1beta1().StatefulSets(utils.TestNs).Get(persisted.Name, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}

	if len(persistedSTS.Spec.VolumeClaimTemplates) == 0 {
		t.Fatal("No PersistentVolumeClaims created for persistent StatefulSet")
	}
}
<commit_msg>e2e/v1beta1: Add test for v1beta1 CustomVersion<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// 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 v1beta1

import (
	"fmt"
	"strings"
	"testing"
	"time"

	habv1beta1 "github.com/habitat-sh/habitat-operator/pkg/apis/habitat/v1beta1"
	utils "github.com/habitat-sh/habitat-operator/test/e2e/v1beta1/framework"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
)

const (
	serviceStartupWaitTime = 1 * time.Minute
	secretUpdateTimeout    = 2 * time.Minute
	secretUpdateQueryTime  = 10 * time.Second

	configMapName = "peer-watch-file"
)

// TestBind tests that the operator correctly created two Habitat Services and bound them together.
func TestBind(t *testing.T) {
	// Get Habitat object from Habitat go example.
	web, err := utils.ConvertHabitat("resources/bind-config/webapp.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(web); err != nil {
		t.Fatal(err)
	}

	// Get Habitat object from Habitat db example.
	db, err := utils.ConvertHabitat("resources/bind-config/db.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(db); err != nil {
		t.Fatal(err)
	}

	// Get Service object from example file.
	svc, err := utils.ConvertService("resources/bind-config/service.yml")
	if err != nil {
		t.Fatal(err)
	}

	// Create Service.
	_, err = framework.KubeClient.CoreV1().Services(utils.TestNs).Create(svc)
	if err != nil {
		t.Fatal(err)
	}
	// Delete Service so it doesn't interfere with other tests.
	defer (func(name string) {
		if err := framework.DeleteService(name); err != nil {
			t.Fatal(err)
		}
	})(svc.Name)

	// Get Secret object from example file.
	sec, err := utils.ConvertSecret("resources/bind-config/secret.yml")
	if err != nil {
		t.Fatal(err)
	}

	// Create Secret.
	sec, err = framework.KubeClient.CoreV1().Secrets(utils.TestNs).Create(sec)
	if err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be ready.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, web.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, db.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Wait until endpoints are ready.
	if err := framework.WaitForEndpoints(svc.ObjectMeta.Name); err != nil {
		t.Fatal(err)
	}

	time.Sleep(serviceStartupWaitTime)

	// Get response from Habitat Service.
	url := fmt.Sprintf("http://%s:30001/", framework.ExternalIP)

	body, err := utils.QueryService(url)
	if err != nil {
		t.Fatal(err)
	}

	// This msg is set in the config of the habitat/bindgo-hab Go Habitat Service.
	expectedMsg := "hello from port: 4444"
	actualMsg := body
	// actualMsg can contain whitespace and newlines or different formatting,
	// the only thing we need to check is it contains the expectedMsg.
	if !strings.Contains(actualMsg, expectedMsg) {
		t.Fatalf("Habitat Service msg does not match one in default.toml. Expected: \"%s\", got: \"%s\"", expectedMsg, actualMsg)
	}

	// Test `user.toml` updates.

	// Update secret.
	newPort := "port = 6333"

	sec.Data["user.toml"] = []byte(newPort)
	if _, err = framework.KubeClient.CoreV1().Secrets(utils.TestNs).Update(sec); err != nil {
		t.Fatalf("Could not update Secret: \"%s\"", err)
	}

	// Wait for SecretVolume to be updated.
	ticker := time.NewTicker(secretUpdateQueryTime)
	defer ticker.Stop()
	timer := time.NewTimer(secretUpdateTimeout)
	defer timer.Stop()

	// Update the message set in the config of the habitat/bindgo-hab Go Habitat Service.
	expectedMsg = fmt.Sprintf("hello from port: %v", 6333)
	for {
		// Check that the port differs after the update.
		actualMsg, err := utils.QueryService(url)
		if err != nil {
			t.Fatal(err)
		}

		// actualMsg can contain whitespace and newlines or different formatting,
		// the only thing we need to check is it contains the expectedMsg.
		if strings.Contains(actualMsg, expectedMsg) {
			break
		}

		fail := func() {
			t.Fatalf("Configuration update did not go through. Expected: \"%s\", got: \"%s\"", expectedMsg, actualMsg)
		}

		select {
		case <-timer.C:
			fail()
		case <-ticker.C:
			// This is to avoid infinite loops when go
			// decides to always pick the ticker channel,
			// even when timer channel is ready too.
			select {
			case <-timer.C:
				fail()
			default:
			}
		}
	}
}

// TestHabitatDelete tests Habitat deletion.
func TestHabitatDelete(t *testing.T) {
	// Get Habitat object from Habitat go example.
	habitat, err := utils.ConvertHabitat("resources/standalone/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(habitat); err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be ready.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, habitat.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Delete Habitat.
	if err := framework.DeleteHabitat(habitat.ObjectMeta.Name); err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be deleted.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, habitat.ObjectMeta.Name, 0); err != nil {
		t.Fatal(err)
	}

	// Check if all the resources the operator creates are deleted.
	// We do not care about secrets being deleted, as the user needs to delete those manually.
	d, err := framework.KubeClient.AppsV1beta1().Deployments(utils.TestNs).Get(habitat.ObjectMeta.Name, metav1.GetOptions{})
	if err == nil && d != nil {
		t.Fatal("Deployment was not deleted.")
	}

	// The CM with the peer IP should still be alive, despite the Habitat being deleted as it was created outside of the scope of a Habitat.
	_, err = framework.KubeClient.CoreV1().ConfigMaps(utils.TestNs).Get(configMapName, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}
}

func TestPersistentStorage(t *testing.T) {
	// We run minikube in a VM on Travis. In that environment, we cannot create PersistentVolumes.
	t.Skip("This test cannot be run successfully in our current testing setup")

	ephemeral, err := utils.ConvertHabitat("resources/standalone/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	persisted, err := utils.ConvertHabitat("resources/persisted/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(ephemeral); err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(persisted); err != nil {
		t.Fatal(err)
	}

	// Delete all PVCs at the end of the test.
	// For dynamically provisioned PVs (as is the case on minikube), this will
	// also delete the PVs.
	defer (func(name string) {
		ls := labels.SelectorFromSet(labels.Set(map[string]string{
			habv1beta1.HabitatNameLabel: name,
		}))

		lo := metav1.ListOptions{
			LabelSelector: ls.String(),
		}

		err := framework.KubeClient.CoreV1().PersistentVolumeClaims(utils.TestNs).DeleteCollection(&metav1.DeleteOptions{}, lo)
		if err != nil {
			t.Fatal(err)
		}
	})(persisted.Name)

	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, persisted.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Test that persistence is only enabled if requested
	ephemeralSTS, err := framework.KubeClient.AppsV1beta1().StatefulSets(utils.TestNs).Get(ephemeral.Name, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}

	if len(ephemeralSTS.Spec.VolumeClaimTemplates) != 0 {
		t.Fatal("PersistentVolumeClaims created for ephemeral StatefulSet")
	}

	persistedSTS, err := framework.KubeClient.AppsV1beta1().StatefulSets(utils.TestNs).Get(persisted.Name, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}

	if len(persistedSTS.Spec.VolumeClaimTemplates) == 0 {
		t.Fatal("No PersistentVolumeClaims created for persistent StatefulSet")
	}
}

func TestV1beta1(t *testing.T) {
	h, err := utils.ConvertHabitat("resources/standalone/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	v := "v1beta1"
	h.CustomVersion = &v

	if err := framework.CreateHabitat(h); err != nil {
		t.Fatal(err)
	}

	if _, err := framework.KubeClient.AppsV1beta1().Deployments(utils.TestNs).Get(h.Name, metav1.GetOptions{}); err != nil {
		t.Fatal("Could not retrieve Deployment")
	}
}
<|endoftext|>


<commit_before>package buffalo

import (
	"net/http"
	"testing"

	"github.com/gobuffalo/buffalo/render"
	"github.com/gobuffalo/httptest"
	"github.com/stretchr/testify/require"
)

// Test_App_Use tests that middleware gets added
func Test_App_Use(t *testing.T) {
	r := require.New(t)

	log := []string{}
	a := New(Options{})
	a.Use(func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "start")
			err := h(c)
			log = append(log, "end")
			return err
		}
	})

	a.GET("/", func(c Context) error {
		log = append(log, "handler")
		return nil
	})

	w := httptest.New(a)
	w.HTML("/").Get()
	r.Len(log, 3)
	r.Equal([]string{"start", "handler", "end"}, log)
}

// Test_Middleware_Replace tests that middleware gets added
func Test_Middleware_Replace(t *testing.T) {
	r := require.New(t)

	log := []string{}
	a := New(Options{})
	mw1 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "m1 start")
			err := h(c)
			log = append(log, "m1 end")
			return err
		}
	}
	mw2 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "m2 start")
			err := h(c)
			log = append(log, "m2 end")
			return err
		}
	}
	a.Use(mw1)
	a.Middleware.Replace(mw1, mw2)

	a.GET("/", func(c Context) error {
		log = append(log, "handler")
		return nil
	})

	w := httptest.New(a)
	w.HTML("/").Get()
	r.Len(log, 3)
	r.Equal([]string{"m2 start", "handler", "m2 end"}, log)
}

// Test_Middleware_Skip tests that middleware gets skipped
func Test_Middleware_Skip(t *testing.T) {
	r := require.New(t)

	log := []string{}
	a := New(Options{})
	mw1 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "mw1 start")
			err := h(c)
			log = append(log, "mw1 end")
			return err
		}
	}
	mw2 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "mw2 start")
			err := h(c)
			log = append(log, "mw2 end")
			return err
		}
	}
	a.Use(mw1)
	a.Use(mw2)

	h1 := func(c Context) error {
		log = append(log, "h1")
		return nil
	}
	h2 := func(c Context) error {
		log = append(log, "h2")
		return nil
	}

	a.GET("/h1", h1)
	a.GET("/h2", h2)

	a.Middleware.Skip(mw2, h2)

	w := httptest.New(a)

	w.HTML("/h2").Get()
	r.Len(log, 3)
	r.Equal([]string{"mw1 start", "h2", "mw1 end"}, log)

	log = []string{}
	w.HTML("/h1").Get()
	r.Len(log, 5)
	r.Equal([]string{"mw1 start", "mw2 start", "h1", "mw2 end", "mw1 end"}, log)
}

type carsResource struct {
	Resource
}

func (ur *carsResource) Show(c Context) error {
	return c.Render(http.StatusOK, render.String("show"))
}

func (ur *carsResource) List(c Context) error {
	return c.Render(http.StatusOK, render.String("list"))
}

// Test_Middleware_Skip tests that middleware gets skipped
func Test_Middleware_Skip_Resource(t *testing.T) {
	r := require.New(t)

	log := []string{}
	mw1 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "mw1 start")
			err := h(c)
			log = append(log, "mw1 end")
			return err
		}
	}

	a := New(Options{})
	var cr Resource = &carsResource{}
	g := a.Resource("/autos", cr)
	g.Use(mw1)

	var ur Resource = &carsResource{}
	g = a.Resource("/cars", ur)
	g.Use(mw1)

	// fmt.Println("set up skip")
	g.Middleware.Skip(mw1, ur.Show)

	w := httptest.New(a)

	// fmt.Println("make autos call")
	log = []string{}
	res := w.HTML("/autos/1").Get()
	r.Len(log, 2)
	r.Equal("show", res.Body.String())

	// fmt.Println("make list call")
	log = []string{}
	res = w.HTML("/cars").Get()
	r.Len(log, 2)
	r.Equal([]string{"mw1 start", "mw1 end"}, log)
	r.Equal("list", res.Body.String())

	// fmt.Println("make show call")
	log = []string{}
	res = w.HTML("/cars/1").Get()
	r.Len(log, 0)
	r.Equal("show", res.Body.String())

}

// Test_Middleware_Clear confirms that middle gets cleared
func Test_Middleware_Clear(t *testing.T) {
	r := require.New(t)
	mws := newMiddlewareStack()
	mw := func(h Handler) Handler { return h }
	mws.Use(mw)
	mws.Skip(mw, voidHandler)

	r.Len(mws.stack, 1)
	r.Len(mws.skips, 1)

	mws.Clear()

	r.Len(mws.stack, 0)
	r.Len(mws.skips, 0)
}

func Test_Middleware_Remove(t *testing.T) {
	r := require.New(t)
	log := []string{}

	mw1 := func(h Handler) Handler {
		log = append(log, "mw1")
		return h
	}

	mw2 := func(h Handler) Handler {
		log = append(log, "mw2")
		return h
	}

	a := New(Options{})
	a.Use(mw2)
	a.Use(mw1)

	var cr Resource = &carsResource{}
	g := a.Resource("/autos", cr)
	g.Middleware.Remove(mw2)

	a.Resource("/all_log_autos", cr)
	w := httptest.New(a)

	ng := a.Resource("/no_log_autos", cr)
	ng.Middleware.Remove(mw1, mw2)

	_ = w.HTML("/autos/1").Get()
	r.Len(log, 1)
	r.Equal("mw1", log[0])

	log = []string{}
	_ = w.HTML("/all_log_autos/1").Get()
	r.Len(log, 2)
	r.Contains(log, "mw2")
	r.Contains(log, "mw1")

	log = []string{}
	_ = w.HTML("/no_log_autos/1").Get()
	r.Len(log, 0)
}
<commit_msg>added test cases for status checking<commit_after>package buffalo

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/gobuffalo/buffalo/render"
	"github.com/gobuffalo/httptest"
	"github.com/stretchr/testify/require"
)

// Test_App_Use tests that middleware gets added
func Test_App_Use(t *testing.T) {
	r := require.New(t)

	log := []string{}
	a := New(Options{})
	a.Use(func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "start")
			err := h(c)
			log = append(log, "end")
			return err
		}
	})

	a.GET("/", func(c Context) error {
		log = append(log, "handler")
		return nil
	})

	w := httptest.New(a)
	w.HTML("/").Get()
	r.Len(log, 3)
	r.Equal([]string{"start", "handler", "end"}, log)
}

// Test_Middleware_Replace tests that middleware gets added
func Test_Middleware_Replace(t *testing.T) {
	r := require.New(t)

	log := []string{}
	a := New(Options{})
	mw1 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "m1 start")
			err := h(c)
			log = append(log, "m1 end")
			return err
		}
	}
	mw2 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "m2 start")
			err := h(c)
			log = append(log, "m2 end")
			return err
		}
	}
	a.Use(mw1)
	a.Middleware.Replace(mw1, mw2)

	a.GET("/", func(c Context) error {
		log = append(log, "handler")
		return nil
	})

	w := httptest.New(a)
	w.HTML("/").Get()
	r.Len(log, 3)
	r.Equal([]string{"m2 start", "handler", "m2 end"}, log)
}

// Test_Middleware_Skip tests that middleware gets skipped
func Test_Middleware_Skip(t *testing.T) {
	r := require.New(t)

	log := []string{}
	a := New(Options{})
	mw1 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "mw1 start")
			err := h(c)
			log = append(log, "mw1 end")
			return err
		}
	}
	mw2 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "mw2 start")
			err := h(c)
			log = append(log, "mw2 end")
			return err
		}
	}
	a.Use(mw1)
	a.Use(mw2)

	h1 := func(c Context) error {
		log = append(log, "h1")
		return nil
	}
	h2 := func(c Context) error {
		log = append(log, "h2")
		return nil
	}

	a.GET("/h1", h1)
	a.GET("/h2", h2)

	a.Middleware.Skip(mw2, h2)

	w := httptest.New(a)

	w.HTML("/h2").Get()
	r.Len(log, 3)
	r.Equal([]string{"mw1 start", "h2", "mw1 end"}, log)

	log = []string{}
	w.HTML("/h1").Get()
	r.Len(log, 5)
	r.Equal([]string{"mw1 start", "mw2 start", "h1", "mw2 end", "mw1 end"}, log)
}

type carsResource struct {
	Resource
}

func (ur *carsResource) Show(c Context) error {
	return c.Render(http.StatusOK, render.String("show"))
}

func (ur *carsResource) List(c Context) error {
	return c.Render(http.StatusOK, render.String("list"))
}

// Test_Middleware_Skip tests that middleware gets skipped
func Test_Middleware_Skip_Resource(t *testing.T) {
	r := require.New(t)

	log := []string{}
	mw1 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "mw1 start")
			err := h(c)
			log = append(log, "mw1 end")
			return err
		}
	}

	a := New(Options{})
	var cr Resource = &carsResource{}
	g := a.Resource("/autos", cr)
	g.Use(mw1)

	var ur Resource = &carsResource{}
	g = a.Resource("/cars", ur)
	g.Use(mw1)

	// fmt.Println("set up skip")
	g.Middleware.Skip(mw1, ur.Show)

	w := httptest.New(a)

	// fmt.Println("make autos call")
	log = []string{}
	res := w.HTML("/autos/1").Get()
	r.Len(log, 2)
	r.Equal("show", res.Body.String())

	// fmt.Println("make list call")
	log = []string{}
	res = w.HTML("/cars").Get()
	r.Len(log, 2)
	r.Equal([]string{"mw1 start", "mw1 end"}, log)
	r.Equal("list", res.Body.String())

	// fmt.Println("make show call")
	log = []string{}
	res = w.HTML("/cars/1").Get()
	r.Len(log, 0)
	r.Equal("show", res.Body.String())

}

// Test_Middleware_Clear confirms that middle gets cleared
func Test_Middleware_Clear(t *testing.T) {
	r := require.New(t)
	mws := newMiddlewareStack()
	mw := func(h Handler) Handler { return h }
	mws.Use(mw)
	mws.Skip(mw, voidHandler)

	r.Len(mws.stack, 1)
	r.Len(mws.skips, 1)

	mws.Clear()

	r.Len(mws.stack, 0)
	r.Len(mws.skips, 0)
}

func Test_Middleware_Remove(t *testing.T) {
	r := require.New(t)
	log := []string{}

	mw1 := func(h Handler) Handler {
		log = append(log, "mw1")
		return h
	}

	mw2 := func(h Handler) Handler {
		log = append(log, "mw2")
		return h
	}

	a := New(Options{})
	a.Use(mw2)
	a.Use(mw1)

	var cr Resource = &carsResource{}
	g := a.Resource("/autos", cr)
	g.Middleware.Remove(mw2)

	a.Resource("/all_log_autos", cr)
	w := httptest.New(a)

	ng := a.Resource("/no_log_autos", cr)
	ng.Middleware.Remove(mw1, mw2)

	_ = w.HTML("/autos/1").Get()
	r.Len(log, 1)
	r.Equal("mw1", log[0])

	log = []string{}
	_ = w.HTML("/all_log_autos/1").Get()
	r.Len(log, 2)
	r.Contains(log, "mw2")
	r.Contains(log, "mw1")

	log = []string{}
	_ = w.HTML("/no_log_autos/1").Get()
	r.Len(log, 0)
}

func Test_AssertMiddleware_NilStatus200(t *testing.T) {
	r := require.New(t)
	var status int

	a := New(Options{})
	a.Use(func(h Handler) Handler {
		return func(c Context) error {
			err := h(c)

			res, ok := c.Response().(*Response)
			r.True(ok)
			status = res.Status

			return err
		}
	})

	a.GET("/200", func(c Context) error {
		c.Response().WriteHeader(http.StatusOK) // explicitly set
		return nil
	})

	a.GET("/404", func(c Context) error {
		c.Response().WriteHeader(http.StatusNotFound) //explicitly set
		return nil
	})

	a.GET("/nil", func(c Context) error {
		return nil // return nil without setting response status. should be OK
	})

	a.GET("/500", func(c Context) error {
		return fmt.Errorf("error") // return error
	})

	a.GET("/502", func(c Context) error {
		return HTTPError{Status: http.StatusBadGateway} // return HTTPError
	})

	a.GET("/panic", func(c Context) error {
		panic("hoy hoy")
	})

	tests := []struct {
		path   string
		code   int
		status int
	}{
		{"/200", http.StatusOK, http.StatusOK}, // when the handler set response code explicitly (e.g. 200, 404)
		{"/404", http.StatusNotFound, http.StatusNotFound},
		{"/nil", http.StatusOK, http.StatusOK},        // when the handler returns nil without setting status code
		{"/502", http.StatusBadGateway, 0},            // set by defaultErrorHandler, when the handler just returns error
		{"/500", http.StatusInternalServerError, 0},   // set by defaultErrorHandler, when the handler returns HTTPError
		{"/panic", http.StatusInternalServerError, 0}, // set by PanicHandler
	}
	w := httptest.New(a)

	for _, tc := range tests {
		res := w.HTML(tc.path).Get()
		r.Equal(tc.status, status)
		r.Equal(tc.code, res.Code)
	}
}
<|endoftext|>


<commit_before>package main

import (
	p0 "./bug0"
	p1 "./bug1"
)

// both p0.T and p1.T are struct { X, Y int }.

var v0 p0.T
var v1 p1.T

// interfaces involving the two

type I0 interface {
	M(p0.T)
}

type I1 interface {
	M(p1.T)
}

// t0 satisfies I0 and p0.I
type t0 int

func (t0) M(p0.T) {}

// t1 satisfies I1 and p1.I
type t1 float

func (t1) M(p1.T) {}

// check static interface assignments
var i0 I0 = t0(0) // ok
var i1 I1 = t1(0) // ok

var i2 I0 = t1(0) // ERROR "is not"
var i3 I1 = t0(0) // ERROR "is not"

var p0i p0.I = t0(0) // ok
var p1i p1.I = t1(0) // ok

var p0i1 p0.I = t1(0) // ERROR "is not"
var p0i2 p1.I = t0(0) // ERROR "is not"

func main() {
	// check that cannot assign one to the other,
	// but can convert.
	v0 = v1 // ERROR "assign"
	v1 = v0 // ERROR "assign"

	v0 = p0.T(v1)
	v1 = p1.T(v0)

	i0 = i1   // ERROR "need type assertion"
	i1 = i0   // ERROR "need type assertion"
	p0i = i1  // ERROR "need type assertion"
	p1i = i0  // ERROR "need type assertion"
	i0 = p1i  // ERROR "need type assertion"
	i1 = p0i  // ERROR "need type assertion"
	p0i = p1i // ERROR "need type assertion"
	p1i = p0i // ERROR "need type assertion"

	i0 = p0i
	p0i = i0

	i1 = p1i
	p1i = i1
}
<commit_msg>Match gccgo error messages.<commit_after>package main

import (
	p0 "./bug0"
	p1 "./bug1"
)

// both p0.T and p1.T are struct { X, Y int }.

var v0 p0.T
var v1 p1.T

// interfaces involving the two

type I0 interface {
	M(p0.T)
}

type I1 interface {
	M(p1.T)
}

// t0 satisfies I0 and p0.I
type t0 int

func (t0) M(p0.T) {}

// t1 satisfies I1 and p1.I
type t1 float

func (t1) M(p1.T) {}

// check static interface assignments
var i0 I0 = t0(0) // ok
var i1 I1 = t1(0) // ok

var i2 I0 = t1(0) // ERROR "is not|incompatible"
var i3 I1 = t0(0) // ERROR "is not|incompatible"

var p0i p0.I = t0(0) // ok
var p1i p1.I = t1(0) // ok

var p0i1 p0.I = t1(0) // ERROR "is not|incompatible"
var p0i2 p1.I = t0(0) // ERROR "is not|incompatible"

func main() {
	// check that cannot assign one to the other,
	// but can convert.
	v0 = v1 // ERROR "assign"
	v1 = v0 // ERROR "assign"

	v0 = p0.T(v1)
	v1 = p1.T(v0)

	i0 = i1   // ERROR "need type assertion|incompatible"
	i1 = i0   // ERROR "need type assertion|incompatible"
	p0i = i1  // ERROR "need type assertion|incompatible"
	p1i = i0  // ERROR "need type assertion|incompatible"
	i0 = p1i  // ERROR "need type assertion|incompatible"
	i1 = p0i  // ERROR "need type assertion|incompatible"
	p0i = p1i // ERROR "need type assertion|incompatible"
	p1i = p0i // ERROR "need type assertion|incompatible"

	i0 = p0i
	p0i = i0

	i1 = p1i
	p1i = i1
}
<|endoftext|>


<commit_before>//etsnunix implements an interface similar to etsn, but for listening
//for connections on a unix socket provided by the etsnsrv command.
package etsnunix

import (
	"errors"
	"net"
	"os"
	"path/filepath"

	"github.com/JImmyFrasche/etsn"
	"github.com/goerlang/fd"
)

//Server encapsulates the state of an etsnsrv listener.
type Server struct {
	dir string
	log func(error)
}

//New creates a new server that advertises its protocols at dir.
//
//logger is called whenever there's an error establishing a connection
//within Listen. Note that the error may be nil.
//If logger is nil, a no op logger is used.
func New(dir string, logger func(error)) *Server {
	if logger == nil {
		logger = func(error) {}
	}
	return &Server{
		dir: dir,
		log: logger,
	}
}

//Listen advertises a single protocol, proto, in the directory the server
//was created with. It will invoke handler in a new goroutine every time
//a fd representing a tcp socket is sent down the unix domain socket
//created at dir/proto by an instance of etnsrv on dir.
//
//Warning: if there is an existing file named dir/proto it will be deleted.
//
//It is safe to call multiple times on same server, with different proto.
func (s *Server) Listen(proto string, handler func(*net.TCPConn) error) error {
	if len(proto) > 255 {
		return etsn.ErrProtocolIdentifierTooLong
	}
	nm := filepath.Join(s.dir, proto)
	if err := os.Remove(nm); err != nil {
		return err
	}
	c, err := net.Dial("unix", nm)
	if err != nil {
		return err
	}
	conn := c.(*net.UnixConn)
	for {
		fs, err := fd.Get(conn, 1, nil)
		if err != nil {
			//BUG(jmf) There are surely many an error that should lead to
			//us breaking out of the listen loop. For example if another
			//process deletes our socket
			s.log(err)
			continue
		}
		if len(fs) != 1 {
			s.log(errors.New("Did not receive exactly one fd"))
			continue
		}
		f := fs[0]
		ic, err := net.FileConn(f)
		if err != nil {
			f.Close()
			s.log(err)
			continue
		}
		s.log(f.Close())
		tcp, ok := ic.(*net.TCPConn)
		if !ok {
			s.log(errors.New("Received invalid socket type"))
			ic.Close()
			continue
		}
		go func() {
			s.log(handler(tcp))
		}()
	}
}
<commit_msg>os.Remove returns file not found error<commit_after>//etsnunix implements an interface similar to etsn, but for listening
//for connections on a unix socket provided by the etsnsrv command.
package etsnunix

import (
	"errors"
	"net"
	"os"
	"path/filepath"

	"github.com/JImmyFrasche/etsn"
	"github.com/goerlang/fd"
)

//Server encapsulates the state of an etsnsrv listener.
type Server struct {
	dir string
	log func(error)
}

//New creates a new server that advertises its protocols at dir.
//
//logger is called whenever there's an error establishing a connection
//within Listen. Note that the error may be nil.
//If logger is nil, a no op logger is used.
func New(dir string, logger func(error)) *Server {
	if logger == nil {
		logger = func(error) {}
	}
	return &Server{
		dir: dir,
		log: logger,
	}
}

//Listen advertises a single protocol, proto, in the directory the server
//was created with. It will invoke handler in a new goroutine every time
//a fd representing a tcp socket is sent down the unix domain socket
//created at dir/proto by an instance of etnsrv on dir.
//
//Warning: if there is an existing file named dir/proto it will be deleted.
//
//It is safe to call multiple times on same server, with different proto.
func (s *Server) Listen(proto string, handler func(*net.TCPConn) error) error {
	if len(proto) > 255 {
		return etsn.ErrProtocolIdentifierTooLong
	}
	nm := filepath.Join(s.dir, proto)
	if err := os.Remove(nm); err != nil {
		pe := err.(*os.PathError)
		if pe.Err.Error() != "no such file or directory" {
			return err
		}
	}
	c, err := net.Dial("unix", nm)
	if err != nil {
		return err
	}
	conn := c.(*net.UnixConn)
	for {
		fs, err := fd.Get(conn, 1, nil)
		if err != nil {
			//BUG(jmf) There are surely many an error that should lead to
			//us breaking out of the listen loop. For example if another
			//process deletes our socket
			s.log(err)
			continue
		}
		if len(fs) != 1 {
			s.log(errors.New("Did not receive exactly one fd"))
			continue
		}
		f := fs[0]
		ic, err := net.FileConn(f)
		if err != nil {
			f.Close()
			s.log(err)
			continue
		}
		s.log(f.Close())
		tcp, ok := ic.(*net.TCPConn)
		if !ok {
			s.log(errors.New("Received invalid socket type"))
			ic.Close()
			continue
		}
		go func() {
			s.log(handler(tcp))
		}()
	}
}
<|endoftext|>