<commit_before>package resolve

import (
	"os"
	"testing"
)

type testCase struct {
	require  string
	from     string
	resolved string
}

func TestResolveExisting(t *testing.T) {
	pwd, err := os.Getwd()

	if err != nil {
		t.Fatal(err)
	}

	testCases := []testCase{
		testCase{"./test/hello.js", pwd, pwd + "/test/hello.js"},
		testCase{"./test/hello", pwd, pwd + "/test/hello.js"},
		testCase{"./test/other_file.js", pwd, pwd + "/test/other_file.js"},
		testCase{"./test/other_file", pwd, pwd + "/test/other_file.js"},
		testCase{"./test/just_dir/hello_1", pwd, pwd + "/test/just_dir/hello_1.js"},
		testCase{"./test/just_dir/hello_2", pwd, pwd + "/test/just_dir/hello_2.js"},
		testCase{"./test/just_dir/index", pwd, pwd + "/test/just_dir/index.js"},
		testCase{"./test/just_dir", pwd, pwd + "/test/just_dir/index.js"},
		testCase{"./test/module_with_main", pwd, pwd + "/test/module_with_main/main.js"},
		testCase{"./test/module_with_main/package.json", pwd, pwd + "/test/module_with_main/package.json"},
		testCase{"./test/module_without_main", pwd, pwd + "/test/module_without_main/index.js"},
		testCase{"./test/not_here/", pwd, ""},
		testCase{"./test/somewhere_else", pwd, ""},
		testCase{"./test/not_found/module.js", pwd, ""},
		testCase{"./test/module_without_main", pwd, pwd + "/test/module_without_main/index.js"},
		// FIXME
		// testCase{"module_1", pwd + "/test/module_0", pwd + "/test/module_0/node_modules/module_1/index.js"},
		testCase{"module_2", pwd + "/test/module_0", ""},
		testCase{"module_1", pwd + "/test/module_0/node_modules/module_1/node_modules/module_2", pwd + "/test/module_0/node_modules/module_1/index.js"},
	}

	for _, testCase := range testCases {
		dependency, err := Resolve(testCase.require, testCase.from)

		if testCase.resolved == "" {

			if err == nil {
				t.Errorf("got no error when resolving %q; expected error", testCase.require)
			}

			if dependency != nil {
				t.Errorf("got dependency %q when resolving %q; expected nil", dependency.Pathname, testCase.require)
			}

		} else {

			if err != nil {
				t.Errorf("got error %q when resolving %q, expected nil", err, testCase.require)
			}

			if dependency == nil {
				t.Errorf("got no dependency when resolving %q; expected %q", testCase.require, testCase.resolved)
				continue
			}

			if dependency.Pathname != testCase.resolved {
				t.Errorf("got dependency %q when resolving %q; expected %q", dependency.Pathname, testCase.require, testCase.resolved)
			}

		}
	}
}
<commit_msg>chore: Avoid testcase name conflict with further tests<commit_after>package resolve

import (
	"os"
	"testing"
)

func TestResolve(t *testing.T) {
	type testCase struct {
		require  string
		from     string
		resolved string
	}

	pwd, err := os.Getwd()

	if err != nil {
		t.Fatal(err)
	}

	testCases := []testCase{
		testCase{"./test/hello.js", pwd, pwd + "/test/hello.js"},
		testCase{"./test/hello", pwd, pwd + "/test/hello.js"},
		testCase{"./test/other_file.js", pwd, pwd + "/test/other_file.js"},
		testCase{"./test/other_file", pwd, pwd + "/test/other_file.js"},
		testCase{"./test/just_dir/hello_1", pwd, pwd + "/test/just_dir/hello_1.js"},
		testCase{"./test/just_dir/hello_2", pwd, pwd + "/test/just_dir/hello_2.js"},
		testCase{"./test/just_dir/index", pwd, pwd + "/test/just_dir/index.js"},
		testCase{"./test/just_dir", pwd, pwd + "/test/just_dir/index.js"},
		testCase{"./test/module_with_main", pwd, pwd + "/test/module_with_main/main.js"},
		testCase{"./test/module_with_main/package.json", pwd, pwd + "/test/module_with_main/package.json"},
		testCase{"./test/module_without_main", pwd, pwd + "/test/module_without_main/index.js"},
		testCase{"./test/not_here/", pwd, ""},
		testCase{"./test/somewhere_else", pwd, ""},
		testCase{"./test/not_found/module.js", pwd, ""},
		testCase{"./test/module_without_main", pwd, pwd + "/test/module_without_main/index.js"},
		// FIXME
		// testCase{"module_1", pwd + "/test/module_0", pwd + "/test/module_0/node_modules/module_1/index.js"},
		testCase{"module_2", pwd + "/test/module_0", ""},
		testCase{"module_1", pwd + "/test/module_0/node_modules/module_1/node_modules/module_2", pwd + "/test/module_0/node_modules/module_1/index.js"},
	}

	for _, testCase := range testCases {
		dependency, err := Resolve(testCase.require, testCase.from)

		if testCase.resolved == "" {

			if err == nil {
				t.Errorf("got no error when resolving %q; expected error", testCase.require)
			}

			if dependency != nil {
				t.Errorf("got dependency %q when resolving %q; expected nil", dependency.Pathname, testCase.require)
			}

		} else {

			if err != nil {
				t.Errorf("got error %q when resolving %q, expected nil", err, testCase.require)
			}

			if dependency == nil {
				t.Errorf("got no dependency when resolving %q; expected %q", testCase.require, testCase.resolved)
				continue
			}

			if dependency.Pathname != testCase.resolved {
				t.Errorf("got dependency %q when resolving %q; expected %q", dependency.Pathname, testCase.require, testCase.resolved)
			}

		}
	}
}
<|endoftext|>


<commit_before>package dal

import (
	"reflect"
	"testing"
	"time"
)

func TestGetPurchases(t *testing.T) {
	db, err := GetMockupDB()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	purchases, err := GetPurchases(db)
	if err != nil {
		t.Error(err)
	}

	if len(purchases) != 2 {
		t.Error("expected 2 purchases")
	}

	mockup1 := Purchase{
		uint64(1), "Test1", 20.0, time.Unix(0, 0),
	}
	if !reflect.DeepEqual(purchases[0], mockup1) {
		t.Error("first retrieved row should match expected")
	}

	mockup2 := Purchase{
		uint64(2), "Test2", 30.0, time.Unix(0, 0),
	}
	if !reflect.DeepEqual(purchases[1], mockup2) {
		t.Error("second retrieved row should match expected")
	}
}

func TestAddPurchase(t *testing.T) {
	db, err := GetMockupDB()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	purchases, err := GetPurchases(db)
	if err != nil {
		t.Error(err)
	}
	if len(purchases) != 2 {
		t.Error("expected 2 purchases")
	}

	newPurchase := Purchase{
		uint64(3), "Rawr", 332.03, time.Now(),
	}
	err = AddPurchase(db, &newPurchase)
	if err != nil {
		t.Error(err)
	}

	purchases, err = GetPurchases(db)
	if err != nil {
		t.Error(err)
	}
	if len(purchases) != 3 {
		t.Error("expected 3 purchases now, AddPurchase failed")
	}
	if !reflect.DeepEqual(newPurchase, purchases[2]) {
		t.Error("new purchase was not saved correctly")
	}
}

func TestGetPurchase(t *testing.T) {
	db, err := GetMockupDB()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	mockup1 := Purchase{
		uint64(1), "Test1", 20.0, time.Unix(0, 0),
	}
	purchase1, err := GetPurchase(db, 1)
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(*purchase1, mockup1) {
		t.Error("first retrieved row should match expected")
	}

	mockup2 := Purchase{
		uint64(2), "Test2", 30.0, time.Unix(0, 0),
	}
	purchase2, err := GetPurchase(db, 2)
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(*purchase2, mockup2) {
		t.Error("second retrieved row should match expected")
	}
}
<commit_msg>fix test<commit_after>package dal

import (
	"reflect"
	"testing"
	"time"
)

func TestGetPurchases(t *testing.T) {
	db, err := GetMockupDB()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	purchases, err := GetPurchases(db)
	if err != nil {
		t.Error(err)
	}

	if len(purchases) != 2 {
		t.Error("expected 2 purchases")
	}

	mockup1 := Purchase{
		uint64(1), "Test1", 20.0, time.Unix(0, 0),
	}
	if !reflect.DeepEqual(purchases[0], mockup1) {
		t.Error("first retrieved row should match expected")
	}

	mockup2 := Purchase{
		uint64(2), "Test2", 30.0, time.Unix(0, 0),
	}
	if !reflect.DeepEqual(purchases[1], mockup2) {
		t.Error("second retrieved row should match expected")
	}
}

func TestAddPurchase(t *testing.T) {
	db, err := GetMockupDB()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	purchases, err := GetPurchases(db)
	if err != nil {
		t.Error(err)
	}
	if len(purchases) != 2 {
		t.Error("expected 2 purchases")
	}

	newPurchase := Purchase{
		uint64(3), "Rawr", 332.03, time.Now(),
	}
	err = AddPurchase(db, &newPurchase)
	if err != nil {
		t.Error(err)
	}

	purchases, err = GetPurchases(db)
	if err != nil {
		t.Error(err)
	}
	if len(purchases) != 3 {
		t.Error("expected 3 purchases now, AddPurchase failed")
	}
	if !reflect.DeepEqual(newPurchase, purchases[0]) {
		t.Error("new purchase was not saved correctly", newPurchase, purchases[2])
	}
}

func TestGetPurchase(t *testing.T) {
	db, err := GetMockupDB()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	mockup1 := Purchase{
		uint64(1), "Test1", 20.0, time.Unix(0, 0),
	}
	purchase1, err := GetPurchase(db, 1)
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(*purchase1, mockup1) {
		t.Error("first retrieved row should match expected")
	}

	mockup2 := Purchase{
		uint64(2), "Test2", 30.0, time.Unix(0, 0),
	}
	purchase2, err := GetPurchase(db, 2)
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(*purchase2, mockup2) {
		t.Error("second retrieved row should match expected")
	}
}
<|endoftext|>


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

package discoverspaces_test

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

	"github.com/juju/juju/api"
	apidiscoverspaces "github.com/juju/juju/api/discoverspaces"
	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/juju/testing"
	"github.com/juju/juju/network"
	"github.com/juju/juju/provider/common"
	"github.com/juju/juju/provider/dummy"
	"github.com/juju/juju/state"
	"github.com/juju/juju/worker"
	"github.com/juju/juju/worker/discoverspaces"
)

type workerSuite struct {
	testing.JujuConnSuite

	Worker  worker.Worker
	OpsChan chan dummy.Operation

	APIConnection api.Connection
	API           *apidiscoverspaces.API
}

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

func (s *workerSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)

	// Unbreak dummy provider methods.
	s.AssertConfigParameterUpdated(c, "broken", "")

	s.APIConnection, _ = s.OpenAPIAsNewMachine(c, state.JobManageEnviron)
	s.API = s.APIConnection.DiscoverSpaces()

	s.OpsChan = make(chan dummy.Operation, 10)
	dummy.Listen(s.OpsChan)
}

func (s *workerSuite) startWorker() {
	s.Worker = discoverspaces.NewWorker(s.API, func() {})
}

func (s *workerSuite) TearDownTest(c *gc.C) {
	if s.Worker != nil {
		c.Assert(worker.Stop(s.Worker), jc.ErrorIsNil)
	}
	s.JujuConnSuite.TearDownTest(c)
}

func (s *workerSuite) TestConvertSpaceName(c *gc.C) {
	empty := set.Strings{}
	nameTests := []struct {
		name     string
		existing set.Strings
		expected string
	}{
		{"foo", empty, "foo"},
		{"foo1", empty, "foo1"},
		{"Foo Thing", empty, "foo-thing"},
		{"foo^9*//++!!!!", empty, "foo9"},
		{"--Foo", empty, "foo"},
		{"---^^&*()!", empty, "empty"},
		{" ", empty, "empty"},
		{"", empty, "empty"},
		{"foo\u2318", empty, "foo"},
		{"foo--", empty, "foo"},
		{"-foo--foo----bar-", empty, "foo-foo-bar"},
		{"foo-", set.NewStrings("foo", "bar", "baz"), "foo-2"},
		{"foo", set.NewStrings("foo", "foo-2"), "foo-3"},
		{"---", set.NewStrings("empty"), "empty-2"},
	}
	for _, test := range nameTests {
		result := discoverspaces.ConvertSpaceName(test.name, test.existing)
		c.Check(result, gc.Equals, test.expected)
	}
}

func (s *workerSuite) TestWorkerIsStringsWorker(c *gc.C) {
	s.startWorker()
	c.Assert(s.Worker, gc.Not(gc.FitsTypeOf), worker.FinishedWorker{})
}

func (s *workerSuite) TestWorkerSupportsSpaceDiscoveryFalse(c *gc.C) {
	s.startWorker()
	spaces, err := s.State.AllSpaces()
	c.Assert(err, jc.ErrorIsNil)

	// No spaces will have been created, worker does nothing.
	for a := common.ShortAttempt.Start(); a.Next(); {
		spaces, err = s.State.AllSpaces()
		if err != nil {
			c.Fatalf("error fetching spaces: %v", err)
		}
		if len(spaces) != 0 {
			c.Fatalf("spaces should not be created, we have %v", len(spaces))
		}
		if !a.HasNext() {
			break
		}
	}
}

