<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package instancecfg_test

import (
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/cloudconfig/instancecfg"
	"github.com/juju/juju/environs/config"
	"github.com/juju/juju/state/multiwatcher"
	"github.com/juju/juju/testing"
	coretools "github.com/juju/juju/tools"
	"github.com/juju/juju/version"
)

type instancecfgSuite struct {
	testing.BaseSuite
}

var _ = gc.Suite(&instancecfgSuite{})

func (*instancecfgSuite) TestInstanceTagsController(c *gc.C) {
	cfg := testing.CustomModelConfig(c, testing.Attrs{})
	controllerJobs := []multiwatcher.MachineJob{multiwatcher.JobManageModel}
	nonControllerJobs := []multiwatcher.MachineJob{multiwatcher.JobHostUnits}
	testInstanceTags(c, cfg, controllerJobs, map[string]string{
		"juju-model-uuid":    testing.ModelTag.Id(),
		"juju-is-controller": "true",
	})
	testInstanceTags(c, cfg, nonControllerJobs, map[string]string{
		"juju-model-uuid": testing.ModelTag.Id(),
	})
}

func (*instancecfgSuite) TestInstanceTagsNoUUID(c *gc.C) {
	attrsWithoutUUID := testing.FakeConfig()
	delete(attrsWithoutUUID, "uuid")
	cfgWithoutUUID, err := config.New(config.NoDefaults, attrsWithoutUUID)
	c.Assert(err, jc.ErrorIsNil)
	testInstanceTags(c,
		cfgWithoutUUID,
		[]multiwatcher.MachineJob(nil),
		map[string]string{"juju-model-uuid": ""},
	)
}

func (*instancecfgSuite) TestInstanceTagsUserSpecified(c *gc.C) {
	cfg := testing.CustomModelConfig(c, testing.Attrs{
		"resource-tags": "a=b c=",
	})
	testInstanceTags(c, cfg, nil, map[string]string{
		"juju-model-uuid": testing.ModelTag.Id(),
		"a":               "b",
		"c":               "",
	})
}

func testInstanceTags(c *gc.C, cfg *config.Config, jobs []multiwatcher.MachineJob, expectTags map[string]string) {
	tags := instancecfg.InstanceTags(cfg, jobs)
	c.Assert(tags, jc.DeepEquals, expectTags)
}

func (*instancecfgSuite) TestJujuTools(c *gc.C) {
	icfg := &instancecfg.InstanceConfig{
		DataDir: "/path/to/datadir/",
		Tools: &coretools.Tools{
			Version: version.MustParseBinary("2.3.4-wily-amd64"),
		},
	}
	c.Assert(icfg.JujuTools(), gc.Equals, "/path/to/datadir/tools/2.3.4-wily-amd64")
}

func (*instancecfgSuite) TestGUITools(c *gc.C) {
	icfg := &instancecfg.InstanceConfig{
		DataDir: "/path/to/datadir/",
	}
	c.Assert(icfg.GUITools(), gc.Equals, "/path/to/datadir/gui")
}
<commit_msg>Fix remaining GUI embedded failing test.<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package instancecfg_test

import (
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/cloudconfig/instancecfg"
	"github.com/juju/juju/environs/config"
	"github.com/juju/juju/state/multiwatcher"
	"github.com/juju/juju/testing"
	coretools "github.com/juju/juju/tools"
	"github.com/juju/juju/version"
)

type instancecfgSuite struct {
	testing.BaseSuite
}

var _ = gc.Suite(&instancecfgSuite{})

func (*instancecfgSuite) TestInstanceTagsController(c *gc.C) {
	cfg := testing.CustomModelConfig(c, testing.Attrs{})
	controllerJobs := []multiwatcher.MachineJob{multiwatcher.JobManageModel}
	nonControllerJobs := []multiwatcher.MachineJob{multiwatcher.JobHostUnits}
	testInstanceTags(c, cfg, controllerJobs, map[string]string{
		"juju-model-uuid":    testing.ModelTag.Id(),
		"juju-is-controller": "true",
	})
	testInstanceTags(c, cfg, nonControllerJobs, map[string]string{
		"juju-model-uuid": testing.ModelTag.Id(),
	})
}

func (*instancecfgSuite) TestInstanceTagsNoUUID(c *gc.C) {
	attrsWithoutUUID := testing.FakeConfig()
	delete(attrsWithoutUUID, "uuid")
	cfgWithoutUUID, err := config.New(config.NoDefaults, attrsWithoutUUID)
	c.Assert(err, jc.ErrorIsNil)
	testInstanceTags(c,
		cfgWithoutUUID,
		[]multiwatcher.MachineJob(nil),
		map[string]string{"juju-model-uuid": ""},
	)
}

func (*instancecfgSuite) TestInstanceTagsUserSpecified(c *gc.C) {
	cfg := testing.CustomModelConfig(c, testing.Attrs{
		"resource-tags": "a=b c=",
	})
	testInstanceTags(c, cfg, nil, map[string]string{
		"juju-model-uuid": testing.ModelTag.Id(),
		"a":               "b",
		"c":               "",
	})
}

func testInstanceTags(c *gc.C, cfg *config.Config, jobs []multiwatcher.MachineJob, expectTags map[string]string) {
	tags := instancecfg.InstanceTags(cfg, jobs)
	c.Assert(tags, jc.DeepEquals, expectTags)
}

func (*instancecfgSuite) TestJujuTools(c *gc.C) {
	icfg := &instancecfg.InstanceConfig{
		DataDir: "/path/to/datadir/",
		Tools: &coretools.Tools{
			Version: version.MustParseBinary("2.3.4-trusty-amd64"),
		},
	}
	c.Assert(icfg.JujuTools(), gc.Equals, "/path/to/datadir/tools/2.3.4-trusty-amd64")
}

func (*instancecfgSuite) TestGUITools(c *gc.C) {
	icfg := &instancecfg.InstanceConfig{
		DataDir: "/path/to/datadir/",
	}
	c.Assert(icfg.GUITools(), gc.Equals, "/path/to/datadir/gui")
}
<|endoftext|>


<commit_before>package space_test

import (
	"github.com/cloudfoundry/cli/cf/api/spacequotas/spacequotasfakes"
	"github.com/cloudfoundry/cli/cf/commandregistry"

	"github.com/cloudfoundry/cli/plugin/models"
	testconfig "github.com/cloudfoundry/cli/testhelpers/configuration"
	testterm "github.com/cloudfoundry/cli/testhelpers/terminal"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/cloudfoundry/cli/cf/api"
	"github.com/cloudfoundry/cli/cf/commands/space"
	"github.com/cloudfoundry/cli/cf/models"
	"github.com/cloudfoundry/cli/cf/requirements"
	"github.com/cloudfoundry/cli/cf/requirements/requirementsfakes"
	"github.com/cloudfoundry/cli/flags"
	. "github.com/cloudfoundry/cli/testhelpers/matchers"
)

