Ejemplo n.º 1
1
func (s *SelfSuite) TestOutputReporter(c *gc.C) {
	manifold := dependency.SelfManifold(s.engine)
	var reporter dependency.Reporter
	err := manifold.Output(s.engine, &reporter)
	c.Check(err, jc.ErrorIsNil)
	c.Check(reporter, gc.Equals, s.engine)
}
Ejemplo n.º 2
0
func (s *StatusSuite) runTestCase(c *gc.C, tc statusTestCase) {
	fakeClient := makeFakeClient(
		0*time.Second, // No API delay
		5*time.Second, // 5 second test timeout
		tc.tags,
		tc.results,
		"", // No API error
	)

	restore := s.patchAPIClient(fakeClient)
	defer restore()

	s.subcommand = &action.StatusCommand{}
	ctx, err := testing.RunCommand(c, s.subcommand, tc.args...)
	if tc.expectError == "" {
		c.Check(err, jc.ErrorIsNil)
	} else {
		c.Check(err, gc.ErrorMatches, tc.expectError)
	}
	if len(tc.results) > 0 {
		buf, err := cmd.DefaultFormatters["yaml"](action.ActionResultsToMap(tc.results))
		c.Check(err, jc.ErrorIsNil)
		c.Check(ctx.Stdout.(*bytes.Buffer).String(), gc.Equals, string(buf)+"\n")
		c.Check(ctx.Stderr.(*bytes.Buffer).String(), gc.Equals, "")
	}
}
Ejemplo n.º 3
0
func (s *SelfSuite) TestOutputInstaller(c *gc.C) {
	manifold := dependency.SelfManifold(s.engine)
	var installer dependency.Installer
	err := manifold.Output(s.engine, &installer)
	c.Check(err, jc.ErrorIsNil)
	c.Check(installer, gc.Equals, s.engine)
}
Ejemplo n.º 4
0
func (s *SelfSuite) TestOutputBadOutput(c *gc.C) {
	manifold := dependency.SelfManifold(s.engine)
	var unknown interface{}
	err := manifold.Output(s.engine, &unknown)
	c.Check(err, gc.ErrorMatches, "out should be a \\*Installer or a \\*Reporter; is .*")
	c.Check(unknown, gc.IsNil)
}
Ejemplo n.º 5
0
func (s *instanceSuite) TestOpenPorts(c *gc.C) {
	// Close the default ports.
	configSetNetwork((*gwacl.Role)(s.role)).InputEndpoints = nil

	responses := preparePortChangeConversation(c, s.role)
	record := gwacl.PatchManagementAPIResponses(responses)
	err := s.instance.OpenPorts("machine-id", []network.PortRange{
		{79, 79, "tcp"}, {587, 587, "tcp"}, {9, 9, "udp"},
	})
	c.Assert(err, jc.ErrorIsNil)

	assertPortChangeConversation(c, *record, []expectedRequest{
		{"GET", ".*/deployments/deployment-one/roles/role-one"}, // GetRole
		{"PUT", ".*/deployments/deployment-one/roles/role-one"}, // UpdateRole
	})

	// A representative UpdateRole payload includes configuration for the
	// ports requested.
	role := &gwacl.PersistentVMRole{}
	err = role.Deserialize((*record)[1].Payload)
	c.Assert(err, jc.ErrorIsNil)
	c.Check(
		*configSetNetwork((*gwacl.Role)(role)).InputEndpoints,
		gc.DeepEquals,
		[]gwacl.InputEndpoint{
			makeInputEndpoint(79, "tcp"),
			makeInputEndpoint(587, "tcp"),
			makeInputEndpoint(9, "udp"),
		},
	)
}
Ejemplo n.º 6
0
func (s *ActionSuite) TestFindActionsByName(c *gc.C) {
	actions := []struct {
		Name       string
		Parameters map[string]interface{}
	}{
		{Name: "action-1", Parameters: map[string]interface{}{}},
		{Name: "fake", Parameters: map[string]interface{}{"yeah": true, "take": nil}},
		{Name: "action-1", Parameters: map[string]interface{}{"yeah": true, "take": nil}},
		{Name: "action-9", Parameters: map[string]interface{}{"district": 9}},
		{Name: "blarney", Parameters: map[string]interface{}{"conversation": []string{"what", "now"}}},
	}

	for _, action := range actions {
		_, err := s.State.EnqueueAction(s.unit.Tag(), action.Name, action.Parameters)
		c.Assert(err, gc.Equals, nil)
	}

	results, err := s.State.FindActionsByName("action-1")
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(len(results), gc.Equals, 2)
	for _, result := range results {
		c.Check(result.Name(), gc.Equals, "action-1")
	}
}
Ejemplo n.º 7
0
func (*ConfigSuite) TestConfigString(c *gc.C) {
	for i, test := range []struct {
		config   Config
		expected string
	}{{
		config:   nil,
		expected: "",
	}, {
		config:   Config{"": INFO},
		expected: "<root>=INFO",
	}, {
		config:   Config{"": UNSPECIFIED},
		expected: "<root>=UNSPECIFIED",
	}, {
		config:   Config{"": DEBUG},
		expected: "<root>=DEBUG",
	}, {
		config:   Config{"test.module": DEBUG},
		expected: "test.module=DEBUG",
	}, {
		config: Config{
			"":             WARNING,
			"module":       INFO,
			"sub.module":   DEBUG,
			"other.module": WARNING,
		},
		expected: "<root>=WARNING;module=INFO;other.module=WARNING;sub.module=DEBUG",
	}} {
		c.Logf("%d: %q", i, test.expected)
		c.Check(test.config.String(), gc.Equals, test.expected)
	}
}
Ejemplo n.º 8
0
// countPolls sets up a machine loop with the given
// addresses and status to be returned from getInstanceInfo,
// waits for coretesting.ShortWait, and returns the
// number of times the instance is polled.
func countPolls(c *gc.C, addrs []network.Address, instId, instStatus string, machineStatus params.Status) int {
	count := int32(0)
	getInstanceInfo := func(id instance.Id) (instanceInfo, error) {
		c.Check(string(id), gc.Equals, instId)
		atomic.AddInt32(&count, 1)
		if addrs == nil {
			return instanceInfo{}, fmt.Errorf("no instance addresses available")
		}
		return instanceInfo{addrs, instStatus}, nil
	}
	context := &testMachineContext{
		getInstanceInfo: getInstanceInfo,
		dyingc:          make(chan struct{}),
	}
	m := &testMachine{
		tag:        names.NewMachineTag("99"),
		instanceId: instance.Id(instId),
		refresh:    func() error { return nil },
		addresses:  addrs,
		life:       params.Alive,
		status:     machineStatus,
	}
	died := make(chan machine)

	go runMachine(context, m, nil, died)

	time.Sleep(coretesting.ShortWait)
	killMachineLoop(c, m, context.dyingc, died)
	c.Assert(context.killAllErr, gc.Equals, nil)
	return int(count)
}
Ejemplo n.º 9
0
func (s *Suite) TestSetStatusMessage(c *gc.C) {
	api := s.mustMakeAPI(c)

	err := api.SetStatusMessage(params.SetMigrationStatusMessageArgs{Message: "foo"})
	c.Assert(err, jc.ErrorIsNil)
	c.Check(s.backend.migration.messageSet, gc.Equals, "foo")
}
Ejemplo n.º 10
0
func (s *ToolsMetadataSuite) TestGenerateWithMirrors(c *gc.C) {

	metadataDir := c.MkDir()
	toolstesting.MakeTools(c, metadataDir, "released", versionStrings)
	ctx := coretesting.Context(c)
	code := cmd.Main(newToolsMetadataCommand(), ctx, []string{"--public", "-d", metadataDir, "--stream", "released"})
	c.Assert(code, gc.Equals, 0)
	output := ctx.Stdout.(*bytes.Buffer).String()

	mirrosTmpl := expectedOutputCommon + `
.*Writing tools/streams/v1/index2\.json
.*Writing tools/streams/v1/index\.json
.*Writing tools/streams/v1/com\.ubuntu\.juju-{{.Stream}}-tools\.json
.*Writing tools/streams/v1/mirrors\.json
`
	expectedOutput := makeExpectedOutput(mirrosTmpl, "released", "released")
	c.Check(output, gc.Matches, expectedOutput)
	metadata := toolstesting.ParseMetadataFromDir(c, metadataDir, "released", true)
	c.Check(metadata, gc.HasLen, len(versionStrings))
	obtainedVersionStrings := make([]string, len(versionStrings))
	for i, metadata := range metadata {
		s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch)
		obtainedVersionStrings[i] = s
	}
	c.Assert(obtainedVersionStrings, gc.DeepEquals, versionStrings)
}
Ejemplo n.º 11
0
func (s *ValidateImageMetadataSuite) TestInitErrors(c *gc.C) {
	for i, t := range validateInitImageErrorTests {
		c.Logf("test %d", i)
		err := coretesting.InitCommand(newValidateImageMetadataCommand(), t.args)
		c.Check(err, gc.ErrorMatches, t.err)
	}
}
Ejemplo n.º 12
0
func (s *statusHistoryPrunerSuite) TestWorker(c *gc.C) {
	var passedMaxLogs int
	fakePruner := func(_ *state.State, maxLogs int) error {
		passedMaxLogs = maxLogs
		return nil
	}
	params := statushistorypruner.HistoryPrunerParams{
		MaxLogsPerState: 3,
		PruneInterval:   coretesting.ShortWait,
	}
	fakeTimer := newMockTimer(coretesting.LongWait)

	fakeTimerFunc := func(d time.Duration) worker.PeriodicTimer {
		// construction of timer should be with 0 because we intend it to
		// run once before waiting.
		c.Assert(d, gc.Equals, 0*time.Nanosecond)
		return fakeTimer
	}
	pruner := statushistorypruner.NewPruneWorker(
		&state.State{},
		&params,
		fakeTimerFunc,
		fakePruner,
	)
	s.AddCleanup(func(*gc.C) {
		pruner.Kill()
		c.Assert(pruner.Wait(), jc.ErrorIsNil)
	})
	err := fakeTimer.(*mockTimer).fire()
	c.Check(err, jc.ErrorIsNil)
	c.Assert(passedMaxLogs, gc.Equals, 3)
	// Reset will have been called with the actual PruneInterval
	c.Assert(fakeTimer.(*mockTimer).period, gc.Equals, coretesting.ShortWait)
}
Ejemplo n.º 13
0
func (s *UserSuite) TestRemoveUserRemovesUserAccess(c *gc.C) {
	user := s.Factory.MakeUser(c, &factory.UserParams{Password: "******"})

	// Assert user exists and can authenticate.
	c.Assert(user.PasswordValid("so sekrit"), jc.IsTrue)

	s.State.SetUserAccess(user.UserTag(), s.State.ModelTag(), permission.AdminAccess)
	s.State.SetUserAccess(user.UserTag(), s.State.ControllerTag(), permission.SuperuserAccess)

	uam, err := s.State.UserAccess(user.UserTag(), s.State.ModelTag())
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(uam.Access, gc.Equals, permission.AdminAccess)

	uac, err := s.State.UserAccess(user.UserTag(), s.State.ControllerTag())
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(uac.Access, gc.Equals, permission.SuperuserAccess)

	// Look for the user.
	u, err := s.State.User(user.UserTag())
	c.Check(err, jc.ErrorIsNil)
	c.Assert(u, jc.DeepEquals, user)

	// Remove the user.
	err = s.State.RemoveUser(user.UserTag())
	c.Check(err, jc.ErrorIsNil)

	uam, err = s.State.UserAccess(user.UserTag(), s.State.ModelTag())
	c.Assert(err, gc.ErrorMatches, fmt.Sprintf("%q user not found", user.UserTag().Name()))

	uac, err = s.State.UserAccess(user.UserTag(), s.State.ControllerTag())
	c.Assert(err, gc.ErrorMatches, fmt.Sprintf("%q user not found", user.UserTag().Name()))
}
Ejemplo n.º 14
0
func (s *UnitSuite) TestRunStop(c *gc.C) {
	_, unit, _, _ := s.primeAgent(c)
	a := s.newAgent(c, unit)
	go func() { c.Check(a.Run(nil), gc.IsNil) }()
	defer func() { c.Check(a.Stop(), gc.IsNil) }()
	waitForUnitActive(s.State, unit, c)
}
Ejemplo n.º 15
0
func (s *UnitSuite) TestParseUnknown(c *gc.C) {
	err := coretesting.InitCommand(NewUnitAgent(nil, nil), []string{
		"--unit-name", "wordpress/1",
		"thundering typhoons",
	})
	c.Check(err, gc.ErrorMatches, `unrecognized args: \["thundering typhoons"\]`)
}
Ejemplo n.º 16
0
func (s *rawConnSuite) TestConnectionWaitOperationTimeout(c *gc.C) {
	s.op.Status = StatusRunning
	err := s.rawConn.waitOperation("proj", s.op, s.strategy)

	c.Check(err, gc.ErrorMatches, ".* timed out .*")
	c.Check(s.callCount, gc.Equals, 4)
}
Ejemplo n.º 17
0
func (s *rawConnSuite) TestConnectionWaitOperation(c *gc.C) {
	original := &compute.Operation{}
	err := s.rawConn.waitOperation("proj", original, s.strategy)

	c.Check(err, jc.ErrorIsNil)
	c.Check(s.callCount, gc.Equals, 1)
}
Ejemplo n.º 18
0
func (s *Suite) TestSetStatusMessageNoMigration(c *gc.C) {
	s.backend.getErr = errors.New("boom")
	api := s.mustMakeAPI(c)

	err := api.SetStatusMessage(params.SetMigrationStatusMessageArgs{Message: "foo"})
	c.Check(err, gc.ErrorMatches, "could not get migration: boom")
}
Ejemplo n.º 19
0
func (s *machineSuite) TestSinglePollWhenInstancInfoUnimplemented(c *gc.C) {
	s.PatchValue(&ShortPoll, 1*time.Millisecond)
	s.PatchValue(&LongPoll, 1*time.Millisecond)
	count := int32(0)
	getInstanceInfo := func(id instance.Id) (instanceInfo, error) {
		c.Check(id, gc.Equals, instance.Id("i1234"))
		atomic.AddInt32(&count, 1)
		err := &params.Error{
			Code:    params.CodeNotImplemented,
			Message: "instance address not implemented",
		}
		return instanceInfo{}, err
	}
	context := &testMachineContext{
		getInstanceInfo: getInstanceInfo,
		dyingc:          make(chan struct{}),
	}
	m := &testMachine{
		tag:        names.NewMachineTag("99"),
		instanceId: "i1234",
		refresh:    func() error { return nil },
		life:       params.Alive,
	}
	died := make(chan machine)

	go runMachine(context, m, nil, died)

	time.Sleep(coretesting.ShortWait)
	killMachineLoop(c, m, context.dyingc, died)
	c.Assert(context.killAllErr, gc.Equals, nil)
	c.Assert(count, gc.Equals, int32(1))
}
Ejemplo n.º 20
0
func (s *Suite) TestReapError(c *gc.C) {
	s.backend.removeErr = errors.New("boom")
	api := s.mustMakeAPI(c)

	err := api.Reap()
	c.Check(err, gc.ErrorMatches, "boom")
}
Ejemplo n.º 21
0
func (s *ActionSuite) TestFindActionTagsByPrefix(c *gc.C) {
	prefix := "feedbeef"
	uuidMock := uuidMockHelper{}
	uuidMock.SetPrefixMask(prefix)
	s.PatchValue(&state.NewUUID, uuidMock.NewUUID)

	actions := []struct {
		Name       string
		Parameters map[string]interface{}
	}{
		{Name: "action-1", Parameters: map[string]interface{}{}},
		{Name: "fake", Parameters: map[string]interface{}{"yeah": true, "take": nil}},
		{Name: "action-9", Parameters: map[string]interface{}{"district": 9}},
		{Name: "blarney", Parameters: map[string]interface{}{"conversation": []string{"what", "now"}}},
	}

	for _, action := range actions {
		_, err := s.State.EnqueueAction(s.unit.Tag(), action.Name, action.Parameters)
		c.Assert(err, gc.Equals, nil)
	}

	tags := s.State.FindActionTagsByPrefix(prefix)

	c.Assert(len(tags), gc.Equals, len(actions))
	for i, tag := range tags {
		c.Logf("check %q against %d:%q", prefix, i, tag)
		c.Check(tag.Id()[:len(prefix)], gc.Equals, prefix)
	}
}
Ejemplo n.º 22
0
func (s *Suite) TestMigrationStatus(c *gc.C) {
	var expectedMacaroons = `
[[{"caveats":[],"location":"location","identifier":"id","signature":"a9802bf274262733d6283a69c62805b5668dbf475bcd7edc25a962833f7c2cba"}]]`[1:]

	api := s.mustMakeAPI(c)
	status, err := api.MigrationStatus()
	c.Assert(err, jc.ErrorIsNil)

	c.Check(status, gc.DeepEquals, params.MasterMigrationStatus{
		Spec: params.MigrationSpec{
			ModelTag: names.NewModelTag(modelUUID).String(),
			TargetInfo: params.MigrationTargetInfo{
				ControllerTag: names.NewControllerTag(controllerUUID).String(),
				Addrs:         []string{"1.1.1.1:1", "2.2.2.2:2"},
				CACert:        "trust me",
				AuthTag:       names.NewUserTag("admin").String(),
				Password:      "******",
				Macaroons:     expectedMacaroons,
			},
		},
		MigrationId:      "id",
		Phase:            "IMPORT",
		PhaseChangedTime: s.backend.migration.PhaseChangedTime(),
	})
}
Ejemplo n.º 23
0
func assertPortChangeConversation(c *gc.C, record []*gwacl.X509Request, expected []expectedRequest) {
	c.Assert(record, gc.HasLen, len(expected))
	for index, request := range record {
		c.Check(request.Method, gc.Equals, expected[index].method)
		c.Check(request.URL, gc.Matches, expected[index].urlpattern)
	}
}
Ejemplo n.º 24
0
func (s *modelManagerSuite) TestCreateModelBadAgentVersion(c *gc.C) {
	s.PatchValue(&version.Current, coretesting.FakeVersionNumber)
	admin := s.AdminUserTag(c)
	s.setAPIUser(c, admin)

	bigger := version.Current
	bigger.Minor += 1

	smaller := version.Current
	smaller.Minor -= 1

	for i, test := range []struct {
		value    interface{}
		errMatch string
	}{
		{
			value:    42,
			errMatch: `failed to create config: agent-version must be a string but has type 'int'`,
		}, {
			value:    "not a number",
			errMatch: `failed to create config: invalid version \"not a number\"`,
		}, {
			value:    bigger.String(),
			errMatch: "failed to create config: agent-version cannot be greater than the server: .*",
		}, {
			value:    smaller.String(),
			errMatch: "failed to create config: no tools found for version .*",
		},
	} {
		c.Logf("test %d", i)
		args := s.createArgsForVersion(c, admin, test.value)
		_, err := s.modelmanager.CreateModel(args)
		c.Check(err, gc.ErrorMatches, test.errMatch)
	}
}
Ejemplo n.º 25
0
func (s *clientSuite) TestClientInstances(c *gc.C) {
	addTestClientServer(c, "", "")
	addTestClientServer(c, jujuMetaInstanceServer, "alien")
	addTestClientServer(c, jujuMetaInstanceStateServer, "alien")
	addTestClientServer(c, jujuMetaInstanceServer, "f54aac3a-9dcd-4a0c-86b5-24091478478c")
	addTestClientServer(c, jujuMetaInstanceServer, "f54aac3a-9dcd-4a0c-86b5-24091478478c")
	suuid := addTestClientServer(c, jujuMetaInstanceStateServer, "f54aac3a-9dcd-4a0c-86b5-24091478478c")

	cli, err := testNewClient(c, mock.Endpoint(""), mock.TestUser, mock.TestPassword)
	c.Assert(err, gc.IsNil)

	ss, err := cli.instances()
	c.Assert(err, gc.IsNil)
	c.Assert(ss, gc.NotNil)
	c.Check(ss, gc.HasLen, 3)

	sm, err := cli.instanceMap()
	c.Assert(err, gc.IsNil)
	c.Assert(sm, gc.NotNil)
	c.Check(sm, gc.HasLen, 3)

	ids, err := cli.getStateServerIds()
	c.Check(err, gc.IsNil)
	c.Check(len(ids), gc.Equals, 1)
	c.Check(string(ids[0]), gc.Equals, suuid)
}
Ejemplo n.º 26
0
func (s *initSystemSuite) checkCreateFileCall(c *gc.C, index int, filename, content string, perm os.FileMode) {
	if content == "" {
		name := filename
		filename = fmt.Sprintf("%s/init/%s/%s.service", s.dataDir, name, name)
		content = s.newConfStr(name)
	}

	call := s.stub.Calls()[index]
	if !c.Check(call.FuncName, gc.Equals, "CreateFile") {
		return
	}
	if !c.Check(call.Args, gc.HasLen, 3) {
		return
	}

	callFilename, callData, callPerm := call.Args[0], call.Args[1], call.Args[2]
	c.Check(callFilename, gc.Equals, filename)

	// Some tests don't generate valid ini files, instead including placeholder
	// strings (e.g. "a\nb\nc\n"). To avoid parsing errors, we only try and
	// parse actual and expected file content if they don't exactly match.
	if content != string(callData.([]byte)) {
		// Parse the ini configurations and compare those.
		expected, err := unit.Deserialize(bytes.NewReader(callData.([]byte)))
		c.Assert(err, jc.ErrorIsNil)
		cfg, err := unit.Deserialize(strings.NewReader(content))
		c.Assert(err, jc.ErrorIsNil)
		c.Check(cfg, jc.SameContents, expected)
	}

	c.Check(callPerm, gc.Equals, perm)
}
Ejemplo n.º 27
0
func (s *initSystemSuite) TestNewServiceMultiline(c *gc.C) {
	s.conf.ExecStart = "a\nb\nc"
	svc := s.newService(c)

	dirname := fmt.Sprintf("%s/init/%s", s.dataDir, s.name)
	script := `
#!/usr/bin/env bash

a
b
c`[1:]
	c.Check(svc, jc.DeepEquals, &systemd.Service{
		Service: common.Service{
			Name: s.name,
			Conf: common.Conf{
				Desc:      s.conf.Desc,
				ExecStart: dirname + "/exec-start.sh",
			},
		},
		UnitName: s.name + ".service",
		ConfName: s.name + ".service",
		Dirname:  dirname,
		Script:   []byte(script),
	})
	// This gives us a more readable output if they aren't equal.
	c.Check(string(svc.Script), gc.Equals, script)
	s.stub.CheckCalls(c, nil)
}
Ejemplo n.º 28
0
func (s *ReportSuite) TestReportError(c *gc.C) {
	s.fix.run(c, func(engine *dependency.Engine) {
		mh1 := newManifoldHarness("missing")
		manifold := mh1.Manifold()
		err := engine.Install("task", manifold)
		c.Assert(err, jc.ErrorIsNil)
		mh1.AssertNoStart(c)

		workertest.CleanKill(c, engine)
		report := engine.Report()
		c.Check(report, jc.DeepEquals, map[string]interface{}{
			"state": "stopped",
			"error": nil,
			"manifolds": map[string]interface{}{
				"task": map[string]interface{}{
					"state":  "stopped",
					"error":  dependency.ErrMissing,
					"inputs": []string{"missing"},
					"resource-log": []map[string]interface{}{{
						"name":  "missing",
						"type":  "<nil>",
						"error": dependency.ErrMissing,
					}},
					"report": (map[string]interface{})(nil),
				},
			},
		})
	})
}
Ejemplo n.º 29
0
func (s *SelfSuite) TestActuallyWorks(c *gc.C) {

	// Create and install a manifold with an unsatisfied dependency.
	mh1 := newManifoldHarness("self")
	err := s.engine.Install("dependent", mh1.Manifold())
	c.Assert(err, jc.ErrorIsNil)
	mh1.AssertNoStart(c)

	// Install an engine inside itself; once it's "started", dependent will
	// be restarted.
	manifold := dependency.SelfManifold(s.engine)
	err = s.engine.Install("self", manifold)
	c.Assert(err, jc.ErrorIsNil)
	mh1.AssertOneStart(c)

	// Check we can still stop it (with a timeout -- injudicious
	// implementation changes could induce deadlocks).
	done := make(chan struct{})
	go func() {
		err := worker.Stop(s.engine)
		c.Check(err, jc.ErrorIsNil)
		close(done)
	}()
	select {
	case <-done:
	case <-time.After(coretesting.LongWait):
		c.Fatalf("timed out")
	}
}
Ejemplo n.º 30
0
func (s *httpSuite) TestHTTPClient(c *gc.C) {
	var handler http.HandlerFunc
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		handler(w, req)
	}))
	defer srv.Close()
	s.client.BaseURL = srv.URL
	for i, test := range httpClientTests {
		c.Logf("test %d: %s", i, test.about)
		handler = test.handler
		var resp interface{}
		if test.expectResponse != nil {
			resp = reflect.New(reflect.TypeOf(test.expectResponse).Elem()).Interface()
		}
		err := s.client.Get("/", resp)
		if test.expectError != "" {
			c.Check(err, gc.ErrorMatches, test.expectError)
			c.Check(params.ErrCode(err), gc.Equals, test.expectErrorCode)
			if err, ok := errors.Cause(err).(*params.Error); ok {
				c.Check(err.Info, jc.DeepEquals, test.expectErrorInfo)
			} else if test.expectErrorInfo != nil {
				c.Fatalf("no error info found in error")
			}
			continue
		}
		c.Check(err, gc.IsNil)
		c.Check(resp, jc.DeepEquals, test.expectResponse)
	}
}