func (s *workerSuite) TestWorkerDiscoversSpaces(c *gc.C) {
	dummy.SetSupportsSpaceDiscovery(true)
	s.startWorker()
	var err error
	var spaces []*state.Space
	for a := common.ShortAttempt.Start(); a.Next(); {
		spaces, err = s.State.AllSpaces()
		if err != nil {
			break
		}
		if len(spaces) == 4 {
			// All spaces have been created.
			break
		}
		if !a.HasNext() {
			c.Fatalf("spaces not imported")
		}
	}
	c.Assert(err, jc.ErrorIsNil)
	expectedSpaces := []network.SpaceInfo{{
		Name:       "foo",
		ProviderId: network.Id("foo"),
		Subnets: []network.SubnetInfo{{
			ProviderId:        network.Id("1"),
			CIDR:              "192.168.1.0/24",
			AvailabilityZones: []string{"zone1"},
		}, {
			ProviderId:        network.Id("2"),
			CIDR:              "192.168.2.0/24",
			AvailabilityZones: []string{"zone1"},
		}}}, {
		Name:       "another-foo-99",
		ProviderId: network.Id("Another Foo 99!"),
		Subnets: []network.SubnetInfo{{
			ProviderId:        network.Id("3"),
			CIDR:              "192.168.3.0/24",
			AvailabilityZones: []string{"zone1"},
		}}}, {
		Name:       "foo-2",
		ProviderId: network.Id("foo-"),
		Subnets: []network.SubnetInfo{{
			ProviderId:        network.Id("4"),
			CIDR:              "192.168.4.0/24",
			AvailabilityZones: []string{"zone1"},
		}}}, {
		Name:       "empty",
		ProviderId: network.Id("---"),
		Subnets: []network.SubnetInfo{{
			ProviderId:        network.Id("5"),
			CIDR:              "192.168.5.0/24",
			AvailabilityZones: []string{"zone1"},
		}}}}
	expectedSpaceMap := make(map[string]network.SpaceInfo)
	for _, space := range expectedSpaces {
		expectedSpaceMap[space.Name] = space
	}
	for _, space := range spaces {
		expected, ok := expectedSpaceMap[space.Name()]
		if !c.Check(ok, jc.IsTrue) {
			continue
		}
		c.Check(space.ProviderId(), gc.Equals, expected.ProviderId)
		subnets, err := space.Subnets()
		if !c.Check(err, jc.ErrorIsNil) {
			continue
		}
		c.Check(len(subnets), gc.Equals, len(expected.Subnets))
		for i, subnet := range subnets {
			expectedSubnet := expected.Subnets[i]
			c.Check(subnet.ProviderId(), gc.Equals, expectedSubnet.ProviderId)
			c.Check([]string{subnet.AvailabilityZone()}, jc.DeepEquals, expectedSubnet.AvailabilityZones)
			c.Check(subnet.CIDR(), gc.Equals, expectedSubnet.CIDR)
		}
	}
}

func (s *workerSuite) TestWorkerIdempotent(c *gc.C) {
	dummy.SetSupportsSpaceDiscovery(true)
	s.startWorker()
	var err error
	var spaces []*state.Space
	for a := common.ShortAttempt.Start(); a.Next(); {
		spaces, err = s.State.AllSpaces()
		if err != nil {
			break
		}
		if len(spaces) == 4 {
			// All spaces have been created.
			break
		}
		if !a.HasNext() {
			c.Fatalf("spaces not imported")
		}
	}
	c.Assert(err, jc.ErrorIsNil)
	newWorker := discoverspaces.NewWorker(s.API, func() {})

	// This ensures that the worker can handle re-importing without error.
	defer func() {
		c.Assert(worker.Stop(newWorker), jc.ErrorIsNil)
	}()

	// Check that no extra spaces are imported.
	for a := common.ShortAttempt.Start(); a.Next(); {
		spaces, err = s.State.AllSpaces()
		if err != nil {
			break
		}
		if len(spaces) != 4 {
			c.Fatalf("unexpected number of spaces: %v", len(spaces))
		}
		if !a.HasNext() {
			break
		}
	}
}

func (s *workerSuite) TestSupportsSpaceDiscoveryBroken(c *gc.C) {
	s.AssertConfigParameterUpdated(c, "broken", "SupportsSpaceDiscovery")

	newWorker := discoverspaces.NewWorker(s.API, func() {})
	err := worker.Stop(newWorker)
	c.Assert(err, gc.ErrorMatches, "dummy.SupportsSpaceDiscovery is broken")
}

func (s *workerSuite) TestSpacesBroken(c *gc.C) {
	dummy.SetSupportsSpaceDiscovery(true)
	s.AssertConfigParameterUpdated(c, "broken", "Spaces")

	newWorker := discoverspaces.NewWorker(s.API, func() {})
	err := worker.Stop(newWorker)
	c.Assert(err, gc.ErrorMatches, "dummy.Spaces is broken")
}

func (s *workerSuite) TestWorkerIgnoresExistingSpacesAndSubnets(c *gc.C) {
	dummy.SetSupportsSpaceDiscovery(true)
	spaceTag := names.NewSpaceTag("foo")
	args := params.CreateSpacesParams{
		Spaces: []params.CreateSpaceParams{{
			Public:     false,
			SpaceTag:   spaceTag.String(),
			ProviderId: "foo",
		}}}
	result, err := s.API.CreateSpaces(args)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(result.Results, gc.HasLen, 1)
	c.Assert(result.Results[0].Error, gc.IsNil)

	subnetArgs := params.AddSubnetsParams{
		Subnets: []params.AddSubnetParams{{
			SubnetProviderId: "1",
			SpaceTag:         spaceTag.String(),
			Zones:            []string{"zone1"},
		}}}
	subnetResult, err := s.API.AddSubnets(subnetArgs)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(subnetResult.Results, gc.HasLen, 1)
	c.Assert(subnetResult.Results[0].Error, gc.IsNil)

	s.startWorker()
	for a := common.ShortAttempt.Start(); a.Next(); {
		spaces, err := s.State.AllSpaces()
		if err != nil {
			break
		}
		if len(spaces) == 4 {
			// All spaces have been created.
			break
		}
		if !a.HasNext() {
			c.Fatalf("spaces not imported")
		}
	}
	c.Assert(err, jc.ErrorIsNil)
}
<commit_msg>Test worker calls setSpacesDiscoveredFunction<commit_after>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package discoverspaces_test

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

	"github.com/juju/juju/api"
	apidiscoverspaces "github.com/juju/juju/api/discoverspaces"
	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/juju/testing"
	"github.com/juju/juju/network"
	"github.com/juju/juju/provider/common"
	"github.com/juju/juju/provider/dummy"
	"github.com/juju/juju/state"
	"github.com/juju/juju/worker"
	"github.com/juju/juju/worker/discoverspaces"
)

type workerSuite struct {
	testing.JujuConnSuite

	Worker  worker.Worker
	OpsChan chan dummy.Operation

	APIConnection    api.Connection
	API              *apidiscoverspaces.API
	spacesDiscovered bool
}

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

func (s *workerSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)

	// Unbreak dummy provider methods.
	s.AssertConfigParameterUpdated(c, "broken", "")

	s.APIConnection, _ = s.OpenAPIAsNewMachine(c, state.JobManageEnviron)
	s.API = s.APIConnection.DiscoverSpaces()

	s.OpsChan = make(chan dummy.Operation, 10)
	dummy.Listen(s.OpsChan)
	s.spacesDiscovered = false
}

func (s *workerSuite) getSetSpacesDiscoveredFunc() func() {
	return func() {
		s.spacesDiscovered = true
	}
}

func (s *workerSuite) startWorker() {
	s.Worker = discoverspaces.NewWorker(s.API, s.getSetSpacesDiscoveredFunc())
}

func (s *workerSuite) TearDownTest(c *gc.C) {
	if s.Worker != nil {
		c.Assert(worker.Stop(s.Worker), jc.ErrorIsNil)
	}
	s.JujuConnSuite.TearDownTest(c)
}

func (s *workerSuite) TestConvertSpaceName(c *gc.C) {
	empty := set.Strings{}
	nameTests := []struct {
		name     string
		existing set.Strings
		expected string
	}{
		{"foo", empty, "foo"},
		{"foo1", empty, "foo1"},
		{"Foo Thing", empty, "foo-thing"},
		{"foo^9*//++!!!!", empty, "foo9"},
		{"--Foo", empty, "foo"},
		{"---^^&*()!", empty, "empty"},
		{" ", empty, "empty"},
		{"", empty, "empty"},
		{"foo\u2318", empty, "foo"},
		{"foo--", empty, "foo"},
		{"-foo--foo----bar-", empty, "foo-foo-bar"},
		{"foo-", set.NewStrings("foo", "bar", "baz"), "foo-2"},
		{"foo", set.NewStrings("foo", "foo-2"), "foo-3"},
		{"---", set.NewStrings("empty"), "empty-2"},
	}
	for _, test := range nameTests {
		result := discoverspaces.ConvertSpaceName(test.name, test.existing)
		c.Check(result, gc.Equals, test.expected)
	}
}

func (s *workerSuite) TestWorkerIsStringsWorker(c *gc.C) {
	s.startWorker()
	c.Assert(s.Worker, gc.Not(gc.FitsTypeOf), worker.FinishedWorker{})
}

func (s *workerSuite) TestWorkerSupportsSpaceDiscoveryFalse(c *gc.C) {
	s.startWorker()
	spaces, err := s.State.AllSpaces()
	c.Assert(err, jc.ErrorIsNil)

	// No spaces will have been created, worker does nothing.
	for a := common.ShortAttempt.Start(); a.Next(); {
		spaces, err = s.State.AllSpaces()
		if err != nil {
			c.Fatalf("error fetching spaces: %v", err)
		}
		if len(spaces) != 0 {
			c.Fatalf("spaces should not be created, we have %v", len(spaces))
		}
		if !a.HasNext() {
			break
		}
	}
	c.Assert(s.spacesDiscovered, jc.IsTrue)
}

func (s *workerSuite) TestWorkerDiscoversSpaces(c *gc.C) {
	dummy.SetSupportsSpaceDiscovery(true)
	s.startWorker()
	var err error
	var spaces []*state.Space
	for a := common.ShortAttempt.Start(); a.Next(); {
		spaces, err = s.State.AllSpaces()
		if err != nil {
			break
		}
		if len(spaces) == 4 {
			// All spaces have been created.
			break
		}
		if !a.HasNext() {
			c.Fatalf("spaces not imported")
		}
	}
	c.Assert(err, jc.ErrorIsNil)
	expectedSpaces := []network.SpaceInfo{{
		Name:       "foo",
		ProviderId: network.Id("foo"),
		Subnets: []network.SubnetInfo{{
			ProviderId:        network.Id("1"),
			CIDR:              "192.168.1.0/24",
			AvailabilityZones: []string{"zone1"},
		}, {
			ProviderId:        network.Id("2"),
			CIDR:              "192.168.2.0/24",
			AvailabilityZones: []string{"zone1"},
		}}}, {
		Name:       "another-foo-99",
		ProviderId: network.Id("Another Foo 99!"),
		Subnets: []network.SubnetInfo{{
			ProviderId:        network.Id("3"),
			CIDR:              "192.168.3.0/24",
			AvailabilityZones: []string{"zone1"},
		}}}, {
		Name:       "foo-2",
		ProviderId: network.Id("foo-"),
		Subnets: []network.SubnetInfo{{
			ProviderId:        network.Id("4"),
			CIDR:              "192.168.4.0/24",
			AvailabilityZones: []string{"zone1"},
		}}}, {
		Name:       "empty",
		ProviderId: network.Id("---"),
		Subnets: []network.SubnetInfo{{
			ProviderId:        network.Id("5"),
			CIDR:              "192.168.5.0/24",
			AvailabilityZones: []string{"zone1"},
		}}}}
	expectedSpaceMap := make(map[string]network.SpaceInfo)
	for _, space := range expectedSpaces {
		expectedSpaceMap[space.Name] = space
	}
	for _, space := range spaces {
		expected, ok := expectedSpaceMap[space.Name()]
		if !c.Check(ok, jc.IsTrue) {
			continue
		}
		c.Check(space.ProviderId(), gc.Equals, expected.ProviderId)
		subnets, err := space.Subnets()
		if !c.Check(err, jc.ErrorIsNil) {
			continue
		}
		c.Check(len(subnets), gc.Equals, len(expected.Subnets))
		for i, subnet := range subnets {
			expectedSubnet := expected.Subnets[i]
			c.Check(subnet.ProviderId(), gc.Equals, expectedSubnet.ProviderId)
			c.Check([]string{subnet.AvailabilityZone()}, jc.DeepEquals, expectedSubnet.AvailabilityZones)
			c.Check(subnet.CIDR(), gc.Equals, expectedSubnet.CIDR)
		}
	}
	c.Assert(s.spacesDiscovered, jc.IsTrue)
}

func (s *workerSuite) TestWorkerIdempotent(c *gc.C) {
	dummy.SetSupportsSpaceDiscovery(true)
	s.startWorker()
	var err error
	var spaces []*state.Space
	for a := common.ShortAttempt.Start(); a.Next(); {
		spaces, err = s.State.AllSpaces()
		if err != nil {
			break
		}
		if len(spaces) == 4 {
			// All spaces have been created.
			break
		}
		if !a.HasNext() {
			c.Fatalf("spaces not imported")
		}
	}
	c.Assert(err, jc.ErrorIsNil)
	newWorker := discoverspaces.NewWorker(s.API, func() {})

	// This ensures that the worker can handle re-importing without error.
	defer func() {
		c.Assert(worker.Stop(newWorker), jc.ErrorIsNil)
	}()

	// Check that no extra spaces are imported.
	for a := common.ShortAttempt.Start(); a.Next(); {
		spaces, err = s.State.AllSpaces()
		if err != nil {
			break
		}
		if len(spaces) != 4 {
			c.Fatalf("unexpected number of spaces: %v", len(spaces))
		}
		if !a.HasNext() {
			break
		}
	}
}

func (s *workerSuite) TestSupportsSpaceDiscoveryBroken(c *gc.C) {
	s.AssertConfigParameterUpdated(c, "broken", "SupportsSpaceDiscovery")

	newWorker := discoverspaces.NewWorker(s.API, s.getSetSpacesDiscoveredFunc())
	err := worker.Stop(newWorker)
	c.Assert(err, gc.ErrorMatches, "dummy.SupportsSpaceDiscovery is broken")
	c.Assert(s.spacesDiscovered, jc.IsTrue)
}