var _ = Describe("space command", func() {
	var (
		ui               *testterm.FakeUI
		loginReq         *requirementsfakes.FakeRequirement
		targetedOrgReq   *requirementsfakes.FakeTargetedOrgRequirement
		reqFactory       *requirementsfakes.FakeFactory
		deps             commandregistry.Dependency
		cmd              space.ShowSpace
		flagContext      flags.FlagContext
		getSpaceModel    *plugin_models.GetSpace_Model
		spaceRequirement *requirementsfakes.FakeSpaceRequirement
		quotaRepo        *spacequotasfakes.FakeSpaceQuotaRepository
	)

	BeforeEach(func() {
		ui = new(testterm.FakeUI)
		quotaRepo = new(spacequotasfakes.FakeSpaceQuotaRepository)
		repoLocator := api.RepositoryLocator{}
		repoLocator = repoLocator.SetSpaceQuotaRepository(quotaRepo)
		getSpaceModel = new(plugin_models.GetSpace_Model)

		deps = commandregistry.Dependency{
			UI:          ui,
			Config:      testconfig.NewRepositoryWithDefaults(),
			RepoLocator: repoLocator,
			PluginModels: &commandregistry.PluginModels{
				Space: getSpaceModel,
			},
		}

		reqFactory = new(requirementsfakes.FakeFactory)

		loginReq = new(requirementsfakes.FakeRequirement)
		loginReq.ExecuteReturns(nil)
		reqFactory.NewLoginRequirementReturns(loginReq)

		targetedOrgReq = new(requirementsfakes.FakeTargetedOrgRequirement)
		targetedOrgReq.ExecuteReturns(nil)
		reqFactory.NewTargetedOrgRequirementReturns(targetedOrgReq)

		spaceRequirement = new(requirementsfakes.FakeSpaceRequirement)
		spaceRequirement.ExecuteReturns(nil)
		reqFactory.NewSpaceRequirementReturns(spaceRequirement)

		cmd = space.ShowSpace{}
		flagContext = flags.NewFlagContext(cmd.MetaData().Flags)
		cmd.SetDependency(deps, false)
	})

	Describe("Requirements", func() {
		Context("when the wrong number of args are provided", func() {
			It("fails with no args", func() {
				flagContext.Parse()
				Expect(func() { cmd.Requirements(reqFactory, flagContext) }).To(Panic())
				Expect(ui.Outputs).To(ContainSubstrings(
					[]string{"FAILED"},
					[]string{"Incorrect Usage. Requires an argument"},
				))
			})
		})

		Context("when provided exactly one arg", func() {
			var actualRequirements []requirements.Requirement

			Context("when no flags are provided", func() {
				BeforeEach(func() {
					flagContext.Parse("my-space")
					actualRequirements = cmd.Requirements(reqFactory, flagContext)
				})

				It("returns a login requirement", func() {
					Expect(reqFactory.NewLoginRequirementCallCount()).To(Equal(1))
					Expect(actualRequirements).To(ContainElement(loginReq))
				})

				It("returns a targeted org requirement", func() {
					Expect(reqFactory.NewTargetedOrgRequirementCallCount()).To(Equal(1))
					Expect(actualRequirements).To(ContainElement(targetedOrgReq))
				})

				It("returns a space requirement", func() {
					Expect(reqFactory.NewSpaceRequirementCallCount()).To(Equal(1))
					Expect(actualRequirements).To(ContainElement(spaceRequirement))
				})
			})
		})
	})

	Describe("Execute", func() {
		var (
			space      models.Space
			spaceQuota models.SpaceQuota
			executeErr error
		)

		BeforeEach(func() {
			org := models.OrganizationFields{
				Name: "my-org",
				GUID: "my-org-guid",
			}

			app := models.ApplicationFields{
				Name: "app1",
				GUID: "app1-guid",
			}

			apps := []models.ApplicationFields{app}

			domain := models.DomainFields{
				Name: "domain1",
				GUID: "domain1-guid",
			}

			domains := []models.DomainFields{domain}

			serviceInstance := models.ServiceInstanceFields{
				Name: "service1",
				GUID: "service1-guid",
			}
			services := []models.ServiceInstanceFields{serviceInstance}

			securityGroup1 := models.SecurityGroupFields{Name: "Nacho Security", Rules: []map[string]interface{}{
				{"protocol": "all", "destination": "0.0.0.0-9.255.255.255", "log": true, "IntTest": 1000},
			}}
			securityGroup2 := models.SecurityGroupFields{Name: "Nacho Prime", Rules: []map[string]interface{}{
				{"protocol": "udp", "ports": "8080-9090", "destination": "198.41.191.47/1"},
			}}
			securityGroups := []models.SecurityGroupFields{securityGroup1, securityGroup2}

			space = models.Space{
				SpaceFields: models.SpaceFields{
					Name: "whose-space-is-it-anyway",
					GUID: "whose-space-is-it-anyway-guid",
				},
				Organization:     org,
				Applications:     apps,
				Domains:          domains,
				ServiceInstances: services,
				SecurityGroups:   securityGroups,
				SpaceQuotaGUID:   "runaway-guid",
			}

			spaceRequirement.GetSpaceReturns(space)

			spaceQuota = models.SpaceQuota{
				Name:                    "runaway",
				GUID:                    "runaway-guid",
				MemoryLimit:             102400,
				InstanceMemoryLimit:     -1,
				RoutesLimit:             111,
				ServicesLimit:           222,
				NonBasicServicesAllowed: false,
				AppInstanceLimit:        7,
				ReservedRoutePortsLimit: "7",
			}

			quotaRepo.FindByGUIDReturns(spaceQuota, nil)
		})

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

		Context("when logged in and an org is targeted", func() {
			BeforeEach(func() {
				err := flagContext.Parse("my-space")
				Expect(err).NotTo(HaveOccurred())
				cmd.Requirements(reqFactory, flagContext)
			})

			Context("when the guid flag is passed", func() {
				BeforeEach(func() {
					err := flagContext.Parse("my-space", "--guid")
					Expect(err).NotTo(HaveOccurred())
				})

				It("shows only the space guid", func() {
					Expect(executeErr).NotTo(HaveOccurred())
					Expect(ui.Outputs).To(ContainSubstrings(
						[]string{"whose-space-is-it-anyway-guid"},
					))

					Expect(ui.Outputs).ToNot(ContainSubstrings(
						[]string{"Getting info for space", "whose-space-is-it-anyway", "my-org", "my-user"},
					))
				})
			})

			Context("when the security-group-rules flag is passed", func() {
				BeforeEach(func() {
					err := flagContext.Parse("my-space", "--security-group-rules")
					Expect(err).NotTo(HaveOccurred())
				})
				It("it shows space information and security group rules", func() {
					Expect(executeErr).NotTo(HaveOccurred())
					Expect(ui.Outputs).To(ContainSubstrings(
						[]string{"Getting rules for the security group", "Nacho Security"},
						[]string{"protocol", "all"},
						[]string{"destination", "0.0.0.0-9.255.255.255"},
						[]string{"Getting rules for the security group", "Nacho Prime"},
						[]string{"protocol", "udp"},
						[]string{"log", "true"},
						[]string{"IntTest", "1000"},
						[]string{"ports", "8080-9090"},
						[]string{"destination", "198.41.191.47/1"},
					))
				})
			})

			Context("when the space has a space quota", func() {
				It("shows information about the given space", func() {
					Expect(executeErr).NotTo(HaveOccurred())
					Expect(ui.Outputs).To(ContainSubstrings(
						[]string{"Getting info for space", "whose-space-is-it-anyway", "my-org", "my-user"},
						[]string{"OK"},
						[]string{"whose-space-is-it-anyway"},
						[]string{"Org", "my-org"},
						[]string{"Apps", "app1"},
						[]string{"Domains", "domain1"},
						[]string{"Services", "service1"},
						[]string{"Security Groups", "Nacho Security", "Nacho Prime"},
						[]string{"Space Quota", "runaway (100G memory limit, unlimited instance memory limit, 111 routes, 222 services, paid services disallowed, 7 app instance limit, 7 route ports)"},
					))
				})

				Context("when the route ports limit is -1", func() {
					BeforeEach(func() {
						spaceQuota.ReservedRoutePortsLimit = "-1"
						quotaRepo.FindByGUIDReturns(spaceQuota, nil)
					})

					It("displays unlimited as the route ports limit", func() {
						Expect(executeErr).NotTo(HaveOccurred())
						Expect(ui.Outputs).To(ContainSubstrings(
							[]string{"unlimited route ports"},
						))
					})
				})

				Context("when the reserved route ports field is not provided by the CC API", func() {
					BeforeEach(func() {
						spaceQuota.ReservedRoutePortsLimit = ""
						quotaRepo.FindByGUIDReturns(spaceQuota, nil)
					})

					It("should not display route ports", func() {
						Expect(executeErr).NotTo(HaveOccurred())
						Expect(ui.Outputs).NotTo(ContainSubstrings(
							[]string{"route ports"},
						))
					})
				})

				Context("when the app instance limit is -1", func() {
					BeforeEach(func() {
						spaceQuota.AppInstanceLimit = -1
						quotaRepo.FindByGUIDReturns(spaceQuota, nil)
					})

					It("displays unlimited as the app instance limit", func() {
						Expect(executeErr).NotTo(HaveOccurred())
						Expect(ui.Outputs).To(ContainSubstrings(
							[]string{"unlimited app instance limit"},
						))
					})
				})
			})

			Context("when the space does not have a space quota", func() {
				BeforeEach(func() {
					space.SpaceQuotaGUID = ""
					spaceRequirement.GetSpaceReturns(space)
				})

				It("shows information without a space quota", func() {
					Expect(executeErr).NotTo(HaveOccurred())
					Expect(quotaRepo.FindByGUIDCallCount()).To(Equal(0))
					Expect(ui.Outputs).To(ContainSubstrings(
						[]string{"Getting info for space", "whose-space-is-it-anyway", "my-org", "my-user"},
						[]string{"OK"},
						[]string{"whose-space-is-it-anyway"},
						[]string{"Org", "my-org"},
						[]string{"Apps", "app1"},
						[]string{"Domains", "domain1"},
						[]string{"Services", "service1"},
						[]string{"Security Groups", "Nacho Security", "Nacho Prime"},
						[]string{"Space Quota"},
					))
				})
			})

			Context("When called as a plugin", func() {
				BeforeEach(func() {
					cmd.SetDependency(deps, true)
				})

				It("Fills in the PluginModel", func() {
					Expect(executeErr).NotTo(HaveOccurred())

					Expect(getSpaceModel.Name).To(Equal("whose-space-is-it-anyway"))
					Expect(getSpaceModel.Guid).To(Equal("whose-space-is-it-anyway-guid"))

					Expect(getSpaceModel.Organization.Name).To(Equal("my-org"))
					Expect(getSpaceModel.Organization.Guid).To(Equal("my-org-guid"))

					Expect(getSpaceModel.Applications).To(HaveLen(1))
					Expect(getSpaceModel.Applications[0].Name).To(Equal("app1"))
					Expect(getSpaceModel.Applications[0].Guid).To(Equal("app1-guid"))

					Expect(getSpaceModel.Domains).To(HaveLen(1))
					Expect(getSpaceModel.Domains[0].Name).To(Equal("domain1"))
					Expect(getSpaceModel.Domains[0].Guid).To(Equal("domain1-guid"))

					Expect(getSpaceModel.ServiceInstances).To(HaveLen(1))
					Expect(getSpaceModel.ServiceInstances[0].Name).To(Equal("service1"))
					Expect(getSpaceModel.ServiceInstances[0].Guid).To(Equal("service1-guid"))

					Expect(getSpaceModel.SecurityGroups).To(HaveLen(2))
					Expect(getSpaceModel.SecurityGroups[0].Name).To(Equal("Nacho Security"))
					Expect(getSpaceModel.SecurityGroups[0].Rules).To(HaveLen(1))
					Expect(getSpaceModel.SecurityGroups[0].Rules[0]).To(HaveLen(4))
					val := getSpaceModel.SecurityGroups[0].Rules[0]["protocol"]
					Expect(val).To(Equal("all"))
					val = getSpaceModel.SecurityGroups[0].Rules[0]["destination"]
					Expect(val).To(Equal("0.0.0.0-9.255.255.255"))

					Expect(getSpaceModel.SecurityGroups[1].Name).To(Equal("Nacho Prime"))
					Expect(getSpaceModel.SecurityGroups[1].Rules).To(HaveLen(1))
					Expect(getSpaceModel.SecurityGroups[1].Rules[0]).To(HaveLen(3))
					val = getSpaceModel.SecurityGroups[1].Rules[0]["protocol"]
					Expect(val).To(Equal("udp"))
					val = getSpaceModel.SecurityGroups[1].Rules[0]["destination"]
					Expect(val).To(Equal("198.41.191.47/1"))
					val = getSpaceModel.SecurityGroups[1].Rules[0]["ports"]
					Expect(val).To(Equal("8080-9090"))

					Expect(getSpaceModel.SpaceQuota.Name).To(Equal("runaway"))
					Expect(getSpaceModel.SpaceQuota.Guid).To(Equal("runaway-guid"))
					Expect(getSpaceModel.SpaceQuota.MemoryLimit).To(Equal(int64(102400)))
					Expect(getSpaceModel.SpaceQuota.InstanceMemoryLimit).To(Equal(int64(-1)))
					Expect(getSpaceModel.SpaceQuota.RoutesLimit).To(Equal(111))
					Expect(getSpaceModel.SpaceQuota.ServicesLimit).To(Equal(222))
					Expect(getSpaceModel.SpaceQuota.NonBasicServicesAllowed).To(BeFalse())
				})
			})
		})
	})
})
<commit_msg>Adds missing error handling<commit_after>package space_test

import (
	"github.com/cloudfoundry/cli/cf/api/spacequotas/spacequotasfakes"
	"github.com/cloudfoundry/cli/cf/commandregistry"

	"github.com/cloudfoundry/cli/plugin/models"
	testconfig "github.com/cloudfoundry/cli/testhelpers/configuration"
	testterm "github.com/cloudfoundry/cli/testhelpers/terminal"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/cloudfoundry/cli/cf/api"
	"github.com/cloudfoundry/cli/cf/commands/space"
	"github.com/cloudfoundry/cli/cf/models"
	"github.com/cloudfoundry/cli/cf/requirements"
	"github.com/cloudfoundry/cli/cf/requirements/requirementsfakes"
	"github.com/cloudfoundry/cli/flags"
	. "github.com/cloudfoundry/cli/testhelpers/matchers"
)

