<commit_before>package v7_test

import (
	"errors"

	"code.cloudfoundry.org/cli/actor/actionerror"
	"code.cloudfoundry.org/cli/actor/v7action"
	"code.cloudfoundry.org/cli/command/commandfakes"
	"code.cloudfoundry.org/cli/command/flag"
	. "code.cloudfoundry.org/cli/command/v7"
	"code.cloudfoundry.org/cli/command/v7/v7fakes"
	"code.cloudfoundry.org/cli/resources"
	"code.cloudfoundry.org/cli/util/configv3"
	"code.cloudfoundry.org/cli/util/ui"

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

var _ = Describe("unmap-route Command", func() {
	var (
		cmd             UnmapRouteCommand
		testUI          *ui.UI
		fakeConfig      *commandfakes.FakeConfig
		fakeSharedActor *commandfakes.FakeSharedActor
		fakeActor       *v7fakes.FakeActor
		input           *Buffer
		binaryName      string
		executeErr      error
		domain          string
		appName         string
		hostname        string
		path            string
		orgGUID         string
		orgName         string
		spaceGUID       string
		spaceName       string
		userName        string
	)

	BeforeEach(func() {
		input = NewBuffer()
		testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer())
		fakeConfig = new(commandfakes.FakeConfig)
		fakeSharedActor = new(commandfakes.FakeSharedActor)
		fakeActor = new(v7fakes.FakeActor)

		binaryName = "faceman"
		fakeConfig.BinaryNameReturns(binaryName)
		appName = "my-app"
		domain = "some-domain.com"
		hostname = "host"
		path = "/path"
		orgGUID = "some-org-guid"
		orgName = "some-org"
		spaceGUID = "some-space-guid"
		spaceName = "some-space"
		userName = "steve"

		cmd = UnmapRouteCommand{
			RequiredArgs: flag.AppDomain{App: appName, Domain: domain},
			Hostname:     hostname,
			Path:         flag.V7RoutePath{Path: path},
			Port:         1024,
			BaseCommand: BaseCommand{
				UI:          testUI,
				Config:      fakeConfig,
				SharedActor: fakeSharedActor,
				Actor:       fakeActor,
			},
		}

		fakeConfig.TargetedOrganizationReturns(configv3.Organization{
			Name: orgName,
			GUID: orgGUID,
		})

		fakeConfig.TargetedSpaceReturns(configv3.Space{
			Name: spaceName,
			GUID: spaceGUID,
		})

		fakeConfig.CurrentUserReturns(configv3.User{Name: userName}, nil)

		fakeActor.GetDomainByNameReturns(
			resources.Domain{Name: "some-domain.com", GUID: "domain-guid"},
			v7action.Warnings{"get-domain-warnings"},
			nil,
		)

		fakeActor.GetApplicationByNameAndSpaceReturns(
			resources.Application{Name: "app", GUID: "app-guid"},
			v7action.Warnings{"get-app-warnings"},
			nil,
		)

		fakeActor.GetRouteByAttributesReturns(
			resources.Route{GUID: "route-guid"},
			v7action.Warnings{"get-route-warnings"},
			nil,
		)

		fakeActor.GetRouteDestinationByAppGUIDReturns(
			resources.RouteDestination{GUID: "destination-guid"},
			v7action.Warnings{"get-destination-warning"},
			nil,
		)

		fakeActor.UnmapRouteReturns(
			v7action.Warnings{"unmap-route-warnings"},
			nil,
		)
	})

	JustBeforeEach(func() {
		executeErr = cmd.Execute(nil)
	})

	When("checking target fails", func() {
		BeforeEach(func() {
			fakeSharedActor.CheckTargetReturns(actionerror.NoOrganizationTargetedError{BinaryName: binaryName})
		})

		It("returns an error", func() {
			Expect(executeErr).To(MatchError(actionerror.NoOrganizationTargetedError{BinaryName: binaryName}))

			Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
			checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
			Expect(checkTargetedOrg).To(BeTrue())
			Expect(checkTargetedSpace).To(BeTrue())
		})
	})

	When("the user is not logged in", func() {
		var expectedErr error

		BeforeEach(func() {
			expectedErr = errors.New("some current user error")
			fakeConfig.CurrentUserReturns(configv3.User{}, expectedErr)
		})

		It("return an error", func() {
			Expect(executeErr).To(Equal(expectedErr))
		})
	})

	When("getting the domain errors", func() {
		BeforeEach(func() {
			fakeActor.GetDomainByNameReturns(resources.Domain{}, v7action.Warnings{"get-domain-warnings"}, errors.New("get-domain-error"))
		})

		It("returns the error and displays warnings", func() {
			Expect(testUI.Err).To(Say("get-domain-warnings"))
			Expect(executeErr).To(MatchError(errors.New("get-domain-error")))
			Expect(fakeActor.UnmapRouteCallCount()).To(Equal(0))
		})
	})

	It("gets the domain and displays warnings", func() {
		Expect(testUI.Err).To(Say("get-domain-warnings"))

		Expect(fakeActor.GetDomainByNameCallCount()).To(Equal(1))
		Expect(fakeActor.GetDomainByNameArgsForCall(0)).To(Equal(domain))
	})

	When("getting the app errors", func() {
		BeforeEach(func() {
			fakeActor.GetApplicationByNameAndSpaceReturns(
				resources.Application{},
				v7action.Warnings{"get-app-warnings"},
				errors.New("get-app-error"),
			)
		})

		It("returns the error and displays warnings", func() {
			Expect(testUI.Err).To(Say("get-app-warnings"))
			Expect(executeErr).To(MatchError(errors.New("get-app-error")))
			Expect(fakeActor.UnmapRouteCallCount()).To(Equal(0))
		})
	})

	It("gets the app and displays the warnings", func() {
		Expect(testUI.Err).To(Say("get-app-warnings"))

		Expect(fakeActor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1))
		actualAppName, actualSpaceGUID := fakeActor.GetApplicationByNameAndSpaceArgsForCall(0)
		Expect(actualAppName).To(Equal(appName))
		Expect(actualSpaceGUID).To(Equal(spaceGUID))
	})

	When("getting the route errors", func() {
		BeforeEach(func() {
			fakeActor.GetRouteByAttributesReturns(
				resources.Route{},
				v7action.Warnings{"get-route-warnings"},
				errors.New("get-route-error"),
			)
		})

		It("returns the error and displays warnings", func() {
			Expect(testUI.Err).To(Say("get-route-warnings"))
			Expect(executeErr).To(MatchError(errors.New("get-route-error")))

			Expect(fakeActor.UnmapRouteCallCount()).To(Equal(0))
		})
	})

	It("gets the routes and and displays warnings", func() {
		Expect(testUI.Err).To(Say("get-route-warnings"))

		Expect(fakeActor.GetRouteByAttributesCallCount()).To(Equal(1))
		actualDomainName, actualDomainGUID, actualHostname, actualPath, actualPort := fakeActor.GetRouteByAttributesArgsForCall(0)
		Expect(actualDomainName).To(Equal("some-domain.com"))
		Expect(actualDomainGUID).To(Equal("domain-guid"))
		Expect(actualHostname).To(Equal(hostname))
		Expect(actualPath).To(Equal(path))
		Expect(actualPort).To(Equal(cmd.Port))
	})

	It("prints flavor text", func() {
		Expect(testUI.Out).To(Say(
			`Removing route %s from app %s in org %s / space %s as %s\.\.\.`,
			"host.some-domain.com/path",
			appName,
			orgName,
			spaceName,
			userName,
		))
	})

	When("getting the route destination fails because the app is not mapped", func() {
		BeforeEach(func() {
			fakeActor.GetRouteDestinationByAppGUIDReturns(
				resources.RouteDestination{},
				v7action.Warnings{"get-destination-warning"},
				actionerror.RouteDestinationNotFoundError{},
			)
		})

		It("prints a message and returns without an error", func() {
			Expect(executeErr).NotTo(HaveOccurred())
			Expect(testUI.Out).To(Say("Route to be unmapped is not currently mapped to the application."))
			Expect(testUI.Out).To(Say("OK"))
		})
	})

	When("getting the route destination fails for another reason", func() {
		BeforeEach(func() {
			fakeActor.GetRouteDestinationByAppGUIDReturns(
				resources.RouteDestination{},
				v7action.Warnings{"get-destination-warning"},
				errors.New("failed to get destination"),
			)
		})

		It("prints warnings and returns the error", func() {
			Expect(executeErr).To(MatchError("failed to get destination"))

			Expect(fakeActor.UnmapRouteCallCount()).To(Equal(0))
		})
	})

	It("gets the route destination and prints the warnings", func() {
		Expect(testUI.Err).To(Say("get-destination-warning"))

		Expect(fakeActor.GetRouteDestinationByAppGUIDCallCount()).To(Equal(1))
		givenRouteGUID, givenAppGUID := fakeActor.GetRouteDestinationByAppGUIDArgsForCall(0)
		Expect(givenRouteGUID).To(Equal("route-guid"))
		Expect(givenAppGUID).To(Equal("app-guid"))
	})

	When("unmapping the route fails", func() {
		BeforeEach(func() {
			fakeActor.UnmapRouteReturns(
				v7action.Warnings{"unmap-route-warnings"},
				errors.New("failed to unmap route"),
			)
		})

		It("prints warnings and returns the error", func() {
			Expect(fakeActor.UnmapRouteCallCount()).To(Equal(1))
			givenRouteGUID, givenDestinationGUID := fakeActor.UnmapRouteArgsForCall(0)
			Expect(givenRouteGUID).To(Equal("route-guid"))
			Expect(givenDestinationGUID).To(Equal("destination-guid"))

			Expect(testUI.Err).To(Say("get-destination-warning"))

			Expect(executeErr).To(MatchError("failed to unmap route"))
		})
	})

	It("prints warnings and does not return an error", func() {
		Expect(executeErr).NotTo(HaveOccurred())
		Expect(testUI.Err).To(Say("get-destination-warning"))
		Expect(testUI.Out).To(Say("OK"))

		Expect(fakeActor.UnmapRouteCallCount()).To(Equal(1))
		givenRouteGUID, givenDestinationGUID := fakeActor.UnmapRouteArgsForCall(0)
		Expect(givenRouteGUID).To(Equal("route-guid"))
		Expect(givenDestinationGUID).To(Equal("destination-guid"))
	})
})
<commit_msg>🐞 V7: TCP routes have `:port-number` appended<commit_after>package v7_test