func (s *workerSuite) TestSpacesBroken(c *gc.C) {
	dummy.SetSupportsSpaceDiscovery(true)
	s.AssertConfigParameterUpdated(c, "broken", "Spaces")

	newWorker := discoverspaces.NewWorker(s.API, s.getSetSpacesDiscoveredFunc())
	err := worker.Stop(newWorker)
	c.Assert(err, gc.ErrorMatches, "dummy.Spaces is broken")
	c.Assert(s.spacesDiscovered, jc.IsTrue)
}

func (s *workerSuite) TestWorkerIgnoresExistingSpacesAndSubnets(c *gc.C) {
	dummy.SetSupportsSpaceDiscovery(true)
	spaceTag := names.NewSpaceTag("foo")
	args := params.CreateSpacesParams{
		Spaces: []params.CreateSpaceParams{{
			Public:     false,
			SpaceTag:   spaceTag.String(),
			ProviderId: "foo",
		}}}
	result, err := s.API.CreateSpaces(args)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(result.Results, gc.HasLen, 1)
	c.Assert(result.Results[0].Error, gc.IsNil)

	subnetArgs := params.AddSubnetsParams{
		Subnets: []params.AddSubnetParams{{
			SubnetProviderId: "1",
			SpaceTag:         spaceTag.String(),
			Zones:            []string{"zone1"},
		}}}
	subnetResult, err := s.API.AddSubnets(subnetArgs)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(subnetResult.Results, gc.HasLen, 1)
	c.Assert(subnetResult.Results[0].Error, gc.IsNil)

	s.startWorker()
	for a := common.ShortAttempt.Start(); a.Next(); {
		spaces, err := s.State.AllSpaces()
		if err != nil {
			break
		}
		if len(spaces) == 4 {
			// All spaces have been created.
			break
		}
		if !a.HasNext() {
			c.Fatalf("spaces not imported")
		}
	}
	c.Assert(err, jc.ErrorIsNil)
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"errors"
	"fmt"
	"log"

	"github.com/satori/go.uuid"

)

type somaMonitoringRequest struct {
	action     string
	admin      bool
	user       string
	Monitoring proto.Monitoring
	reply      chan somaResult
}

type somaMonitoringResult struct {
	ResultError error
	Monitoring  proto.Monitoring
}

func (a *somaMonitoringResult) SomaAppendError(r *somaResult, err error) {
	if err != nil {
		r.Systems = append(r.Systems, somaMonitoringResult{ResultError: err})
	}
}

func (a *somaMonitoringResult) SomaAppendResult(r *somaResult) {
	r.Systems = append(r.Systems, *a)
}

/* Read Access
 */
type somaMonitoringReadHandler struct {
	input     chan somaMonitoringRequest
	shutdown  chan bool
	conn      *sql.DB
	list_stmt *sql.Stmt
	show_stmt *sql.Stmt
	scli_stmt *sql.Stmt
}

func (r *somaMonitoringReadHandler) run() {
	var err error

	if r.list_stmt, err = r.conn.Prepare(stmt.ListAllMonitoringSystems); err != nil {
		log.Fatal("monitoring/list: ", err)
	}
	defer r.list_stmt.Close()

	if r.show_stmt, err = r.conn.Prepare(stmt.ShowMonitoringSystem); err != nil {
		log.Fatal("monitoring/show: ", err)
	}
	defer r.show_stmt.Close()

	if r.scli_stmt, err = r.conn.Prepare(stmt.ListScopedMonitoringSystems); err != nil {
		log.Fatal("monitoring/scoped-list: ", err)
	}
	defer r.scli_stmt.Close()

runloop:
	for {
		select {
		case <-r.shutdown:
			break runloop
		case req := <-r.input:
			go func() {
				r.process(&req)
			}()
		}
	}
}

func (r *somaMonitoringReadHandler) process(q *somaMonitoringRequest) {
	var (
		id, name, mode, contact, team string
		rows                          *sql.Rows
		callback                      sql.NullString
		callbackString                string
		err                           error
	)
	result := somaResult{}

	switch q.action {
	case "list":
		if q.admin {
			log.Printf("R: monitorings/list")
			rows, err = r.list_stmt.Query()
		} else {
			log.Printf("R: monitorings/scoped-list for %s", q.user)
			rows, err = r.list_stmt.Query(q.user)
		}
		if result.SetRequestError(err) {
			q.reply <- result
			return
		}
		defer rows.Close()

		for rows.Next() {
			err := rows.Scan(
				&id,
				&name,
			)
			result.Append(err, &somaMonitoringResult{
				Monitoring: proto.Monitoring{
					Id:   id,
					Name: name,
				},
			})
		}
	case "show":
		log.Printf("R: monitoring/show for %s", q.Monitoring.Id)
		err = r.show_stmt.QueryRow(q.Monitoring.Id).Scan(
			&id,
			&name,
			&mode,
			&contact,
			&team,
			&callback,
		)
		if err != nil {
			if err == sql.ErrNoRows {
				result.SetNotFound()
			} else {
				_ = result.SetRequestError(err)
			}
			q.reply <- result
			return
		}

		if callback.Valid {
			callbackString = callback.String
		} else {
			callbackString = ""
		}
		result.Append(err, &somaMonitoringResult{
			Monitoring: proto.Monitoring{
				Id:       id,
				Name:     name,
				Mode:     mode,
				Contact:  contact,
				TeamId:   team,
				Callback: callbackString,
			},
		})
	default:
		result.SetNotImplemented()
	}
	q.reply <- result
}

/* Write Access
 */
type somaMonitoringWriteHandler struct {
	input    chan somaMonitoringRequest
	shutdown chan bool
	conn     *sql.DB
	add_stmt *sql.Stmt
	del_stmt *sql.Stmt
}

func (w *somaMonitoringWriteHandler) run() {
	var err error

	w.add_stmt, err = w.conn.Prepare(`
INSERT INTO soma.monitoring_systems (
	monitoring_id,
	monitoring_name,
	monitoring_system_mode,
	monitoring_contact,
	monitoring_owner_team,
	monitoring_callback_uri)
SELECT $1::uuid, $2::varchar, $3::varchar, $4::uuid, $5::uuid, $6::text
WHERE NOT EXISTS (
	SELECT monitoring_id
	FROM   soma.monitoring_systems
	WHERE  monitoring_id = $1::uuid
    OR     monitoring_name = $2::varchar);`)
	if err != nil {
		log.Fatal("monitoring/add: ", err)
	}
	defer w.add_stmt.Close()

	w.del_stmt, err = w.conn.Prepare(`
DELETE FROM soma.monitoring_systems
WHERE  monitoring_id = $1::uuid;`)
	if err != nil {
		log.Fatal("monitoring/delete: ", err)
	}
	defer w.del_stmt.Close()

runloop:
	for {
		select {
		case <-w.shutdown:
			break runloop
		case req := <-w.input:
			w.process(&req)
		}
	}
}

func (w *somaMonitoringWriteHandler) process(q *somaMonitoringRequest) {
	var (
		callback sql.NullString
		res      sql.Result
		err      error
	)
	result := somaResult{}

	switch q.action {
	case "add":
		log.Printf("R: monitoring/add for %s", q.Monitoring.Name)
		id := uuid.NewV4()
		if q.Monitoring.Callback == "" {
			callback = sql.NullString{
				String: "",
				Valid:  false,
			}
		} else {
			callback = sql.NullString{
				String: q.Monitoring.Callback,
				Valid:  true,
			}
		}
		res, err = w.add_stmt.Exec(
			id.String(),
			q.Monitoring.Name,
			q.Monitoring.Mode,
			q.Monitoring.Contact,
			q.Monitoring.TeamId,
			callback,
		)
		q.Monitoring.Id = id.String()
	case "delete":
		log.Printf("R: monitoring/delete for %s", q.Monitoring.Id)
		res, err = w.del_stmt.Exec(
			q.Monitoring.Id,
		)
	default:
		log.Printf("R: unimplemented monitorings/%s", q.action)
		result.SetNotImplemented()
		q.reply <- result
		return
	}
	if result.SetRequestError(err) {
		q.reply <- result
		return
	}

	rowCnt, _ := res.RowsAffected()
	switch {
	case rowCnt == 0:
		result.Append(errors.New("No rows affected"), &somaMonitoringResult{})
	case rowCnt > 1:
		result.Append(fmt.Errorf("Too many rows affected: %d", rowCnt),
			&somaMonitoringResult{})
	default:
		result.Append(nil, &somaMonitoringResult{
			Monitoring: q.Monitoring,
		})
	}
	q.reply <- result
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>FIX scoped monitoring lookup<commit_after>package main

import (
	"database/sql"
	"errors"
	"fmt"
	"log"

	"github.com/satori/go.uuid"

)

type somaMonitoringRequest struct {
	action     string
	admin      bool
	user       string
	Monitoring proto.Monitoring
	reply      chan somaResult
}

type somaMonitoringResult struct {
	ResultError error
	Monitoring  proto.Monitoring
}

func (a *somaMonitoringResult) SomaAppendError(r *somaResult, err error) {
	if err != nil {
		r.Systems = append(r.Systems, somaMonitoringResult{ResultError: err})
	}
}

func (a *somaMonitoringResult) SomaAppendResult(r *somaResult) {
	r.Systems = append(r.Systems, *a)
}

/* Read Access
 */
type somaMonitoringReadHandler struct {
	input     chan somaMonitoringRequest
	shutdown  chan bool
	conn      *sql.DB
	list_stmt *sql.Stmt
	show_stmt *sql.Stmt
	scli_stmt *sql.Stmt
}

func (r *somaMonitoringReadHandler) run() {
	var err error

	if r.list_stmt, err = r.conn.Prepare(stmt.ListAllMonitoringSystems); err != nil {
		log.Fatal("monitoring/list: ", err)
	}
	defer r.list_stmt.Close()

	if r.show_stmt, err = r.conn.Prepare(stmt.ShowMonitoringSystem); err != nil {
		log.Fatal("monitoring/show: ", err)
	}
	defer r.show_stmt.Close()

	if r.scli_stmt, err = r.conn.Prepare(stmt.ListScopedMonitoringSystems); err != nil {
		log.Fatal("monitoring/scoped-list: ", err)
	}
	defer r.scli_stmt.Close()

runloop:
	for {
		select {
		case <-r.shutdown:
			break runloop
		case req := <-r.input:
			go func() {
				r.process(&req)
			}()
		}
	}
}

func (r *somaMonitoringReadHandler) process(q *somaMonitoringRequest) {
	var (
		id, name, mode, contact, team string
		rows                          *sql.Rows
		callback                      sql.NullString
		callbackString                string
		err                           error
	)
	result := somaResult{}

	switch q.action {
	case "list":
		if q.admin {
			log.Printf("R: monitorings/list")
			rows, err = r.list_stmt.Query()
		} else {
			log.Printf("R: monitorings/scoped-list for %s", q.user)
			rows, err = r.scli_stmt.Query(q.user)
		}
		if result.SetRequestError(err) {
			q.reply <- result
			return
		}
		defer rows.Close()

		for rows.Next() {
			err := rows.Scan(
				&id,
				&name,
			)
			result.Append(err, &somaMonitoringResult{
				Monitoring: proto.Monitoring{
					Id:   id,
					Name: name,
				},
			})
		}
	case "show":
		log.Printf("R: monitoring/show for %s", q.Monitoring.Id)
		err = r.show_stmt.QueryRow(q.Monitoring.Id).Scan(
			&id,
			&name,
			&mode,
			&contact,
			&team,
			&callback,
		)
		if err != nil {
			if err == sql.ErrNoRows {
				result.SetNotFound()
			} else {
				_ = result.SetRequestError(err)
			}
			q.reply <- result
			return
		}

		if callback.Valid {
			callbackString = callback.String
		} else {
			callbackString = ""
		}
		result.Append(err, &somaMonitoringResult{
			Monitoring: proto.Monitoring{
				Id:       id,
				Name:     name,
				Mode:     mode,
				Contact:  contact,
				TeamId:   team,
				Callback: callbackString,
			},
		})
	default:
		result.SetNotImplemented()
	}
	q.reply <- result
}

/* Write Access
 */
type somaMonitoringWriteHandler struct {
	input    chan somaMonitoringRequest
	shutdown chan bool
	conn     *sql.DB
	add_stmt *sql.Stmt
	del_stmt *sql.Stmt
}

func (w *somaMonitoringWriteHandler) run() {
	var err error

	w.add_stmt, err = w.conn.Prepare(`
INSERT INTO soma.monitoring_systems (
	monitoring_id,
	monitoring_name,
	monitoring_system_mode,
	monitoring_contact,
	monitoring_owner_team,
	monitoring_callback_uri)
SELECT $1::uuid, $2::varchar, $3::varchar, $4::uuid, $5::uuid, $6::text
WHERE NOT EXISTS (
	SELECT monitoring_id
	FROM   soma.monitoring_systems
	WHERE  monitoring_id = $1::uuid
    OR     monitoring_name = $2::varchar);`)
	if err != nil {
		log.Fatal("monitoring/add: ", err)
	}
	defer w.add_stmt.Close()

	w.del_stmt, err = w.conn.Prepare(`
DELETE FROM soma.monitoring_systems
WHERE  monitoring_id = $1::uuid;`)
	if err != nil {
		log.Fatal("monitoring/delete: ", err)
	}
	defer w.del_stmt.Close()

runloop:
	for {
		select {
		case <-w.shutdown:
			break runloop
		case req := <-w.input:
			w.process(&req)
		}
	}
}

func (w *somaMonitoringWriteHandler) process(q *somaMonitoringRequest) {
	var (
		callback sql.NullString
		res      sql.Result
		err      error
	)
	result := somaResult{}

	switch q.action {
	case "add":
		log.Printf("R: monitoring/add for %s", q.Monitoring.Name)
		id := uuid.NewV4()
		if q.Monitoring.Callback == "" {
			callback = sql.NullString{
				String: "",
				Valid:  false,
			}
		} else {
			callback = sql.NullString{
				String: q.Monitoring.Callback,
				Valid:  true,
			}
		}
		res, err = w.add_stmt.Exec(
			id.String(),
			q.Monitoring.Name,
			q.Monitoring.Mode,
			q.Monitoring.Contact,
			q.Monitoring.TeamId,
			callback,
		)
		q.Monitoring.Id = id.String()
	case "delete":
		log.Printf("R: monitoring/delete for %s", q.Monitoring.Id)
		res, err = w.del_stmt.Exec(
			q.Monitoring.Id,
		)
	default:
		log.Printf("R: unimplemented monitorings/%s", q.action)
		result.SetNotImplemented()
		q.reply <- result
		return
	}
	if result.SetRequestError(err) {
		q.reply <- result
		return
	}

	rowCnt, _ := res.RowsAffected()
	switch {
	case rowCnt == 0:
		result.Append(errors.New("No rows affected"), &somaMonitoringResult{})
	case rowCnt > 1:
		result.Append(fmt.Errorf("Too many rows affected: %d", rowCnt),
			&somaMonitoringResult{})
	default:
		result.Append(nil, &somaMonitoringResult{
			Monitoring: q.Monitoring,
		})
	}
	q.reply <- result
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>


<commit_before>package websession

import (
	"github.com/kr/pretty"
	"golang.org/x/net/context"
	"net/http"
	"reflect"
	"testing"
	"zenhack.net/go/sandstorm/capnp/util"
	"zenhack.net/go/sandstorm/capnp/websession"
	"zenhack.net/go/sandstorm/websession/pogs"
	"zombiezen.com/go/capnproto2/pogs"
)

type testCase struct {
	name     string
	handler  http.Handler
	request  testRequest
	response websession_pogs.Response
}

type testRequest interface {
	Call(ctx context.Context, ws websession.WebSession) (websession_pogs.Response, error)
}

type GetHeadReq websession_pogs.Get_args

func (req GetHeadReq) Call(ctx context.Context, ws websession.WebSession) (websession_pogs.Response, error) {
	resp, err := ws.Get(ctx, func(p websession.WebSession_get_Params) error {
		return pogs.Insert(websession.WebSession_get_Params_TypeID, p.Struct, req)
	}).Struct()
	if err != nil {
		return websession_pogs.Response{}, err
	}
	goResp := websession_pogs.Response{}
	err = pogs.Extract(&goResp, websession.WebSession_Response_TypeID, resp.Struct)
	return goResp, err
}

var testCases = []testCase{
	{
		name: "Simple 200 OK",
		request: GetHeadReq{
			Path:       "/",
			IgnoreBody: false,
		},
		handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		}),
		response: websession_pogs.Response{
			Which: websession.WebSession_Response_Which_content,
			Content: websession_pogs.Response_content{
				StatusCode: websession.WebSession_Response_SuccessCode_ok,
				Body: websession_pogs.Response_content_body{
					Which:  websession.WebSession_Response_content_body_Which_stream,
					Stream: util.Handle_ServerToClient(struct{}{}),
				},
			},
		},
	},
}