var _ = Describe("space command", func() {
	var (
		ui               *testterm.FakeUI
		loginReq         *requirementsfakes.FakeRequirement
		targetedOrgReq   *requirementsfakes.FakeTargetedOrgRequirement
		reqFactory       *requirementsfakes.FakeFactory
		deps             commandregistry.Dependency
		cmd              space.ShowSpace
		flagContext      flags.FlagContext
		getSpaceModel    *plugin_models.GetSpace_Model
		spaceRequirement *requirementsfakes.FakeSpaceRequirement
		quotaRepo        *spacequotasfakes.FakeSpaceQuotaRepository
	)

	BeforeEach(func() {
		ui = new(testterm.FakeUI)
		quotaRepo = new(spacequotasfakes.FakeSpaceQuotaRepository)
		repoLocator := api.RepositoryLocator{}
		repoLocator = repoLocator.SetSpaceQuotaRepository(quotaRepo)
		getSpaceModel = new(plugin_models.GetSpace_Model)

		deps = commandregistry.Dependency{
			UI:          ui,
			Config:      testconfig.NewRepositoryWithDefaults(),
			RepoLocator: repoLocator,
			PluginModels: &commandregistry.PluginModels{
				Space: getSpaceModel,
			},
		}

		reqFactory = new(requirementsfakes.FakeFactory)

		loginReq = new(requirementsfakes.FakeRequirement)
		loginReq.ExecuteReturns(nil)
		reqFactory.NewLoginRequirementReturns(loginReq)

		targetedOrgReq = new(requirementsfakes.FakeTargetedOrgRequirement)
		targetedOrgReq.ExecuteReturns(nil)
		reqFactory.NewTargetedOrgRequirementReturns(targetedOrgReq)

		spaceRequirement = new(requirementsfakes.FakeSpaceRequirement)
		spaceRequirement.ExecuteReturns(nil)
		reqFactory.NewSpaceRequirementReturns(spaceRequirement)

		cmd = space.ShowSpace{}
		flagContext = flags.NewFlagContext(cmd.MetaData().Flags)
		cmd.SetDependency(deps, false)
	})

	Describe("Requirements", func() {
		Context("when the wrong number of args are provided", func() {
			BeforeEach(func() {
				err := flagContext.Parse()
				Expect(err).NotTo(HaveOccurred())
			})

			It("fails with no args", func() {
				Expect(func() { cmd.Requirements(reqFactory, flagContext) }).To(Panic())
				Expect(ui.Outputs).To(ContainSubstrings(
					[]string{"FAILED"},
					[]string{"Incorrect Usage. Requires an argument"},
				))
			})
		})

		Context("when provided exactly one arg", func() {
			var actualRequirements []requirements.Requirement

			Context("when no flags are provided", func() {
				BeforeEach(func() {
					err := flagContext.Parse("my-space")
					Expect(err).NotTo(HaveOccurred())
					actualRequirements = cmd.Requirements(reqFactory, flagContext)
				})

				It("returns a login requirement", func() {
					Expect(reqFactory.NewLoginRequirementCallCount()).To(Equal(1))
					Expect(actualRequirements).To(ContainElement(loginReq))
				})

				It("returns a targeted org requirement", func() {
					Expect(reqFactory.NewTargetedOrgRequirementCallCount()).To(Equal(1))
					Expect(actualRequirements).To(ContainElement(targetedOrgReq))
				})

				It("returns a space requirement", func() {
					Expect(reqFactory.NewSpaceRequirementCallCount()).To(Equal(1))
					Expect(actualRequirements).To(ContainElement(spaceRequirement))
				})
			})
		})
	})

	Describe("Execute", func() {
		var (
			space      models.Space
			spaceQuota models.SpaceQuota
			executeErr error
		)

		BeforeEach(func() {
			org := models.OrganizationFields{
				Name: "my-org",
				GUID: "my-org-guid",
			}

			app := models.ApplicationFields{
				Name: "app1",
				GUID: "app1-guid",
			}

			apps := []models.ApplicationFields{app}

			domain := models.DomainFields{
				Name: "domain1",
				GUID: "domain1-guid",
			}

			domains := []models.DomainFields{domain}

			serviceInstance := models.ServiceInstanceFields{
				Name: "service1",
				GUID: "service1-guid",
			}
			services := []models.ServiceInstanceFields{serviceInstance}

			securityGroup1 := models.SecurityGroupFields{Name: "Nacho Security", Rules: []map[string]interface{}{
				{"protocol": "all", "destination": "0.0.0.0-9.255.255.255", "log": true, "IntTest": 1000},
			}}
			securityGroup2 := models.SecurityGroupFields{Name: "Nacho Prime", Rules: []map[string]interface{}{
				{"protocol": "udp", "ports": "8080-9090", "destination": "198.41.191.47/1"},
			}}
			securityGroups := []models.SecurityGroupFields{securityGroup1, securityGroup2}

			space = models.Space{
				SpaceFields: models.SpaceFields{
					Name: "whose-space-is-it-anyway",
					GUID: "whose-space-is-it-anyway-guid",
				},
				Organization:     org,
				Applications:     apps,
				Domains:          domains,
				ServiceInstances: services,
				SecurityGroups:   securityGroups,
				SpaceQuotaGUID:   "runaway-guid",
			}

			spaceRequirement.GetSpaceReturns(space)

			spaceQuota = models.SpaceQuota{
				Name:                    "runaway",
				GUID:                    "runaway-guid",
				MemoryLimit:             102400,
				InstanceMemoryLimit:     -1,
				RoutesLimit:             111,
				ServicesLimit:           222,
				NonBasicServicesAllowed: false,
				AppInstanceLimit:        7,
				ReservedRoutePortsLimit: "7",
			}

			quotaRepo.FindByGUIDReturns(spaceQuota, nil)
		})

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

		Context("when logged in and an org is targeted", func() {
			BeforeEach(func() {
				err := flagContext.Parse("my-space")
				Expect(err).NotTo(HaveOccurred())
				cmd.Requirements(reqFactory, flagContext)
			})

			Context("when the guid flag is passed", func() {
				BeforeEach(func() {
					err := flagContext.Parse("my-space", "--guid")
					Expect(err).NotTo(HaveOccurred())
				})

				It("shows only the space guid", func() {
					Expect(executeErr).NotTo(HaveOccurred())
					Expect(ui.Outputs).To(ContainSubstrings(
						[]string{"whose-space-is-it-anyway-guid"},
					))

					Expect(ui.Outputs).ToNot(ContainSubstrings(
						[]string{"Getting info for space", "whose-space-is-it-anyway", "my-org", "my-user"},
					))
				})
			})

			Context("when the security-group-rules flag is passed", func() {
				BeforeEach(func() {
					err := flagContext.Parse("my-space", "--security-group-rules")
					Expect(err).NotTo(HaveOccurred())
				})
				It("it shows space information and security group rules", func() {
					Expect(executeErr).NotTo(HaveOccurred())
					Expect(ui.Outputs).To(ContainSubstrings(
						[]string{"Getting rules for the security group", "Nacho Security"},
						[]string{"protocol", "all"},
						[]string{"destination", "0.0.0.0-9.255.255.255"},
						[]string{"Getting rules for the security group", "Nacho Prime"},
						[]string{"protocol", "udp"},
						[]string{"log", "true"},
						[]string{"IntTest", "1000"},
						[]string{"ports", "8080-9090"},
						[]string{"destination", "198.41.191.47/1"},
					))
				})
			})

			Context("when the space has a space quota", func() {
				It("shows information about the given space", func() {
					Expect(executeErr).NotTo(HaveOccurred())
					Expect(ui.Outputs).To(ContainSubstrings(
						[]string{"Getting info for space", "whose-space-is-it-anyway", "my-org", "my-user"},
						[]string{"OK"},
						[]string{"whose-space-is-it-anyway"},
						[]string{"Org", "my-org"},
						[]string{"Apps", "app1"},
						[]string{"Domains", "domain1"},
						[]string{"Services", "service1"},
						[]string{"Security Groups", "Nacho Security", "Nacho Prime"},
						[]string{"Space Quota", "runaway (100G memory limit, unlimited instance memory limit, 111 routes, 222 services, paid services disallowed, 7 app instance limit, 7 route ports)"},
					))
				})

				Context("when the route ports limit is -1", func() {
					BeforeEach(func() {
						spaceQuota.ReservedRoutePortsLimit = "-1"
						quotaRepo.FindByGUIDReturns(spaceQuota, nil)
					})

					It("displays unlimited as the route ports limit", func() {
						Expect(executeErr).NotTo(HaveOccurred())
						Expect(ui.Outputs).To(ContainSubstrings(
							[]string{"unlimited route ports"},
						))
					})
				})

				Context("when the reserved route ports field is not provided by the CC API", func() {
					BeforeEach(func() {
						spaceQuota.ReservedRoutePortsLimit = ""
						quotaRepo.FindByGUIDReturns(spaceQuota, nil)
					})

					It("should not display route ports", func() {
						Expect(executeErr).NotTo(HaveOccurred())
						Expect(ui.Outputs).NotTo(ContainSubstrings(
							[]string{"route ports"},
						))
					})
				})

				Context("when the app instance limit is -1", func() {
					BeforeEach(func() {
						spaceQuota.AppInstanceLimit = -1
						quotaRepo.FindByGUIDReturns(spaceQuota, nil)
					})

					It("displays unlimited as the app instance limit", func() {
						Expect(executeErr).NotTo(HaveOccurred())
						Expect(ui.Outputs).To(ContainSubstrings(
							[]string{"unlimited app instance limit"},
						))
					})
				})
			})

			Context("when the space does not have a space quota", func() {
				BeforeEach(func() {
					space.SpaceQuotaGUID = ""
					spaceRequirement.GetSpaceReturns(space)
				})

				It("shows information without a space quota", func() {
					Expect(executeErr).NotTo(HaveOccurred())
					Expect(quotaRepo.FindByGUIDCallCount()).To(Equal(0))
					Expect(ui.Outputs).To(ContainSubstrings(
						[]string{"Getting info for space", "whose-space-is-it-anyway", "my-org", "my-user"},
						[]string{"OK"},
						[]string{"whose-space-is-it-anyway"},
						[]string{"Org", "my-org"},
						[]string{"Apps", "app1"},
						[]string{"Domains", "domain1"},
						[]string{"Services", "service1"},
						[]string{"Security Groups", "Nacho Security", "Nacho Prime"},
						[]string{"Space Quota"},
					))
				})
			})

			Context("When called as a plugin", func() {
				BeforeEach(func() {
					cmd.SetDependency(deps, true)
				})

				It("Fills in the PluginModel", func() {
					Expect(executeErr).NotTo(HaveOccurred())

					Expect(getSpaceModel.Name).To(Equal("whose-space-is-it-anyway"))
					Expect(getSpaceModel.Guid).To(Equal("whose-space-is-it-anyway-guid"))

					Expect(getSpaceModel.Organization.Name).To(Equal("my-org"))
					Expect(getSpaceModel.Organization.Guid).To(Equal("my-org-guid"))

					Expect(getSpaceModel.Applications).To(HaveLen(1))
					Expect(getSpaceModel.Applications[0].Name).To(Equal("app1"))
					Expect(getSpaceModel.Applications[0].Guid).To(Equal("app1-guid"))

					Expect(getSpaceModel.Domains).To(HaveLen(1))
					Expect(getSpaceModel.Domains[0].Name).To(Equal("domain1"))
					Expect(getSpaceModel.Domains[0].Guid).To(Equal("domain1-guid"))

					Expect(getSpaceModel.ServiceInstances).To(HaveLen(1))
					Expect(getSpaceModel.ServiceInstances[0].Name).To(Equal("service1"))
					Expect(getSpaceModel.ServiceInstances[0].Guid).To(Equal("service1-guid"))

					Expect(getSpaceModel.SecurityGroups).To(HaveLen(2))
					Expect(getSpaceModel.SecurityGroups[0].Name).To(Equal("Nacho Security"))
					Expect(getSpaceModel.SecurityGroups[0].Rules).To(HaveLen(1))
					Expect(getSpaceModel.SecurityGroups[0].Rules[0]).To(HaveLen(4))
					val := getSpaceModel.SecurityGroups[0].Rules[0]["protocol"]
					Expect(val).To(Equal("all"))
					val = getSpaceModel.SecurityGroups[0].Rules[0]["destination"]
					Expect(val).To(Equal("0.0.0.0-9.255.255.255"))

					Expect(getSpaceModel.SecurityGroups[1].Name).To(Equal("Nacho Prime"))
					Expect(getSpaceModel.SecurityGroups[1].Rules).To(HaveLen(1))
					Expect(getSpaceModel.SecurityGroups[1].Rules[0]).To(HaveLen(3))
					val = getSpaceModel.SecurityGroups[1].Rules[0]["protocol"]
					Expect(val).To(Equal("udp"))
					val = getSpaceModel.SecurityGroups[1].Rules[0]["destination"]
					Expect(val).To(Equal("198.41.191.47/1"))
					val = getSpaceModel.SecurityGroups[1].Rules[0]["ports"]
					Expect(val).To(Equal("8080-9090"))

					Expect(getSpaceModel.SpaceQuota.Name).To(Equal("runaway"))
					Expect(getSpaceModel.SpaceQuota.Guid).To(Equal("runaway-guid"))
					Expect(getSpaceModel.SpaceQuota.MemoryLimit).To(Equal(int64(102400)))
					Expect(getSpaceModel.SpaceQuota.InstanceMemoryLimit).To(Equal(int64(-1)))
					Expect(getSpaceModel.SpaceQuota.RoutesLimit).To(Equal(111))
					Expect(getSpaceModel.SpaceQuota.ServicesLimit).To(Equal(222))
					Expect(getSpaceModel.SpaceQuota.NonBasicServicesAllowed).To(BeFalse())
				})
			})
		})
	})
})
<|endoftext|>