import (
	"errors"

	"code.cloudfoundry.org/cli/actor/actionerror"
	"code.cloudfoundry.org/cli/actor/v7action"
	"code.cloudfoundry.org/cli/command/commandfakes"
	"code.cloudfoundry.org/cli/command/flag"
	. "code.cloudfoundry.org/cli/command/v7"
	"code.cloudfoundry.org/cli/command/v7/v7fakes"
	"code.cloudfoundry.org/cli/resources"
	"code.cloudfoundry.org/cli/util/configv3"
	"code.cloudfoundry.org/cli/util/ui"

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

var _ = Describe("unmap-route Command", func() {
	var (
		cmd             UnmapRouteCommand
		testUI          *ui.UI
		fakeConfig      *commandfakes.FakeConfig
		fakeSharedActor *commandfakes.FakeSharedActor
		fakeActor       *v7fakes.FakeActor
		input           *Buffer
		binaryName      string
		executeErr      error
		domain          string
		appName         string
		hostname        string
		path            string
		orgGUID         string
		orgName         string
		spaceGUID       string
		spaceName       string
		userName        string
		port            int
	)

	BeforeEach(func() {
		input = NewBuffer()
		testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer())
		fakeConfig = new(commandfakes.FakeConfig)
		fakeSharedActor = new(commandfakes.FakeSharedActor)
		fakeActor = new(v7fakes.FakeActor)

		binaryName = "faceman"
		fakeConfig.BinaryNameReturns(binaryName)
		appName = "my-app"
		domain = "some-domain.com"
		hostname = "host"
		path = "/path"
		orgGUID = "some-org-guid"
		orgName = "some-org"
		spaceGUID = "some-space-guid"
		spaceName = "some-space"
		userName = "steve"
		port = 0

		cmd = UnmapRouteCommand{
			RequiredArgs: flag.AppDomain{App: appName, Domain: domain},
			Hostname:     hostname,
			Path:         flag.V7RoutePath{Path: path},
			Port:         port,
			BaseCommand: BaseCommand{
				UI:          testUI,
				Config:      fakeConfig,
				SharedActor: fakeSharedActor,
				Actor:       fakeActor,
			},
		}

		fakeConfig.TargetedOrganizationReturns(configv3.Organization{
			Name: orgName,
			GUID: orgGUID,
		})

		fakeConfig.TargetedSpaceReturns(configv3.Space{
			Name: spaceName,
			GUID: spaceGUID,
		})

		fakeConfig.CurrentUserReturns(configv3.User{Name: userName}, nil)

		fakeActor.GetDomainByNameReturns(
			resources.Domain{Name: "some-domain.com", GUID: "domain-guid"},
			v7action.Warnings{"get-domain-warnings"},
			nil,
		)

		fakeActor.GetApplicationByNameAndSpaceReturns(
			resources.Application{Name: "app", GUID: "app-guid"},
			v7action.Warnings{"get-app-warnings"},
			nil,
		)

		fakeActor.GetRouteByAttributesReturns(
			resources.Route{GUID: "route-guid"},
			v7action.Warnings{"get-route-warnings"},
			nil,
		)

		fakeActor.GetRouteDestinationByAppGUIDReturns(
			resources.RouteDestination{GUID: "destination-guid"},
			v7action.Warnings{"get-destination-warning"},
			nil,
		)

		fakeActor.UnmapRouteReturns(
			v7action.Warnings{"unmap-route-warnings"},
			nil,
		)
	})

	JustBeforeEach(func() {
		executeErr = cmd.Execute(nil)
	})

	When("checking target fails", func() {
		BeforeEach(func() {
			fakeSharedActor.CheckTargetReturns(actionerror.NoOrganizationTargetedError{BinaryName: binaryName})
		})

		It("returns an error", func() {
			Expect(executeErr).To(MatchError(actionerror.NoOrganizationTargetedError{BinaryName: binaryName}))

			Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
			checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
			Expect(checkTargetedOrg).To(BeTrue())
			Expect(checkTargetedSpace).To(BeTrue())
		})
	})

	When("the user is not logged in", func() {
		var expectedErr error

		BeforeEach(func() {
			expectedErr = errors.New("some current user error")
			fakeConfig.CurrentUserReturns(configv3.User{}, expectedErr)
		})

		It("return an error", func() {
			Expect(executeErr).To(Equal(expectedErr))
		})
	})

	When("getting the domain errors", func() {
		BeforeEach(func() {
			fakeActor.GetDomainByNameReturns(resources.Domain{}, v7action.Warnings{"get-domain-warnings"}, errors.New("get-domain-error"))
		})

		It("returns the error and displays warnings", func() {
			Expect(testUI.Err).To(Say("get-domain-warnings"))
			Expect(executeErr).To(MatchError(errors.New("get-domain-error")))
			Expect(fakeActor.UnmapRouteCallCount()).To(Equal(0))
		})
	})

	It("gets the domain and displays warnings", func() {
		Expect(testUI.Err).To(Say("get-domain-warnings"))

		Expect(fakeActor.GetDomainByNameCallCount()).To(Equal(1))
		Expect(fakeActor.GetDomainByNameArgsForCall(0)).To(Equal(domain))
	})

	When("getting the app errors", func() {
		BeforeEach(func() {
			fakeActor.GetApplicationByNameAndSpaceReturns(
				resources.Application{},
				v7action.Warnings{"get-app-warnings"},
				errors.New("get-app-error"),
			)
		})

		It("returns the error and displays warnings", func() {
			Expect(testUI.Err).To(Say("get-app-warnings"))
			Expect(executeErr).To(MatchError(errors.New("get-app-error")))
			Expect(fakeActor.UnmapRouteCallCount()).To(Equal(0))
		})
	})

	It("gets the app and displays the warnings", func() {
		Expect(testUI.Err).To(Say("get-app-warnings"))

		Expect(fakeActor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1))
		actualAppName, actualSpaceGUID := fakeActor.GetApplicationByNameAndSpaceArgsForCall(0)
		Expect(actualAppName).To(Equal(appName))
		Expect(actualSpaceGUID).To(Equal(spaceGUID))
	})

	When("getting the route errors", func() {
		BeforeEach(func() {
			fakeActor.GetRouteByAttributesReturns(
				resources.Route{},
				v7action.Warnings{"get-route-warnings"},
				errors.New("get-route-error"),
			)
		})

		It("returns the error and displays warnings", func() {
			Expect(testUI.Err).To(Say("get-route-warnings"))
			Expect(executeErr).To(MatchError(errors.New("get-route-error")))

			Expect(fakeActor.UnmapRouteCallCount()).To(Equal(0))
		})
	})

	When("the route is TCP", func() {
		BeforeEach(func() {
			cmd.Hostname = ""
			cmd.Path = flag.V7RoutePath{Path: ""}
			cmd.Port = 1024
		})

		It("gets the routes and displays warnings", func() {
			Expect(testUI.Err).To(Say("get-route-warnings"))

			Expect(testUI.Out).To(Say(
				`Removing route %s from app %s in org %s / space %s as %s\.\.\.`,
				"some-domain.com:1024",
				appName,
				orgName,
				spaceName,
				userName,
			))

			Expect(fakeActor.GetRouteByAttributesCallCount()).To(Equal(1))
			actualDomainName, actualDomainGUID, _, _, actualPort := fakeActor.GetRouteByAttributesArgsForCall(0)
			Expect(actualDomainName).To(Equal("some-domain.com"))
			Expect(actualDomainGUID).To(Equal("domain-guid"))
			Expect(actualPort).To(Equal(1024))
		})
	})

	It("gets the routes and displays warnings", func() {
		Expect(testUI.Err).To(Say("get-route-warnings"))

		Expect(fakeActor.GetRouteByAttributesCallCount()).To(Equal(1))
		actualDomainName, actualDomainGUID, actualHostname, actualPath, actualPort := fakeActor.GetRouteByAttributesArgsForCall(0)
		Expect(actualDomainName).To(Equal("some-domain.com"))
		Expect(actualDomainGUID).To(Equal("domain-guid"))
		Expect(actualHostname).To(Equal(hostname))
		Expect(actualPath).To(Equal(path))
		Expect(actualPort).To(Equal(0))
	})

	It("prints flavor text", func() {
		Expect(testUI.Out).To(Say(
			`Removing route %s from app %s in org %s / space %s as %s\.\.\.`,
			"host.some-domain.com/path",
			appName,
			orgName,
			spaceName,
			userName,
		))
	})

	When("getting the route destination fails because the app is not mapped", func() {
		BeforeEach(func() {
			fakeActor.GetRouteDestinationByAppGUIDReturns(
				resources.RouteDestination{},
				v7action.Warnings{"get-destination-warning"},
				actionerror.RouteDestinationNotFoundError{},
			)
		})

		It("prints a message and returns without an error", func() {
			Expect(executeErr).NotTo(HaveOccurred())
			Expect(testUI.Out).To(Say("Route to be unmapped is not currently mapped to the application."))
			Expect(testUI.Out).To(Say("OK"))
		})
	})

	When("getting the route destination fails for another reason", func() {
		BeforeEach(func() {
			fakeActor.GetRouteDestinationByAppGUIDReturns(
				resources.RouteDestination{},
				v7action.Warnings{"get-destination-warning"},
				errors.New("failed to get destination"),
			)
		})

		It("prints warnings and returns the error", func() {
			Expect(executeErr).To(MatchError("failed to get destination"))

			Expect(fakeActor.UnmapRouteCallCount()).To(Equal(0))
		})
	})

	It("gets the route destination and prints the warnings", func() {
		Expect(testUI.Err).To(Say("get-destination-warning"))

		Expect(fakeActor.GetRouteDestinationByAppGUIDCallCount()).To(Equal(1))
		givenRouteGUID, givenAppGUID := fakeActor.GetRouteDestinationByAppGUIDArgsForCall(0)
		Expect(givenRouteGUID).To(Equal("route-guid"))
		Expect(givenAppGUID).To(Equal("app-guid"))
	})

	When("unmapping the route fails", func() {
		BeforeEach(func() {
			fakeActor.UnmapRouteReturns(
				v7action.Warnings{"unmap-route-warnings"},
				errors.New("failed to unmap route"),
			)
		})

		It("prints warnings and returns the error", func() {
			Expect(fakeActor.UnmapRouteCallCount()).To(Equal(1))
			givenRouteGUID, givenDestinationGUID := fakeActor.UnmapRouteArgsForCall(0)
			Expect(givenRouteGUID).To(Equal("route-guid"))
			Expect(givenDestinationGUID).To(Equal("destination-guid"))

			Expect(testUI.Err).To(Say("get-destination-warning"))

			Expect(executeErr).To(MatchError("failed to unmap route"))
		})
	})

	It("prints warnings and does not return an error", func() {
		Expect(executeErr).NotTo(HaveOccurred())
		Expect(testUI.Err).To(Say("get-destination-warning"))
		Expect(testUI.Out).To(Say("OK"))

		Expect(fakeActor.UnmapRouteCallCount()).To(Equal(1))
		givenRouteGUID, givenDestinationGUID := fakeActor.UnmapRouteArgsForCall(0)
		Expect(givenRouteGUID).To(Equal("route-guid"))
		Expect(givenDestinationGUID).To(Equal("destination-guid"))
	})
})
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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 acceptance

import (
	"testing"

	"github.com/GoogleCloudPlatform/buildpacks/internal/acceptance"
)

func init() {
	acceptance.DefineFlags()
}

