~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/cmd/juju/user/change_password_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2014 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package user_test
 
5
 
 
6
import (
 
7
        "strings"
 
8
 
 
9
        "github.com/juju/cmd"
 
10
        "github.com/juju/errors"
 
11
        "github.com/juju/testing"
 
12
        jc "github.com/juju/testing/checkers"
 
13
        gc "gopkg.in/check.v1"
 
14
        "gopkg.in/juju/names.v2"
 
15
        "gopkg.in/macaroon.v1"
 
16
 
 
17
        "github.com/juju/juju/cmd/juju/user"
 
18
        "github.com/juju/juju/jujuclient"
 
19
        "github.com/juju/juju/jujuclient/jujuclienttesting"
 
20
        coretesting "github.com/juju/juju/testing"
 
21
)
 
22
 
 
23
type ChangePasswordCommandSuite struct {
 
24
        BaseSuite
 
25
        mockAPI *mockChangePasswordAPI
 
26
        store   jujuclient.ClientStore
 
27
}
 
28
 
 
29
var _ = gc.Suite(&ChangePasswordCommandSuite{})
 
30
 
 
31
func (s *ChangePasswordCommandSuite) SetUpTest(c *gc.C) {
 
32
        s.BaseSuite.SetUpTest(c)
 
33
        s.mockAPI = &mockChangePasswordAPI{}
 
34
        s.store = s.BaseSuite.store
 
35
}
 
36
 
 
37
func (s *ChangePasswordCommandSuite) run(c *gc.C, args ...string) (*cmd.Context, error) {
 
38
        changePasswordCommand, _ := user.NewChangePasswordCommandForTest(s.mockAPI, s.store)
 
39
        ctx := coretesting.Context(c)
 
40
        ctx.Stdin = strings.NewReader("sekrit\nsekrit\n")
 
41
        err := coretesting.InitCommand(changePasswordCommand, args)
 
42
        if err != nil {
 
43
                return ctx, err
 
44
        }
 
45
        return ctx, changePasswordCommand.Run(ctx)
 
46
}
 
47
 
 
48
func (s *ChangePasswordCommandSuite) TestInit(c *gc.C) {
 
49
        for i, test := range []struct {
 
50
                args        []string
 
51
                user        string
 
52
                errorString string
 
53
        }{
 
54
                {
 
55
                // no args is fine
 
56
                }, {
 
57
                        args: []string{"foobar"},
 
58
                        user: "foobar",
 
59
                }, {
 
60
                        args:        []string{"--foobar"},
 
61
                        errorString: "flag provided but not defined: --foobar",
 
62
                }, {
 
63
                        args:        []string{"foobar", "extra"},
 
64
                        errorString: `unrecognized args: \["extra"\]`,
 
65
                },
 
66
        } {
 
67
                c.Logf("test %d", i)
 
68
                wrappedCommand, command := user.NewChangePasswordCommandForTest(nil, s.store)
 
69
                err := coretesting.InitCommand(wrappedCommand, test.args)
 
70
                if test.errorString == "" {
 
71
                        c.Check(command.User, gc.Equals, test.user)
 
72
                } else {
 
73
                        c.Check(err, gc.ErrorMatches, test.errorString)
 
74
                }
 
75
        }
 
76
}
 
77
 
 
78
func (s *ChangePasswordCommandSuite) assertAPICalls(c *gc.C, user, pass string) {
 
79
        var offset int
 
80
        if user == "current-user@local" {
 
81
                s.mockAPI.CheckCall(c, 0, "CreateLocalLoginMacaroon", names.NewUserTag(user))
 
82
                offset += 1
 
83
        }
 
84
        s.mockAPI.CheckCall(c, offset, "SetPassword", user, pass)
 
85
}
 
86
 
 
87
func (s *ChangePasswordCommandSuite) TestChangePassword(c *gc.C) {
 
88
        context, err := s.run(c)
 
89
        c.Assert(err, jc.ErrorIsNil)
 
90
        s.assertAPICalls(c, "current-user@local", "sekrit")
 
91
        c.Assert(coretesting.Stdout(context), gc.Equals, "")
 
92
        c.Assert(coretesting.Stderr(context), gc.Equals, `
 
93
password: 
 
94
type password again: 
 
95
Your password has been updated.
 
96
`[1:])
 
97
}
 
98
 
 
99
func (s *ChangePasswordCommandSuite) TestChangePasswordFail(c *gc.C) {
 
100
        s.mockAPI.SetErrors(nil, errors.New("failed to do something"))
 
101
        _, err := s.run(c)
 
102
        c.Assert(err, gc.ErrorMatches, "failed to do something")
 
103
        s.assertAPICalls(c, "current-user@local", "sekrit")
 
104
}
 
105
 
 
106
// We create a macaroon, but fail to write it to accounts.yaml.
 
107
// We should not call SetPassword subsequently.
 
108
func (s *ChangePasswordCommandSuite) TestNoSetPasswordAfterFailedWrite(c *gc.C) {
 
109
        store := jujuclienttesting.NewStubStore()
 
110
        store.AccountDetailsFunc = func(string) (*jujuclient.AccountDetails, error) {
 
111
                return &jujuclient.AccountDetails{"user", "old-password", ""}, nil
 
112
        }
 
113
        store.ControllerByNameFunc = func(string) (*jujuclient.ControllerDetails, error) {
 
114
                return &jujuclient.ControllerDetails{}, nil
 
115
        }
 
116
        s.store = store
 
117
        store.SetErrors(nil, errors.New("failed to write"))
 
118
 
 
119
        _, err := s.run(c)
 
120
        c.Assert(err, gc.ErrorMatches, "failed to update client credentials: failed to write")
 
121
        s.mockAPI.CheckCallNames(c, "CreateLocalLoginMacaroon") // no SetPassword
 
122
}
 
123
 
 
124
func (s *ChangePasswordCommandSuite) TestChangeOthersPassword(c *gc.C) {
 
125
        // The checks for user existence and admin rights are tested
 
126
        // at the apiserver level.
 
127
        _, err := s.run(c, "other")
 
128
        c.Assert(err, jc.ErrorIsNil)
 
129
        s.assertAPICalls(c, "other@local", "sekrit")
 
130
}
 
131
 
 
132
type mockChangePasswordAPI struct {
 
133
        testing.Stub
 
134
}
 
135
 
 
136
func (m *mockChangePasswordAPI) CreateLocalLoginMacaroon(tag names.UserTag) (*macaroon.Macaroon, error) {
 
137
        m.MethodCall(m, "CreateLocalLoginMacaroon", tag)
 
138
        if err := m.NextErr(); err != nil {
 
139
                return nil, err
 
140
        }
 
141
        return fakeLocalLoginMacaroon(tag), nil
 
142
}
 
143
 
 
144
func (m *mockChangePasswordAPI) SetPassword(username, password string) error {
 
145
        m.MethodCall(m, "SetPassword", username, password)
 
146
        return m.NextErr()
 
147
}
 
148
 
 
149
func (*mockChangePasswordAPI) Close() error {
 
150
        return nil
 
151
}
 
152
 
 
153
func fakeLocalLoginMacaroon(tag names.UserTag) *macaroon.Macaroon {
 
154
        mac, err := macaroon.New([]byte("abcdefghijklmnopqrstuvwx"), tag.Canonical(), "juju")
 
155
        if err != nil {
 
156
                panic(err)
 
157
        }
 
158
        return mac
 
159
}