<commit_before>/*
Copyright 2020 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 app

import (
	"encoding/json"
	"fmt"
	"github.com/spf13/cobra"
	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/cloud-provider-gcp/cmd/auth-provider-gcp/credentialconfig"
	"k8s.io/cloud-provider-gcp/cmd/auth-provider-gcp/plugin"
	klog "k8s.io/klog/v2"
	"net/http"
)

var (
	authFlow string
)

const (
	gcrAuthFlow             = "gcr"
	dockerConfigAuthFlow    = "dockercfg"
	dockerConfigURLAuthFlow = "dockercfg-url"
)

// NewGetCredentialsCommand returns a cobra command that retrieves auth credentials after validating flags.
func NewGetCredentialsCommand() (*cobra.Command, error) {
	cmd := &cobra.Command{
		Use:   "get-credentials",
		Short: "Get authentication credentials",
		RunE: func(cmd *cobra.Command, args []string) error {
			klog.V(2).Infof("get-credentials %s", authFlow)
			transport := utilnet.SetTransportDefaults(&http.Transport{})
			var provider credentialconfig.DockerConfigProvider
			if authFlow == gcrAuthFlow {
				provider = plugin.MakeRegistryProvider(transport)
			} else if authFlow == dockerConfigAuthFlow {
				provider = plugin.MakeDockerConfigProvider(transport)
			} else {
				provider = plugin.MakeDockerConfigURLProvider(transport)
			}
			authCredentials, err := plugin.GetResponse(provider)
			if err != nil {
				return err
			}
			jsonResponse, err := json.Marshal(authCredentials)
			if err != nil {
				return err
			}
			fmt.Println(string(jsonResponse))
			return nil
		},
	}
	defineFlags(cmd)
	if err := validateFlags(); err != nil {
		return nil, err
	}
	return cmd, nil
}

func defineFlags(credCmd *cobra.Command) {
	credCmd.Flags().StringVarP(&authFlow, "authFlow", "a", gcrAuthFlow, "authentication flow (valid values are gcr, dockercfg, and dockercfg-url)")
}

func validateFlags() error {
	if authFlow != gcrAuthFlow && authFlow != dockerConfigAuthFlow && authFlow != dockerConfigURLAuthFlow {
		return fmt.Errorf("invalid value \"%s\" for authFlow (must be one of \"%s\", \"%s\", or \"%s\")", authFlow, gcrAuthFlow, dockerConfigAuthFlow, dockerConfigURLAuthFlow)
	}
	return nil
}
<commit_msg>Move anonymous function to getCredentials in getcredentials.go.<commit_after>/*
Copyright 2020 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 app

import (
	"encoding/json"
	"fmt"
	"github.com/spf13/cobra"
	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/cloud-provider-gcp/cmd/auth-provider-gcp/credentialconfig"
	"k8s.io/cloud-provider-gcp/cmd/auth-provider-gcp/plugin"
	klog "k8s.io/klog/v2"
	"net/http"
)

var (
	authFlow string
)

const (
	gcrAuthFlow             = "gcr"
	dockerConfigAuthFlow    = "dockercfg"
	dockerConfigURLAuthFlow = "dockercfg-url"
)

// NewGetCredentialsCommand returns a cobra command that retrieves auth credentials after validating flags.
func NewGetCredentialsCommand() (*cobra.Command, error) {
	cmd := &cobra.Command{
		Use:   "get-credentials",
		Short: "Get authentication credentials",
		RunE:  getCredentials,
	}
	defineFlags(cmd)
	if err := validateFlags(); err != nil {
		return nil, err
	}
	return cmd, nil
}

func getCredentials(cmd *cobra.Command, args []string) error {
	klog.V(2).Infof("get-credentials %s", authFlow)
	transport := utilnet.SetTransportDefaults(&http.Transport{})
	var provider credentialconfig.DockerConfigProvider
	if authFlow == gcrAuthFlow {
		provider = plugin.MakeRegistryProvider(transport)
	} else if authFlow == dockerConfigAuthFlow {
		provider = plugin.MakeDockerConfigProvider(transport)
	} else {
		provider = plugin.MakeDockerConfigURLProvider(transport)
	}
	authCredentials, err := plugin.GetResponse(provider)
	if err != nil {
		return err
	}
	jsonResponse, err := json.Marshal(authCredentials)
	if err != nil {
		return err
	}
	fmt.Println(string(jsonResponse))
	return nil
}

func defineFlags(credCmd *cobra.Command) {
	credCmd.Flags().StringVarP(&authFlow, "authFlow", "a", gcrAuthFlow, "authentication flow (valid values are gcr, dockercfg, and dockercfg-url)")
}

func validateFlags() error {
	if authFlow != gcrAuthFlow && authFlow != dockerConfigAuthFlow && authFlow != dockerConfigURLAuthFlow {
		return fmt.Errorf("invalid value \"%s\" for authFlow (must be one of \"%s\", \"%s\", or \"%s\")", authFlow, gcrAuthFlow, dockerConfigAuthFlow, dockerConfigURLAuthFlow)
	}
	return nil
}
<|endoftext|>


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

// Package sort provides primitives for sorting slices and user-defined
// collections.
package sort

import "math"

// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package.  The methods require that the
// elements of the collection be enumerated by an integer index.
type Interface interface {
	// Len is the number of elements in the collection.
	Len() int
	// Less returns whether the element with index i should sort
	// before the element with index j.
	Less(i, j int) bool
	// Swap swaps the elements with indexes i and j.
	Swap(i, j int)
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// Insertion sort
func insertionSort(data Interface, a, b int) {
	for i := a + 1; i < b; i++ {
		for j := i; j > a && data.Less(j, j-1); j-- {
			data.Swap(j, j-1)
		}
	}
}

// siftDown implements the heap property on data[lo, hi).
// first is an offset into the array where the root of the heap lies.
func siftDown(data Interface, lo, hi, first int) {
	root := lo
	for {
		child := 2*root + 1
		if child >= hi {
			break
		}
		if child+1 < hi && data.Less(first+child, first+child+1) {
			child++
		}
		if !data.Less(first+root, first+child) {
			return
		}
		data.Swap(first+root, first+child)
		root = child
	}
}

func heapSort(data Interface, a, b int) {
	first := a
	lo := 0
	hi := b - a

	// Build heap with greatest element at top.
	for i := (hi - 1) / 2; i >= 0; i-- {
		siftDown(data, i, hi, first)
	}

	// Pop elements, largest first, into end of data.
	for i := hi - 1; i >= 0; i-- {
		data.Swap(first, first+i)
		siftDown(data, lo, i, first)
	}
}

// Quicksort, following Bentley and McIlroy,
// ``Engineering a Sort Function,'' SP&E November 1993.

// medianOfThree moves the median of the three values data[a], data[b], data[c] into data[a].
func medianOfThree(data Interface, a, b, c int) {
	m0 := b
	m1 := a
	m2 := c
	// bubble sort on 3 elements
	if data.Less(m1, m0) {
		data.Swap(m1, m0)
	}
	if data.Less(m2, m1) {
		data.Swap(m2, m1)
	}
	if data.Less(m1, m0) {
		data.Swap(m1, m0)
	}
	// now data[m0] <= data[m1] <= data[m2]
}

func swapRange(data Interface, a, b, n int) {
	for i := 0; i < n; i++ {
		data.Swap(a+i, b+i)
	}
}

func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
	m := lo + (hi-lo)/2 // Written like this to avoid integer overflow.
	if hi-lo > 40 {
		// Tukey's ``Ninther,'' median of three medians of three.
		s := (hi - lo) / 8
		medianOfThree(data, lo, lo+s, lo+2*s)
		medianOfThree(data, m, m-s, m+s)
		medianOfThree(data, hi-1, hi-1-s, hi-1-2*s)
	}
	medianOfThree(data, lo, m, hi-1)

	// Invariants are:
	//	data[lo] = pivot (set up by ChoosePivot)
	//	data[lo <= i < a] = pivot
	//	data[a <= i < b] < pivot
	//	data[b <= i < c] is unexamined
	//	data[c <= i < d] > pivot
	//	data[d <= i < hi] = pivot
	//
	// Once b meets c, can swap the "= pivot" sections
	// into the middle of the slice.
	pivot := lo
	a, b, c, d := lo+1, lo+1, hi, hi
	for b < c {
		if data.Less(b, pivot) { // data[b] < pivot
			b++
			continue
		}
		if !data.Less(pivot, b) { // data[b] = pivot
			data.Swap(a, b)
			a++
			b++
			continue
		}
		if data.Less(pivot, c-1) { // data[c-1] > pivot
			c--
			continue
		}
		if !data.Less(c-1, pivot) { // data[c-1] = pivot
			data.Swap(c-1, d-1)
			c--
			d--
			continue
		}
		// data[b] > pivot; data[c-1] < pivot
		data.Swap(b, c-1)
		b++
		c--
	}

	n := min(b-a, a-lo)
	swapRange(data, lo, b-n, n)

	n = min(hi-d, d-c)
	swapRange(data, c, hi-n, n)

	return lo + b - a, hi - (d - c)
}

func quickSort(data Interface, a, b, maxDepth int) {
	for b-a > 7 {
		if maxDepth == 0 {
			heapSort(data, a, b)
			return
		}
		maxDepth--
		mlo, mhi := doPivot(data, a, b)
		// Avoiding recursion on the larger subproblem guarantees
		// a stack depth of at most lg(b-a).
		if mlo-a < b-mhi {
			quickSort(data, a, mlo, maxDepth)
			a = mhi // i.e., quickSort(data, mhi, b)
		} else {
			quickSort(data, mhi, b, maxDepth)
			b = mlo // i.e., quickSort(data, a, mlo)
		}
	}
	if b-a > 1 {
		insertionSort(data, a, b)
	}
}

func Sort(data Interface) {
	// Switch to heapsort if depth of 2*ceil(lg(n)) is reached.
	n := data.Len()
	maxDepth := 0
	for 1<<uint(maxDepth) < n {
		maxDepth++
	}
	maxDepth *= 2
	quickSort(data, 0, n, maxDepth)
}

func IsSorted(data Interface) bool {
	n := data.Len()
	for i := n - 1; i > 0; i-- {
		if data.Less(i, i-1) {
			return false
		}
	}
	return true
}

// Convenience types for common cases

// IntSlice attaches the methods of Interface to []int, sorting in increasing order.
type IntSlice []int

func (p IntSlice) Len() int           { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p IntSlice) Sort() { Sort(p) }

// Float64Slice attaches the methods of Interface to []float64, sorting in increasing order.
type Float64Slice []float64

func (p Float64Slice) Len() int           { return len(p) }
func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] || math.IsNaN(p[i]) && !math.IsNaN(p[j]) }
func (p Float64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p Float64Slice) Sort() { Sort(p) }

// StringSlice attaches the methods of Interface to []string, sorting in increasing order.
type StringSlice []string

func (p StringSlice) Len() int           { return len(p) }
func (p StringSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p StringSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p StringSlice) Sort() { Sort(p) }

// Convenience wrappers for common cases

// Ints sorts a slice of ints in increasing order.
func Ints(a []int) { Sort(IntSlice(a)) }

// Float64s sorts a slice of float64s in increasing order.
func Float64s(a []float64) { Sort(Float64Slice(a)) }

// Strings sorts a slice of strings in increasing order.
func Strings(a []string) { Sort(StringSlice(a)) }

// IntsAreSorted tests whether a slice of ints is sorted in increasing order.
func IntsAreSorted(a []int) bool { return IsSorted(IntSlice(a)) }

// Float64sAreSorted tests whether a slice of float64s is sorted in increasing order.
func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Slice(a)) }

// StringsAreSorted tests whether a slice of strings is sorted in increasing order.
func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
<commit_msg>sort: document two undocumented functions<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package sort provides primitives for sorting slices and user-defined
// collections.
package sort

import "math"

// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package.  The methods require that the
// elements of the collection be enumerated by an integer index.
type Interface interface {
	// Len is the number of elements in the collection.
	Len() int
	// Less returns whether the element with index i should sort
	// before the element with index j.
	Less(i, j int) bool
	// Swap swaps the elements with indexes i and j.
	Swap(i, j int)
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// Insertion sort
func insertionSort(data Interface, a, b int) {
	for i := a + 1; i < b; i++ {
		for j := i; j > a && data.Less(j, j-1); j-- {
			data.Swap(j, j-1)
		}
	}
}

// siftDown implements the heap property on data[lo, hi).
// first is an offset into the array where the root of the heap lies.
func siftDown(data Interface, lo, hi, first int) {
	root := lo
	for {
		child := 2*root + 1
		if child >= hi {
			break
		}
		if child+1 < hi && data.Less(first+child, first+child+1) {
			child++
		}
		if !data.Less(first+root, first+child) {
			return
		}
		data.Swap(first+root, first+child)
		root = child
	}
}

func heapSort(data Interface, a, b int) {
	first := a
	lo := 0
	hi := b - a

	// Build heap with greatest element at top.
	for i := (hi - 1) / 2; i >= 0; i-- {
		siftDown(data, i, hi, first)
	}

	// Pop elements, largest first, into end of data.
	for i := hi - 1; i >= 0; i-- {
		data.Swap(first, first+i)
		siftDown(data, lo, i, first)
	}
}

// Quicksort, following Bentley and McIlroy,
// ``Engineering a Sort Function,'' SP&E November 1993.

// medianOfThree moves the median of the three values data[a], data[b], data[c] into data[a].
func medianOfThree(data Interface, a, b, c int) {
	m0 := b
	m1 := a
	m2 := c
	// bubble sort on 3 elements
	if data.Less(m1, m0) {
		data.Swap(m1, m0)
	}
	if data.Less(m2, m1) {
		data.Swap(m2, m1)
	}
	if data.Less(m1, m0) {
		data.Swap(m1, m0)
	}
	// now data[m0] <= data[m1] <= data[m2]
}

func swapRange(data Interface, a, b, n int) {
	for i := 0; i < n; i++ {
		data.Swap(a+i, b+i)
	}
}

func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
	m := lo + (hi-lo)/2 // Written like this to avoid integer overflow.
	if hi-lo > 40 {
		// Tukey's ``Ninther,'' median of three medians of three.
		s := (hi - lo) / 8
		medianOfThree(data, lo, lo+s, lo+2*s)
		medianOfThree(data, m, m-s, m+s)
		medianOfThree(data, hi-1, hi-1-s, hi-1-2*s)
	}
	medianOfThree(data, lo, m, hi-1)

	// Invariants are:
	//	data[lo] = pivot (set up by ChoosePivot)
	//	data[lo <= i < a] = pivot
	//	data[a <= i < b] < pivot
	//	data[b <= i < c] is unexamined
	//	data[c <= i < d] > pivot
	//	data[d <= i < hi] = pivot
	//
	// Once b meets c, can swap the "= pivot" sections
	// into the middle of the slice.
	pivot := lo
	a, b, c, d := lo+1, lo+1, hi, hi
	for b < c {
		if data.Less(b, pivot) { // data[b] < pivot
			b++
			continue
		}
		if !data.Less(pivot, b) { // data[b] = pivot
			data.Swap(a, b)
			a++
			b++
			continue
		}
		if data.Less(pivot, c-1) { // data[c-1] > pivot
			c--
			continue
		}
		if !data.Less(c-1, pivot) { // data[c-1] = pivot
			data.Swap(c-1, d-1)
			c--
			d--
			continue
		}
		// data[b] > pivot; data[c-1] < pivot
		data.Swap(b, c-1)
		b++
		c--
	}

	n := min(b-a, a-lo)
	swapRange(data, lo, b-n, n)

	n = min(hi-d, d-c)
	swapRange(data, c, hi-n, n)

	return lo + b - a, hi - (d - c)
}

func quickSort(data Interface, a, b, maxDepth int) {
	for b-a > 7 {
		if maxDepth == 0 {
			heapSort(data, a, b)
			return
		}
		maxDepth--
		mlo, mhi := doPivot(data, a, b)
		// Avoiding recursion on the larger subproblem guarantees
		// a stack depth of at most lg(b-a).
		if mlo-a < b-mhi {
			quickSort(data, a, mlo, maxDepth)
			a = mhi // i.e., quickSort(data, mhi, b)
		} else {
			quickSort(data, mhi, b, maxDepth)
			b = mlo // i.e., quickSort(data, a, mlo)
		}
	}
	if b-a > 1 {
		insertionSort(data, a, b)
	}
}

// Sort sorts data.
// The algorithm used is not guaranteed to be a stable sort.
func Sort(data Interface) {
	// Switch to heapsort if depth of 2*ceil(lg(n)) is reached.
	n := data.Len()
	maxDepth := 0
	for 1<<uint(maxDepth) < n {
		maxDepth++
	}
	maxDepth *= 2
	quickSort(data, 0, n, maxDepth)
}

// IsSorted reports whether data is sorted.
func IsSorted(data Interface) bool {
	n := data.Len()
	for i := n - 1; i > 0; i-- {
		if data.Less(i, i-1) {
			return false
		}
	}
	return true
}

// Convenience types for common cases

// IntSlice attaches the methods of Interface to []int, sorting in increasing order.
type IntSlice []int

func (p IntSlice) Len() int           { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p IntSlice) Sort() { Sort(p) }

// Float64Slice attaches the methods of Interface to []float64, sorting in increasing order.
type Float64Slice []float64

func (p Float64Slice) Len() int           { return len(p) }
func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] || math.IsNaN(p[i]) && !math.IsNaN(p[j]) }
func (p Float64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p Float64Slice) Sort() { Sort(p) }

// StringSlice attaches the methods of Interface to []string, sorting in increasing order.
type StringSlice []string

func (p StringSlice) Len() int           { return len(p) }
func (p StringSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p StringSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p StringSlice) Sort() { Sort(p) }

// Convenience wrappers for common cases

// Ints sorts a slice of ints in increasing order.
func Ints(a []int) { Sort(IntSlice(a)) }

// Float64s sorts a slice of float64s in increasing order.
func Float64s(a []float64) { Sort(Float64Slice(a)) }

// Strings sorts a slice of strings in increasing order.
func Strings(a []string) { Sort(StringSlice(a)) }

// IntsAreSorted tests whether a slice of ints is sorted in increasing order.
func IntsAreSorted(a []int) bool { return IsSorted(IntSlice(a)) }

// Float64sAreSorted tests whether a slice of float64s is sorted in increasing order.
func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Slice(a)) }

// StringsAreSorted tests whether a slice of strings is sorted in increasing order.
func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
<|endoftext|>


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

package time

// TODO(rsc): This implementation of Tick is a
// simple placeholder.  Eventually, there will need to be
// a single central time server no matter how many tickers
// are active.
//
// Also, if timeouts become part of the select statement,
// perhaps the Ticker is just:
//
//	func Ticker(ns int64, c chan int64) {
//		for {
//			select { timeout ns: }
//			nsec, err := Nanoseconds();
//			c <- nsec;
//		}

// A Ticker holds a synchronous channel that delivers `ticks' of a clock
// at intervals.
type Ticker struct {
	C        <-chan int64 // The channel on which the ticks are delivered.
	ns       int64
	shutdown bool
}

// Stop turns off a ticker.  After Stop, no more ticks will be delivered.
func (t *Ticker) Stop() { t.shutdown = true }

func (t *Ticker) ticker(c chan<- int64) {
	now := Nanoseconds()
	when := now
	for !t.shutdown {
		when += t.ns // next alarm

		// if c <- now took too long, skip ahead
		if when < now {
			// one big step
			when += (now - when) / t.ns * t.ns
		}
		for when <= now {
			// little steps until when > now
			when += t.ns
		}

		Sleep(when - now)
		now = Nanoseconds()
		if t.shutdown {
			return
		}
		c <- now
	}
}

// Tick is a convenience wrapper for NewTicker providing access to the ticking
// channel only.  Useful for clients that have no need to shut down the ticker.
func Tick(ns int64) <-chan int64 {
	if ns <= 0 {
		return nil
	}
	return NewTicker(ns).C
}

// Ticker returns a new Ticker containing a synchronous channel that will
// send the time, in nanoseconds, every ns nanoseconds.  It adjusts the
// intervals to make up for pauses in delivery of the ticks.
func NewTicker(ns int64) *Ticker {
	if ns <= 0 {
		return nil
	}
	c := make(chan int64)
	t := &Ticker{c, ns, false}
	go t.ticker(c)
	return t
}
<commit_msg>time: make tick.Stop a little more robust<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package time

// TODO(rsc): This implementation of Tick is a
// simple placeholder.  Eventually, there will need to be
// a single central time server no matter how many tickers
// are active.
//
// Also, if timeouts become part of the select statement,
// perhaps the Ticker is just:
//
//	func Ticker(ns int64, c chan int64) {
//		for {
//			select { timeout ns: }
//			nsec, err := Nanoseconds();
//			c <- nsec;
//		}

// A Ticker holds a synchronous channel that delivers `ticks' of a clock
// at intervals.
type Ticker struct {
	C        <-chan int64 // The channel on which the ticks are delivered.
	done     chan bool
	ns       int64
	shutdown bool
}

// Stop turns off a ticker.  After Stop, no more ticks will be sent.
func (t *Ticker) Stop() {
	t.shutdown = true
	go t.drain()
}

func (t *Ticker) drain() {
	for {
		select {
		case <-t.C:
		case <-t.done:
			return
		}
	}
}

func (t *Ticker) ticker(c chan<- int64) {
	now := Nanoseconds()
	when := now
	for !t.shutdown {
		when += t.ns // next alarm

		// if c <- now took too long, skip ahead
		if when < now {
			// one big step
			when += (now - when) / t.ns * t.ns
		}
		for when <= now {
			// little steps until when > now
			when += t.ns
		}

		for !t.shutdown && when > now {
			// limit individual sleeps so that stopped
			// long-term tickers don't pile up.
			const maxSleep = 1e9
			if when-now > maxSleep {
				Sleep(maxSleep)
			} else {
				Sleep(when - now)
			}
			now = Nanoseconds()
		}
		if t.shutdown {
			break
		}
		c <- now
	}
	t.done <- true
}

// Tick is a convenience wrapper for NewTicker providing access to the ticking
// channel only.  Useful for clients that have no need to shut down the ticker.
func Tick(ns int64) <-chan int64 {
	if ns <= 0 {
		return nil
	}
	return NewTicker(ns).C
}

// Ticker returns a new Ticker containing a synchronous channel that will
// send the time, in nanoseconds, every ns nanoseconds.  It adjusts the
// intervals to make up for pauses in delivery of the ticks.
func NewTicker(ns int64) *Ticker {
	if ns <= 0 {
		return nil
	}
	c := make(chan int64)
	t := &Ticker{c, make(chan bool), ns, false}
	go t.ticker(c)
	return t
}
<|endoftext|>


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

// Functions and constants to support text encoded in UTF-8.
// This package calls a Unicode character a rune for brevity.
package utf8

import "unicode"	// only needed for a couple of constants

// Numbers fundamental to the encoding.
const (
	RuneError	= unicode.ReplacementChar;	// the "error" Rune or "replacement character".
	RuneSelf	= 0x80;				// characters below Runeself are represented as themselves in a single byte.
	UTFMax		= 4;				// maximum number of bytes of a UTF-8 encoded Unicode character.
)

const (
	_T1	= 0x00;	// 0000 0000
	_Tx	= 0x80;	// 1000 0000
	_T2	= 0xC0;	// 1100 0000
	_T3	= 0xE0;	// 1110 0000
	_T4	= 0xF0;	// 1111 0000
	_T5	= 0xF8;	// 1111 1000

	_Maskx	= 0x3F;	// 0011 1111
	_Mask2	= 0x1F;	// 0001 1111
	_Mask3	= 0x0F;	// 0000 1111
	_Mask4	= 0x07;	// 0000 0111

	_Rune1Max	= 1<<7 - 1;
	_Rune2Max	= 1<<11 - 1;
	_Rune3Max	= 1<<16 - 1;
	_Rune4Max	= 1<<21 - 1;
)

func decodeRuneInternal(p []byte) (rune, size int, short bool) {
	n := len(p);
	if n < 1 {
		return RuneError, 0, true
	}
	c0 := p[0];

	// 1-byte, 7-bit sequence?
	if c0 < _Tx {
		return int(c0), 1, false
	}

	// unexpected continuation byte?
	if c0 < _T2 {
		return RuneError, 1, false
	}

	// need first continuation byte
	if n < 2 {
		return RuneError, 1, true
	}
	c1 := p[1];
	if c1 < _Tx || _T2 <= c1 {
		return RuneError, 1, false
	}

	// 2-byte, 11-bit sequence?
	if c0 < _T3 {
		rune = int(c0&_Mask2)<<6 | int(c1&_Maskx);
		if rune <= _Rune1Max {
			return RuneError, 1, false
		}
		return rune, 2, false;
	}

	// need second continuation byte
	if n < 3 {
		return RuneError, 1, true
	}
	c2 := p[2];
	if c2 < _Tx || _T2 <= c2 {
		return RuneError, 1, false
	}

	// 3-byte, 16-bit sequence?
	if c0 < _T4 {
		rune = int(c0&_Mask3)<<12 | int(c1&_Maskx)<<6 | int(c2&_Maskx);
		if rune <= _Rune2Max {
			return RuneError, 1, false
		}
		return rune, 3, false;
	}

	// need third continuation byte
	if n < 4 {
		return RuneError, 1, true
	}
	c3 := p[3];
	if c3 < _Tx || _T2 <= c3 {
		return RuneError, 1, false
	}

	// 4-byte, 21-bit sequence?
	if c0 < _T5 {
		rune = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx);
		if rune <= _Rune3Max {
			return RuneError, 1, false
		}
		return rune, 4, false;
	}

	// error
	return RuneError, 1, false;
}

func decodeRuneInStringInternal(s string) (rune, size int, short bool) {
	n := len(s);
	if n < 1 {
		return RuneError, 0, true
	}
	c0 := s[0];

	// 1-byte, 7-bit sequence?
	if c0 < _Tx {
		return int(c0), 1, false
	}

	// unexpected continuation byte?
	if c0 < _T2 {
		return RuneError, 1, false
	}

	// need first continuation byte
	if n < 2 {
		return RuneError, 1, true
	}
	c1 := s[1];
	if c1 < _Tx || _T2 <= c1 {
		return RuneError, 1, false
	}

	// 2-byte, 11-bit sequence?
	if c0 < _T3 {
		rune = int(c0&_Mask2)<<6 | int(c1&_Maskx);
		if rune <= _Rune1Max {
			return RuneError, 1, false
		}
		return rune, 2, false;
	}

	// need second continuation byte
	if n < 3 {
		return RuneError, 1, true
	}
	c2 := s[2];
	if c2 < _Tx || _T2 <= c2 {
		return RuneError, 1, false
	}

	// 3-byte, 16-bit sequence?
	if c0 < _T4 {
		rune = int(c0&_Mask3)<<12 | int(c1&_Maskx)<<6 | int(c2&_Maskx);
		if rune <= _Rune2Max {
			return RuneError, 1, false
		}
		return rune, 3, false;
	}

	// need third continuation byte
	if n < 4 {
		return RuneError, 1, true
	}
	c3 := s[3];
	if c3 < _Tx || _T2 <= c3 {
		return RuneError, 1, false
	}

	// 4-byte, 21-bit sequence?
	if c0 < _T5 {
		rune = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx);
		if rune <= _Rune3Max {
			return RuneError, 1, false
		}
		return rune, 4, false;
	}

	// error
	return RuneError, 1, false;
}

// FullRune reports whether the bytes in p begin with a full UTF-8 encoding of a rune.
// An invalid encoding is considered a full Rune since it will convert as a width-1 error rune.
func FullRune(p []byte) bool {
	_, _, short := decodeRuneInternal(p);
	return !short;
}

// FullRuneInString is like FullRune but its input is a string.
func FullRuneInString(s string) bool {
	_, _, short := decodeRuneInStringInternal(s);
	return !short;
}

// DecodeRune unpacks the first UTF-8 encoding in p and returns the rune and its width in bytes.
func DecodeRune(p []byte) (rune, size int) {
	rune, size, _ = decodeRuneInternal(p);
	return;
}

// DecodeRuneInString is like DecodeRune but its input is a string.
func DecodeRuneInString(s string) (rune, size int) {
	rune, size, _ = decodeRuneInStringInternal(s);
	return;
}

// RuneLen returns the number of bytes required to encode the rune.
func RuneLen(rune int) int {
	switch {
	case rune <= _Rune1Max:
		return 1
	case rune <= _Rune2Max:
		return 2
	case rune <= _Rune3Max:
		return 3
	case rune <= _Rune4Max:
		return 4
	}
	return -1;
}

// EncodeRune writes into p (which must be large enough) the UTF-8 encoding of the rune.
// It returns the number of bytes written.
func EncodeRune(rune int, p []byte) int {
	// Negative values are erroneous.
	if rune < 0 {
		rune = RuneError
	}

	if rune <= _Rune1Max {
		p[0] = byte(rune);
		return 1;
	}

	if rune <= _Rune2Max {
		p[0] = _T2 | byte(rune>>6);
		p[1] = _Tx | byte(rune)&_Maskx;
		return 2;
	}

	if rune > unicode.MaxRune {
		rune = RuneError
	}

	if rune <= _Rune3Max {
		p[0] = _T3 | byte(rune>>12);
		p[1] = _Tx | byte(rune>>6)&_Maskx;
		p[2] = _Tx | byte(rune)&_Maskx;
		return 3;
	}

	p[0] = _T4 | byte(rune>>18);
	p[1] = _Tx | byte(rune>>12)&_Maskx;
	p[2] = _Tx | byte(rune>>6)&_Maskx;
	p[3] = _Tx | byte(rune)&_Maskx;
	return 4;
}

// RuneCount returns the number of runes in p.  Erroneous and short
// encodings are treated as single runes of width 1 byte.
func RuneCount(p []byte) int {
	i := 0;
	var n int;
	for n = 0; i < len(p); n++ {
		if p[i] < RuneSelf {
			i++
		} else {
			_, size := DecodeRune(p[i:]);
			i += size;
		}
	}
	return n;
}

// RuneCountInString is like RuneCount but its input is a string.
func RuneCountInString(s string) (n int) {
	for _ = range s {
		n++
	}
	return;
}

// RuneStart reports whether the byte could be the first byte of
// an encoded rune.  Second and subsequent bytes always have the top
// two bits set to 10.
func RuneStart(b byte) bool	{ return b&0xC0 != 0x80 }
<commit_msg>simpler fix for the negative rune problem, spotted seconds after submitting the previous fix.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Functions and constants to support text encoded in UTF-8.
// This package calls a Unicode character a rune for brevity.
package utf8

import "unicode"	// only needed for a couple of constants

// Numbers fundamental to the encoding.
const (
	RuneError	= unicode.ReplacementChar;	// the "error" Rune or "replacement character".
	RuneSelf	= 0x80;				// characters below Runeself are represented as themselves in a single byte.
	UTFMax		= 4;				// maximum number of bytes of a UTF-8 encoded Unicode character.
)

const (
	_T1	= 0x00;	// 0000 0000
	_Tx	= 0x80;	// 1000 0000
	_T2	= 0xC0;	// 1100 0000
	_T3	= 0xE0;	// 1110 0000
	_T4	= 0xF0;	// 1111 0000
	_T5	= 0xF8;	// 1111 1000

	_Maskx	= 0x3F;	// 0011 1111
	_Mask2	= 0x1F;	// 0001 1111
	_Mask3	= 0x0F;	// 0000 1111
	_Mask4	= 0x07;	// 0000 0111

	_Rune1Max	= 1<<7 - 1;
	_Rune2Max	= 1<<11 - 1;
	_Rune3Max	= 1<<16 - 1;
	_Rune4Max	= 1<<21 - 1;
)

func decodeRuneInternal(p []byte) (rune, size int, short bool) {
	n := len(p);
	if n < 1 {
		return RuneError, 0, true
	}
	c0 := p[0];

	// 1-byte, 7-bit sequence?
	if c0 < _Tx {
		return int(c0), 1, false
	}

	// unexpected continuation byte?
	if c0 < _T2 {
		return RuneError, 1, false
	}

	// need first continuation byte
	if n < 2 {
		return RuneError, 1, true
	}
	c1 := p[1];
	if c1 < _Tx || _T2 <= c1 {
		return RuneError, 1, false
	}

	// 2-byte, 11-bit sequence?
	if c0 < _T3 {
		rune = int(c0&_Mask2)<<6 | int(c1&_Maskx);
		if rune <= _Rune1Max {
			return RuneError, 1, false
		}
		return rune, 2, false;
	}

	// need second continuation byte
	if n < 3 {
		return RuneError, 1, true
	}
	c2 := p[2];
	if c2 < _Tx || _T2 <= c2 {
		return RuneError, 1, false
	}

	// 3-byte, 16-bit sequence?
	if c0 < _T4 {
		rune = int(c0&_Mask3)<<12 | int(c1&_Maskx)<<6 | int(c2&_Maskx);
		if rune <= _Rune2Max {
			return RuneError, 1, false
		}
		return rune, 3, false;
	}

	// need third continuation byte
	if n < 4 {
		return RuneError, 1, true
	}
	c3 := p[3];
	if c3 < _Tx || _T2 <= c3 {
		return RuneError, 1, false
	}

	// 4-byte, 21-bit sequence?
	if c0 < _T5 {
		rune = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx);
		if rune <= _Rune3Max {
			return RuneError, 1, false
		}
		return rune, 4, false;
	}

	// error
	return RuneError, 1, false;
}

func decodeRuneInStringInternal(s string) (rune, size int, short bool) {
	n := len(s);
	if n < 1 {
		return RuneError, 0, true
	}
	c0 := s[0];

	// 1-byte, 7-bit sequence?
	if c0 < _Tx {
		return int(c0), 1, false
	}

	// unexpected continuation byte?
	if c0 < _T2 {
		return RuneError, 1, false
	}

	// need first continuation byte
	if n < 2 {
		return RuneError, 1, true
	}
	c1 := s[1];
	if c1 < _Tx || _T2 <= c1 {
		return RuneError, 1, false
	}

	// 2-byte, 11-bit sequence?
	if c0 < _T3 {
		rune = int(c0&_Mask2)<<6 | int(c1&_Maskx);
		if rune <= _Rune1Max {
			return RuneError, 1, false
		}
		return rune, 2, false;
	}

	// need second continuation byte
	if n < 3 {
		return RuneError, 1, true
	}
	c2 := s[2];
	if c2 < _Tx || _T2 <= c2 {
		return RuneError, 1, false
	}

	// 3-byte, 16-bit sequence?
	if c0 < _T4 {
		rune = int(c0&_Mask3)<<12 | int(c1&_Maskx)<<6 | int(c2&_Maskx);
		if rune <= _Rune2Max {
			return RuneError, 1, false
		}
		return rune, 3, false;
	}

	// need third continuation byte
	if n < 4 {
		return RuneError, 1, true
	}
	c3 := s[3];
	if c3 < _Tx || _T2 <= c3 {
		return RuneError, 1, false
	}

	// 4-byte, 21-bit sequence?
	if c0 < _T5 {
		rune = int(c0&_Mask4)<<18 | int(c1&_Maskx)<<12 | int(c2&_Maskx)<<6 | int(c3&_Maskx);
		if rune <= _Rune3Max {
			return RuneError, 1, false
		}
		return rune, 4, false;
	}

	// error
	return RuneError, 1, false;
}

// FullRune reports whether the bytes in p begin with a full UTF-8 encoding of a rune.
// An invalid encoding is considered a full Rune since it will convert as a width-1 error rune.
func FullRune(p []byte) bool {
	_, _, short := decodeRuneInternal(p);
	return !short;
}

// FullRuneInString is like FullRune but its input is a string.
func FullRuneInString(s string) bool {
	_, _, short := decodeRuneInStringInternal(s);
	return !short;
}

// DecodeRune unpacks the first UTF-8 encoding in p and returns the rune and its width in bytes.
func DecodeRune(p []byte) (rune, size int) {
	rune, size, _ = decodeRuneInternal(p);
	return;
}

// DecodeRuneInString is like DecodeRune but its input is a string.
func DecodeRuneInString(s string) (rune, size int) {
	rune, size, _ = decodeRuneInStringInternal(s);
	return;
}

// RuneLen returns the number of bytes required to encode the rune.
func RuneLen(rune int) int {
	switch {
	case rune <= _Rune1Max:
		return 1
	case rune <= _Rune2Max:
		return 2
	case rune <= _Rune3Max:
		return 3
	case rune <= _Rune4Max:
		return 4
	}
	return -1;
}

// EncodeRune writes into p (which must be large enough) the UTF-8 encoding of the rune.
// It returns the number of bytes written.
func EncodeRune(rune int, p []byte) int {
	// Negative values are erroneous.  Making it unsigned addresses the problem.
	r := uint(rune);

	if r <= _Rune1Max {
		p[0] = byte(r);
		return 1;
	}

	if r <= _Rune2Max {
		p[0] = _T2 | byte(r>>6);
		p[1] = _Tx | byte(r)&_Maskx;
		return 2;
	}

	if r > unicode.MaxRune {
		r = RuneError
	}

	if r <= _Rune3Max {
		p[0] = _T3 | byte(r>>12);
		p[1] = _Tx | byte(r>>6)&_Maskx;
		p[2] = _Tx | byte(r)&_Maskx;
		return 3;
	}

	p[0] = _T4 | byte(r>>18);
	p[1] = _Tx | byte(r>>12)&_Maskx;
	p[2] = _Tx | byte(r>>6)&_Maskx;
	p[3] = _Tx | byte(r)&_Maskx;
	return 4;
}

// RuneCount returns the number of runes in p.  Erroneous and short
// encodings are treated as single runes of width 1 byte.
func RuneCount(p []byte) int {
	i := 0;
	var n int;
	for n = 0; i < len(p); n++ {
		if p[i] < RuneSelf {
			i++
		} else {
			_, size := DecodeRune(p[i:]);
			i += size;
		}
	}
	return n;
}

// RuneCountInString is like RuneCount but its input is a string.
func RuneCountInString(s string) (n int) {
	for _ = range s {
		n++
	}
	return;
}

// RuneStart reports whether the byte could be the first byte of
// an encoded rune.  Second and subsequent bytes always have the top
// two bits set to 10.
func RuneStart(b byte) bool	{ return b&0xC0 != 0x80 }
<|endoftext|>


<commit_before>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package manual

import (
	"fmt"
	"os"

	gc "launchpad.net/gocheck"

	"launchpad.net/juju-core/environs/storage"
	envtesting "launchpad.net/juju-core/environs/testing"
	"launchpad.net/juju-core/instance"
	"launchpad.net/juju-core/juju/testing"
	jc "launchpad.net/juju-core/testing/checkers"
	"launchpad.net/juju-core/version"
)

type provisionerSuite struct {
	testing.JujuConnSuite
}

var _ = gc.Suite(&provisionerSuite{})

func (s *provisionerSuite) getArgs(c *gc.C) ProvisionMachineArgs {
	hostname, err := os.Hostname()
	c.Assert(err, gc.IsNil)
	return ProvisionMachineArgs{
		Host:  hostname,
		State: s.State,
	}
}

func (s *provisionerSuite) TestProvisionMachine(c *gc.C) {
	const series = "precise"
	const arch = "amd64"

	args := s.getArgs(c)
	hostname := args.Host
	args.Host = "ubuntu@" + args.Host

	envtesting.RemoveTools(c, s.Conn.Environ.Storage())
	envtesting.RemoveTools(c, s.Conn.Environ.PublicStorage().(storage.Storage))
	defer fakeSSH{
		series: series, arch: arch, skipProvisionAgent: true,
	}.install(c).Restore()
	m, err := ProvisionMachine(args)
	c.Assert(err, gc.ErrorMatches, "no tools available")
	c.Assert(m, gc.IsNil)

	cfg := s.Conn.Environ.Config()
	number, ok := cfg.AgentVersion()
	c.Assert(ok, jc.IsTrue)
	binVersion := version.Binary{number, series, arch}
	envtesting.AssertUploadFakeToolsVersions(c, s.Conn.Environ.Storage(), binVersion)

	for i, errorCode := range []int{255, 0} {
		c.Logf("test %d: code %d", i, errorCode)
		defer fakeSSH{
			series: series,
			arch:   arch,
			provisionAgentExitCode: errorCode,
		}.install(c).Restore()
		m, err = ProvisionMachine(args)
		if errorCode != 0 {
			c.Assert(err, gc.ErrorMatches, fmt.Sprintf("exit status %d", errorCode))
			c.Assert(m, gc.IsNil)
		} else {
			c.Assert(err, gc.IsNil)
			c.Assert(m, gc.NotNil)
			// machine ID will be incremented. Even though we failed and the
			// machine is removed, the ID is not reused.
			c.Assert(m.Id(), gc.Equals, fmt.Sprint(i))
			instanceId, err := m.InstanceId()
			c.Assert(err, gc.IsNil)
			c.Assert(instanceId, gc.Equals, instance.Id("manual:"+hostname))
		}
	}

	// Attempting to provision a machine twice should fail. We effect
	// this by checking for existing juju upstart configurations.
	defer installFakeSSH(c, "", "/etc/init/jujud-machine-0.conf", 0)()
	_, err = ProvisionMachine(args)
	c.Assert(err, gc.Equals, ErrProvisioned)
	defer installFakeSSH(c, "", "/etc/init/jujud-machine-0.conf", 255)()
	_, err = ProvisionMachine(args)
	c.Assert(err, gc.ErrorMatches, "error checking if provisioned: exit status 255")
}
<commit_msg>Fix test<commit_after>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package manual

import (
	"fmt"
	"os"

	gc "launchpad.net/gocheck"

	"launchpad.net/juju-core/environs/storage"
	envtesting "launchpad.net/juju-core/environs/testing"
	"launchpad.net/juju-core/errors"
	"launchpad.net/juju-core/instance"
	"launchpad.net/juju-core/juju/testing"
	jc "launchpad.net/juju-core/testing/checkers"
	"launchpad.net/juju-core/version"
)

type provisionerSuite struct {
	testing.JujuConnSuite
}

var _ = gc.Suite(&provisionerSuite{})

func (s *provisionerSuite) getArgs(c *gc.C) ProvisionMachineArgs {
	hostname, err := os.Hostname()
	c.Assert(err, gc.IsNil)
	return ProvisionMachineArgs{
		Host:  hostname,
		State: s.State,
	}
}

func (s *provisionerSuite) TestProvisionMachine(c *gc.C) {
	const series = "precise"
	const arch = "amd64"

	args := s.getArgs(c)
	hostname := args.Host
	args.Host = "ubuntu@" + args.Host

	envtesting.RemoveTools(c, s.Conn.Environ.Storage())
	envtesting.RemoveTools(c, s.Conn.Environ.PublicStorage().(storage.Storage))
	defer fakeSSH{
		series: series, arch: arch, skipProvisionAgent: true,
	}.install(c).Restore()
	m, err := ProvisionMachine(args)
	c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
	c.Assert(m, gc.IsNil)

	cfg := s.Conn.Environ.Config()
	number, ok := cfg.AgentVersion()
	c.Assert(ok, jc.IsTrue)
	binVersion := version.Binary{number, series, arch}
	envtesting.AssertUploadFakeToolsVersions(c, s.Conn.Environ.Storage(), binVersion)

	for i, errorCode := range []int{255, 0} {
		c.Logf("test %d: code %d", i, errorCode)
		defer fakeSSH{
			series: series,
			arch:   arch,
			provisionAgentExitCode: errorCode,
		}.install(c).Restore()
		m, err = ProvisionMachine(args)
		if errorCode != 0 {
			c.Assert(err, gc.ErrorMatches, fmt.Sprintf("exit status %d", errorCode))
			c.Assert(m, gc.IsNil)
		} else {
			c.Assert(err, gc.IsNil)
			c.Assert(m, gc.NotNil)
			// machine ID will be incremented. Even though we failed and the
			// machine is removed, the ID is not reused.
			c.Assert(m.Id(), gc.Equals, fmt.Sprint(i))
			instanceId, err := m.InstanceId()
			c.Assert(err, gc.IsNil)
			c.Assert(instanceId, gc.Equals, instance.Id("manual:"+hostname))
		}
	}

	// Attempting to provision a machine twice should fail. We effect
	// this by checking for existing juju upstart configurations.
	defer installFakeSSH(c, "", "/etc/init/jujud-machine-0.conf", 0)()
	_, err = ProvisionMachine(args)
	c.Assert(err, gc.Equals, ErrProvisioned)
	defer installFakeSSH(c, "", "/etc/init/jujud-machine-0.conf", 255)()
	_, err = ProvisionMachine(args)
	c.Assert(err, gc.ErrorMatches, "error checking if provisioned: exit status 255")
}
<|endoftext|>


<commit_before>// Copyright 2014, Google 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 planbuilder

import (
	"fmt"

	log "github.com/ngaut/logging"
	"github.com/wandoulabs/cm/sqlparser"
	"github.com/wandoulabs/cm/vt/schema"
)

func analyzeSelect(sel *sqlparser.Select, getTable TableGetter) (plan *ExecPlan, err error) {
	// Default plan
	plan = &ExecPlan{
		PlanId:     PLAN_PASS_SELECT,
		FieldQuery: GenerateFieldQuery(sel),
		FullQuery:  GenerateSelectLimitQuery(sel),
	}

	// from
	tableName, hasHints := analyzeFrom(sel.From)
	if tableName == "" {
		plan.Reason = REASON_TABLE
		return plan, nil
	}
	tableInfo, err := plan.setTableInfo(tableName, getTable)
	if err != nil {
		return nil, err
	}

	// There are bind variables in the SELECT list
	if plan.FieldQuery == nil {
		plan.Reason = REASON_SELECT_LIST
		return plan, nil
	}

	if sel.Distinct != "" || sel.GroupBy != nil || sel.Having != nil {
		plan.Reason = REASON_SELECT
		return plan, nil
	}

	// Don't improve the plan if the select is locking the row
	if sel.Lock != "" {
		plan.Reason = REASON_LOCK
		return plan, nil
	}

	// Further improvements possible only if table is row-cached
	if tableInfo.CacheType == schema.CACHE_NONE || tableInfo.CacheType == schema.CACHE_W {
		plan.Reason = REASON_NOCACHE
		return plan, nil
	}

	// Select expressions
	selects, err := analyzeSelectExprs(sel.SelectExprs, tableInfo)
	if err != nil {
		return nil, err
	}
	if selects == nil {
		plan.Reason = REASON_SELECT_LIST
		return plan, nil
	}
	plan.ColumnNumbers = selects

	// where
	conditions := analyzeWhere(sel.Where)
	if conditions == nil {
		plan.Reason = REASON_WHERE
		return plan, nil
	}

	// order
	if sel.OrderBy != nil {
		plan.Reason = REASON_ORDER
		return plan, nil
	}

	// This check should never fail because we only cache tables with primary keys.
	if len(tableInfo.Indexes) == 0 || tableInfo.Indexes[0].Name != "PRIMARY" {
		panic("unexpected")
	}

	log.Debugf("%+v", tableInfo.Indexes[0])
	pkValues, err := getPKValues(conditions, tableInfo.Indexes[0])
	if err != nil {
		return nil, err
	}
	if pkValues != nil {
		plan.IndexUsed = "PRIMARY"
		offset, rowcount, err := sel.Limit.Limits()
		if err != nil {
			return nil, err
		}
		if offset != nil {
			plan.Reason = REASON_LIMIT
			return plan, nil
		}
		plan.Limit = rowcount
		plan.PlanId = PLAN_PK_IN
		//todo:comment by liuqi, we do not need OuterQuery right now
		//plan.OuterQuery = GenerateSelectOuterQuery(sel, tableInfo)
		plan.PKValues = pkValues
		return plan, nil
	}

	// TODO: Analyze hints to improve plan.
	if hasHints {
		plan.Reason = REASON_HAS_HINTS
		return plan, nil
	}

	indexUsed := getIndexMatch(conditions, tableInfo.Indexes)
	if indexUsed == nil {
		plan.Reason = REASON_NOINDEX_MATCH
		return plan, nil
	}
	plan.IndexUsed = indexUsed.Name
	if plan.IndexUsed == "PRIMARY" {
		plan.Reason = REASON_PKINDEX
		return plan, nil
	}
	var missing bool
	for _, cnum := range selects {
		if indexUsed.FindDataColumn(tableInfo.Columns[cnum].Name) != -1 {
			continue
		}
		missing = true
		break
	}
	if !missing {
		plan.Reason = REASON_COVERING
		return plan, nil
	}
	plan.PlanId = PLAN_SELECT_SUBQUERY
	plan.OuterQuery = GenerateSelectOuterQuery(sel, tableInfo)
	plan.Subquery = GenerateSelectSubquery(sel, tableInfo, plan.IndexUsed)
	return plan, nil
}

func analyzeSelectExprs(exprs sqlparser.SelectExprs, table *schema.Table) (selects []int, err error) {
	selects = make([]int, 0, len(exprs))
	for _, expr := range exprs {
		switch expr := expr.(type) {
		case *sqlparser.StarExpr:
			// Append all columns.
			for colIndex := range table.Columns {
				selects = append(selects, colIndex)
			}
		case *sqlparser.NonStarExpr:
			name := sqlparser.GetColName(expr.Expr)
			if name == "" {
				// Not a simple column name.
				return nil, nil
			}
			colIndex := table.FindColumn(name)
			if colIndex == -1 {
				return nil, fmt.Errorf("column %s not found in table %s", name, table.Name)
			}
			selects = append(selects, colIndex)
		default:
			panic("unreachable")
		}
	}
	return selects, nil
}

func analyzeFrom(tableExprs sqlparser.TableExprs) (tablename string, hasHints bool) {
	if len(tableExprs) > 1 {
		return "", false
	}
	node, ok := tableExprs[0].(*sqlparser.AliasedTableExpr)
	if !ok {
		return "", false
	}
	return sqlparser.GetTableName(node.Expr), node.Hints != nil
}

func analyzeWhere(node *sqlparser.Where) (conditions []sqlparser.BoolExpr) {
	if node == nil {
		return nil
	}
	return analyzeBoolean(node.Expr)
}

func analyzeBoolean(node sqlparser.BoolExpr) (conditions []sqlparser.BoolExpr) {
	switch node := node.(type) {
	case *sqlparser.AndExpr:
		left := analyzeBoolean(node.Left)
		right := analyzeBoolean(node.Right)
		if left == nil || right == nil {
			return nil
		}
		if sqlparser.HasINClause(left) && sqlparser.HasINClause(right) {
			return nil
		}
		return append(left, right...)
	case *sqlparser.ParenBoolExpr:
		return analyzeBoolean(node.Expr)
	case *sqlparser.ComparisonExpr:
		switch {
		case sqlparser.StringIn(
			node.Operator,
			sqlparser.AST_EQ,
			sqlparser.AST_LT,
			sqlparser.AST_GT,
			sqlparser.AST_LE,
			sqlparser.AST_GE,
			sqlparser.AST_NSE,
			sqlparser.AST_LIKE):
			if sqlparser.IsColName(node.Left) && sqlparser.IsValue(node.Right) {
				return []sqlparser.BoolExpr{node}
			}
		case node.Operator == sqlparser.AST_IN:
			if sqlparser.IsColName(node.Left) && sqlparser.IsSimpleTuple(node.Right) {
				return []sqlparser.BoolExpr{node}
			}
		}
	case *sqlparser.RangeCond:
		if node.Operator != sqlparser.AST_BETWEEN {
			return nil
		}
		if sqlparser.IsColName(node.Left) && sqlparser.IsValue(node.From) && sqlparser.IsValue(node.To) {
			return []sqlparser.BoolExpr{node}
		}
	}
	return nil
}
<commit_msg>Revert "Revert "disable GenerateSelectOuterQuery and GenerateSelectSubquery""<commit_after>// Copyright 2014, Google 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 planbuilder

import (
	"fmt"

	"github.com/wandoulabs/cm/sqlparser"
	"github.com/wandoulabs/cm/vt/schema"
)

func analyzeSelect(sel *sqlparser.Select, getTable TableGetter) (plan *ExecPlan, err error) {
	// Default plan
	plan = &ExecPlan{
		PlanId: PLAN_PASS_SELECT,
		//todo: comment by liuqi, we do not need it now
		//FieldQuery: GenerateFieldQuery(sel),
		//FullQuery:  GenerateSelectLimitQuery(sel),
	}

	// from
	tableName, hasHints := analyzeFrom(sel.From)
	if tableName == "" {
		plan.Reason = REASON_TABLE
		return plan, nil
	}
	tableInfo, err := plan.setTableInfo(tableName, getTable)
	if err != nil {
		return nil, err
	}

	// There are bind variables in the SELECT list
	if plan.FieldQuery == nil {
		plan.Reason = REASON_SELECT_LIST
		return plan, nil
	}

	if sel.Distinct != "" || sel.GroupBy != nil || sel.Having != nil {
		plan.Reason = REASON_SELECT
		return plan, nil
	}

	// Don't improve the plan if the select is locking the row
	if sel.Lock != "" {
		plan.Reason = REASON_LOCK
		return plan, nil
	}

	// Further improvements possible only if table is row-cached
	if tableInfo.CacheType == schema.CACHE_NONE || tableInfo.CacheType == schema.CACHE_W {
		plan.Reason = REASON_NOCACHE
		return plan, nil
	}

	// Select expressions
	selects, err := analyzeSelectExprs(sel.SelectExprs, tableInfo)
	if err != nil {
		return nil, err
	}
	if selects == nil {
		plan.Reason = REASON_SELECT_LIST
		return plan, nil
	}
	plan.ColumnNumbers = selects

	// where
	conditions := analyzeWhere(sel.Where)
	if conditions == nil {
		plan.Reason = REASON_WHERE
		return plan, nil
	}

	// order
	if sel.OrderBy != nil {
		plan.Reason = REASON_ORDER
		return plan, nil
	}

	// This check should never fail because we only cache tables with primary keys.
	if len(tableInfo.Indexes) == 0 || tableInfo.Indexes[0].Name != "PRIMARY" {
		panic("unexpected")
	}

	//log.Debugf("%+v", tableInfo.Indexes[0])
	pkValues, err := getPKValues(conditions, tableInfo.Indexes[0])
	if err != nil {
		return nil, err
	}
	if pkValues != nil {
		plan.IndexUsed = "PRIMARY"
		offset, rowcount, err := sel.Limit.Limits()
		if err != nil {
			return nil, err
		}
		if offset != nil {
			plan.Reason = REASON_LIMIT
			return plan, nil
		}
		plan.Limit = rowcount
		plan.PlanId = PLAN_PK_IN
		//todo:comment by liuqi, we do not need OuterQuery right now
		//plan.OuterQuery = GenerateSelectOuterQuery(sel, tableInfo)
		plan.PKValues = pkValues
		return plan, nil
	}

	// TODO: Analyze hints to improve plan.
	if hasHints {
		plan.Reason = REASON_HAS_HINTS
		return plan, nil
	}

	indexUsed := getIndexMatch(conditions, tableInfo.Indexes)
	if indexUsed == nil {
		plan.Reason = REASON_NOINDEX_MATCH
		return plan, nil
	}
	plan.IndexUsed = indexUsed.Name
	if plan.IndexUsed == "PRIMARY" {
		plan.Reason = REASON_PKINDEX
		return plan, nil
	}
	var missing bool
	for _, cnum := range selects {
		if indexUsed.FindDataColumn(tableInfo.Columns[cnum].Name) != -1 {
			continue
		}
		missing = true
		break
	}
	if !missing {
		plan.Reason = REASON_COVERING
		return plan, nil
	}
	plan.PlanId = PLAN_SELECT_SUBQUERY
	//plan.OuterQuery = GenerateSelectOuterQuery(sel, tableInfo)
	//plan.Subquery = GenerateSelectSubquery(sel, tableInfo, plan.IndexUsed)
	return plan, nil
}

func analyzeSelectExprs(exprs sqlparser.SelectExprs, table *schema.Table) (selects []int, err error) {
	selects = make([]int, 0, len(exprs))
	for _, expr := range exprs {
		switch expr := expr.(type) {
		case *sqlparser.StarExpr:
			// Append all columns.
			for colIndex := range table.Columns {
				selects = append(selects, colIndex)
			}
		case *sqlparser.NonStarExpr:
			name := sqlparser.GetColName(expr.Expr)
			if name == "" {
				// Not a simple column name.
				return nil, nil
			}
			colIndex := table.FindColumn(name)
			if colIndex == -1 {
				return nil, fmt.Errorf("column %s not found in table %s", name, table.Name)
			}
			selects = append(selects, colIndex)
		default:
			panic("unreachable")
		}
	}
	return selects, nil
}

func analyzeFrom(tableExprs sqlparser.TableExprs) (tablename string, hasHints bool) {
	if len(tableExprs) > 1 {
		return "", false
	}
	node, ok := tableExprs[0].(*sqlparser.AliasedTableExpr)
	if !ok {
		return "", false
	}
	return sqlparser.GetTableName(node.Expr), node.Hints != nil
}

func analyzeWhere(node *sqlparser.Where) (conditions []sqlparser.BoolExpr) {
	if node == nil {
		return nil
	}
	return analyzeBoolean(node.Expr)
}

func analyzeBoolean(node sqlparser.BoolExpr) (conditions []sqlparser.BoolExpr) {
	switch node := node.(type) {
	case *sqlparser.AndExpr:
		left := analyzeBoolean(node.Left)
		right := analyzeBoolean(node.Right)
		if left == nil || right == nil {
			return nil
		}
		if sqlparser.HasINClause(left) && sqlparser.HasINClause(right) {
			return nil
		}
		return append(left, right...)
	case *sqlparser.ParenBoolExpr:
		return analyzeBoolean(node.Expr)
	case *sqlparser.ComparisonExpr:
		switch {
		case sqlparser.StringIn(
			node.Operator,
			sqlparser.AST_EQ,
			sqlparser.AST_LT,
			sqlparser.AST_GT,
			sqlparser.AST_LE,
			sqlparser.AST_GE,
			sqlparser.AST_NSE,
			sqlparser.AST_LIKE):
			if sqlparser.IsColName(node.Left) && sqlparser.IsValue(node.Right) {
				return []sqlparser.BoolExpr{node}
			}
		case node.Operator == sqlparser.AST_IN:
			if sqlparser.IsColName(node.Left) && sqlparser.IsSimpleTuple(node.Right) {
				return []sqlparser.BoolExpr{node}
			}
		}
	case *sqlparser.RangeCond:
		if node.Operator != sqlparser.AST_BETWEEN {
			return nil
		}
		if sqlparser.IsColName(node.Left) && sqlparser.IsValue(node.From) && sqlparser.IsValue(node.To) {
			return []sqlparser.BoolExpr{node}
		}
	}
	return nil
}
<|endoftext|>