func TestAcceptancePython(t *testing.T) {
	builder, cleanup := acceptance.CreateBuilder(t)
	t.Cleanup(cleanup)

	testCases := []acceptance.Test{
		{
			Name:    "entrypoint from procfile web",
			App:     "python/simple",
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:       "entrypoint from procfile custom",
			App:        "python/simple",
			Path:       "/custom",
			Entrypoint: "custom", // Must match the non-web process in Procfile.
			MustUse:    []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:    "entrypoint from env",
			App:     "python/simple",
			Path:    "/custom",
			Env:     []string{"GOOGLE_ENTRYPOINT=gunicorn -b :8080 custom:app"},
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:    "entrypoint with env var",
			App:     "python/simple",
			Path:    "/env?want=bar",
			Env:     []string{"GOOGLE_ENTRYPOINT=FOO=bar gunicorn -b :8080 main:app"},
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:    "runtime version from env",
			App:     "python/version",
			Path:    "/version?want=3.8.0",
			Env:     []string{"GOOGLE_RUNTIME_VERSION=3.8.0"},
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:    "runtime version from .python-version",
			App:     "python/version",
			Path:    "/version?want=3.8.1",
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:       "selected via GOOGLE_RUNTIME",
			App:        "override",
			Env:        []string{"GOOGLE_RUNTIME=python", "GOOGLE_ENTRYPOINT=gunicorn -b :8080 main:app"},
			MustUse:    []string{pythonRuntime},
			MustNotUse: []string{goRuntime, javaRuntime, nodeRuntime},
		},
		{
			Name:    "python with client-side scripts correctly builds as a python app",
			App:     "python/scripts",
			Env:     []string{"GOOGLE_ENTRYPOINT=gunicorn -b :8080 main:app"},
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
	}
	// Tests for all published versions of Python.
	// Unlike with the other languages, we control the versions published to GCS.
	for _, v := range []string{
		"3.7.0",
		"3.7.1",
		"3.7.2",
		"3.7.3",
		"3.7.4",
		"3.7.5",
		"3.7.6",
		"3.7.7",
		"3.7.8",
		"3.7.9",
		"3.8.0",
		"3.8.1",
		"3.8.2",
		"3.8.3",
		"3.8.4",
		"3.8.5",
		"3.8.6",
	} {
		testCases = append(testCases, acceptance.Test{
			Name:    "runtime version " + v,
			App:     "python/version",
			Path:    "/version?want=" + v,
			Env:     []string{"GOOGLE_RUNTIME_VERSION=" + v},
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		})
	}
	for _, tc := range testCases {
		tc := tc
		t.Run(tc.Name, func(t *testing.T) {
			t.Parallel()

			acceptance.TestApp(t, builder, tc)
		})
	}
}

func TestFailuresPython(t *testing.T) {
	builder, cleanup := acceptance.CreateBuilder(t)
	t.Cleanup(cleanup)

	testCases := []acceptance.FailureTest{
		{
			Name:      "bad runtime version",
			App:       "python/simple",
			Env:       []string{"GOOGLE_RUNTIME_VERSION=BAD_NEWS_BEARS", "GOOGLE_ENTRYPOINT=gunicorn -b :8080 main:app"},
			MustMatch: "Runtime version BAD_NEWS_BEARS does not exist",
		},
		{
			Name:      "python-version empty",
			App:       "python/empty_version",
			MustMatch: ".python-version exists but does not specify a version",
		},
		{
			Name:      "missing entrypoint",
			App:       "python/missing_entrypoint",
			MustMatch: `for Python, an entrypoint must be manually set, either with "GOOGLE_ENTRYPOINT" env var or by creating a "Procfile" file`,
		},
	}

	for _, tc := range testCases {
		tc := tc
		t.Run(tc.Name, func(t *testing.T) {
			t.Parallel()

			acceptance.TestBuildFailure(t, builder, tc)
		})
	}
}
<commit_msg>Update available versions for Python runtime buildpack<commit_after>// Copyright 2020 Google LLC
//
// 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 acceptance

import (
	"testing"

	"github.com/GoogleCloudPlatform/buildpacks/internal/acceptance"
)

func init() {
	acceptance.DefineFlags()
}

func TestAcceptancePython(t *testing.T) {
	builder, cleanup := acceptance.CreateBuilder(t)
	t.Cleanup(cleanup)

	testCases := []acceptance.Test{
		{
			Name:    "entrypoint from procfile web",
			App:     "python/simple",
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:       "entrypoint from procfile custom",
			App:        "python/simple",
			Path:       "/custom",
			Entrypoint: "custom", // Must match the non-web process in Procfile.
			MustUse:    []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:    "entrypoint from env",
			App:     "python/simple",
			Path:    "/custom",
			Env:     []string{"GOOGLE_ENTRYPOINT=gunicorn -b :8080 custom:app"},
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:    "entrypoint with env var",
			App:     "python/simple",
			Path:    "/env?want=bar",
			Env:     []string{"GOOGLE_ENTRYPOINT=FOO=bar gunicorn -b :8080 main:app"},
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:    "runtime version from env",
			App:     "python/version",
			Path:    "/version?want=3.8.0",
			Env:     []string{"GOOGLE_RUNTIME_VERSION=3.8.0"},
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:    "runtime version from .python-version",
			App:     "python/version",
			Path:    "/version?want=3.8.1",
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
		{
			Name:       "selected via GOOGLE_RUNTIME",
			App:        "override",
			Env:        []string{"GOOGLE_RUNTIME=python", "GOOGLE_ENTRYPOINT=gunicorn -b :8080 main:app"},
			MustUse:    []string{pythonRuntime},
			MustNotUse: []string{goRuntime, javaRuntime, nodeRuntime},
		},
		{
			Name:    "python with client-side scripts correctly builds as a python app",
			App:     "python/scripts",
			Env:     []string{"GOOGLE_ENTRYPOINT=gunicorn -b :8080 main:app"},
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		},
	}
	// Tests for all published versions of Python.
	// Unlike with the other languages, we control the versions published to GCS.
	for _, v := range []string{
		"3.7.0",
		"3.7.1",
		"3.7.2",
		"3.7.3",
		"3.7.4",
		"3.7.5",
		"3.7.6",
		"3.7.7",
		"3.7.8",
		"3.7.9",
		"3.7.10",
		"3.8.0",
		"3.8.1",
		"3.8.2",
		"3.8.3",
		"3.8.4",
		"3.8.5",
		"3.8.6",
		"3.8.7",
		"3.8.8",
		"3.8.9",
		"3.8.10",
		"3.9.0",
		"3.9.1",
		"3.9.2",
		// 3.9.3 is not currently available.
		"3.9.4",
		"3.9.5",
	} {
		testCases = append(testCases, acceptance.Test{
			Name:    "runtime version " + v,
			App:     "python/version",
			Path:    "/version?want=" + v,
			Env:     []string{"GOOGLE_RUNTIME_VERSION=" + v},
			MustUse: []string{pythonRuntime, pythonPIP, entrypoint},
		})
	}
	for _, tc := range testCases {
		tc := tc
		t.Run(tc.Name, func(t *testing.T) {
			t.Parallel()

			acceptance.TestApp(t, builder, tc)
		})
	}
}

func TestFailuresPython(t *testing.T) {
	builder, cleanup := acceptance.CreateBuilder(t)
	t.Cleanup(cleanup)

	testCases := []acceptance.FailureTest{
		{
			Name:      "bad runtime version",
			App:       "python/simple",
			Env:       []string{"GOOGLE_RUNTIME_VERSION=BAD_NEWS_BEARS", "GOOGLE_ENTRYPOINT=gunicorn -b :8080 main:app"},
			MustMatch: "Runtime version BAD_NEWS_BEARS does not exist",
		},
		{
			Name:      "python-version empty",
			App:       "python/empty_version",
			MustMatch: ".python-version exists but does not specify a version",
		},
		{
			Name:      "missing entrypoint",
			App:       "python/missing_entrypoint",
			MustMatch: `for Python, an entrypoint must be manually set, either with "GOOGLE_ENTRYPOINT" env var or by creating a "Procfile" file`,
		},
	}

	for _, tc := range testCases {
		tc := tc
		t.Run(tc.Name, func(t *testing.T) {
			t.Parallel()

			acceptance.TestBuildFailure(t, builder, tc)
		})
	}
}
<|endoftext|>


<commit_before>package xattr_tests

// xattr integration tests.
//
// These tests are not integrated into the "matrix" tests because of the need
// to switch TMPDIR to /var/tmp.
// TODO: check if it actually causes trouble in the "matrix" tests.

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"syscall"
	"testing"

	"github.com/pkg/xattr"

	"github.com/rfjakob/gocryptfs/internal/cryptocore"
	"github.com/rfjakob/gocryptfs/tests/test_helpers"
)

func TestMain(m *testing.M) {
	// On modern Linux distributions, /tmp may be on tmpfs,
	// which does not support user xattrs. Try /var/tmp instead
	if !xattrSupported(test_helpers.TmpDir) && os.TempDir() == "/tmp" {
		fmt.Printf("Switching from /tmp to /var/tmp for xattr tests\n")
		test_helpers.SwitchTMPDIR("/var/tmp")
	}
	if !xattrSupported(test_helpers.TmpDir) {
		fmt.Printf("xattrs not supported on %q\n", test_helpers.TmpDir)
		os.Exit(1)
	}
	test_helpers.ResetTmpDir(true)
	// Write deterministic diriv so encrypted filenames are deterministic.
	os.Remove(test_helpers.DefaultCipherDir + "/gocryptfs.diriv")
	diriv := []byte("1234567890123456")
	err := ioutil.WriteFile(test_helpers.DefaultCipherDir+"/gocryptfs.diriv", diriv, 0400)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	test_helpers.MountOrExit(test_helpers.DefaultCipherDir, test_helpers.DefaultPlainDir, "-zerokey")
	r := m.Run()
	test_helpers.UnmountPanic(test_helpers.DefaultPlainDir)
	os.RemoveAll(test_helpers.TmpDir)
	os.Exit(r)
}

func setGetRmList(fn string) error {
	// List
	list, err := xattr.LList(fn)
	if err != nil {
		return err
	}
	if len(list) > 0 {
		return fmt.Errorf("Should have gotten empty result, got %v", list)
	}
	attr := "user.foo"
	// Set
	val1 := []byte("123456789")
	err = xattr.LSet(fn, attr, val1)
	if err != nil {
		return err
	}
	// Read back
	val2, err := xattr.LGet(fn, attr)
	if err != nil {
		return err
	}
	if !bytes.Equal(val1, val2) {
		return fmt.Errorf("wrong readback value: %v != %v", val1, val2)
	}
	// Remove
	err = xattr.LRemove(fn, attr)
	if err != nil {
		return err
	}
	// Read back
	val3, err := xattr.LGet(fn, attr)
	if err == nil {
		return fmt.Errorf("attr is still there after deletion!? val3=%v", val3)
	}
	// List
	list, err = xattr.LList(fn)
	if err != nil {
		return err
	}
	if len(list) > 0 {
		return fmt.Errorf("Should have gotten empty result, got %v", list)
	}
	return nil
}

// Test xattr set, get, rm on a regular file.
func TestSetGetRmRegularFile(t *testing.T) {
	fn := test_helpers.DefaultPlainDir + "/TestSetGetRmRegularFile"
	err := ioutil.WriteFile(fn, nil, 0700)
	if err != nil {
		t.Fatalf("creating empty file failed: %v", err)
	}
	err = setGetRmList(fn)
	if err != nil {
		t.Error(err)
	}
}

// Test xattr set, get, rm on a fifo. This should not hang.
func TestSetGetRmFifo(t *testing.T) {
	fn := test_helpers.DefaultPlainDir + "/TestSetGetRmFifo"
	err := syscall.Mkfifo(fn, 0700)
	if err != nil {
		t.Fatalf("creating fifo failed: %v", err)
	}
	// We expect to get EPERM, but we should not hang:
	// $ setfattr -n user.foo -v XXXXX fifo
	// setfattr: fifo: Operation not permitted
	setGetRmList(fn)
}

func TestXattrSetEmpty(t *testing.T) {
	attr := "user.foo"
	fn := test_helpers.DefaultPlainDir + "/TestXattrSetEmpty1"
	err := ioutil.WriteFile(fn, nil, 0700)
	if err != nil {
		t.Fatalf("creating empty file failed: %v", err)
	}
	// Make sure it does not exist already
	_, err = xattr.LGet(fn, attr)
	if err == nil {
		t.Fatal("we should have got an error here")
	}
	// Set empty value
	err = xattr.LSet(fn, attr, nil)
	if err != nil {
		t.Fatal(err)
	}
	// Read back
	val, err := xattr.LGet(fn, attr)
	if err != nil {
		t.Fatal(err)
	}
	if len(val) != 0 {
		t.Errorf("wrong length: want=0 have=%d", len(val))
	}
	// Overwrite empty value with something
	val1 := []byte("xyz123")
	err = xattr.LSet(fn, attr, val1)
	if err != nil {
		t.Fatal(err)
	}
	// Read back
	val2, err := xattr.LGet(fn, attr)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(val1, val2) {
		t.Fatalf("wrong readback value: %v != %v", val1, val2)
	}
	// Overwrite something with empty value
	err = xattr.LSet(fn, attr, nil)
	if err != nil {
		t.Fatal(err)
	}
	// Read back
	val, err = xattr.LGet(fn, attr)
	if err != nil {
		t.Fatal(err)
	}
	if len(val) != 0 {
		t.Errorf("wrong length: want=0 have=%d", len(val2))
	}
}

func TestXattrList(t *testing.T) {
	fn := test_helpers.DefaultPlainDir + "/TestXattrList"
	err := ioutil.WriteFile(fn, nil, 0700)
	if err != nil {
		t.Fatalf("creating empty file failed: %v", err)
	}
	val := []byte("xxxxxxxxyyyyyyyyyyyyyyyzzzzzzzzzzzzz")
	num := 20
	for i := 1; i <= num; i++ {
		attr := fmt.Sprintf("user.TestXattrList.%02d", i)
		err = xattr.LSet(fn, attr, val)
		if err != nil {
			t.Fatal(err)
		}
	}
	names, err := xattr.LList(fn)
	if err != nil {
		t.Fatal(err)
	}
	if len(names) != num {
		t.Errorf("wrong number of names, want=%d have=%d", num, len(names))
	}
	for _, n := range names {
		if !strings.HasPrefix(n, "user.TestXattrList.") {
			t.Errorf("unexpected attr name: %q", n)
		}
	}
}

func xattrSupported(path string) bool {
	_, err := xattr.LGet(path, "user.xattrSupported-dummy-value")
	if err == nil {
		return true
	}
	err2 := err.(*xattr.Error)
	if err2.Err == syscall.EOPNOTSUPP {
		return false
	}
	return true
}

func TestBase64XattrRead(t *testing.T) {
	attrName := "user.test"
	attrName2 := "user.test2"
	encryptedAttrName := "user.gocryptfs.LB1kHHVrX1OEBdLmj3LTKw"
	encryptedAttrName2 := "user.gocryptfs.d2yn5l7-0zUVqviADw-Oyw"
	attrValue := fmt.Sprintf("test.%d", cryptocore.RandUint64())

	fileName := "TestBase64Xattr"
	encryptedFileName := "BaGak7jIoqAZQMlP0N5uCw"

	plainFn := test_helpers.DefaultPlainDir + "/" + fileName
	encryptedFn := test_helpers.DefaultCipherDir + "/" + encryptedFileName
	err := ioutil.WriteFile(plainFn, nil, 0700)
	if err != nil {
		t.Fatalf("creating empty file failed: %v", err)
	}
	if _, err2 := os.Stat(encryptedFn); os.IsNotExist(err2) {
		t.Fatalf("encrypted file does not exist: %v", err2)
	}
	xattr.LSet(plainFn, attrName, []byte(attrValue))

	encryptedAttrValue, err1 := xattr.LGet(encryptedFn, encryptedAttrName)
	if err1 != nil {
		t.Fatal(err1)
	}

	xattr.LSet(encryptedFn, encryptedAttrName2, encryptedAttrValue)
	plainValue, err := xattr.LGet(plainFn, attrName2)

	if err != nil || string(plainValue) != attrValue {
		t.Fatalf("Attribute binary value decryption error: have=%q want=%q err=%v", string(plainValue), attrValue, err)
	}

	encryptedAttrValue64 := base64.RawURLEncoding.EncodeToString(encryptedAttrValue)
	xattr.LSet(encryptedFn, encryptedAttrName2, []byte(encryptedAttrValue64))

	plainValue, err = xattr.LGet(plainFn, attrName2)
	if err != nil || string(plainValue) != attrValue {
		t.Fatalf("Attribute base64-encoded value decryption error %s != %s %v", string(plainValue), attrValue, err)
	}

	// Remount with -wpanic=false so gocryptfs does not panics when it sees
	// the broken xattrs
	test_helpers.UnmountPanic(test_helpers.DefaultPlainDir)
	test_helpers.MountOrExit(test_helpers.DefaultCipherDir, test_helpers.DefaultPlainDir, "-zerokey", "-wpanic=false")

	brokenVals := []string{
		"111",
		"raw-test-long-block123",
		"raw-test-long-block123-xyz11111111111111111111111111111111111111",
		"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
	}
	for _, val := range brokenVals {
		xattr.LSet(encryptedFn, encryptedAttrName2, []byte(val))
		plainValue, err = xattr.LGet(plainFn, attrName2)
		err2, _ := err.(*xattr.Error)
		if err == nil || err2.Err != syscall.EIO {
			t.Fatalf("Incorrect handling of broken data %s %v", string(plainValue), err)
		}
	}
}
<commit_msg>tests: xattr: set on 0200 file, list on 0000 file<commit_after>package xattr_tests

// xattr integration tests.
//
// These tests are not integrated into the "matrix" tests because of the need
// to switch TMPDIR to /var/tmp.
// TODO: check if it actually causes trouble in the "matrix" tests.

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"syscall"
	"testing"

	"github.com/pkg/xattr"

	"github.com/rfjakob/gocryptfs/internal/cryptocore"
	"github.com/rfjakob/gocryptfs/tests/test_helpers"
)