func TestTable(t *testing.T) {
	for _, v := range testCases {
		ctx := context.TODO()
		handlerWS := websession.WebSession_ServerToClient(FromHandler(ctx, v.handler))
		resp, err := v.request.Call(ctx, handlerWS)
		if err != nil {
			t.Errorf("Error in v.reqeust.Call in table test case %q: %v",
				v.name, err)
			continue
		}
		if !responseEq(v.response, resp) {
			t.Errorf("Unexpected response in table test case %q", v.name)
			pretty.Ldiff(t, resp, v.response)
			continue
		}
	}
}

func responseEq(expected, actual websession_pogs.Response) bool {
	// reflect.DeepEqual does what we want for *most* of the data,
	// but not the interfaces. So, we set those to nil before the check,
	// then restore them.
	eStream := expected.Content.Body.Stream
	aStream := actual.Content.Body.Stream
	expected.Content.Body.Stream.Client = nil
	actual.Content.Body.Stream.Client = nil
	eq := reflect.DeepEqual(expected, actual)
	expected.Content.Body.Stream = eStream
	actual.Content.Body.Stream = aStream

	// either the clients should both be nil, or neither of them
	// should be.
	return eq && (eStream.Client == nil) == (aStream.Client == nil)
}
<commit_msg>Add a response stream.<commit_after>package websession

import (
	"bytes"
	"github.com/kr/pretty"
	"golang.org/x/net/context"
	"io"
	"net/http"
	"reflect"
	"testing"
	util_capnp "zenhack.net/go/sandstorm/capnp/util"
	"zenhack.net/go/sandstorm/capnp/websession"
	"zenhack.net/go/sandstorm/util"
	"zenhack.net/go/sandstorm/websession/pogs"
	"zombiezen.com/go/capnproto2/pogs"
)

type testCase struct {
	name     string
	handler  http.Handler
	request  testRequest
	response testResponse
}

type testRequest interface {
	Call(ctx context.Context, ws websession.WebSession) (testResponse, error)
}

type testResponse struct {
	resp       websession_pogs.Response
	streamBody []byte
}

type GetHeadReq websession_pogs.Get_args

func (req GetHeadReq) Call(ctx context.Context, ws websession.WebSession) (testResponse, error) {
	r, w := io.Pipe()
	buf := &bytes.Buffer{}
	done := make(chan struct{})
	go func() {
		io.Copy(buf, r)
		done <- struct{}{}
	}()
	req.Context.ResponseStream = util_capnp.ByteStream_ServerToClient(
		&util.WriteCloserByteStream{w},
	)
	resp, err := ws.Get(ctx, func(p websession.WebSession_get_Params) error {
		return pogs.Insert(websession.WebSession_get_Params_TypeID, p.Struct, req)
	}).Struct()
	if err != nil {
		return testResponse{}, err
	}
	goResp := testResponse{
		resp: websession_pogs.Response{},
	}
	err = pogs.Extract(&goResp.resp, websession.WebSession_Response_TypeID, resp.Struct)
	r.Close()
	<-done
	goResp.streamBody = buf.Bytes()
	return goResp, err
}

var testCases = []testCase{
	{
		name: "Simple 200 OK",
		request: GetHeadReq{
			Path:       "/",
			IgnoreBody: false,
		},
		handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		}),
		response: testResponse{
			resp: websession_pogs.Response{
				Which: websession.WebSession_Response_Which_content,
				Content: websession_pogs.Response_content{
					StatusCode: websession.WebSession_Response_SuccessCode_ok,
					Body: websession_pogs.Response_content_body{
						Which:  websession.WebSession_Response_content_body_Which_stream,
						Stream: util_capnp.Handle_ServerToClient(struct{}{}),
					},
				},
			},
			streamBody: []byte{},
		},
	},
}

func TestTable(t *testing.T) {
	for _, v := range testCases {
		ctx := context.TODO()
		handlerWS := websession.WebSession_ServerToClient(FromHandler(ctx, v.handler))
		resp, err := v.request.Call(ctx, handlerWS)
		if err != nil {
			t.Errorf("Error in v.reqeust.Call in table test case %q: %v",
				v.name, err)
			continue
		}
		if !responseEq(v.response, resp) {
			t.Errorf("Unexpected response in table test case %q", v.name)
			pretty.Ldiff(t, resp, v.response)
			continue
		}
	}
}

func responseEq(expected, actual testResponse) bool {
	// reflect.DeepEqual does what we want for *most* of the data,
	// but not the interfaces. So, we set those to nil before the check,
	// then restore them.
	eStream := &expected.resp.Content.Body.Stream
	aStream := &actual.resp.Content.Body.Stream
	eClient := eStream.Client
	aClient := aStream.Client
	eStream.Client = nil
	aStream.Client = nil
	defer func() {
		eStream.Client = eClient
		aStream.Client = aClient
	}()

	return reflect.DeepEqual(expected, actual) &&
		// either the clients should both be nil, or neither of them
		// should be:
		(eClient == nil) == (aClient == nil)
}
<|endoftext|>


<commit_before>package lz4_test

import (
	"bytes"
	"io"
	"io/ioutil"
	"testing"

	"github.com/pierrec/lz4/v4"
	"github.com/pierrec/lz4/v4/internal/lz4block"
)

func BenchmarkCompress(b *testing.B) {
	buf := make([]byte, len(pg1661))
	var c lz4.Compressor

	n, _ := c.CompressBlock(pg1661, buf)

	b.ReportAllocs()
	b.ResetTimer()
	b.ReportMetric(float64(n), "outbytes")

	for i := 0; i < b.N; i++ {
		_, _ = c.CompressBlock(pg1661, buf)
	}
}

func BenchmarkCompressRandom(b *testing.B) {
	buf := make([]byte, len(randomLZ4))
	var c lz4.Compressor

	n, _ := c.CompressBlock(pg1661, buf)

	b.ReportAllocs()
	b.SetBytes(int64(len(random)))
	b.ResetTimer()
	b.ReportMetric(float64(n), "outbytes")

	for i := 0; i < b.N; i++ {
		_, _ = c.CompressBlock(random, buf)
	}
}

func BenchmarkCompressHC(b *testing.B) {
	buf := make([]byte, len(pg1661))
	c := lz4.CompressorHC{Level: 16}

	n, _ := c.CompressBlock(pg1661, buf)

	b.ReportAllocs()
	b.ResetTimer()
	b.ReportMetric(float64(n), "outbytes")

	for i := 0; i < b.N; i++ {
		_, _ = c.CompressBlock(pg1661, buf)
	}
}

func BenchmarkUncompress(b *testing.B) {
	buf := make([]byte, len(pg1661))

	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_, _ = lz4block.UncompressBlock(pg1661LZ4, buf, nil)
	}
}

func mustLoadFile(f string) []byte {
	b, err := ioutil.ReadFile(f)
	if err != nil {
		panic(err)
	}
	return b
}

var (
	pg1661    = mustLoadFile("testdata/pg1661.txt")
	digits    = mustLoadFile("testdata/e.txt")
	twain     = mustLoadFile("testdata/Mark.Twain-Tom.Sawyer.txt")
	random    = mustLoadFile("testdata/random.data")
	pg1661LZ4 = mustLoadFile("testdata/pg1661.txt.lz4")
	digitsLZ4 = mustLoadFile("testdata/e.txt.lz4")
	twainLZ4  = mustLoadFile("testdata/Mark.Twain-Tom.Sawyer.txt.lz4")
	randomLZ4 = mustLoadFile("testdata/random.data.lz4")
)

func benchmarkUncompress(b *testing.B, compressed []byte) {
	r := bytes.NewReader(compressed)
	zr := lz4.NewReader(r)

	// Decompress once to determine the uncompressed size of testfile.
	_, err := io.Copy(ioutil.Discard, zr)
	if err != nil {
		b.Fatal(err)
	}

	b.SetBytes(int64(len(compressed)))
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		r.Reset(compressed)
		zr.Reset(r)
		_, _ = io.Copy(ioutil.Discard, zr)
	}
}

func BenchmarkUncompressPg1661(b *testing.B) { benchmarkUncompress(b, pg1661LZ4) }
func BenchmarkUncompressDigits(b *testing.B) { benchmarkUncompress(b, digitsLZ4) }
func BenchmarkUncompressTwain(b *testing.B)  { benchmarkUncompress(b, twainLZ4) }
func BenchmarkUncompressRand(b *testing.B)   { benchmarkUncompress(b, randomLZ4) }

func benchmarkCompress(b *testing.B, uncompressed []byte) {
	w := bytes.NewBuffer(nil)
	zw := lz4.NewWriter(w)
	r := bytes.NewReader(uncompressed)

	// Compress once to determine the compressed size of testfile.
	_, err := io.Copy(zw, r)
	if err != nil {
		b.Fatal(err)
	}
	if err := zw.Close(); err != nil {
		b.Fatal(err)
	}

	b.SetBytes(int64(len(uncompressed)))
	b.ReportAllocs()
	b.ResetTimer()
	b.ReportMetric(float64(w.Len()), "outbytes")

	for i := 0; i < b.N; i++ {
		r.Reset(uncompressed)
		zw.Reset(w)
		_, _ = io.Copy(zw, r)
	}
}

func BenchmarkCompressPg1661(b *testing.B) { benchmarkCompress(b, pg1661) }
func BenchmarkCompressDigits(b *testing.B) { benchmarkCompress(b, digits) }
func BenchmarkCompressTwain(b *testing.B)  { benchmarkCompress(b, twain) }
func BenchmarkCompressRand(b *testing.B)   { benchmarkCompress(b, random) }

// Benchmark to check reallocations upon Reset().
// See issue https://github.com/pierrec/lz4/issues/52.
func BenchmarkWriterReset(b *testing.B) {
	b.ReportAllocs()

	zw := lz4.NewWriter(nil)
	src := mustLoadFile("testdata/gettysburg.txt")
	var buf bytes.Buffer

	for n := 0; n < b.N; n++ {
		buf.Reset()
		zw.Reset(&buf)

		_, _ = zw.Write(src)
		_ = zw.Close()
	}
}
<commit_msg>Fix BenchmarkCompressRandom<commit_after>package lz4_test

import (
	"bytes"
	"io"
	"io/ioutil"
	"testing"

	"github.com/pierrec/lz4/v4"
	"github.com/pierrec/lz4/v4/internal/lz4block"
)

func BenchmarkCompress(b *testing.B) {
	buf := make([]byte, len(pg1661))
	var c lz4.Compressor

	n, _ := c.CompressBlock(pg1661, buf)

	b.ReportAllocs()
	b.ResetTimer()
	b.ReportMetric(float64(n), "outbytes")

	for i := 0; i < b.N; i++ {
		_, _ = c.CompressBlock(pg1661, buf)
	}
}

func BenchmarkCompressRandom(b *testing.B) {
	buf := make([]byte, lz4.CompressBlockBound(len(random)))
	var c lz4.Compressor

	n, _ := c.CompressBlock(random, buf)

	b.ReportAllocs()
	b.SetBytes(int64(len(random)))
	b.ResetTimer()
	b.ReportMetric(float64(n), "outbytes")

	for i := 0; i < b.N; i++ {
		_, _ = c.CompressBlock(random, buf)
	}
}

