github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/romulus/agree/agree_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package agree_test 5 6 import ( 7 "runtime" 8 "sync" 9 "testing" 10 11 "github.com/juju/cmd" 12 "github.com/juju/cmd/cmdtesting" 13 "github.com/juju/terms-client/api" 14 "github.com/juju/terms-client/api/wireformat" 15 jujutesting "github.com/juju/testing" 16 jc "github.com/juju/testing/checkers" 17 gc "gopkg.in/check.v1" 18 19 "github.com/juju/juju/cmd/juju/romulus/agree" 20 "github.com/juju/juju/jujuclient" 21 coretesting "github.com/juju/juju/testing" 22 ) 23 24 func TestPackage(t *testing.T) { 25 gc.TestingT(t) 26 } 27 28 var _ = gc.Suite(&agreeSuite{}) 29 30 var testTerms = "Test Terms" 31 32 type agreeSuite struct { 33 client *mockClient 34 coretesting.FakeJujuXDGDataHomeSuite 35 } 36 37 func (s *agreeSuite) SetUpTest(c *gc.C) { 38 s.FakeJujuXDGDataHomeSuite.SetUpTest(c) 39 s.client = &mockClient{} 40 41 jujutesting.PatchValue(agree.ClientNew, func(...api.ClientOption) (api.Client, error) { 42 return s.client, nil 43 }) 44 } 45 46 func (s *agreeSuite) TestAgreementNothingToSign(c *gc.C) { 47 jujutesting.PatchValue(agree.UserAnswer, func() (string, error) { 48 return "y", nil 49 }) 50 51 s.client.user = "test-user" 52 s.client.setUnsignedTerms([]wireformat.GetTermsResponse{}) 53 54 ctx, err := s.runCommand(c, "test-term/1") 55 c.Assert(err, jc.ErrorIsNil) 56 c.Assert(cmdtesting.Stdout(ctx), gc.Equals, `Already agreed 57 `) 58 } 59 60 func (s *agreeSuite) TestAgreement(c *gc.C) { 61 if runtime.GOOS == "windows" { 62 c.Skip("less not on windows, bug 1614330") 63 } 64 var answer string 65 jujutesting.PatchValue(agree.UserAnswer, func() (string, error) { 66 return answer, nil 67 }) 68 69 s.client.user = "test-user" 70 s.client.setUnsignedTerms([]wireformat.GetTermsResponse{{ 71 Name: "test-term", 72 Revision: 1, 73 Content: testTerms, 74 }}) 75 tests := []struct { 76 about string 77 args []string 78 err string 79 stdout string 80 answer string 81 apiCalls []jujutesting.StubCall 82 clientTerms []wireformat.GetTermsResponse 83 }{{ 84 about: "everything works", 85 args: []string{"test-term/1", "--yes"}, 86 stdout: "Agreed to revision 1 of test-term for Juju users\n", 87 apiCalls: []jujutesting.StubCall{{FuncName: "SaveAgreement", Args: []interface{}{&wireformat.SaveAgreements{Agreements: []wireformat.SaveAgreement{{TermName: "test-term", TermRevision: 1}}}}}}, 88 }, { 89 about: "everything works with owner term", 90 args: []string{"owner/test-term/1", "--yes"}, 91 stdout: "Agreed to revision 1 of owner/test-term for Juju users\n", 92 apiCalls: []jujutesting.StubCall{{FuncName: "SaveAgreement", Args: []interface{}{&wireformat.SaveAgreements{Agreements: []wireformat.SaveAgreement{{TermOwner: "owner", TermName: "test-term", TermRevision: 1}}}}}}, 93 }, { 94 about: "cannot parse revision number", 95 args: []string{"test-term/abc"}, 96 err: `must specify a valid term revision "test-term/abc"`, 97 }, { 98 about: "missing arguments", 99 args: []string{}, 100 err: "missing arguments", 101 }, { 102 about: "everything works - user accepts", 103 args: []string{"test-term/1"}, 104 answer: "y", 105 stdout: ` 106 === test-term/1: 0001-01-01 00:00:00 +0000 UTC === 107 Test Terms 108 ======== 109 Do you agree to the displayed terms? (Y/n): Agreed to revision 1 of test-term for Juju users 110 `, 111 apiCalls: []jujutesting.StubCall{{ 112 FuncName: "GetUnunsignedTerms", Args: []interface{}{ 113 &wireformat.CheckAgreementsRequest{Terms: []string{"test-term/1"}}, 114 }, 115 }, { 116 FuncName: "SaveAgreement", Args: []interface{}{ 117 &wireformat.SaveAgreements{Agreements: []wireformat.SaveAgreement{{TermName: "test-term", TermRevision: 1}}}, 118 }, 119 }}, 120 }, { 121 about: "everything works - user refuses", 122 args: []string{"test-term/1"}, 123 answer: "n", 124 stdout: ` 125 === test-term/1: 0001-01-01 00:00:00 +0000 UTC === 126 Test Terms 127 ======== 128 Do you agree to the displayed terms? (Y/n): You didn't agree to the presented terms. 129 `, 130 apiCalls: []jujutesting.StubCall{{ 131 FuncName: "GetUnunsignedTerms", Args: []interface{}{ 132 &wireformat.CheckAgreementsRequest{Terms: []string{"test-term/1"}}, 133 }, 134 }}, 135 }, { 136 about: "must not accept 0 revision", 137 args: []string{"test-term/0", "--yes"}, 138 err: `must specify a valid term revision "test-term/0"`, 139 }, { 140 about: "user accepts, multiple terms", 141 args: []string{"test-term/1", "test-term/2"}, 142 answer: "y", 143 stdout: ` 144 === test-term/1: 0001-01-01 00:00:00 +0000 UTC === 145 Test Terms 146 ======== 147 Do you agree to the displayed terms? (Y/n): Agreed to revision 1 of test-term for Juju users 148 `, 149 apiCalls: []jujutesting.StubCall{ 150 { 151 FuncName: "GetUnunsignedTerms", Args: []interface{}{ 152 &wireformat.CheckAgreementsRequest{Terms: []string{"test-term/1", "test-term/2"}}, 153 }, 154 }, { 155 FuncName: "SaveAgreement", Args: []interface{}{ 156 &wireformat.SaveAgreements{Agreements: []wireformat.SaveAgreement{ 157 {TermName: "test-term", TermRevision: 1}, 158 }}, 159 }, 160 }}, 161 }, { 162 about: "valid then unknown arguments", 163 args: []string{"test-term/1", "unknown", "arguments"}, 164 err: `must specify a valid term revision "unknown"`, 165 }, { 166 about: "user accepts all the terms", 167 args: []string{"test-term/1", "test-term/2", "--yes"}, 168 stdout: `Agreed to revision 1 of test-term for Juju users 169 Agreed to revision 2 of test-term for Juju users 170 `, 171 apiCalls: []jujutesting.StubCall{ 172 {FuncName: "SaveAgreement", Args: []interface{}{&wireformat.SaveAgreements{ 173 Agreements: []wireformat.SaveAgreement{ 174 {TermName: "test-term", TermRevision: 1}, 175 {TermName: "test-term", TermRevision: 2}, 176 }}}}}, 177 }, { 178 about: "everything works with term owner - user accepts", 179 clientTerms: []wireformat.GetTermsResponse{{ 180 Name: "test-term", 181 Owner: "test-owner", 182 Revision: 1, 183 Content: testTerms, 184 }}, 185 args: []string{"test-owner/test-term/1"}, 186 answer: "y", 187 stdout: ` 188 === test-owner/test-term/1: 0001-01-01 00:00:00 +0000 UTC === 189 Test Terms 190 ======== 191 Do you agree to the displayed terms? (Y/n): Agreed to revision 1 of test-owner/test-term for Juju users 192 `, 193 apiCalls: []jujutesting.StubCall{{ 194 FuncName: "GetUnunsignedTerms", Args: []interface{}{ 195 &wireformat.CheckAgreementsRequest{Terms: []string{"test-owner/test-term/1"}}, 196 }, 197 }, { 198 FuncName: "SaveAgreement", Args: []interface{}{ 199 &wireformat.SaveAgreements{Agreements: []wireformat.SaveAgreement{{TermOwner: "test-owner", TermName: "test-term", TermRevision: 1}}}, 200 }, 201 }}, 202 }} 203 for i, test := range tests { 204 s.client.ResetCalls() 205 if len(test.clientTerms) > 0 { 206 s.client.setUnsignedTerms(test.clientTerms) 207 } 208 c.Logf("running test %d: %s", i, test.about) 209 if test.answer != "" { 210 answer = test.answer 211 } 212 ctx, err := s.runCommand(c, test.args...) 213 if test.err != "" { 214 c.Assert(err, gc.ErrorMatches, test.err) 215 } else { 216 c.Assert(err, jc.ErrorIsNil) 217 } 218 if ctx != nil { 219 c.Assert(cmdtesting.Stdout(ctx), gc.Equals, test.stdout) 220 } 221 if len(test.apiCalls) > 0 { 222 s.client.CheckCalls(c, test.apiCalls) 223 } 224 } 225 } 226 227 func (s *agreeSuite) runCommand(c *gc.C, args ...string) (*cmd.Context, error) { 228 cmd := agree.NewAgreeCommand() 229 cmd.SetClientStore(newMockStore()) 230 return cmdtesting.RunCommand(c, cmd, args...) 231 } 232 233 type mockClient struct { 234 api.Client 235 jujutesting.Stub 236 237 lock sync.Mutex 238 user string 239 terms []wireformat.GetTermsResponse 240 unsignedTerms []wireformat.GetTermsResponse 241 } 242 243 func (c *mockClient) setUnsignedTerms(t []wireformat.GetTermsResponse) { 244 c.lock.Lock() 245 defer c.lock.Unlock() 246 c.unsignedTerms = t 247 } 248 249 // SaveAgreement saves user's agreement to the specified 250 // revision of the terms documents 251 func (c *mockClient) SaveAgreement(p *wireformat.SaveAgreements) (*wireformat.SaveAgreementResponses, error) { 252 c.AddCall("SaveAgreement", p) 253 responses := make([]wireformat.AgreementResponse, len(p.Agreements)) 254 for i, agreement := range p.Agreements { 255 responses[i] = wireformat.AgreementResponse{ 256 User: c.user, 257 Owner: agreement.TermOwner, 258 Term: agreement.TermName, 259 Revision: agreement.TermRevision, 260 } 261 } 262 return &wireformat.SaveAgreementResponses{responses}, nil 263 } 264 265 func (c *mockClient) GetUnsignedTerms(p *wireformat.CheckAgreementsRequest) ([]wireformat.GetTermsResponse, error) { 266 c.MethodCall(c, "GetUnunsignedTerms", p) 267 r := make([]wireformat.GetTermsResponse, len(c.unsignedTerms)) 268 copy(r, c.unsignedTerms) 269 return r, nil 270 } 271 272 func (c *mockClient) GetUsersAgreements() ([]wireformat.AgreementResponse, error) { 273 c.MethodCall(c, "GetUsersAgreements") 274 return []wireformat.AgreementResponse{}, nil 275 } 276 277 func newMockStore() *jujuclient.MemStore { 278 store := jujuclient.NewMemStore() 279 store.CurrentControllerName = "foo" 280 store.Controllers["foo"] = jujuclient.ControllerDetails{ 281 APIEndpoints: []string{"0.1.2.3:1234"}, 282 } 283 return store 284 }