func TestMain(m *testing.M) {
	// On modern Linux distributions, /tmp may be on tmpfs,
	// which does not support user xattrs. Try /var/tmp instead
	if !xattrSupported(test_helpers.TmpDir) && os.TempDir() == "/tmp" {
		fmt.Printf("Switching from /tmp to /var/tmp for xattr tests\n")
		test_helpers.SwitchTMPDIR("/var/tmp")
	}
	if !xattrSupported(test_helpers.TmpDir) {
		fmt.Printf("xattrs not supported on %q\n", test_helpers.TmpDir)
		os.Exit(1)
	}
	test_helpers.ResetTmpDir(true)
	// Write deterministic diriv so encrypted filenames are deterministic.
	os.Remove(test_helpers.DefaultCipherDir + "/gocryptfs.diriv")
	diriv := []byte("1234567890123456")
	err := ioutil.WriteFile(test_helpers.DefaultCipherDir+"/gocryptfs.diriv", diriv, 0400)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	test_helpers.MountOrExit(test_helpers.DefaultCipherDir, test_helpers.DefaultPlainDir, "-zerokey")
	r := m.Run()
	test_helpers.UnmountPanic(test_helpers.DefaultPlainDir)
	os.RemoveAll(test_helpers.TmpDir)
	os.Exit(r)
}

func setGetRmList(fn string) error {
	// List
	list, err := xattr.LList(fn)
	if err != nil {
		return err
	}
	if len(list) > 0 {
		return fmt.Errorf("Should have gotten empty result, got %v", list)
	}
	attr := "user.foo"
	// Set
	val1 := []byte("123456789")
	err = xattr.LSet(fn, attr, val1)
	if err != nil {
		return err
	}
	// Read back
	val2, err := xattr.LGet(fn, attr)
	if err != nil {
		return err
	}
	if !bytes.Equal(val1, val2) {
		return fmt.Errorf("wrong readback value: %v != %v", val1, val2)
	}
	// Remove
	err = xattr.LRemove(fn, attr)
	if err != nil {
		return err
	}
	// Read back
	val3, err := xattr.LGet(fn, attr)
	if err == nil {
		return fmt.Errorf("attr is still there after deletion!? val3=%v", val3)
	}
	// List
	list, err = xattr.LList(fn)
	if err != nil {
		return err
	}
	if len(list) > 0 {
		return fmt.Errorf("Should have gotten empty result, got %v", list)
	}
	return nil
}

// Test xattr set, get, rm on a regular file.
func TestSetGetRmRegularFile(t *testing.T) {
	fn := test_helpers.DefaultPlainDir + "/TestSetGetRmRegularFile"
	err := ioutil.WriteFile(fn, []byte("12345"), 0700)
	if err != nil {
		t.Fatalf("creating empty file failed: %v", err)
	}
	err = setGetRmList(fn)
	if err != nil {
		t.Error(err)
	}
	fi, _ := os.Lstat(fn)
	if fi.Size() != 5 {
		t.Errorf("file size has changed!? size=%d", fi.Size())
	}
}

// Test xattr set, get, rm on a fifo. This should not hang.
func TestSetGetRmFifo(t *testing.T) {
	fn := test_helpers.DefaultPlainDir + "/TestSetGetRmFifo"
	err := syscall.Mkfifo(fn, 0700)
	if err != nil {
		t.Fatalf("creating fifo failed: %v", err)
	}
	// We expect to get EPERM, but we should not hang:
	// $ setfattr -n user.foo -v XXXXX fifo
	// setfattr: fifo: Operation not permitted
	setGetRmList(fn)
}

func TestXattrSetEmpty(t *testing.T) {
	attr := "user.foo"
	fn := test_helpers.DefaultPlainDir + "/TestXattrSetEmpty1"
	err := ioutil.WriteFile(fn, nil, 0700)
	if err != nil {
		t.Fatalf("creating empty file failed: %v", err)
	}
	// Make sure it does not exist already
	_, err = xattr.LGet(fn, attr)
	if err == nil {
		t.Fatal("we should have got an error here")
	}
	// Set empty value
	err = xattr.LSet(fn, attr, nil)
	if err != nil {
		t.Fatal(err)
	}
	// Read back
	val, err := xattr.LGet(fn, attr)
	if err != nil {
		t.Fatal(err)
	}
	if len(val) != 0 {
		t.Errorf("wrong length: want=0 have=%d", len(val))
	}
	// Overwrite empty value with something
	val1 := []byte("xyz123")
	err = xattr.LSet(fn, attr, val1)
	if err != nil {
		t.Fatal(err)
	}
	// Read back
	val2, err := xattr.LGet(fn, attr)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(val1, val2) {
		t.Fatalf("wrong readback value: %v != %v", val1, val2)
	}
	// Overwrite something with empty value
	err = xattr.LSet(fn, attr, nil)
	if err != nil {
		t.Fatal(err)
	}
	// Read back
	val, err = xattr.LGet(fn, attr)
	if err != nil {
		t.Fatal(err)
	}
	if len(val) != 0 {
		t.Errorf("wrong length: want=0 have=%d", len(val2))
	}
}

func TestXattrList(t *testing.T) {
	fn := test_helpers.DefaultPlainDir + "/TestXattrList"
	err := ioutil.WriteFile(fn, nil, 0700)
	if err != nil {
		t.Fatalf("creating empty file failed: %v", err)
	}
	val := []byte("xxxxxxxxyyyyyyyyyyyyyyyzzzzzzzzzzzzz")
	num := 20
	for i := 1; i <= num; i++ {
		attr := fmt.Sprintf("user.TestXattrList.%02d", i)
		err = xattr.LSet(fn, attr, val)
		if err != nil {
			t.Fatal(err)
		}
	}
	names, err := xattr.LList(fn)
	if err != nil {
		t.Fatal(err)
	}
	if len(names) != num {
		t.Errorf("wrong number of names, want=%d have=%d", num, len(names))
	}
	for _, n := range names {
		if !strings.HasPrefix(n, "user.TestXattrList.") {
			t.Errorf("unexpected attr name: %q", n)
		}
	}
}

func xattrSupported(path string) bool {
	_, err := xattr.LGet(path, "user.xattrSupported-dummy-value")
	if err == nil {
		return true
	}
	err2 := err.(*xattr.Error)
	if err2.Err == syscall.EOPNOTSUPP {
		return false
	}
	return true
}

func TestBase64XattrRead(t *testing.T) {
	attrName := "user.test"
	attrName2 := "user.test2"
	encryptedAttrName := "user.gocryptfs.LB1kHHVrX1OEBdLmj3LTKw"
	encryptedAttrName2 := "user.gocryptfs.d2yn5l7-0zUVqviADw-Oyw"
	attrValue := fmt.Sprintf("test.%d", cryptocore.RandUint64())

	fileName := "TestBase64Xattr"
	encryptedFileName := "BaGak7jIoqAZQMlP0N5uCw"

	plainFn := test_helpers.DefaultPlainDir + "/" + fileName
	encryptedFn := test_helpers.DefaultCipherDir + "/" + encryptedFileName
	err := ioutil.WriteFile(plainFn, nil, 0700)
	if err != nil {
		t.Fatalf("creating empty file failed: %v", err)
	}
	if _, err2 := os.Stat(encryptedFn); os.IsNotExist(err2) {
		t.Fatalf("encrypted file does not exist: %v", err2)
	}
	xattr.LSet(plainFn, attrName, []byte(attrValue))

	encryptedAttrValue, err1 := xattr.LGet(encryptedFn, encryptedAttrName)
	if err1 != nil {
		t.Fatal(err1)
	}

	xattr.LSet(encryptedFn, encryptedAttrName2, encryptedAttrValue)
	plainValue, err := xattr.LGet(plainFn, attrName2)

	if err != nil || string(plainValue) != attrValue {
		t.Fatalf("Attribute binary value decryption error: have=%q want=%q err=%v", string(plainValue), attrValue, err)
	}

	encryptedAttrValue64 := base64.RawURLEncoding.EncodeToString(encryptedAttrValue)
	xattr.LSet(encryptedFn, encryptedAttrName2, []byte(encryptedAttrValue64))

	plainValue, err = xattr.LGet(plainFn, attrName2)
	if err != nil || string(plainValue) != attrValue {
		t.Fatalf("Attribute base64-encoded value decryption error %s != %s %v", string(plainValue), attrValue, err)
	}

	// Remount with -wpanic=false so gocryptfs does not panics when it sees
	// the broken xattrs
	test_helpers.UnmountPanic(test_helpers.DefaultPlainDir)
	test_helpers.MountOrExit(test_helpers.DefaultCipherDir, test_helpers.DefaultPlainDir, "-zerokey", "-wpanic=false")

	brokenVals := []string{
		"111",
		"raw-test-long-block123",
		"raw-test-long-block123-xyz11111111111111111111111111111111111111",
		"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
	}
	for _, val := range brokenVals {
		xattr.LSet(encryptedFn, encryptedAttrName2, []byte(val))
		plainValue, err = xattr.LGet(plainFn, attrName2)
		err2, _ := err.(*xattr.Error)
		if err == nil || err2.Err != syscall.EIO {
			t.Fatalf("Incorrect handling of broken data %s %v", string(plainValue), err)
		}
	}
}

// Listing xattrs should work even when we don't have read access
func TestList0000File(t *testing.T) {
	fn := test_helpers.DefaultPlainDir + "/TestList0000File"
	err := ioutil.WriteFile(fn, nil, 0000)
	if err != nil {
		t.Fatalf("creating empty file failed: %v", err)
	}
	_, err = xattr.LList(fn)
	if err != nil {
		t.Error(err)
	}
}