func BenchmarkCompressHC(b *testing.B) {
	buf := make([]byte, len(pg1661))
	c := lz4.CompressorHC{Level: 16}

	n, _ := c.CompressBlock(pg1661, buf)

	b.ReportAllocs()
	b.ResetTimer()
	b.ReportMetric(float64(n), "outbytes")

	for i := 0; i < b.N; i++ {
		_, _ = c.CompressBlock(pg1661, buf)
	}
}

func BenchmarkUncompress(b *testing.B) {
	buf := make([]byte, len(pg1661))

	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_, _ = lz4block.UncompressBlock(pg1661LZ4, buf, nil)
	}
}

func mustLoadFile(f string) []byte {
	b, err := ioutil.ReadFile(f)
	if err != nil {
		panic(err)
	}
	return b
}

var (
	pg1661    = mustLoadFile("testdata/pg1661.txt")
	digits    = mustLoadFile("testdata/e.txt")
	twain     = mustLoadFile("testdata/Mark.Twain-Tom.Sawyer.txt")
	random    = mustLoadFile("testdata/random.data")
	pg1661LZ4 = mustLoadFile("testdata/pg1661.txt.lz4")
	digitsLZ4 = mustLoadFile("testdata/e.txt.lz4")
	twainLZ4  = mustLoadFile("testdata/Mark.Twain-Tom.Sawyer.txt.lz4")
	randomLZ4 = mustLoadFile("testdata/random.data.lz4")
)

func benchmarkUncompress(b *testing.B, compressed []byte) {
	r := bytes.NewReader(compressed)
	zr := lz4.NewReader(r)

	// Decompress once to determine the uncompressed size of testfile.
	_, err := io.Copy(ioutil.Discard, zr)
	if err != nil {
		b.Fatal(err)
	}

	b.SetBytes(int64(len(compressed)))
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		r.Reset(compressed)
		zr.Reset(r)
		_, _ = io.Copy(ioutil.Discard, zr)
	}
}

func BenchmarkUncompressPg1661(b *testing.B) { benchmarkUncompress(b, pg1661LZ4) }
func BenchmarkUncompressDigits(b *testing.B) { benchmarkUncompress(b, digitsLZ4) }
func BenchmarkUncompressTwain(b *testing.B)  { benchmarkUncompress(b, twainLZ4) }
func BenchmarkUncompressRand(b *testing.B)   { benchmarkUncompress(b, randomLZ4) }

func benchmarkCompress(b *testing.B, uncompressed []byte) {
	w := bytes.NewBuffer(nil)
	zw := lz4.NewWriter(w)
	r := bytes.NewReader(uncompressed)

	// Compress once to determine the compressed size of testfile.
	_, err := io.Copy(zw, r)
	if err != nil {
		b.Fatal(err)
	}
	if err := zw.Close(); err != nil {
		b.Fatal(err)
	}

	b.SetBytes(int64(len(uncompressed)))
	b.ReportAllocs()
	b.ResetTimer()
	b.ReportMetric(float64(w.Len()), "outbytes")

	for i := 0; i < b.N; i++ {
		r.Reset(uncompressed)
		zw.Reset(w)
		_, _ = io.Copy(zw, r)
	}
}

func BenchmarkCompressPg1661(b *testing.B) { benchmarkCompress(b, pg1661) }
func BenchmarkCompressDigits(b *testing.B) { benchmarkCompress(b, digits) }
func BenchmarkCompressTwain(b *testing.B)  { benchmarkCompress(b, twain) }
func BenchmarkCompressRand(b *testing.B)   { benchmarkCompress(b, random) }

// Benchmark to check reallocations upon Reset().
// See issue https://github.com/pierrec/lz4/issues/52.
func BenchmarkWriterReset(b *testing.B) {
	b.ReportAllocs()

	zw := lz4.NewWriter(nil)
	src := mustLoadFile("testdata/gettysburg.txt")
	var buf bytes.Buffer

	for n := 0; n < b.N; n++ {
		buf.Reset()
		zw.Reset(&buf)

		_, _ = zw.Write(src)
		_ = zw.Close()
	}
}
<|endoftext|>


<commit_before>package translatedassert

import "testing"

type UnaryExample struct {
	x        interface{}
	expected interface{}
}

func TestUnaryOpADD(t *testing.T) {
	tests := []UnaryExample{
		{1, 1},
		{uint8(1), uint8(1)},
		{uint16(1), uint16(1)},
		{uint32(1), uint32(1)},
		{uint64(1), uint64(1)},
		{int8(1), int8(1)},
		{int16(1), int16(1)},
		{int32(1), int32(1)},
		{int64(1), int64(1)},
		{float32(1), float32(1)},
		{float64(1), float64(1)},
		{complex(1, 0), complex(1, 0)},
		{complex64(complex(1, 0)), complex64(complex(1, 0))},
	}

	for _, test := range tests {
		got := UnaryOpADD(test.x)
		if !eq(test.expected, got) {
			t.Errorf(`UnaryOpADD(%v) = %v, but got %v`, test.x, test.expected, got)
		}
	}
}

func TestUnaryOpSUB(t *testing.T) {
	var u uint = 1
	var u8 uint8 = 1
	var u16 uint16 = 1
	var u32 uint32 = 1
	var u64 uint64 = 1
	tests := []UnaryExample{
		{1, -1},
		{int8(1), -int8(1)},
		{int16(1), -int16(1)},
		{int32(1), -int32(1)},
		{int64(1), -int64(1)},
		{u, -u},
		{u8, -u8},
		{u16, -u16},
		{u32, -u32},
		{u64, -u64},
		{float32(1), -float32(1)},
		{float64(1), -float64(1)},
		{complex(1, 0), -complex(1, 0)},
		{complex64(complex(1, 0)), -complex64(complex(1, 0))},
	}

	for _, test := range tests {
		got := UnaryOpSUB(test.x)
		if !eq(test.expected, got) {
			t.Errorf(`UnaryOpSUB(%v) = %v, but got %v`, test.x, test.expected, got)
		}
	}
}

func TestUnaryOpNOT(t *testing.T) {
	tests := []UnaryExample{
		{true, false},
		{false, true},
	}

	for _, test := range tests {
		got := UnaryOpNOT(test.x)
		if !eq(test.expected, got) {
			t.Errorf(`UnaryOpNOT(%v) = %v, but got %v`, test.x, test.expected, got)
		}
	}
}

func TestUnaryOpXOR(t *testing.T) {
	tests := []UnaryExample{
		{-1, ^-1},
		{0, ^0},
		{1, ^1},
		{uint(1), ^uint(1)},
		{uint8(1), ^uint8(1)},
		{uint16(1), ^uint16(1)},
		{uint32(1), ^uint32(1)},
		{uint64(1), ^uint64(1)},
		{int8(1), ^int8(1)},
		{int16(1), ^int16(1)},
		{int32(1), ^int32(1)},
		{int64(1), ^int64(1)},
	}

	for _, test := range tests {
		got := UnaryOpXOR(test.x)
		if !eq(test.expected, got) {
			t.Errorf(`UnaryOpXOR(%v) = %v, but got %v`, test.x, test.expected, got)
		}
	}
}
<commit_msg>add uint test for translatedassert/unary_op.go<commit_after>package translatedassert

import "testing"

type UnaryExample struct {
	x        interface{}
	expected interface{}
}

func TestUnaryOpADD(t *testing.T) {
	tests := []UnaryExample{
		{1, 1},
		{uint(1), uint(1)},
		{uint8(1), uint8(1)},
		{uint16(1), uint16(1)},
		{uint32(1), uint32(1)},
		{uint64(1), uint64(1)},
		{int8(1), int8(1)},
		{int16(1), int16(1)},
		{int32(1), int32(1)},
		{int64(1), int64(1)},
		{float32(1), float32(1)},
		{float64(1), float64(1)},
		{complex(1, 0), complex(1, 0)},
		{complex64(complex(1, 0)), complex64(complex(1, 0))},
	}

	for _, test := range tests {
		got := UnaryOpADD(test.x)
		if !eq(test.expected, got) {
			t.Errorf(`UnaryOpADD(%v) = %v, but got %v`, test.x, test.expected, got)
		}
	}
}

func TestUnaryOpSUB(t *testing.T) {
	var u uint = 1
	var u8 uint8 = 1
	var u16 uint16 = 1
	var u32 uint32 = 1
	var u64 uint64 = 1
	tests := []UnaryExample{
		{1, -1},
		{int8(1), -int8(1)},
		{int16(1), -int16(1)},
		{int32(1), -int32(1)},
		{int64(1), -int64(1)},
		{u, -u},
		{u8, -u8},
		{u16, -u16},
		{u32, -u32},
		{u64, -u64},
		{float32(1), -float32(1)},
		{float64(1), -float64(1)},
		{complex(1, 0), -complex(1, 0)},
		{complex64(complex(1, 0)), -complex64(complex(1, 0))},
	}

	for _, test := range tests {
		got := UnaryOpSUB(test.x)
		if !eq(test.expected, got) {
			t.Errorf(`UnaryOpSUB(%v) = %v, but got %v`, test.x, test.expected, got)
		}
	}
}

func TestUnaryOpNOT(t *testing.T) {
	tests := []UnaryExample{
		{true, false},
		{false, true},
	}

	for _, test := range tests {
		got := UnaryOpNOT(test.x)
		if !eq(test.expected, got) {
			t.Errorf(`UnaryOpNOT(%v) = %v, but got %v`, test.x, test.expected, got)
		}
	}
}

func TestUnaryOpXOR(t *testing.T) {
	tests := []UnaryExample{
		{-1, ^-1},
		{0, ^0},
		{1, ^1},
		{uint(1), ^uint(1)},
		{uint8(1), ^uint8(1)},
		{uint16(1), ^uint16(1)},
		{uint32(1), ^uint32(1)},
		{uint64(1), ^uint64(1)},
		{int8(1), ^int8(1)},
		{int16(1), ^int16(1)},
		{int32(1), ^int32(1)},
		{int64(1), ^int64(1)},
	}

	for _, test := range tests {
		got := UnaryOpXOR(test.x)
		if !eq(test.expected, got) {
			t.Errorf(`UnaryOpXOR(%v) = %v, but got %v`, test.x, test.expected, got)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package proggen

import (
	"bytes"
	"github.com/google/syzkaller/prog"
	"github.com/google/syzkaller/tools/syz-trace2syz/parser"
	"strconv"
	"unicode"
)

var discriminatorArgs = map[string][]int{
	"bpf":         {0},
	"fcntl":       {1},
	"ioprio_get":  {0},
	"socket":      {0, 1, 2},
	"socketpair":  {0, 1, 2},
	"ioctl":       {0, 1},
	"getsockopt":  {1, 2},
	"setsockopt":  {1, 2},
	"accept":      {0},
	"accept4":     {0},
	"bind":        {0},
	"connect":     {0},
	"recvfrom":    {0},
	"sendto":      {0},
	"sendmsg":     {0},
	"getsockname": {0},
	"openat":      {1},
}

var openDiscriminatorArgs = map[string]int{
	"open":         0,
	"openat":       1,
	"syz_open_dev": 0,
}

type callSelector interface {
	Select(call *parser.Syscall) *prog.Syscall
}

func newSelectors(target *prog.Target, returnCache returnCache) []callSelector {
	sc := newSelectorCommon(target, returnCache)
	return []callSelector{
		&defaultCallSelector{sc},
		&openCallSelector{sc},
	}
}

type selectorCommon struct {
	target      *prog.Target
	returnCache returnCache
	callCache   map[string][]*prog.Syscall
}

func newSelectorCommon(target *prog.Target, returnCache returnCache) *selectorCommon {
	return &selectorCommon{
		target:      target,
		returnCache: returnCache,
		callCache:   make(map[string][]*prog.Syscall),
	}
}

// matches strace file string with a constant string in openat or syz_open_dev
// if the string in openat or syz_open_dev has a # then this method will
// return the corresponding  id from the strace string
func (cs *selectorCommon) matchFilename(syzFile, straceFile []byte) (bool, int) {
	syzFile = bytes.Trim(syzFile, "\x00")
	straceFile = bytes.Trim(straceFile, "\x00")
	if len(syzFile) != len(straceFile) {
		return false, -1
	}
	var id []byte
	dev := -1
	for i, c := range syzFile {
		x := straceFile[i]
		if c == x {
			continue
		}
		if c != '#' || !unicode.IsDigit(rune(x)) {
			return false, -1
		}
		id = append(id, x)
	}
	if len(id) > 0 {
		dev, _ = strconv.Atoi(string(id))
	}
	return true, dev
}

// callSet returns all syscalls with the given name.
func (cs *selectorCommon) callSet(callName string) []*prog.Syscall {
	calls, ok := cs.callCache[callName]
	if ok {
		return calls
	}
	for _, call := range cs.target.Syscalls {
		if call.CallName == callName {
			calls = append(calls, call)
		}
	}
	cs.callCache[callName] = calls
	return calls
}

type openCallSelector struct {
	*selectorCommon
}

// Select returns the best matching descrimination for this syscall.
func (cs *openCallSelector) Select(call *parser.Syscall) *prog.Syscall {
	if _, ok := openDiscriminatorArgs[call.CallName]; !ok {
		return nil
	}
	for callName := range openDiscriminatorArgs {
		for _, variant := range cs.callSet(callName) {
			match, devID := cs.matchOpen(variant, call)
			if !match {
				continue
			}
			if call.CallName == "open" && callName == "openat" {
				cwd := parser.Constant(cs.target.ConstMap["AT_FDCWD"])
				call.Args = append([]parser.IrType{cwd}, call.Args...)
				return variant
			}
			if match && call.CallName == "open" && callName == "syz_open_dev" {
				if devID < 0 {
					return variant
				}
				args := []parser.IrType{call.Args[0], parser.Constant(uint64(devID))}
				call.Args = append(args, call.Args[1:]...)
				return variant
			}
		}
	}
	return nil
}

func (cs *openCallSelector) matchOpen(meta *prog.Syscall, call *parser.Syscall) (bool, int) {
	straceFileArg := call.Args[openDiscriminatorArgs[call.CallName]]
	straceBuf := straceFileArg.(*parser.BufferType).Val
	syzFileArg := meta.Args[openDiscriminatorArgs[meta.CallName]].Type
	if _, ok := syzFileArg.(*prog.PtrType); !ok {
		return false, -1
	}
	syzBuf := syzFileArg.(*prog.PtrType).Elem.(*prog.BufferType)
	if syzBuf.Kind != prog.BufferString {
		return false, -1
	}
	for _, val := range syzBuf.Values {
		match, devID := cs.matchFilename([]byte(val), []byte(straceBuf))
		if match {
			return match, devID
		}
	}
	return false, -1
}

type defaultCallSelector struct {
	*selectorCommon
}

// Select returns the best matching descrimination for this syscall.
func (cs *defaultCallSelector) Select(call *parser.Syscall) *prog.Syscall {
	var match *prog.Syscall
	discriminators := discriminatorArgs[call.CallName]
	if len(discriminators) == 0 {
		return nil
	}
	score := 0
	for _, meta := range cs.callSet(call.CallName) {
		if score1 := cs.matchCall(meta, call, discriminators); score1 > score {
			match, score = meta, score1
		}
	}
	return match
}

// matchCall returns match score between meta and call.
// Higher score means better match, -1 if they are not matching at all.
func (cs *defaultCallSelector) matchCall(meta *prog.Syscall, call *parser.Syscall, discriminators []int) int {
	score := 0
	for _, i := range discriminators {
		if i >= len(meta.Args) || i >= len(call.Args) {
			return -1
		}
		typ := meta.Args[i].Type
		arg := call.Args[i]
		switch t := typ.(type) {
		case *prog.ConstType:
			// Consts must match precisely.
			constant, ok := arg.(parser.Constant)
			if !ok || constant.Val() != t.Val {
				return -1
			}
			score += 10
		case *prog.FlagsType:
			// Flags may or may not match, but matched flags increase score.
			constant, ok := arg.(parser.Constant)
			if !ok {
				return -1
			}
			val := constant.Val()
			for _, v := range t.Vals {
				if v == val {
					score++
					break
				}
			}
		case *prog.ResourceType:
			// Resources must match one of subtypes,
			// the more precise match, the higher the score.
			retArg := cs.returnCache.get(t, arg)
			if retArg == nil {
				return -1
			}
			matched := false
			for i, kind := range retArg.Type().(*prog.ResourceType).Desc.Kind {
				if kind == t.Desc.Name {
					score += i + 1
					matched = true
					break
				}
			}
			if !matched {
				return -1
			}
		case *prog.PtrType:
			switch r := t.Elem.(type) {
			case *prog.BufferType:
				matched := false
				buffer, ok := arg.(*parser.BufferType)
				if !ok {
					return -1
				}
				if r.Kind != prog.BufferString {
					return -1
				}
				for _, val := range r.Values {
					matched, _ = cs.matchFilename([]byte(val), []byte(buffer.Val))
					if matched {
						score++
						break
					}
				}
				if !matched {
					return -1
				}
			}
		}
	}
	return score
}
<commit_msg>tools/syz-trace2syz: fix a panic in tests<commit_after>// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package proggen

import (
	"bytes"
	"github.com/google/syzkaller/prog"
	"github.com/google/syzkaller/tools/syz-trace2syz/parser"
	"strconv"
	"unicode"
)

var discriminatorArgs = map[string][]int{
	"bpf":         {0},
	"fcntl":       {1},
	"ioprio_get":  {0},
	"socket":      {0, 1, 2},
	"socketpair":  {0, 1, 2},
	"ioctl":       {0, 1},
	"getsockopt":  {1, 2},
	"setsockopt":  {1, 2},
	"accept":      {0},
	"accept4":     {0},
	"bind":        {0},
	"connect":     {0},
	"recvfrom":    {0},
	"sendto":      {0},
	"sendmsg":     {0},
	"getsockname": {0},
	"openat":      {1},
}

var openDiscriminatorArgs = map[string]int{
	"open":         0,
	"openat":       1,
	"syz_open_dev": 0,
}

type callSelector interface {
	Select(call *parser.Syscall) *prog.Syscall
}

func newSelectors(target *prog.Target, returnCache returnCache) []callSelector {
	sc := newSelectorCommon(target, returnCache)
	return []callSelector{
		&defaultCallSelector{sc},
		&openCallSelector{sc},
	}
}

type selectorCommon struct {
	target      *prog.Target
	returnCache returnCache
	callCache   map[string][]*prog.Syscall
}

func newSelectorCommon(target *prog.Target, returnCache returnCache) *selectorCommon {
	return &selectorCommon{
		target:      target,
		returnCache: returnCache,
		callCache:   make(map[string][]*prog.Syscall),
	}
}

// matches strace file string with a constant string in openat or syz_open_dev
// if the string in openat or syz_open_dev has a # then this method will
// return the corresponding  id from the strace string
func (cs *selectorCommon) matchFilename(syzFile, straceFile []byte) (bool, int) {
	syzFile = bytes.Trim(syzFile, "\x00")
	straceFile = bytes.Trim(straceFile, "\x00")
	if len(syzFile) != len(straceFile) {
		return false, -1
	}
	var id []byte
	dev := -1
	for i, c := range syzFile {
		x := straceFile[i]
		if c == x {
			continue
		}
		if c != '#' || !unicode.IsDigit(rune(x)) {
			return false, -1
		}
		id = append(id, x)
	}
	if len(id) > 0 {
		dev, _ = strconv.Atoi(string(id))
	}
	return true, dev
}

// callSet returns all syscalls with the given name.
func (cs *selectorCommon) callSet(callName string) []*prog.Syscall {
	calls, ok := cs.callCache[callName]
	if ok {
		return calls
	}
	for _, call := range cs.target.Syscalls {
		if call.CallName == callName {
			calls = append(calls, call)
		}
	}
	cs.callCache[callName] = calls
	return calls
}

type openCallSelector struct {
	*selectorCommon
}

// Select returns the best matching descrimination for this syscall.
func (cs *openCallSelector) Select(call *parser.Syscall) *prog.Syscall {
	if _, ok := openDiscriminatorArgs[call.CallName]; !ok {
		return nil
	}
	for callName := range openDiscriminatorArgs {
		for _, variant := range cs.callSet(callName) {
			match, devID := cs.matchOpen(variant, call)
			if !match {
				continue
			}
			if call.CallName == "open" && callName == "openat" {
				cwd := parser.Constant(cs.target.ConstMap["AT_FDCWD"])
				call.Args = append([]parser.IrType{cwd}, call.Args...)
				return variant
			}
			if match && call.CallName == "open" && callName == "syz_open_dev" {
				if devID < 0 {
					return variant
				}
				args := []parser.IrType{call.Args[0], parser.Constant(uint64(devID))}
				call.Args = append(args, call.Args[1:]...)
				return variant
			}
		}
	}
	return nil
}

func (cs *openCallSelector) matchOpen(meta *prog.Syscall, call *parser.Syscall) (bool, int) {
	straceFileArg := call.Args[openDiscriminatorArgs[call.CallName]]
	straceBuf := straceFileArg.(*parser.BufferType).Val
	syzFileArg := meta.Args[openDiscriminatorArgs[meta.CallName]].Type
	if _, ok := syzFileArg.(*prog.PtrType); !ok {
		return false, -1
	}
	syzBuf, ok := syzFileArg.(*prog.PtrType).Elem.(*prog.BufferType)
	if !ok {
		return false, -1
	}
	if syzBuf.Kind != prog.BufferString {
		return false, -1
	}
	for _, val := range syzBuf.Values {
		match, devID := cs.matchFilename([]byte(val), []byte(straceBuf))
		if match {
			return match, devID
		}
	}
	return false, -1
}

type defaultCallSelector struct {
	*selectorCommon
}

// Select returns the best matching descrimination for this syscall.
func (cs *defaultCallSelector) Select(call *parser.Syscall) *prog.Syscall {
	var match *prog.Syscall
	discriminators := discriminatorArgs[call.CallName]
	if len(discriminators) == 0 {
		return nil
	}
	score := 0
	for _, meta := range cs.callSet(call.CallName) {
		if score1 := cs.matchCall(meta, call, discriminators); score1 > score {
			match, score = meta, score1
		}
	}
	return match
}

// matchCall returns match score between meta and call.
// Higher score means better match, -1 if they are not matching at all.
func (cs *defaultCallSelector) matchCall(meta *prog.Syscall, call *parser.Syscall, discriminators []int) int {
	score := 0
	for _, i := range discriminators {
		if i >= len(meta.Args) || i >= len(call.Args) {
			return -1
		}
		typ := meta.Args[i].Type
		arg := call.Args[i]
		switch t := typ.(type) {
		case *prog.ConstType:
			// Consts must match precisely.
			constant, ok := arg.(parser.Constant)
			if !ok || constant.Val() != t.Val {
				return -1
			}
			score += 10
		case *prog.FlagsType:
			// Flags may or may not match, but matched flags increase score.
			constant, ok := arg.(parser.Constant)
			if !ok {
				return -1
			}
			val := constant.Val()
			for _, v := range t.Vals {
				if v == val {
					score++
					break
				}
			}
		case *prog.ResourceType:
			// Resources must match one of subtypes,
			// the more precise match, the higher the score.
			retArg := cs.returnCache.get(t, arg)
			if retArg == nil {
				return -1
			}
			matched := false
			for i, kind := range retArg.Type().(*prog.ResourceType).Desc.Kind {
				if kind == t.Desc.Name {
					score += i + 1
					matched = true
					break
				}
			}
			if !matched {
				return -1
			}
		case *prog.PtrType:
			switch r := t.Elem.(type) {
			case *prog.BufferType:
				matched := false
				buffer, ok := arg.(*parser.BufferType)
				if !ok {
					return -1
				}
				if r.Kind != prog.BufferString {
					return -1
				}
				for _, val := range r.Values {
					matched, _ = cs.matchFilename([]byte(val), []byte(buffer.Val))
					if matched {
						score++
						break
					}
				}
				if !matched {
					return -1
				}
			}
		}
	}
	return score
}
<|endoftext|>


<commit_before>package trust

import (
	"fmt"
	"testing"

	"github.com/docker/cli/e2e/internal/fixtures"
	"github.com/docker/cli/internal/test/environment"
	"gotest.tools/assert"
	is "gotest.tools/assert/cmp"
	"gotest.tools/fs"
	"gotest.tools/icmd"
	"gotest.tools/skip"
)

const (
	localImage = "registry:5000/signlocal:v1"
	signImage  = "registry:5000/sign:v1"
)

func TestSignLocalImage(t *testing.T) {
	skip.If(t, environment.RemoteDaemon())

	dir := fixtures.SetupConfigFile(t)
	defer dir.Remove()
	icmd.RunCmd(icmd.Command("docker", "pull", fixtures.AlpineImage)).Assert(t, icmd.Success)
	icmd.RunCommand("docker", "tag", fixtures.AlpineImage, signImage).Assert(t, icmd.Success)
	result := icmd.RunCmd(
		icmd.Command("docker", "trust", "sign", signImage),
		fixtures.WithPassphrase("root_password", "repo_password"),
		fixtures.WithConfig(dir.Path()), fixtures.WithNotary)
	result.Assert(t, icmd.Success)
	assert.Check(t, is.Contains(result.Stdout(), fmt.Sprintf("v1: digest: sha256:%s", fixtures.AlpineSha)))

}

func TestSignWithLocalFlag(t *testing.T) {
	skip.If(t, environment.RemoteDaemon())

	dir := fixtures.SetupConfigFile(t)
	defer dir.Remove()
	setupTrustedImageForOverwrite(t, dir)
	result := icmd.RunCmd(
		icmd.Command("docker", "trust", "sign", "--local", localImage),
		fixtures.WithPassphrase("root_password", "repo_password"),
		fixtures.WithConfig(dir.Path()), fixtures.WithNotary)
	result.Assert(t, icmd.Success)
	assert.Check(t, is.Contains(result.Stdout(), fmt.Sprintf("v1: digest: sha256:%s", fixtures.BusyboxSha)))
}

func setupTrustedImageForOverwrite(t *testing.T, dir fs.Dir) {
	icmd.RunCmd(icmd.Command("docker", "pull", fixtures.AlpineImage)).Assert(t, icmd.Success)
	icmd.RunCommand("docker", "tag", fixtures.AlpineImage, localImage).Assert(t, icmd.Success)
	result := icmd.RunCmd(
		icmd.Command("docker", "-D", "trust", "sign", localImage),
		fixtures.WithPassphrase("root_password", "repo_password"),
		fixtures.WithConfig(dir.Path()), fixtures.WithNotary)
	result.Assert(t, icmd.Success)
	assert.Check(t, is.Contains(result.Stdout(), fmt.Sprintf("v1: digest: sha256:%s", fixtures.AlpineSha)))
	icmd.RunCmd(icmd.Command("docker", "pull", fixtures.BusyboxImage)).Assert(t, icmd.Success)
	icmd.RunCommand("docker", "tag", fixtures.BusyboxImage, localImage).Assert(t, icmd.Success)
}
<commit_msg>e2e: remove unnecessary trailing newline (whitespace)<commit_after>package trust

import (
	"fmt"
	"testing"

	"github.com/docker/cli/e2e/internal/fixtures"
	"github.com/docker/cli/internal/test/environment"
	"gotest.tools/assert"
	is "gotest.tools/assert/cmp"
	"gotest.tools/fs"
	"gotest.tools/icmd"
	"gotest.tools/skip"
)

const (
	localImage = "registry:5000/signlocal:v1"
	signImage  = "registry:5000/sign:v1"
)

func TestSignLocalImage(t *testing.T) {
	skip.If(t, environment.RemoteDaemon())

	dir := fixtures.SetupConfigFile(t)
	defer dir.Remove()
	icmd.RunCmd(icmd.Command("docker", "pull", fixtures.AlpineImage)).Assert(t, icmd.Success)
	icmd.RunCommand("docker", "tag", fixtures.AlpineImage, signImage).Assert(t, icmd.Success)
	result := icmd.RunCmd(
		icmd.Command("docker", "trust", "sign", signImage),
		fixtures.WithPassphrase("root_password", "repo_password"),
		fixtures.WithConfig(dir.Path()), fixtures.WithNotary)
	result.Assert(t, icmd.Success)
	assert.Check(t, is.Contains(result.Stdout(), fmt.Sprintf("v1: digest: sha256:%s", fixtures.AlpineSha)))
}

func TestSignWithLocalFlag(t *testing.T) {
	skip.If(t, environment.RemoteDaemon())

	dir := fixtures.SetupConfigFile(t)
	defer dir.Remove()
	setupTrustedImageForOverwrite(t, dir)
	result := icmd.RunCmd(
		icmd.Command("docker", "trust", "sign", "--local", localImage),
		fixtures.WithPassphrase("root_password", "repo_password"),
		fixtures.WithConfig(dir.Path()), fixtures.WithNotary)
	result.Assert(t, icmd.Success)
	assert.Check(t, is.Contains(result.Stdout(), fmt.Sprintf("v1: digest: sha256:%s", fixtures.BusyboxSha)))
}

func setupTrustedImageForOverwrite(t *testing.T, dir fs.Dir) {
	icmd.RunCmd(icmd.Command("docker", "pull", fixtures.AlpineImage)).Assert(t, icmd.Success)
	icmd.RunCommand("docker", "tag", fixtures.AlpineImage, localImage).Assert(t, icmd.Success)
	result := icmd.RunCmd(
		icmd.Command("docker", "-D", "trust", "sign", localImage),
		fixtures.WithPassphrase("root_password", "repo_password"),
		fixtures.WithConfig(dir.Path()), fixtures.WithNotary)
	result.Assert(t, icmd.Success)
	assert.Check(t, is.Contains(result.Stdout(), fmt.Sprintf("v1: digest: sha256:%s", fixtures.AlpineSha)))
	icmd.RunCmd(icmd.Command("docker", "pull", fixtures.BusyboxImage)).Assert(t, icmd.Success)
	icmd.RunCommand("docker", "tag", fixtures.BusyboxImage, localImage).Assert(t, icmd.Success)
}
<|endoftext|>


<commit_before>package gitlab

import (
	"fmt"
	"net/url"
)

// BuildVariablesService handles communication with the project variables related methods
// of the Gitlab API
//
// Gitlab API Docs : https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/build_variables.md
type BuildVariablesService struct {
	client *Client
}

// BuildVariable represents a variable available for each build of the given project
//
// Gitlab API Docs : https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/build_variables.md
type BuildVariable struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

func (v BuildVariable) String() string {
	return Stringify(v)
}

// ListBuildVariablesOptions are the parameters to ListBuildVariables()
//
// Gitlab API Docs:
// https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/build_variables.md#list-project-variables
type ListBuildVariablesOptions struct {
	ListOptions
}

// ListBuildVariables gets the a list of project variables in a project
//
// Gitlab API Docs:
// https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/build_variables.md#list-project-variables
func (s *BuildVariablesService) ListBuildVariables(pid interface{}, opts *ListBuildVariablesOptions, options ...OptionFunc) ([]*BuildVariable, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/variables", url.QueryEscape(project))

	req, err := s.client.NewRequest("GET", u, opts, options)
	if err != nil {
		return nil, nil, err
	}

	var v []*BuildVariable
	resp, err := s.client.Do(req, &v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}

// GetBuildVariable gets a single project variable of a project
//
// Gitlab API Docs:
// https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/build_variables.md#show-variable-details
func (s *BuildVariablesService) GetBuildVariable(pid interface{}, key string, options ...OptionFunc) (*BuildVariable, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/variables/%s", url.QueryEscape(project), key)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	v := new(BuildVariable)
	resp, err := s.client.Do(req, v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}

// CreateBuildVariable creates a variable for a given project
//
// Gitlab API Docs:
// https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/build_variables.md#create-variable
func (s *BuildVariablesService) CreateBuildVariable(pid interface{}, key, value string, options ...OptionFunc) (*BuildVariable, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/variables", url.QueryEscape(project))

	req, err := s.client.NewRequest("POST", u, BuildVariable{key, value}, options)
	if err != nil {
		return nil, nil, err
	}

	v := new(BuildVariable)
	resp, err := s.client.Do(req, v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}

// UpdateBuildVariable updates an existing project variable
// The variable key must exist
//
// Gitlab API Docs:
// https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/build_variables.md#update-variable
func (s *BuildVariablesService) UpdateBuildVariable(pid interface{}, key, value string, options ...OptionFunc) (*BuildVariable, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/variables/%s", url.QueryEscape(project), key)

	req, err := s.client.NewRequest("PUT", u, BuildVariable{key, value}, options)
	if err != nil {
		return nil, nil, err
	}

	v := new(BuildVariable)
	resp, err := s.client.Do(req, v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}

// RemoveBuildVariable removes a project variable of a given project identified by its key
//
// Gitlab API Docs:
// https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/build_variables.md#remove-variable
func (s *BuildVariablesService) RemoveBuildVariable(pid interface{}, key string, options ...OptionFunc) (*Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, err
	}
	u := fmt.Sprintf("projects/%s/variables/%s", url.QueryEscape(project), key)

	req, err := s.client.NewRequest("DELETE", u, nil, options)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}
<commit_msg>Add ability to paginate build variables (#159)<commit_after>package gitlab

import (
	"fmt"
	"net/url"
)

// BuildVariablesService handles communication with the project variables related methods
// of the Gitlab API
//
// Gitlab API Docs : https://docs.gitlab.com/ce/api/build_variables.html
type BuildVariablesService struct {
	client *Client
}

// BuildVariable represents a variable available for each build of the given project
//
// Gitlab API Docs : https://docs.gitlab.com/ce/api/build_variables.html
type BuildVariable struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

func (v BuildVariable) String() string {
	return Stringify(v)
}

// ListBuildVariablesOptions are the parameters to ListBuildVariables()
//
// Gitlab API Docs:
// https://docs.gitlab.com/ce/api/build_variables.html#list-project-variables
type ListBuildVariablesOptions struct {
	ListOptions
}

// ListBuildVariables gets the a list of project variables in a project
//
// Gitlab API Docs:
// https://docs.gitlab.com/ce/api/build_variables.html#list-project-variables
func (s *BuildVariablesService) ListBuildVariables(pid interface{}, opts *ListBuildVariablesOptions, options ...OptionFunc) ([]*BuildVariable, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/variables", url.QueryEscape(project))

	req, err := s.client.NewRequest("GET", u, opts, options)
	if err != nil {
		return nil, nil, err
	}

	var v []*BuildVariable
	resp, err := s.client.Do(req, &v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}

// GetBuildVariable gets a single project variable of a project
//
// Gitlab API Docs:
// https://docs.gitlab.com/ce/api/build_variables.html#show-variable-details
func (s *BuildVariablesService) GetBuildVariable(pid interface{}, key string, options ...OptionFunc) (*BuildVariable, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/variables/%s", url.QueryEscape(project), key)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	v := new(BuildVariable)
	resp, err := s.client.Do(req, v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}

// CreateBuildVariable creates a variable for a given project
//
// Gitlab API Docs:
// https://docs.gitlab.com/ce/api/build_variables.html#create-variable
func (s *BuildVariablesService) CreateBuildVariable(pid interface{}, key, value string, options ...OptionFunc) (*BuildVariable, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/variables", url.QueryEscape(project))

	req, err := s.client.NewRequest("POST", u, BuildVariable{key, value}, options)
	if err != nil {
		return nil, nil, err
	}

	v := new(BuildVariable)
	resp, err := s.client.Do(req, v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}

// UpdateBuildVariable updates an existing project variable
// The variable key must exist
//
// Gitlab API Docs:
// https://docs.gitlab.com/ce/api/build_variables.html#update-variable
func (s *BuildVariablesService) UpdateBuildVariable(pid interface{}, key, value string, options ...OptionFunc) (*BuildVariable, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/variables/%s", url.QueryEscape(project), key)

	req, err := s.client.NewRequest("PUT", u, BuildVariable{key, value}, options)
	if err != nil {
		return nil, nil, err
	}

	v := new(BuildVariable)
	resp, err := s.client.Do(req, v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}

// RemoveBuildVariable removes a project variable of a given project identified by its key
//
// Gitlab API Docs:
// https://docs.gitlab.com/ce/api/build_variables.html#remove-variable
func (s *BuildVariablesService) RemoveBuildVariable(pid interface{}, key string, options ...OptionFunc) (*Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, err
	}
	u := fmt.Sprintf("projects/%s/variables/%s", url.QueryEscape(project), key)

	req, err := s.client.NewRequest("DELETE", u, nil, options)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}
<|endoftext|>


<commit_before>package reflector

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

type Obj struct {
	iface interface{}

	isStruct      bool
	isPtrToStruct bool

	// If ptr to struct, this field will contain the type of that struct
	underlyingType reflect.Type

	objType reflect.Type
	objKind reflect.Kind
}

func panicIfErr(err error) {
	if err != nil {
		panic(err.Error())
	}
}

func NewFromType(ty reflect.Type) *Obj {
	return New(reflect.New(ty).Interface())
}

func New(obj interface{}) *Obj {
	o := &Obj{iface: obj}
	o.objType = reflect.TypeOf(obj)
	o.objKind = o.objType.Kind()

	ty := o.Type()
	if ty.Kind() == reflect.Struct {
		o.isStruct = true
	}
	if ty.Kind() == reflect.Ptr && ty.Elem().Kind() == reflect.Struct {
		ty = ty.Elem()
		o.isPtrToStruct = true
	}
	o.underlyingType = ty
	return o
}

func (o *Obj) Fields() []ObjField {
	return o.fields(reflect.TypeOf(o.iface), false)
}

func (o Obj) FieldsFlattened() []ObjField {
	return o.fields(reflect.TypeOf(o.iface), true)
}

func (o *Obj) fields(ty reflect.Type, flatten bool) []ObjField {
	fields := make([]ObjField, 0)

	if ty.Kind() == reflect.Ptr {
		ty = ty.Elem()
	}

	if ty.Kind() != reflect.Struct {
		return fields // No need to populate nonstructs
	}

	for i := 0; i < ty.NumField(); i++ {
		field := ty.Field(i)

		k := field.Type.Kind()
		if string(field.Name[0]) == strings.ToUpper(string(field.Name[0])) {
			if flatten && k == reflect.Struct && field.Anonymous {
				fields = append(fields, o.fields(field.Type, flatten)...)
			} else {
				fields = append(fields, *newObjField(o, field.Name))
			}
		}
	}

	return fields
}

func (o Obj) IsPtr() bool {
	return o.objKind == reflect.Ptr
}

func (o Obj) IsStructOrPtrToStruct() bool {
	return o.isStruct || o.isPtrToStruct
}

func (o *Obj) Field(name string) *ObjField {
	return &ObjField{
		obj:  o,
		name: name,
	}
}

func (o Obj) Type() reflect.Type {
	return o.objType
}

func (o Obj) Kind() reflect.Kind {
	return o.objKind
}

func (o *Obj) Method(name string) *ObjMethod {
	return newObjMethod(o, name)
}

func (o *Obj) Methods() []ObjMethod {
	res := []ObjMethod{}
	ty := o.Type()
	for i := 0; i < ty.NumMethod(); i++ {
		method := ty.Method(i)
		res = append(res, *newObjMethod(o, method.Name))
	}
	return res
}

type ObjField struct {
	obj  *Obj
	name string
}

func newObjField(obj *Obj, name string) *ObjField {
	return &ObjField{
		obj:  obj,
		name: name,
	}
}

func (of *ObjField) Name() string {
	return of.name
}

func (of *ObjField) Kind() reflect.Kind {
	ty, err := of.Type()
	if err != nil {
		return reflect.Invalid
	}
	return ty.Kind()
}

func (of *ObjField) Type() (reflect.Type, error) {
	value, err := of.Get()
	if err != nil {
		return nil, fmt.Errorf("Invalid field %s in %T", of.name, of.obj.iface)
	}
	return reflect.TypeOf(value), nil
}

func (of *ObjField) Tag(tag string) (string, error) {
	_, field, err := of.field()
	if err != nil {
		return "", err
	}
	return (*field).Tag.Get(tag), nil
}

func (of *ObjField) Tags() (map[string]string, error) {
	_, field, err := of.field()
	if err != nil {
		return nil, err
	}

	res := map[string]string{}
	tag := (*field).Tag

	// This code is copied/modified from: reflect/type.go:
	for tag != "" {
		// Skip leading space.
		i := 0
		for i < len(tag) && tag[i] == ' ' {
			i++
		}
		tag = tag[i:]
		if tag == "" {
			break
		}

		// Scan to colon. A space, a quote or a control character is a syntax error.
		// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
		// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
		// as it is simpler to inspect the tag's bytes than the tag's runes.
		i = 0
		for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
			i++
		}
		if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
			break
		}
		name := string(tag[:i])
		tag = tag[i+1:]

		// Scan quoted string to find value.
		i = 1
		for i < len(tag) && tag[i] != '"' {
			if tag[i] == '\\' {
				i++
			}
			i++
		}
		if i >= len(tag) {
			break
		}
		qvalue := string(tag[:i+1])
		tag = tag[i+1:]

		value, err := strconv.Unquote(qvalue)
		if err != nil {
			return nil, fmt.Errorf("Cannot unquote tag %s in %T.%s: %s", name, of.obj.iface, of.name, err.Error())
		}
		res[name] = value
		/*
			if key == name {
				value, err := strconv.Unquote(qvalue)
				if err != nil {
					break
				}
				return value
			}
		*/
	}

	return res, nil
}

// TagExpanded returns the tag value "expanded" with commas
func (of *ObjField) TagExpanded(tag string) ([]string, error) {
	_, field, err := of.field()
	if err != nil {
		return nil, err
	}
	return strings.Split((*field).Tag.Get(tag), ","), nil
}

func (of *ObjField) Valid() bool {
	if !of.obj.IsStructOrPtrToStruct() {
		return false
	}
	_, found := of.obj.underlyingType.FieldByName(of.name)
	return found
}

func (of *ObjField) Set(value interface{}) error {
	if !of.obj.IsStructOrPtrToStruct() {
		return fmt.Errorf("Cannot set %s in %T because obj is not a pointer to struct", of.name, of.obj.iface)
	}

	v := reflect.ValueOf(value)
	var field reflect.Value
	if of.obj.isPtrToStruct {
		field = reflect.ValueOf(of.obj.iface).Elem().FieldByName(of.name)
	} else {
		field = reflect.ValueOf(of.obj.iface).FieldByName(of.name)
	}

	if !field.IsValid() {
		return fmt.Errorf("Field %s in %T not valid", of.name, of.obj.iface)
	}
	if !field.CanSet() {
		return fmt.Errorf("Field %s in %T not settable", of.name, of.obj.iface)
	}

	field.Set(v)

	return nil
}

func (of *ObjField) field() (*reflect.Value, *reflect.StructField, error) {
	if !of.obj.IsStructOrPtrToStruct() {
		return nil, nil, fmt.Errorf("Cannot get %s in %T because underlying obj is not a struct", of.name, of.obj.iface)
	}

	var valueField reflect.Value
	var structField reflect.StructField
	var found bool
	if of.obj.isPtrToStruct {
		valueField = reflect.ValueOf(of.obj.iface).Elem().FieldByName(of.name)
		structField, found = reflect.TypeOf(of.obj.iface).Elem().FieldByName(of.name)
	} else {
		valueField = reflect.ValueOf(of.obj.iface).FieldByName(of.name)
		structField, found = reflect.TypeOf(of.obj.iface).FieldByName(of.name)
	}

	if !found {
		return nil, nil, fmt.Errorf("Field not found %s in %T", of.name, of.obj.iface)
	}

	return &valueField, &structField, nil
}

func (of *ObjField) Get() (interface{}, error) {
	fptr, _, err := of.field()
	if err != nil {
		return nil, err
	}
	field := *fptr

	if !field.IsValid() {
		return nil, fmt.Errorf("Invalid field %s in %T", of.name, of.obj.iface)
	}

	value := field.Interface()
	return value, nil
}

type ObjMethod struct {
	obj    *Obj
	name   string
	method reflect.Value
}

func newObjMethod(obj *Obj, name string) *ObjMethod {
	return &ObjMethod{
		obj:    obj,
		name:   name,
		method: reflect.ValueOf(obj.iface).MethodByName(name),
	}
}

func (om *ObjMethod) InTypes() []reflect.Type {
	method := reflect.ValueOf(om.obj.iface).MethodByName(om.name)
	if !method.IsValid() {
		return []reflect.Type{}
	}
	ty := method.Type()
	out := make([]reflect.Type, ty.NumIn())
	for i := 0; i < ty.NumIn(); i++ {
		out[i] = ty.In(i)
	}
	return out
}

func (om *ObjMethod) OutTypes() []reflect.Type {
	method := reflect.ValueOf(om.obj.iface).MethodByName(om.name)
	if !method.IsValid() {
		return []reflect.Type{}
	}
	ty := method.Type()
	out := make([]reflect.Type, ty.NumOut())
	for i := 0; i < ty.NumOut(); i++ {
		out[i] = ty.Out(i)
	}
	return out
}

func (om *ObjMethod) IsValid() bool {
	return om.method.IsValid()
}

// Call calls this method. Note that in the error returning value is not the error from the method call
func (om *ObjMethod) Call(args ...interface{}) (*CallResult, error) {
	if !om.method.IsValid() {
		return nil, fmt.Errorf("Invalid method %s in %T", om.name, om.obj.iface)
	}
	in := make([]reflect.Value, len(args))
	for n := range args {
		in[n] = reflect.ValueOf(args[n])
	}
	out := om.method.Call(in)
	res := make([]interface{}, len(out))
	for n := range out {
		res[n] = out[n].Interface()
	}
	return newCallResult(res), nil
}

type CallResult struct {
	Result []interface{}
	Error  error
}

func newCallResult(res []interface{}) *CallResult {
	cr := &CallResult{Result: res}
	if len(res) == 0 {
		return cr
	}
	errorCandidate := res[len(res)-1]
	if errorCandidate != nil {
		if err, is := errorCandidate.(error); is {
			cr.Error = err
		}
	}
	return cr
}

// IsError checks if the last value is a non-nil error
func (cr *CallResult) IsError() bool {
	return cr.Error != nil
}
<commit_msg>Cleanup<commit_after>package reflector

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

type Obj struct {
	iface interface{}

	isStruct      bool
	isPtrToStruct bool

	// If ptr to struct, this field will contain the type of that struct
	underlyingType reflect.Type

	objType reflect.Type
	objKind reflect.Kind
}

func NewFromType(ty reflect.Type) *Obj {
	return New(reflect.New(ty).Interface())
}

func New(obj interface{}) *Obj {
	o := &Obj{iface: obj}
	o.objType = reflect.TypeOf(obj)
	o.objKind = o.objType.Kind()

	ty := o.Type()
	if ty.Kind() == reflect.Struct {
		o.isStruct = true
	}
	if ty.Kind() == reflect.Ptr && ty.Elem().Kind() == reflect.Struct {
		ty = ty.Elem()
		o.isPtrToStruct = true
	}
	o.underlyingType = ty
	return o
}

func (o *Obj) Fields() []ObjField {
	return o.fields(reflect.TypeOf(o.iface), false)
}

func (o Obj) FieldsFlattened() []ObjField {
	return o.fields(reflect.TypeOf(o.iface), true)
}

func (o *Obj) fields(ty reflect.Type, flatten bool) []ObjField {
	fields := make([]ObjField, 0)

	if ty.Kind() == reflect.Ptr {
		ty = ty.Elem()
	}

	if ty.Kind() != reflect.Struct {
		return fields // No need to populate nonstructs
	}

	for i := 0; i < ty.NumField(); i++ {
		field := ty.Field(i)

		k := field.Type.Kind()
		if string(field.Name[0]) == strings.ToUpper(string(field.Name[0])) {
			if flatten && k == reflect.Struct && field.Anonymous {
				fields = append(fields, o.fields(field.Type, flatten)...)
			} else {
				fields = append(fields, *newObjField(o, field.Name))
			}
		}
	}

	return fields
}

func (o Obj) IsPtr() bool {
	return o.objKind == reflect.Ptr
}

func (o Obj) IsStructOrPtrToStruct() bool {
	return o.isStruct || o.isPtrToStruct
}

func (o *Obj) Field(name string) *ObjField {
	return &ObjField{
		obj:  o,
		name: name,
	}
}

func (o Obj) Type() reflect.Type {
	return o.objType
}

func (o Obj) Kind() reflect.Kind {
	return o.objKind
}

func (o *Obj) Method(name string) *ObjMethod {
	return newObjMethod(o, name)
}

func (o *Obj) Methods() []ObjMethod {
	res := []ObjMethod{}
	ty := o.Type()
	for i := 0; i < ty.NumMethod(); i++ {
		method := ty.Method(i)
		res = append(res, *newObjMethod(o, method.Name))
	}
	return res
}

type ObjField struct {
	obj  *Obj
	name string
}

func newObjField(obj *Obj, name string) *ObjField {
	return &ObjField{
		obj:  obj,
		name: name,
	}
}

func (of *ObjField) Name() string {
	return of.name
}

func (of *ObjField) Kind() reflect.Kind {
	ty, err := of.Type()
	if err != nil {
		return reflect.Invalid
	}
	return ty.Kind()
}

func (of *ObjField) Type() (reflect.Type, error) {
	value, err := of.Get()
	if err != nil {
		return nil, fmt.Errorf("Invalid field %s in %T", of.name, of.obj.iface)
	}
	return reflect.TypeOf(value), nil
}

func (of *ObjField) Tag(tag string) (string, error) {
	_, field, err := of.field()
	if err != nil {
		return "", err
	}
	return (*field).Tag.Get(tag), nil
}

func (of *ObjField) Tags() (map[string]string, error) {
	_, field, err := of.field()
	if err != nil {
		return nil, err
	}

	res := map[string]string{}
	tag := (*field).Tag

	// This code is copied/modified from: reflect/type.go:
	for tag != "" {
		// Skip leading space.
		i := 0
		for i < len(tag) && tag[i] == ' ' {
			i++
		}
		tag = tag[i:]
		if tag == "" {
			break
		}

		// Scan to colon. A space, a quote or a control character is a syntax error.
		// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
		// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
		// as it is simpler to inspect the tag's bytes than the tag's runes.
		i = 0
		for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
			i++
		}
		if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
			break
		}
		name := string(tag[:i])
		tag = tag[i+1:]

		// Scan quoted string to find value.
		i = 1
		for i < len(tag) && tag[i] != '"' {
			if tag[i] == '\\' {
				i++
			}
			i++
		}
		if i >= len(tag) {
			break
		}
		qvalue := string(tag[:i+1])
		tag = tag[i+1:]

		value, err := strconv.Unquote(qvalue)
		if err != nil {
			return nil, fmt.Errorf("Cannot unquote tag %s in %T.%s: %s", name, of.obj.iface, of.name, err.Error())
		}
		res[name] = value
		/*
			if key == name {
				value, err := strconv.Unquote(qvalue)
				if err != nil {
					break
				}
				return value
			}
		*/
	}

	return res, nil
}

// TagExpanded returns the tag value "expanded" with commas
func (of *ObjField) TagExpanded(tag string) ([]string, error) {
	_, field, err := of.field()
	if err != nil {
		return nil, err
	}
	return strings.Split((*field).Tag.Get(tag), ","), nil
}

func (of *ObjField) Valid() bool {
	if !of.obj.IsStructOrPtrToStruct() {
		return false
	}
	_, found := of.obj.underlyingType.FieldByName(of.name)
	return found
}

func (of *ObjField) Set(value interface{}) error {
	if !of.obj.IsStructOrPtrToStruct() {
		return fmt.Errorf("Cannot set %s in %T because obj is not a pointer to struct", of.name, of.obj.iface)
	}

	v := reflect.ValueOf(value)
	var field reflect.Value
	if of.obj.isPtrToStruct {
		field = reflect.ValueOf(of.obj.iface).Elem().FieldByName(of.name)
	} else {
		field = reflect.ValueOf(of.obj.iface).FieldByName(of.name)
	}

	if !field.IsValid() {
		return fmt.Errorf("Field %s in %T not valid", of.name, of.obj.iface)
	}
	if !field.CanSet() {
		return fmt.Errorf("Field %s in %T not settable", of.name, of.obj.iface)
	}

	field.Set(v)

	return nil
}

func (of *ObjField) field() (*reflect.Value, *reflect.StructField, error) {
	if !of.obj.IsStructOrPtrToStruct() {
		return nil, nil, fmt.Errorf("Cannot get %s in %T because underlying obj is not a struct", of.name, of.obj.iface)
	}

	var valueField reflect.Value
	var structField reflect.StructField
	var found bool
	if of.obj.isPtrToStruct {
		valueField = reflect.ValueOf(of.obj.iface).Elem().FieldByName(of.name)
		structField, found = reflect.TypeOf(of.obj.iface).Elem().FieldByName(of.name)
	} else {
		valueField = reflect.ValueOf(of.obj.iface).FieldByName(of.name)
		structField, found = reflect.TypeOf(of.obj.iface).FieldByName(of.name)
	}

	if !found {
		return nil, nil, fmt.Errorf("Field not found %s in %T", of.name, of.obj.iface)
	}

	return &valueField, &structField, nil
}

func (of *ObjField) Get() (interface{}, error) {
	fptr, _, err := of.field()
	if err != nil {
		return nil, err
	}
	field := *fptr

	if !field.IsValid() {
		return nil, fmt.Errorf("Invalid field %s in %T", of.name, of.obj.iface)
	}

	value := field.Interface()
	return value, nil
}

type ObjMethod struct {
	obj    *Obj
	name   string
	method reflect.Value
}

func newObjMethod(obj *Obj, name string) *ObjMethod {
	return &ObjMethod{
		obj:    obj,
		name:   name,
		method: reflect.ValueOf(obj.iface).MethodByName(name),
	}
}

func (om *ObjMethod) InTypes() []reflect.Type {
	method := reflect.ValueOf(om.obj.iface).MethodByName(om.name)
	if !method.IsValid() {
		return []reflect.Type{}
	}
	ty := method.Type()
	out := make([]reflect.Type, ty.NumIn())
	for i := 0; i < ty.NumIn(); i++ {
		out[i] = ty.In(i)
	}
	return out
}

func (om *ObjMethod) OutTypes() []reflect.Type {
	method := reflect.ValueOf(om.obj.iface).MethodByName(om.name)
	if !method.IsValid() {
		return []reflect.Type{}
	}
	ty := method.Type()
	out := make([]reflect.Type, ty.NumOut())
	for i := 0; i < ty.NumOut(); i++ {
		out[i] = ty.Out(i)
	}
	return out
}

func (om *ObjMethod) IsValid() bool {
	return om.method.IsValid()
}

// Call calls this method. Note that in the error returning value is not the error from the method call
func (om *ObjMethod) Call(args ...interface{}) (*CallResult, error) {
	if !om.method.IsValid() {
		return nil, fmt.Errorf("Invalid method %s in %T", om.name, om.obj.iface)
	}
	in := make([]reflect.Value, len(args))
	for n := range args {
		in[n] = reflect.ValueOf(args[n])
	}
	out := om.method.Call(in)
	res := make([]interface{}, len(out))
	for n := range out {
		res[n] = out[n].Interface()
	}
	return newCallResult(res), nil
}

type CallResult struct {
	Result []interface{}
	Error  error
}

func newCallResult(res []interface{}) *CallResult {
	cr := &CallResult{Result: res}
	if len(res) == 0 {
		return cr
	}
	errorCandidate := res[len(res)-1]
	if errorCandidate != nil {
		if err, is := errorCandidate.(error); is {
			cr.Error = err
		}
	}
	return cr
}

// IsError checks if the last value is a non-nil error
func (cr *CallResult) IsError() bool {
	return cr.Error != nil
}
<|endoftext|>