// Setting xattrs should work even when we don't have read access
func TestSet0200File(t *testing.T) {
	fn := test_helpers.DefaultPlainDir + "/TestSet0200File"
	err := ioutil.WriteFile(fn, nil, 0200)
	if err != nil {
		t.Fatalf("creating empty file failed: %v", err)
	}
	err = xattr.LSet(fn, "user.foo", []byte("bar"))
	if err != nil {
		t.Error(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"image"
	"image/color"
	"io"
	"os"
	"os/exec"
	"time"

	"github.com/lucasb-eyer/go-colorful"
	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/logger"
	"github.com/ninjasphere/go-ninja/model"
	ledmodel "github.com/ninjasphere/sphere-go-led-controller/model"
	"github.com/ninjasphere/sphere-go-led-controller/ui"
	"github.com/ninjasphere/sphere-go-led-controller/util"
	"github.com/tarm/goserial"
)

var log = logger.GetLogger("sphere-go-led-controller")

type LedController struct {
	controlEnabled bool
	controlLayout  *ui.PaneLayout
	pairingLayout  *ui.PairingLayout
	conn           *ninja.Connection
	serial         io.ReadWriteCloser
	waiting        chan bool
}

func GetLEDConnection(baudRate int) (io.ReadWriteCloser, error) {

	log.Debugf("Resetting LED Matrix")
	cmd := exec.Command("/usr/local/bin/reset-led-matrix")
	output, err := cmd.Output()
	log.Debugf("Output from reset: %s", output)

	c := &serial.Config{Name: "/dev/tty.ledmatrix", Baud: baudRate}
	s, err := serial.OpenPort(c)
	if err != nil {
		return nil, err
	}

	// Now we wait for the init string
	buf := make([]byte, 16)
	_, err = s.Read(buf)
	if err != nil {
		log.Fatalf("Failed to read initialisation string from led matrix : %s", err)
	}
	if string(buf[0:3]) != "LED" {
		log.Infof("Expected init string 'LED', got '%s'.", buf)
		s.Close()
		return nil, fmt.Errorf("Bad init string..")
	}

	log.Debugf("Read init string from LED Matrix: %s", buf)

	return s, nil
}

const baudRate = 115200

func NewLedController(conn *ninja.Connection) (*LedController, error) {

	s, err := GetLEDConnection(baudRate * 2)

	if err != nil {
		log.Warningf("Failed to connect to LED using baud rate: %d, trying %d", baudRate*2, baudRate)
		s, err = GetLEDConnection(baudRate)
		if err != nil {
			log.Fatalf("Failed to connect to LED display: %s", err)
		}
	}
	// Send a blank image to the led matrix
	util.WriteLEDMatrix(image.NewRGBA(image.Rect(0, 0, 16, 16)), s)

	controller := &LedController{
		conn:          conn,
		pairingLayout: ui.NewPairingLayout(conn),
		serial:        s,
		waiting:       make(chan bool),
	}

	conn.MustExportService(controller, "$node/"+config.Serial()+"/led-controller", &model.ServiceAnnouncement{
		Schema: "/service/led-controller",
	})

	return controller, nil
}

func (c *LedController) start(enableControl bool) {
	c.controlEnabled = enableControl

	frameWritten := make(chan bool)

	go func() {
		for {
			if c.controlEnabled {

				if c.controlLayout == nil {

					log.Infof("Enabling layout... clearing LED")

					util.WriteLEDMatrix(image.NewRGBA(image.Rect(0, 0, 16, 16)), c.serial)

					c.controlLayout = getPaneLayout(c.conn)
					log.Infof("Finished control layout")
				}

				image, wake, err := c.controlLayout.Render()
				if err != nil {
					log.Fatalf("Unable to render()", err)
				}

				go func() {
					util.WriteLEDMatrix(image, c.serial)
					frameWritten <- true
				}()

				select {
				case <-frameWritten:
					// All good.
				case <-time.After(10 * time.Second):
					log.Infof("Timeout writing to LED matrix. Quitting.")
					os.Exit(1)
					// Timed out writing to the led matrix. For now. Boot!
					//cmd := exec.Command("reboot")
					//output, err := cmd.Output()

					//log.Debugf("Output from reboot: %s err: %s", output, err)
				}

				if wake != nil {
					log.Infof("Waiting as the UI is asleep")
					select {
					case <-wake:
						log.Infof("UI woke up!")
					case <-c.waiting:
						log.Infof("Got a command from rpc...")
					}
				}

			} else {

				image, err := c.pairingLayout.Render()
				if err != nil {
					log.Fatalf("Unable to render()", err)
				}
				util.WriteLEDMatrix(image, c.serial)

			}
		}
	}()
}

func (c *LedController) EnableControl() error {
	c.controlEnabled = true
	c.gotCommand()
	return nil
}

func (c *LedController) DisableControl() error {
	c.controlEnabled = false
	c.gotCommand()
	return nil
}

type PairingCodeRequest struct {
	Code        string `json:"code"`
	DisplayTime int    `json:"displayTime"`
}

func (c *LedController) DisplayPairingCode(req *PairingCodeRequest) error {
	c.controlEnabled = false
	c.pairingLayout.ShowCode(req.Code)
	c.gotCommand()
	return nil
}

type ColorRequest struct {
	Color       string `json:"color"`
	DisplayTime int    `json:"displayTime"`
}

func (c *LedController) DisplayColor(req *ColorRequest) error {
	col, err := colorful.Hex(req.Color)

	if err != nil {
		return err
	}

	c.controlEnabled = false
	c.pairingLayout.ShowColor(col)
	c.gotCommand()
	return nil
}

type IconRequest struct {
	Icon        string `json:"icon"`
	DisplayTime int    `json:"displayTime"`
}

func (c *LedController) DisplayIcon(req *IconRequest) error {
	c.controlEnabled = false
	c.pairingLayout.ShowIcon(req.Icon)
	c.gotCommand()
	return nil
}

func (c *LedController) DisplayResetMode(m *ledmodel.ResetMode) error {
	c.controlEnabled = false
	fade := m.Duration > 0 && !m.Hold
	loading := false
	var col color.Color
	switch m.Mode {
	case "reboot":
		col, _ = colorful.Hex("#00FF00")
	case "reset-userdata":
		col, _ = colorful.Hex("#FFFF00")
	case "reset-root":
		col, _ = colorful.Hex("#FF0000")
	default:
		loading = true
	}

	if loading {
		c.pairingLayout.ShowIcon("loading.gif")
	} else if fade {
		c.pairingLayout.ShowFadingShrinkingColor(col, m.Duration)
	} else {
		c.pairingLayout.ShowColor(col)
	}

	c.gotCommand()
	return nil
}

func (c *LedController) gotCommand() {
	select {
	case c.waiting <- true:
	default:
	}
}

// Load from a config file instead...
func getPaneLayout(conn *ninja.Connection) *ui.PaneLayout {
	layout, wake := ui.NewPaneLayout(false)

	mediaPane := ui.NewMediaPane(&ui.MediaPaneImages{
		Volume: "images/media-volume-speaker.gif",
		Mute:   "images/media-volume-mute.png",
		Play:   "images/media-play.png",
		Pause:  "images/media-pause.png",
		Stop:   "images/media-stop.png",
		Next:   "images/media-next.png",
	}, conn)
	layout.AddPane(mediaPane)

	if len(os.Getenv("CERTIFICATION")) > 0 {
		layout.AddPane(ui.NewCertPane(conn.GetMqttClient()))
	} else {
		//layout.AddPane(ui.NewTextScrollPane("Exit Music (For A Film)"))

		heaterPane := ui.NewOnOffPane("images/heater-off.png", "images/heater-on.gif", func(state bool) {
			log.Debugf("Heater state: %t", state)
		}, conn, "heater")
		layout.AddPane(heaterPane)
	}

	lightPane := ui.NewLightPane("images/light-off.png", "images/light-on.png", func(state bool) {
		log.Debugf("Light on-off state: %t", state)
	}, func(state float64) {
		log.Debugf("Light color state: %f", state)
	}, conn)
	layout.AddPane(lightPane)

	fanPane := ui.NewOnOffPane("images/fan-off.png", "images/fan-on.gif", func(state bool) {
		log.Debugf("Fan state: %t", state)
	}, conn, "fan")

	layout.AddPane(fanPane)

	go func() {
		<-wake
	}()

	go layout.Wake()

	return layout
}
<commit_msg>Print FPS to debug<commit_after>package main

import (
	"fmt"
	"image"
	"image/color"
	"io"
	"os"
	"os/exec"
	"time"

	"github.com/lucasb-eyer/go-colorful"
	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/logger"
	"github.com/ninjasphere/go-ninja/model"
	ledmodel "github.com/ninjasphere/sphere-go-led-controller/model"
	"github.com/ninjasphere/sphere-go-led-controller/ui"
	"github.com/ninjasphere/sphere-go-led-controller/util"
	"github.com/tarm/goserial"
)

var log = logger.GetLogger("sphere-go-led-controller")

var fps Tick = Tick{
	name: "Pane FPS",
}

type LedController struct {
	controlEnabled bool
	controlLayout  *ui.PaneLayout
	pairingLayout  *ui.PairingLayout
	conn           *ninja.Connection
	serial         io.ReadWriteCloser
	waiting        chan bool
}

func GetLEDConnection(baudRate int) (io.ReadWriteCloser, error) {

	log.Debugf("Resetting LED Matrix")
	cmd := exec.Command("/usr/local/bin/reset-led-matrix")
	output, err := cmd.Output()
	log.Debugf("Output from reset: %s", output)

	c := &serial.Config{Name: "/dev/tty.ledmatrix", Baud: baudRate}
	s, err := serial.OpenPort(c)
	if err != nil {
		return nil, err
	}

	// Now we wait for the init string
	buf := make([]byte, 16)
	_, err = s.Read(buf)
	if err != nil {
		log.Fatalf("Failed to read initialisation string from led matrix : %s", err)
	}
	if string(buf[0:3]) != "LED" {
		log.Infof("Expected init string 'LED', got '%s'.", buf)
		s.Close()
		return nil, fmt.Errorf("Bad init string..")
	}

	log.Debugf("Read init string from LED Matrix: %s", buf)

	return s, nil
}

const baudRate = 115200

func NewLedController(conn *ninja.Connection) (*LedController, error) {

	s, err := GetLEDConnection(baudRate * 2)

	if err != nil {
		log.Warningf("Failed to connect to LED using baud rate: %d, trying %d", baudRate*2, baudRate)
		s, err = GetLEDConnection(baudRate)
		if err != nil {
			log.Fatalf("Failed to connect to LED display: %s", err)
		}
	}
	// Send a blank image to the led matrix
	util.WriteLEDMatrix(image.NewRGBA(image.Rect(0, 0, 16, 16)), s)

	controller := &LedController{
		conn:          conn,
		pairingLayout: ui.NewPairingLayout(conn),
		serial:        s,
		waiting:       make(chan bool),
	}

	conn.MustExportService(controller, "$node/"+config.Serial()+"/led-controller", &model.ServiceAnnouncement{
		Schema: "/service/led-controller",
	})

	return controller, nil
}

func (c *LedController) start(enableControl bool) {
	c.controlEnabled = enableControl

	frameWritten := make(chan bool)

	go func() {
		fps.start()

		for {
			fps.tick()

			if c.controlEnabled {

				if c.controlLayout == nil {

					log.Infof("Enabling layout... clearing LED")

					util.WriteLEDMatrix(image.NewRGBA(image.Rect(0, 0, 16, 16)), c.serial)

					c.controlLayout = getPaneLayout(c.conn)
					log.Infof("Finished control layout")
				}

				image, wake, err := c.controlLayout.Render()
				if err != nil {
					log.Fatalf("Unable to render()", err)
				}

				go func() {
					util.WriteLEDMatrix(image, c.serial)
					frameWritten <- true
				}()

				select {
				case <-frameWritten:
					// All good.
				case <-time.After(10 * time.Second):
					log.Infof("Timeout writing to LED matrix. Quitting.")
					os.Exit(1)
					// Timed out writing to the led matrix. For now. Boot!
					//cmd := exec.Command("reboot")
					//output, err := cmd.Output()

					//log.Debugf("Output from reboot: %s err: %s", output, err)
				}

				if wake != nil {
					log.Infof("Waiting as the UI is asleep")
					select {
					case <-wake:
						log.Infof("UI woke up!")
					case <-c.waiting:
						log.Infof("Got a command from rpc...")
					}
				}

			} else {

				image, err := c.pairingLayout.Render()
				if err != nil {
					log.Fatalf("Unable to render()", err)
				}
				util.WriteLEDMatrix(image, c.serial)

			}
		}
	}()
}

func (c *LedController) EnableControl() error {
	c.controlEnabled = true
	c.gotCommand()
	return nil
}

func (c *LedController) DisableControl() error {
	c.controlEnabled = false
	c.gotCommand()
	return nil
}

type PairingCodeRequest struct {
	Code        string `json:"code"`
	DisplayTime int    `json:"displayTime"`
}

func (c *LedController) DisplayPairingCode(req *PairingCodeRequest) error {
	c.controlEnabled = false
	c.pairingLayout.ShowCode(req.Code)
	c.gotCommand()
	return nil
}

type ColorRequest struct {
	Color       string `json:"color"`
	DisplayTime int    `json:"displayTime"`
}

func (c *LedController) DisplayColor(req *ColorRequest) error {
	col, err := colorful.Hex(req.Color)

	if err != nil {
		return err
	}

	c.controlEnabled = false
	c.pairingLayout.ShowColor(col)
	c.gotCommand()
	return nil
}

type IconRequest struct {
	Icon        string `json:"icon"`
	DisplayTime int    `json:"displayTime"`
}

func (c *LedController) DisplayIcon(req *IconRequest) error {
	c.controlEnabled = false
	c.pairingLayout.ShowIcon(req.Icon)
	c.gotCommand()
	return nil
}

func (c *LedController) DisplayResetMode(m *ledmodel.ResetMode) error {
	c.controlEnabled = false
	fade := m.Duration > 0 && !m.Hold
	loading := false
	var col color.Color
	switch m.Mode {
	case "reboot":
		col, _ = colorful.Hex("#00FF00")
	case "reset-userdata":
		col, _ = colorful.Hex("#FFFF00")
	case "reset-root":
		col, _ = colorful.Hex("#FF0000")
	default:
		loading = true
	}

	if loading {
		c.pairingLayout.ShowIcon("loading.gif")
	} else if fade {
		c.pairingLayout.ShowFadingShrinkingColor(col, m.Duration)
	} else {
		c.pairingLayout.ShowColor(col)
	}

	c.gotCommand()
	return nil
}

func (c *LedController) gotCommand() {
	select {
	case c.waiting <- true:
	default:
	}
}

// Load from a config file instead...
func getPaneLayout(conn *ninja.Connection) *ui.PaneLayout {
	layout, wake := ui.NewPaneLayout(false)

	mediaPane := ui.NewMediaPane(&ui.MediaPaneImages{
		Volume: "images/media-volume-speaker.gif",
		Mute:   "images/media-volume-mute.png",
		Play:   "images/media-play.png",
		Pause:  "images/media-pause.png",
		Stop:   "images/media-stop.png",
		Next:   "images/media-next.png",
	}, conn)
	layout.AddPane(mediaPane)

	if len(os.Getenv("CERTIFICATION")) > 0 {
		layout.AddPane(ui.NewCertPane(conn.GetMqttClient()))
	} else {
		//layout.AddPane(ui.NewTextScrollPane("Exit Music (For A Film)"))

		heaterPane := ui.NewOnOffPane("images/heater-off.png", "images/heater-on.gif", func(state bool) {
			log.Debugf("Heater state: %t", state)
		}, conn, "heater")
		layout.AddPane(heaterPane)
	}

	lightPane := ui.NewLightPane("images/light-off.png", "images/light-on.png", func(state bool) {
		log.Debugf("Light on-off state: %t", state)
	}, func(state float64) {
		log.Debugf("Light color state: %f", state)
	}, conn)
	layout.AddPane(lightPane)

	fanPane := ui.NewOnOffPane("images/fan-off.png", "images/fan-on.gif", func(state bool) {
		log.Debugf("Fan state: %t", state)
	}, conn, "fan")

	layout.AddPane(fanPane)

	go func() {
		<-wake
	}()

	go layout.Wake()

	return layout
}

type Tick struct {
	count int
	name  string
}

func (t *Tick) tick() {
	t.count++
}

func (t *Tick) start() {
	go func() {
		for {
			time.Sleep(time.Second)
			log.Debugf("%s - %d", t.name, t.count)
			t.count = 0
		}
	}()
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Pani Networks
// 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.

// Main entry point for Kubernetes listener
package main

import (
	"flag"
	"fmt"
	"github.com/romana/core/common"
	"github.com/romana/core/romana/kubernetes"
)

func main() {
	rootURL := flag.String("rootURL", "", "Romana Root service URL")
	version := flag.Bool("version", false, "Build Information.")
	username := flag.String("username", "", "Username")
	password := flag.String("password", "", "Password")

	flag.Parse()

	if *version {
		fmt.Println(common.BuildInfo())
		return
	}
	cred := common.MakeCredentialFromCliArgs(*username, *password)
	kubernetes.Run(*rootURL, cred)
}
<commit_msg>Add service loop in kubernetes listener main.go<commit_after>// Copyright (c) 2016 Pani Networks
// 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.

// Main entry point for Kubernetes listener
package main

import (
	"flag"
	"fmt"
	"github.com/romana/core/common"
	"github.com/romana/core/romana/kubernetes"
)

func main() {
	rootURL := flag.String("rootURL", "", "Romana Root service URL")
	version := flag.Bool("version", false, "Build Information.")
	username := flag.String("username", "", "Username")
	password := flag.String("password", "", "Password")

	flag.Parse()

	if *version {
		fmt.Println(common.BuildInfo())
		return
	}
	cred := common.MakeCredentialFromCliArgs(*username, *password)
	svcInfo, err := kubernetes.Run(*rootURL, cred)
	if err != nil {
		panic(err)
	}
	for {
		msg := <-svcInfo.Channel
		fmt.Println(msg)
	}
}
<|endoftext|>


<commit_before>package factory

import "time"
import "chant/app/models"

import "regexp"

func SoundFromText(text string, user *model.User) (sound model.Sound, err error) {
	exp, _ := regexp.Compile("(https?)://(soundcloud.com|www.youtube.com)/(.+)")
	matched := exp.FindAllStringSubmatch(text, 1)
	if len(matched) == 0 || len(matched[0]) < 4 {
		err = NotSoundError{"ようつべとサンクラじゃない"}
		return
	}
	sound = model.Sound{
		"sound",
		user,
		soundSourceFromMatchedMap(matched[0]),
		int(time.Now().Unix()),
	}
	err = nil
	return
}

func soundSourceFromMatchedMap(matched []string) model.SoundSource {
	url := matched[0]
	vendor := vendorFromName(matched[2])
	hash := vendor.GetHash(url)
	return model.SoundSource{
		vendor,
		url,
		hash,
	}
}
func vendorFromName(vendorName string) model.Vendor {
	switch vendorName {
	case "www.youtube.com":
		return model.YouTube{
			Name: "youtube",
		}
	case "soundcloud.com":
		return model.SoundCloud{
			Name: "soundcloud",
		}
	}
	return model.UnknownVendor{
		Name: "unknown",
	}
}

type NotSoundError struct {
	message string
}

func (nse NotSoundError) Error() string {
	return nse.message
}
<commit_msg>Use strict regex for sound<commit_after>package factory

import "time"
import "chant/app/models"

import "regexp"

func SoundFromText(text string, user *model.User) (sound model.Sound, err error) {
	exp, _ := regexp.Compile("^(https?)://(soundcloud.com|www.youtube.com)/(.+)")
	matched := exp.FindAllStringSubmatch(text, 1)
	if len(matched) == 0 || len(matched[0]) < 4 {
		err = NotSoundError{"ようつべとサンクラじゃない"}
		return
	}
	sound = model.Sound{
		"sound",
		user,
		soundSourceFromMatchedMap(matched[0]),
		int(time.Now().Unix()),
	}
	err = nil
	return
}

func soundSourceFromMatchedMap(matched []string) model.SoundSource {
	url := matched[0]
	vendor := vendorFromName(matched[2])
	hash := vendor.GetHash(url)
	return model.SoundSource{
		vendor,
		url,
		hash,
	}
}
func vendorFromName(vendorName string) model.Vendor {
	switch vendorName {
	case "www.youtube.com":
		return model.YouTube{
			Name: "youtube",
		}
	case "soundcloud.com":
		return model.SoundCloud{
			Name: "soundcloud",
		}
	}
	return model.UnknownVendor{
		Name: "unknown",
	}
}

type NotSoundError struct {
	message string
}

func (nse NotSoundError) Error() string {
	return nse.message
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Vitess Authors.

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

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

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

package endtoend

import (
	"context"
	"fmt"
	"testing"

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

	"vitess.io/vitess/go/mysql/fakesqldb"
	"vitess.io/vitess/go/sqltypes"
	"vitess.io/vitess/go/vt/logutil"
	"vitess.io/vitess/go/vt/topo/memorytopo"
	"vitess.io/vitess/go/vt/vtctl/grpcvtctldserver"
	"vitess.io/vitess/go/vt/vttablet/tabletservermock"
	"vitess.io/vitess/go/vt/vttablet/tmclient"
	"vitess.io/vitess/go/vt/wrangler"
	"vitess.io/vitess/go/vt/wrangler/testlib"

	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
	vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata"
)

func TestInitShardPrimary(t *testing.T) {
	ts := memorytopo.NewServer("cell1")
	tmc := tmclient.NewTabletManagerClient()
	wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmc)

	primaryDb := fakesqldb.New(t)
	primaryDb.AddQuery("create database if not exists `vt_test_keyspace`", &sqltypes.Result{InsertID: 0, RowsAffected: 0})

	tablet1 := testlib.NewFakeTablet(t, wr, "cell1", 0, topodatapb.TabletType_PRIMARY, primaryDb)
	tablet2 := testlib.NewFakeTablet(t, wr, "cell1", 1, topodatapb.TabletType_REPLICA, nil)
	tablet3 := testlib.NewFakeTablet(t, wr, "cell1", 2, topodatapb.TabletType_REPLICA, nil)

	tablet1.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"CREATE DATABASE IF NOT EXISTS _vt",
		"SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal",
		"ALTER TABLE _vt.reparent_journal CHANGE COLUMN primary_alias master_alias VARBINARY(32) NOT NULL",
		"CREATE DATABASE IF NOT EXISTS _vt",
		"SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal",
		"ALTER TABLE _vt.reparent_journal CHANGE COLUMN primary_alias master_alias VARBINARY(32) NOT NULL",
		"SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, master_alias, replication_position) VALUES",
	}

	tablet2.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"FAKE RESET ALL REPLICATION",
		"FAKE SET SLAVE POSITION",
		"FAKE SET MASTER",
		"START SLAVE",
	}
	tablet2.FakeMysqlDaemon.SetReplicationSourceInputs = append(tablet2.FakeMysqlDaemon.SetReplicationSourceInputs, fmt.Sprintf("%v:%v", tablet1.Tablet.Hostname, tablet1.Tablet.MysqlPort))

	tablet3.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"FAKE RESET ALL REPLICATION",
		"FAKE SET SLAVE POSITION",
		"FAKE SET MASTER",
		"START SLAVE",
	}
	tablet3.FakeMysqlDaemon.SetReplicationSourceInputs = append(tablet3.FakeMysqlDaemon.SetReplicationSourceInputs, fmt.Sprintf("%v:%v", tablet1.Tablet.Hostname, tablet1.Tablet.MysqlPort))

	for _, tablet := range []*testlib.FakeTablet{tablet1, tablet2, tablet3} {
		tablet.StartActionLoop(t, wr)
		defer tablet.StopActionLoop(t)

		tablet.TM.QueryServiceControl.(*tabletservermock.Controller).SetQueryServiceEnabledForTests(true)
	}

	vtctld := grpcvtctldserver.NewVtctldServer(ts)
	resp, err := vtctld.InitShardPrimary(context.Background(), &vtctldatapb.InitShardPrimaryRequest{
		Keyspace:                tablet1.Tablet.Keyspace,
		Shard:                   tablet1.Tablet.Shard,
		PrimaryElectTabletAlias: tablet1.Tablet.Alias,
	})

	assert.NoError(t, err)
	assert.NotNil(t, resp)
}

func TestInitShardPrimaryNoFormerPrimary(t *testing.T) {
	ts := memorytopo.NewServer("cell1")
	tmc := tmclient.NewTabletManagerClient()
	wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmc)

	primaryDb := fakesqldb.New(t)
	primaryDb.AddQuery("create database if not exists `vt_test_keyspace`", &sqltypes.Result{InsertID: 0, RowsAffected: 0})

	tablet1 := testlib.NewFakeTablet(t, wr, "cell1", 0, topodatapb.TabletType_REPLICA, primaryDb)
	tablet2 := testlib.NewFakeTablet(t, wr, "cell1", 1, topodatapb.TabletType_REPLICA, nil)
	tablet3 := testlib.NewFakeTablet(t, wr, "cell1", 2, topodatapb.TabletType_REPLICA, nil)

	tablet1.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"CREATE DATABASE IF NOT EXISTS _vt",
		"SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal",
		"ALTER TABLE _vt.reparent_journal CHANGE COLUMN primary_alias master_alias VARBINARY(32) NOT NULL",
		"CREATE DATABASE IF NOT EXISTS _vt",
		"SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal",
		"ALTER TABLE _vt.reparent_journal CHANGE COLUMN primary_alias master_alias VARBINARY(32) NOT NULL",
		"SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, master_alias, replication_position) VALUES",
	}

	tablet2.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"FAKE SET SLAVE POSITION",
		"FAKE SET MASTER",
		"START SLAVE",
	}
	tablet2.FakeMysqlDaemon.SetReplicationSourceInputs = append(tablet2.FakeMysqlDaemon.SetReplicationSourceInputs, fmt.Sprintf("%v:%v", tablet1.Tablet.Hostname, tablet1.Tablet.MysqlPort))

	tablet3.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"FAKE SET SLAVE POSITION",
		"FAKE SET MASTER",
		"START SLAVE",
	}
	tablet3.FakeMysqlDaemon.SetReplicationSourceInputs = append(tablet3.FakeMysqlDaemon.SetReplicationSourceInputs, fmt.Sprintf("%v:%v", tablet1.Tablet.Hostname, tablet1.Tablet.MysqlPort))

	for _, tablet := range []*testlib.FakeTablet{tablet1, tablet2, tablet3} {
		tablet.StartActionLoop(t, wr)
		defer tablet.StopActionLoop(t)

		tablet.TM.QueryServiceControl.(*tabletservermock.Controller).SetQueryServiceEnabledForTests(true)
	}

	vtctld := grpcvtctldserver.NewVtctldServer(ts)
	_, err := vtctld.InitShardPrimary(context.Background(), &vtctldatapb.InitShardPrimaryRequest{
		Keyspace:                tablet1.Tablet.Keyspace,
		Shard:                   tablet1.Tablet.Shard,
		PrimaryElectTabletAlias: tablet1.Tablet.Alias,
	})

	assert.Error(t, err)

	resp, err := vtctld.InitShardPrimary(context.Background(), &vtctldatapb.InitShardPrimaryRequest{
		Keyspace:                tablet1.Tablet.Keyspace,
		Shard:                   tablet1.Tablet.Shard,
		PrimaryElectTabletAlias: tablet1.Tablet.Alias,
		Force:                   true,
	})
	assert.NoError(t, err)
	assert.NotNil(t, resp)
	tablet1PostInit, err := ts.GetTablet(context.Background(), tablet1.Tablet.Alias)
	require.NoError(t, err)
	assert.Equal(t, topodatapb.TabletType_PRIMARY, tablet1PostInit.Type)
}
<commit_msg>test: SetDurabilityPolicies in endtoend tests for InitShardPrimary<commit_after>/*
Copyright 2020 The Vitess Authors.

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

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

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

package endtoend

import (
	"context"
	"fmt"
	"testing"

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

	"vitess.io/vitess/go/mysql/fakesqldb"
	"vitess.io/vitess/go/sqltypes"
	"vitess.io/vitess/go/vt/logutil"
	"vitess.io/vitess/go/vt/topo/memorytopo"
	"vitess.io/vitess/go/vt/vtctl/grpcvtctldserver"
	"vitess.io/vitess/go/vt/vtctl/reparentutil"
	"vitess.io/vitess/go/vt/vttablet/tabletservermock"
	"vitess.io/vitess/go/vt/vttablet/tmclient"
	"vitess.io/vitess/go/vt/wrangler"
	"vitess.io/vitess/go/vt/wrangler/testlib"

	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
	vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata"
)

func TestInitShardPrimary(t *testing.T) {
	ts := memorytopo.NewServer("cell1")
	tmc := tmclient.NewTabletManagerClient()
	wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmc)
	_ = reparentutil.SetDurabilityPolicy("none", nil)

	primaryDb := fakesqldb.New(t)
	primaryDb.AddQuery("create database if not exists `vt_test_keyspace`", &sqltypes.Result{InsertID: 0, RowsAffected: 0})

	tablet1 := testlib.NewFakeTablet(t, wr, "cell1", 0, topodatapb.TabletType_PRIMARY, primaryDb)
	tablet2 := testlib.NewFakeTablet(t, wr, "cell1", 1, topodatapb.TabletType_REPLICA, nil)
	tablet3 := testlib.NewFakeTablet(t, wr, "cell1", 2, topodatapb.TabletType_REPLICA, nil)

	tablet1.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"CREATE DATABASE IF NOT EXISTS _vt",
		"SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal",
		"ALTER TABLE _vt.reparent_journal CHANGE COLUMN primary_alias master_alias VARBINARY(32) NOT NULL",
		"CREATE DATABASE IF NOT EXISTS _vt",
		"SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal",
		"ALTER TABLE _vt.reparent_journal CHANGE COLUMN primary_alias master_alias VARBINARY(32) NOT NULL",
		"SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, master_alias, replication_position) VALUES",
	}

	tablet2.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"FAKE RESET ALL REPLICATION",
		"FAKE SET SLAVE POSITION",
		"FAKE SET MASTER",
		"START SLAVE",
	}
	tablet2.FakeMysqlDaemon.SetReplicationSourceInputs = append(tablet2.FakeMysqlDaemon.SetReplicationSourceInputs, fmt.Sprintf("%v:%v", tablet1.Tablet.Hostname, tablet1.Tablet.MysqlPort))

	tablet3.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"FAKE RESET ALL REPLICATION",
		"FAKE SET SLAVE POSITION",
		"FAKE SET MASTER",
		"START SLAVE",
	}
	tablet3.FakeMysqlDaemon.SetReplicationSourceInputs = append(tablet3.FakeMysqlDaemon.SetReplicationSourceInputs, fmt.Sprintf("%v:%v", tablet1.Tablet.Hostname, tablet1.Tablet.MysqlPort))

	for _, tablet := range []*testlib.FakeTablet{tablet1, tablet2, tablet3} {
		tablet.StartActionLoop(t, wr)
		defer tablet.StopActionLoop(t)

		tablet.TM.QueryServiceControl.(*tabletservermock.Controller).SetQueryServiceEnabledForTests(true)
	}

	vtctld := grpcvtctldserver.NewVtctldServer(ts)
	resp, err := vtctld.InitShardPrimary(context.Background(), &vtctldatapb.InitShardPrimaryRequest{
		Keyspace:                tablet1.Tablet.Keyspace,
		Shard:                   tablet1.Tablet.Shard,
		PrimaryElectTabletAlias: tablet1.Tablet.Alias,
	})

	assert.NoError(t, err)
	assert.NotNil(t, resp)
}

func TestInitShardPrimaryNoFormerPrimary(t *testing.T) {
	ts := memorytopo.NewServer("cell1")
	tmc := tmclient.NewTabletManagerClient()
	wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmc)
	_ = reparentutil.SetDurabilityPolicy("none", nil)

	primaryDb := fakesqldb.New(t)
	primaryDb.AddQuery("create database if not exists `vt_test_keyspace`", &sqltypes.Result{InsertID: 0, RowsAffected: 0})

	tablet1 := testlib.NewFakeTablet(t, wr, "cell1", 0, topodatapb.TabletType_REPLICA, primaryDb)
	tablet2 := testlib.NewFakeTablet(t, wr, "cell1", 1, topodatapb.TabletType_REPLICA, nil)
	tablet3 := testlib.NewFakeTablet(t, wr, "cell1", 2, topodatapb.TabletType_REPLICA, nil)

	tablet1.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"CREATE DATABASE IF NOT EXISTS _vt",
		"SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal",
		"ALTER TABLE _vt.reparent_journal CHANGE COLUMN primary_alias master_alias VARBINARY(32) NOT NULL",
		"CREATE DATABASE IF NOT EXISTS _vt",
		"SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal",
		"ALTER TABLE _vt.reparent_journal CHANGE COLUMN primary_alias master_alias VARBINARY(32) NOT NULL",
		"SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, master_alias, replication_position) VALUES",
	}

	tablet2.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"FAKE SET SLAVE POSITION",
		"FAKE SET MASTER",
		"START SLAVE",
	}
	tablet2.FakeMysqlDaemon.SetReplicationSourceInputs = append(tablet2.FakeMysqlDaemon.SetReplicationSourceInputs, fmt.Sprintf("%v:%v", tablet1.Tablet.Hostname, tablet1.Tablet.MysqlPort))

	tablet3.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
		"FAKE RESET ALL REPLICATION",
		"FAKE SET SLAVE POSITION",
		"FAKE SET MASTER",
		"START SLAVE",
	}
	tablet3.FakeMysqlDaemon.SetReplicationSourceInputs = append(tablet3.FakeMysqlDaemon.SetReplicationSourceInputs, fmt.Sprintf("%v:%v", tablet1.Tablet.Hostname, tablet1.Tablet.MysqlPort))

	for _, tablet := range []*testlib.FakeTablet{tablet1, tablet2, tablet3} {
		tablet.StartActionLoop(t, wr)
		defer tablet.StopActionLoop(t)

		tablet.TM.QueryServiceControl.(*tabletservermock.Controller).SetQueryServiceEnabledForTests(true)
	}

	vtctld := grpcvtctldserver.NewVtctldServer(ts)
	_, err := vtctld.InitShardPrimary(context.Background(), &vtctldatapb.InitShardPrimaryRequest{
		Keyspace:                tablet1.Tablet.Keyspace,
		Shard:                   tablet1.Tablet.Shard,
		PrimaryElectTabletAlias: tablet1.Tablet.Alias,
	})

	assert.Error(t, err)

	resp, err := vtctld.InitShardPrimary(context.Background(), &vtctldatapb.InitShardPrimaryRequest{
		Keyspace:                tablet1.Tablet.Keyspace,
		Shard:                   tablet1.Tablet.Shard,
		PrimaryElectTabletAlias: tablet1.Tablet.Alias,
		Force:                   true,
	})
	assert.NoError(t, err)
	assert.NotNil(t, resp)
	tablet1PostInit, err := ts.GetTablet(context.Background(), tablet1.Tablet.Alias)
	require.NoError(t, err)
	assert.Equal(t, topodatapb.TabletType_PRIMARY, tablet1PostInit.Type)
}
<|endoftext|>


<commit_before>// +build gofuzz

package types

func FuzzJourney(data []byte) int {
	var j = &Journey{}

	// Let's unmarshal
	err := j.UnmarshalJSON(data)
	if err != nil {
		return 0
	}

	// Now that it is unmarshalled, let's the string method !
	_ = j.String()

	return 1
}
<commit_msg>types: Simplify FuzzJourney<commit_after>// +build gofuzz

package types

func FuzzJourney(data []byte) int {
	var j = &Journey{}

	// Let's unmarshal
	err := j.UnmarshalJSON(data)
	if err != nil {
		return 0
	}

	// Now that it is unmarshalled, let's the string method !
	j.String()

	return 1
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package kuberuntime

import (
	"net"
	"net/http"
	"testing"
	"time"

	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/stretchr/testify/assert"

	compbasemetrics "k8s.io/component-base/metrics"
	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
	"k8s.io/kubernetes/pkg/kubelet/metrics"
)

func TestRecordOperation(t *testing.T) {
	// Use local registry
	var registry = compbasemetrics.NewKubeRegistry()
	registry.MustRegister(metrics.RuntimeOperations)
	registry.MustRegister(metrics.RuntimeOperationsDuration)
	registry.MustRegister(metrics.RuntimeOperationsErrors)

	l, err := net.Listen("tcp", "127.0.0.1:0")
	assert.NoError(t, err)
	defer l.Close()

	prometheusURL := "http://" + l.Addr().String() + "/metrics"
	mux := http.NewServeMux()
	handler := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
	mux.Handle("/metrics", handler)
	server := &http.Server{
		Addr:    l.Addr().String(),
		Handler: mux,
	}
	go func() {
		server.Serve(l)
	}()

	recordOperation("create_container", time.Now())
	runtimeOperationsCounterExpected := "kubelet_runtime_operations_total{operation_type=\"create_container\"} 1"
	runtimeOperationsDurationExpected := "kubelet_runtime_operations_duration_seconds_count{operation_type=\"create_container\"} 1"

	assert.HTTPBodyContains(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		mux.ServeHTTP(w, r)
	}), "GET", prometheusURL, nil, runtimeOperationsCounterExpected)

	assert.HTTPBodyContains(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		mux.ServeHTTP(w, r)
	}), "GET", prometheusURL, nil, runtimeOperationsDurationExpected)

	registry.Reset()
}

func TestInstrumentedVersion(t *testing.T) {
	fakeRuntime, _, _, _ := createTestRuntimeManager()
	irs := newInstrumentedRuntimeService(fakeRuntime)
	vr, err := irs.Version("1")
	assert.NoError(t, err)
	assert.Equal(t, kubeRuntimeAPIVersion, vr.Version)
}

func TestStatus(t *testing.T) {
	fakeRuntime, _, _, _ := createTestRuntimeManager()
	fakeRuntime.FakeStatus = &runtimeapi.RuntimeStatus{
		Conditions: []*runtimeapi.RuntimeCondition{
			{Type: runtimeapi.RuntimeReady, Status: false},
			{Type: runtimeapi.NetworkReady, Status: true},
		},
	}
	irs := newInstrumentedRuntimeService(fakeRuntime)
	actural, err := irs.Status()
	assert.NoError(t, err)
	expected := &runtimeapi.RuntimeStatus{
		Conditions: []*runtimeapi.RuntimeCondition{
			{Type: runtimeapi.RuntimeReady, Status: false},
			{Type: runtimeapi.NetworkReady, Status: true},
		},
	}
	assert.Equal(t, expected, actural)
}
<commit_msg>Use defer in non-loop<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package kuberuntime

import (
	"net"
	"net/http"
	"testing"
	"time"

	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/stretchr/testify/assert"

	compbasemetrics "k8s.io/component-base/metrics"
	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
	"k8s.io/kubernetes/pkg/kubelet/metrics"
)

func TestRecordOperation(t *testing.T) {
	// Use local registry
	var registry = compbasemetrics.NewKubeRegistry()
	defer registry.Reset()
	registry.MustRegister(metrics.RuntimeOperations)
	registry.MustRegister(metrics.RuntimeOperationsDuration)
	registry.MustRegister(metrics.RuntimeOperationsErrors)

	l, err := net.Listen("tcp", "127.0.0.1:0")
	assert.NoError(t, err)
	defer l.Close()

	prometheusURL := "http://" + l.Addr().String() + "/metrics"
	mux := http.NewServeMux()
	handler := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
	mux.Handle("/metrics", handler)
	server := &http.Server{
		Addr:    l.Addr().String(),
		Handler: mux,
	}
	go func() {
		server.Serve(l)
	}()

	recordOperation("create_container", time.Now())
	runtimeOperationsCounterExpected := "kubelet_runtime_operations_total{operation_type=\"create_container\"} 1"
	runtimeOperationsDurationExpected := "kubelet_runtime_operations_duration_seconds_count{operation_type=\"create_container\"} 1"

	assert.HTTPBodyContains(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		mux.ServeHTTP(w, r)
	}), "GET", prometheusURL, nil, runtimeOperationsCounterExpected)

	assert.HTTPBodyContains(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		mux.ServeHTTP(w, r)
	}), "GET", prometheusURL, nil, runtimeOperationsDurationExpected)
}

func TestInstrumentedVersion(t *testing.T) {
	fakeRuntime, _, _, _ := createTestRuntimeManager()
	irs := newInstrumentedRuntimeService(fakeRuntime)
	vr, err := irs.Version("1")
	assert.NoError(t, err)
	assert.Equal(t, kubeRuntimeAPIVersion, vr.Version)
}

func TestStatus(t *testing.T) {
	fakeRuntime, _, _, _ := createTestRuntimeManager()
	fakeRuntime.FakeStatus = &runtimeapi.RuntimeStatus{
		Conditions: []*runtimeapi.RuntimeCondition{
			{Type: runtimeapi.RuntimeReady, Status: false},
			{Type: runtimeapi.NetworkReady, Status: true},
		},
	}
	irs := newInstrumentedRuntimeService(fakeRuntime)
	actural, err := irs.Status()
	assert.NoError(t, err)
	expected := &runtimeapi.RuntimeStatus{
		Conditions: []*runtimeapi.RuntimeCondition{
			{Type: runtimeapi.RuntimeReady, Status: false},
			{Type: runtimeapi.NetworkReady, Status: true},
		},
	}
	assert.Equal(t, expected, actural)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"
)

type jsonRPCRequest struct {
	JsonRPC string      `json:"jsonrpc"`
	Id      string      `json:"id"`
	Method  string      `json:"method"`
	Params  interface{} `json:"params,omitempty"`
}

func NewJSONRPCRequest(id string) *jsonRPCRequest {
	var req = new(jsonRPCRequest)
	req.JsonRPC = "2.0"
	req.Id = id
	if id == "" {
		req.Id = strconv.FormatInt(time.Now().UnixNano(), 10)
	}
	return req
}

func (r *jsonRPCRequest) setMethodAndParams(args []string) error {
	switch {
	case len(args) == 0:
		return fmt.Errorf("missing 'method' (first argument)")
	case len(args) == 1:
		r.Method = args[0]
	case len(args) > 1:
		r.Method = args[0]

		if strings.ContainsRune(args[1], '=') {
			// if first argument conatins a '=' i assume
			// a list of key-value pairs, forming a map
			// or an 'object' in javascript terms
			r.Params = kvPairsToMap(args[1:])

		} else if len(args[1]) > 1 && args[1][0] == '{' {
			var obj, err = stringToJSObject(args[1])
			if err != nil {
				return err
			}
			r.Params = obj
		} else {
			r.Params = args[1:]
		}
	}
	return nil
}

func (r *jsonRPCRequest) toJSON() (string, error) {
	var buf = bytes.NewBuffer(nil)
	var encoder = json.NewEncoder(buf)
	if err := encoder.Encode(r); err != nil {
		return "", err
	}
	return buf.String(), nil
}

func kvPairsToMap(pairs []string) map[string]interface{} {
	var m = make(map[string]interface{})
	for _, elem := range pairs {
		var (
			parts = strings.SplitN(elem, "=", 2)
			key   = parts[0]
			val   interface{}
		)

		if len(parts) == 2 {
			// if the value can be parsed as a float, we assume
			// a json.Number
			if _, err := strconv.ParseFloat(parts[1], 64); err == nil {
				val = json.Number(parts[1])
			} else {
				val = parts[1]
			}
		}
		m[key] = val
	}
	return m
}

func stringToJSObject(s string) (interface{}, error) {
	var obj interface{}
	var decoder = json.NewDecoder(strings.NewReader(s))
	if err := decoder.Decode(&obj); err != nil {
		return nil, err
	}
	return obj, nil
}
<commit_msg>tolerate whitespace before json parameter map<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"
)

type jsonRPCRequest struct {
	JsonRPC string      `json:"jsonrpc"`
	Id      string      `json:"id"`
	Method  string      `json:"method"`
	Params  interface{} `json:"params,omitempty"`
}

func NewJSONRPCRequest(id string) *jsonRPCRequest {
	var req = new(jsonRPCRequest)
	req.JsonRPC = "2.0"
	req.Id = id
	if id == "" {
		req.Id = strconv.FormatInt(time.Now().UnixNano(), 10)
	}
	return req
}

func (r *jsonRPCRequest) setMethodAndParams(args []string) error {
	switch {
	case len(args) == 0:
		return fmt.Errorf("missing 'method' (first argument)")
	case len(args) == 1:
		r.Method = args[0]
	case len(args) > 1:
		r.Method = args[0]

		if strings.ContainsRune(args[1], '=') {
			// if first argument conatins a '=' i assume
			// a list of key-value pairs, forming a map
			// or an 'object' in javascript terms
			r.Params = kvPairsToMap(args[1:])

		} else if len(args[1]) > 1 && strings.TrimLeft(args[1], " \n\t")[0] == '{' {
			var obj, err = stringToJSObject(args[1])
			if err != nil {
				return err
			}
			r.Params = obj
		} else {
			r.Params = args[1:]
		}
	}
	return nil
}

func (r *jsonRPCRequest) toJSON() (string, error) {
	var buf = bytes.NewBuffer(nil)
	var encoder = json.NewEncoder(buf)
	if err := encoder.Encode(r); err != nil {
		return "", err
	}
	return buf.String(), nil
}

func kvPairsToMap(pairs []string) map[string]interface{} {
	var m = make(map[string]interface{})
	for _, elem := range pairs {
		var (
			parts = strings.SplitN(elem, "=", 2)
			key   = parts[0]
			val   interface{}
		)

		if len(parts) == 2 {
			// if the value can be parsed as a float, we assume
			// a json.Number
			if _, err := strconv.ParseFloat(parts[1], 64); err == nil {
				val = json.Number(parts[1])
			} else {
				val = parts[1]
			}
		}
		m[key] = val
	}
	return m
}

func stringToJSObject(s string) (interface{}, error) {
	var obj interface{}
	var decoder = json.NewDecoder(strings.NewReader(s))
	if err := decoder.Decode(&obj); err != nil {
		return nil, err
	}
	return obj, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 Circonus, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package api

import (
	"encoding/json"
	"fmt"
	"net/url"
	"regexp"
	"strings"
)

// BrokerDetail instance attributes
type BrokerDetail struct {
	CN           string   `json:"cn"`
	ExternalHost string   `json:"external_host"`
	ExternalPort int      `json:"external_port"`
	IP           string   `json:"ipaddress"`
	MinVer       int      `json:"minimum_version_required"`
	Modules      []string `json:"modules"`
	Port         int      `json:"port"`
	Skew         string   `json:"skew"`
	Status       string   `json:"status"`
	Version      int      `json:"version"`
}

// Broker definition
type Broker struct {
	CID       string         `json:"_cid"`
	Details   []BrokerDetail `json:"_details"`
	Latitude  string         `json:"_latitude"`
	Longitude string         `json:"_longitude"`
	Name      string         `json:"_name"`
	Tags      []string       `json:"_tags"`
	Type      string         `json:"_type"`
}

const (
	baseBrokerPath = "/broker"
	brokerCIDRegex = "^" + baseBrokerPath + "/[0-9]+$"
)

// FetchBrokerByID fetch a broker configuration by [group]id
func (a *API) FetchBrokerByID(id IDType) (*Broker, error) {
	if id <= 0 {
		return nil, fmt.Errorf("Invalid broker ID [%d]", id)
	}
	cid := CIDType(fmt.Sprintf("%s/%d", baseBrokerPath, id))
	return a.FetchBroker(&cid)
}

// FetchBroker fetch a broker configuration by cid
func (a *API) FetchBroker(cid *CIDType) (*Broker, error) {
	if cid == nil || *cid == "" {
		return nil, fmt.Errorf("Invalid broker CID [none]")
	}

	brokerCID := string(*cid)

	matched, err := regexp.MatchString(brokerCIDRegex, brokerCID)
	if err != nil {
		return nil, err
	}
	if !matched {
		return nil, fmt.Errorf("Invalid broker CID [%s]", brokerCID)
	}

	reqURL := url.URL{
		Path: brokerCID,
	}

	result, err := a.Get(reqURL.String())
	if err != nil {
		return nil, err
	}

	response := new(Broker)
	if err := json.Unmarshal(result, &response); err != nil {
		return nil, err
	}

	return response, nil

}

// FetchBrokersByTag return list of brokers with a specific tag
func (a *API) FetchBrokersByTag(searchTags TagType) (*[]Broker, error) {
	if len(searchTags) == 0 {
		return a.FetchBrokers()
	}

	filter := map[string]string{
		"f__tags_has": strings.Replace(strings.Join(searchTags, ","), ",", "&f__tags_has=", -1),
	}

	return a.SearchBrokers(nil, &filter)
}

// // BrokerSearch return a list of brokers matching a query/filter
// func (a *API) BrokerSearch(query SearchQueryType) ([]Broker, error) {
// 	queryURL := fmt.Sprintf("/broker?%s", string(query))
//
// 	result, err := a.Get(queryURL)
// 	if err != nil {
// 		return nil, err
// 	}
//
// 	var brokers []Broker
// 	if err := json.Unmarshal(result, &brokers); err != nil {
// 		return nil, err
// 	}
//
// 	return brokers, nil
// }

// SearchBrokers returns list of annotations matching a search query and/or filter
//    - a search query (see: https://login.circonus.com/resources/api#searching)
//    - a filter (see: https://login.circonus.com/resources/api#filtering)
func (a *API) SearchBrokers(searchCriteria *SearchQueryType, filterCriteria *map[string]string) (*[]Broker, error) {

	if (searchCriteria == nil || *searchCriteria == "") && (filterCriteria == nil || len(*filterCriteria) == 0) {
		return a.FetchBrokers()
	}

	reqURL := url.URL{
		Path: baseBrokerPath,
	}

	q := url.Values{}

	if searchCriteria != nil && *searchCriteria != "" {
		q.Set("search", string(*searchCriteria))
	}

	if filterCriteria != nil && len(*filterCriteria) > 0 {
		for filter, criteria := range *filterCriteria {
			q.Set(filter, criteria)
		}
	}

	reqURL.RawQuery = q.Encode()

	resp, err := a.Get(reqURL.String())
	if err != nil {
		return nil, fmt.Errorf("[ERROR] API call error %+v", err)
	}

	var results []Broker
	if err := json.Unmarshal(resp, &results); err != nil {
		return nil, err
	}

	return &results, nil
}

// FetchBrokers return list of all brokers available to the api token/app
func (a *API) FetchBrokers() (*[]Broker, error) {
	result, err := a.Get("/broker")
	if err != nil {
		return nil, err
	}

	var response []Broker
	if err := json.Unmarshal(result, &response); err != nil {
		return nil, err
	}

	return &response, nil
}
<commit_msg>upd: remove obsolete code<commit_after>// Copyright 2016 Circonus, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package api

import (
	"encoding/json"
	"fmt"
	"net/url"
	"regexp"
	"strings"
)

// BrokerDetail instance attributes
type BrokerDetail struct {
	CN           string   `json:"cn"`
	ExternalHost string   `json:"external_host"`
	ExternalPort int      `json:"external_port"`
	IP           string   `json:"ipaddress"`
	MinVer       int      `json:"minimum_version_required"`
	Modules      []string `json:"modules"`
	Port         int      `json:"port"`
	Skew         string   `json:"skew"`
	Status       string   `json:"status"`
	Version      int      `json:"version"`
}

// Broker definition
type Broker struct {
	CID       string         `json:"_cid"`
	Details   []BrokerDetail `json:"_details"`
	Latitude  string         `json:"_latitude"`
	Longitude string         `json:"_longitude"`
	Name      string         `json:"_name"`
	Tags      []string       `json:"_tags"`
	Type      string         `json:"_type"`
}

const (
	baseBrokerPath = "/broker"
	brokerCIDRegex = "^" + baseBrokerPath + "/[0-9]+$"
)

// FetchBroker fetch a broker configuration by cid
func (a *API) FetchBroker(cid *CIDType) (*Broker, error) {
	if cid == nil || *cid == "" {
		return nil, fmt.Errorf("Invalid broker CID [none]")
	}

	brokerCID := string(*cid)

	matched, err := regexp.MatchString(brokerCIDRegex, brokerCID)
	if err != nil {
		return nil, err
	}
	if !matched {
		return nil, fmt.Errorf("Invalid broker CID [%s]", brokerCID)
	}

	reqURL := url.URL{
		Path: brokerCID,
	}

	result, err := a.Get(reqURL.String())
	if err != nil {
		return nil, err
	}

	response := new(Broker)
	if err := json.Unmarshal(result, &response); err != nil {
		return nil, err
	}

	return response, nil

}

// FetchBrokerByID fetch a broker configuration by [group]id
func (a *API) FetchBrokerByID(id IDType) (*Broker, error) {
	if id <= 0 {
		return nil, fmt.Errorf("Invalid broker ID [%d]", id)
	}
	cid := CIDType(fmt.Sprintf("%s/%d", baseBrokerPath, id))
	return a.FetchBroker(&cid)
}

// FetchBrokers return list of all brokers available to the api token/app
func (a *API) FetchBrokers() (*[]Broker, error) {
	result, err := a.Get("/broker")
	if err != nil {
		return nil, err
	}

	var response []Broker
	if err := json.Unmarshal(result, &response); err != nil {
		return nil, err
	}

	return &response, nil
}

// FetchBrokersByTag return list of brokers with a specific tag
func (a *API) FetchBrokersByTag(searchTags TagType) (*[]Broker, error) {
	if len(searchTags) == 0 {
		return a.FetchBrokers()
	}

	filter := map[string]string{
		"f__tags_has": strings.Replace(strings.Join(searchTags, ","), ",", "&f__tags_has=", -1),
	}

	return a.SearchBrokers(nil, &filter)
}

// SearchBrokers returns list of annotations matching a search query and/or filter
//    - a search query (see: https://login.circonus.com/resources/api#searching)
//    - a filter (see: https://login.circonus.com/resources/api#filtering)
func (a *API) SearchBrokers(searchCriteria *SearchQueryType, filterCriteria *map[string]string) (*[]Broker, error) {

	if (searchCriteria == nil || *searchCriteria == "") && (filterCriteria == nil || len(*filterCriteria) == 0) {
		return a.FetchBrokers()
	}

	reqURL := url.URL{
		Path: baseBrokerPath,
	}

	q := url.Values{}

	if searchCriteria != nil && *searchCriteria != "" {
		q.Set("search", string(*searchCriteria))
	}

	if filterCriteria != nil && len(*filterCriteria) > 0 {
		for filter, criteria := range *filterCriteria {
			q.Set(filter, criteria)
		}
	}

	reqURL.RawQuery = q.Encode()

	resp, err := a.Get(reqURL.String())
	if err != nil {
		return nil, fmt.Errorf("[ERROR] API call error %+v", err)
	}

	var results []Broker
	if err := json.Unmarshal(resp, &results); err != nil {
		return nil, err
	}

	return &results, nil
}
<|endoftext|>