1 // Copyright © 2010 Fazlul Shahriar <fshahriar@gmail.com> and
2 // Copyright © 2014 Blake Gentry <blakesgentry@gmail.com>.
3 // See LICENSE file for license details.
17 var expectedMachines = []*Machine{
18 &Machine{Name: "mail.google.com", Login: "joe@gmail.com", Password: "somethingSecret", Account: "justagmail"},
19 &Machine{Name: "ray", Login: "demo", Password: "mypassword", Account: ""},
20 &Machine{Name: "weirdlogin", Login: "uname", Password: "pass#pass", Account: ""},
21 &Machine{Name: "google.com", Login: "alice@google.com", Password: "secure"},
22 &Machine{Name: "", Login: "anonymous", Password: "joe@example.com", Account: ""},
24 var expectedMacros = Macros{
25 "allput": "put src/*",
26 "allput2": " put src/*\nput src2/*",
29 func eqMachine(a *Machine, b *Machine) bool {
30 return a.Name == b.Name &&
32 a.Password == b.Password &&
33 a.Account == b.Account
36 func testExpected(n *Netrc, t *testing.T) {
37 if len(expectedMachines) != len(n.machines) {
38 t.Errorf("expected %d machines, got %d", len(expectedMachines), len(n.machines))
40 for i, e := range expectedMachines {
41 if !eqMachine(e, n.machines[i]) {
42 t.Errorf("bad machine; expected %v, got %v\n", e, n.machines[i])
47 if len(expectedMacros) != len(n.macros) {
48 t.Errorf("expected %d macros, got %d", len(expectedMacros), len(n.macros))
50 for k, v := range expectedMacros {
52 t.Errorf("bad macro for %s; expected %q, got %q\n", k, v, n.macros[k])
58 var newTokenTests = []struct {
62 {"machine", tkMachine},
63 {"\n\n\tmachine", tkMachine},
64 {"\n machine", tkMachine},
65 {"default", tkDefault},
67 {"password", tkPassword},
68 {"account", tkAccount},
70 {"\n # comment stuff ", tkComment},
71 {"\n # I am another comment", tkComment},
72 {"\n\t\n ", tkWhitespace},
75 var newTokenInvalidTests = []string{
78 "account#unspaced comment",
81 func TestNewToken(t *testing.T) {
82 for _, tktest := range newTokenTests {
83 tok, err := newToken([]byte(tktest.rawkind))
87 if tok.kind != tktest.tkind {
88 t.Errorf("expected tok.kind %d, got %d", tktest.tkind, tok.kind)
90 if string(tok.rawkind) != tktest.rawkind {
91 t.Errorf("expected tok.rawkind %q, got %q", tktest.rawkind, string(tok.rawkind))
95 for _, tktest := range newTokenInvalidTests {
96 _, err := newToken([]byte(tktest))
98 t.Errorf("expected error with %q, got none", tktest)
103 func TestParse(t *testing.T) {
104 r := netrcReader("examples/good.netrc", t)
112 func TestParseFile(t *testing.T) {
113 n, err := ParseFile("examples/good.netrc")
119 _, err = ParseFile("examples/bad_default_order.netrc")
121 t.Error("expected an error parsing bad_default_order.netrc, got none")
122 } else if !err.(*Error).BadDefaultOrder() {
123 t.Error("expected BadDefaultOrder() to be true, got false")
126 _, err = ParseFile("examples/this_file_doesnt_exist.netrc")
128 t.Error("expected an error loading this_file_doesnt_exist.netrc, got none")
129 } else if _, ok := err.(*os.PathError); !ok {
130 t.Errorf("expected *os.Error, got %v", err)
134 func TestFindMachine(t *testing.T) {
135 m, err := FindMachine("examples/good.netrc", "ray")
139 if !eqMachine(m, expectedMachines[1]) {
140 t.Errorf("bad machine; expected %v, got %v\n", expectedMachines[1], m)
143 t.Errorf("expected m.IsDefault() to be false")
146 m, err = FindMachine("examples/good.netrc", "non.existent")
150 if !eqMachine(m, expectedMachines[4]) {
151 t.Errorf("bad machine; expected %v, got %v\n", expectedMachines[3], m)
154 t.Errorf("expected m.IsDefault() to be true")
158 func TestNetrcFindMachine(t *testing.T) {
159 n, err := ParseFile("examples/good.netrc")
164 m := n.FindMachine("ray")
165 if !eqMachine(m, expectedMachines[1]) {
166 t.Errorf("bad machine; expected %v, got %v\n", expectedMachines[1], m)
169 t.Errorf("expected def to be false")
173 m = n.FindMachine("nonexistent")
175 t.Errorf("expected nil, got %v", m)
179 func TestMarshalText(t *testing.T) {
180 // load up expected netrc Marshal output
181 expected, err := ioutil.ReadAll(netrcReader("examples/good.netrc", t))
186 n, err := ParseFile("examples/good.netrc")
191 result, err := n.MarshalText()
195 if string(result) != string(expected) {
196 t.Errorf("expected:\n%q\ngot:\n%q", string(expected), string(result))
199 // make sure tokens w/ no value are not serialized
200 m := n.FindMachine("mail.google.com")
202 result, err = n.MarshalText()
206 if strings.Contains(string(result), "\tpassword \n") {
207 fmt.Println(string(result))
208 t.Errorf("expected zero-value password token to not be serialzed")
212 var newMachineTests = []struct {
218 {"heroku.com", "dodging-samurai-42@heroku.com", "octocatdodgeballchampions", "2011+2013"},
219 {"bgentry.io", "special@test.com", "noacct", ""},
220 {"github.io", "2@test.com", "", "acctwithnopass"},
221 {"someotherapi.com", "", "passonly", ""},
224 func TestNewMachine(t *testing.T) {
225 n, err := ParseFile("examples/good.netrc")
233 // make sure that tokens without a value are not serialized at all
234 for _, test := range newMachineTests {
236 _ = n.NewMachine(test.name, test.login, test.password, test.account)
238 bodyb, _ := n.MarshalText()
239 body := string(bodyb)
241 // ensure desired values are present when they should be
242 if !strings.Contains(body, "machine") {
243 t.Errorf("NewMachine() %s missing keyword 'machine'", test.name)
245 if !strings.Contains(body, test.name) {
246 t.Errorf("NewMachine() %s missing value %q", test.name, test.name)
248 if test.login != "" && !strings.Contains(body, "login "+test.login) {
249 t.Errorf("NewMachine() %s missing value %q", test.name, "login "+test.login)
251 if test.password != "" && !strings.Contains(body, "password "+test.password) {
252 t.Errorf("NewMachine() %s missing value %q", test.name, "password "+test.password)
254 if test.account != "" && !strings.Contains(body, "account "+test.account) {
255 t.Errorf("NewMachine() %s missing value %q", test.name, "account "+test.account)
258 // ensure undesired values are not present when they shouldn't be
259 if test.login == "" && strings.Contains(body, "login") {
260 t.Errorf("NewMachine() %s contains unexpected value %q", test.name, "login")
262 if test.password == "" && strings.Contains(body, "password") {
263 t.Errorf("NewMachine() %s contains unexpected value %q", test.name, "password")
265 if test.account == "" && strings.Contains(body, "account") {
266 t.Errorf("NewMachine() %s contains unexpected value %q", test.name, "account")
271 func testNewMachine(t *testing.T, n *Netrc) {
272 for _, test := range newMachineTests {
273 mcount := len(n.machines)
275 bodyb, _ := n.MarshalText()
276 body := string(bodyb)
277 for _, value := range []string{test.name, test.login, test.password, test.account} {
278 if value != "" && strings.Contains(body, value) {
279 t.Errorf("MarshalText() before NewMachine() contained unexpected %q", value)
283 // test prefix for machine token
285 if len(n.tokens) == 0 {
289 m := n.NewMachine(test.name, test.login, test.password, test.account)
291 t.Fatalf("NewMachine() returned nil")
294 if len(n.machines) != mcount+1 {
295 t.Errorf("n.machines count expected %d, got %d", mcount+1, len(n.machines))
298 if m.Name != test.name {
299 t.Errorf("m.Name expected %q, got %q", test.name, m.Name)
301 if m.Login != test.login {
302 t.Errorf("m.Login expected %q, got %q", test.login, m.Login)
304 if m.Password != test.password {
305 t.Errorf("m.Password expected %q, got %q", test.password, m.Password)
307 if m.Account != test.account {
308 t.Errorf("m.Account expected %q, got %q", test.account, m.Account)
311 checkToken(t, "nametoken", m.nametoken, tkMachine, prefix+"machine", test.name)
312 checkToken(t, "logintoken", m.logintoken, tkLogin, "\n\tlogin", test.login)
313 checkToken(t, "passtoken", m.passtoken, tkPassword, "\n\tpassword", test.password)
314 checkToken(t, "accounttoken", m.accounttoken, tkAccount, "\n\taccount", test.account)
315 // check marshal output
316 bodyb, _ = n.MarshalText()
318 for _, value := range []string{test.name, test.login, test.password, test.account} {
319 if !strings.Contains(body, value) {
320 t.Errorf("MarshalText() after NewMachine() did not include %q as expected", value)
326 func checkToken(t *testing.T, name string, tok *token, kind tkType, rawkind, value string) {
328 t.Errorf("%s not defined", name)
331 if tok.kind != kind {
332 t.Errorf("%s expected kind %d, got %d", name, kind, tok.kind)
334 if string(tok.rawkind) != rawkind {
335 t.Errorf("%s expected rawkind %q, got %q", name, rawkind, string(tok.rawkind))
337 if tok.value != value {
338 t.Errorf("%s expected value %q, got %q", name, value, tok.value)
340 if tok.value != value {
341 t.Errorf("%s expected value %q, got %q", name, value, tok.value)
345 func TestNewMachineGoesBeforeDefault(t *testing.T) {
346 n, err := ParseFile("examples/good.netrc")
350 m := n.NewMachine("mymachine", "mylogin", "mypassword", "myaccount")
351 if m2 := n.machines[len(n.machines)-2]; m2 != m {
352 t.Errorf("expected machine %v, got %v", m, m2)
356 func TestRemoveMachine(t *testing.T) {
357 n, err := ParseFile("examples/good.netrc")
362 tests := []string{"mail.google.com", "weirdlogin"}
364 for _, name := range tests {
365 mcount := len(n.machines)
367 m := n.FindMachine(name)
369 t.Fatalf("machine %q not found", name)
372 t.Fatalf("expected machine %q, got default instead", name)
374 n.RemoveMachine(name)
376 if len(n.machines) != mcount-1 {
377 t.Errorf("n.machines count expected %d, got %d", mcount-1, len(n.machines))
380 // make sure Machine is no longer returned by FindMachine()
381 if m2 := n.FindMachine(name); m2 != nil && !m2.IsDefault() {
382 t.Errorf("Machine %q not removed from Machines list", name)
385 // make sure tokens are not present in tokens list
386 for _, token := range []*token{m.nametoken, m.logintoken, m.passtoken, m.accounttoken} {
388 for _, tok2 := range n.tokens {
390 t.Errorf("token not removed from tokens list: %v", token)
397 bodyb, _ := n.MarshalText()
398 body := string(bodyb)
399 for _, value := range []string{m.Name, m.Login, m.Password, m.Account} {
400 if value != "" && strings.Contains(body, value) {
401 t.Errorf("MarshalText() after RemoveMachine() contained unexpected %q", value)
407 func TestUpdateLogin(t *testing.T) {
408 n, err := ParseFile("examples/good.netrc")
419 {true, "mail.google.com", "joe@gmail.com", "joe2@gmail.com"},
420 {false, "heroku.com", "", "dodging-samurai-42@heroku.com"},
423 bodyb, _ := n.MarshalText()
424 body := string(bodyb)
425 for _, test := range tests {
426 if strings.Contains(body, test.newlogin) {
427 t.Errorf("MarshalText() before UpdateLogin() contained unexpected %q", test.newlogin)
431 for _, test := range tests {
432 m := n.FindMachine(test.name)
433 if m.IsDefault() == test.exists {
434 t.Errorf("expected machine %s to not exist, but it did", test.name)
437 m = n.NewMachine(test.name, test.newlogin, "", "")
440 t.Errorf("machine %s was nil", test.name)
443 m.UpdateLogin(test.newlogin)
444 m := n.FindMachine(test.name)
445 if m.Login != test.newlogin {
446 t.Errorf("expected new login %q, got %q", test.newlogin, m.Login)
448 if m.logintoken.value != test.newlogin {
449 t.Errorf("expected m.logintoken %q, got %q", test.newlogin, m.logintoken.value)
454 bodyb, _ = n.MarshalText()
456 for _, test := range tests {
457 if test.exists && strings.Contains(body, test.oldlogin) {
458 t.Errorf("MarshalText() after UpdateLogin() contained unexpected %q", test.oldlogin)
460 if !strings.Contains(body, test.newlogin) {
461 t.Errorf("MarshalText after UpdatePassword did not contain %q as expected", test.newlogin)
466 func TestUpdatePassword(t *testing.T) {
467 n, err := ParseFile("examples/good.netrc")
478 {true, "ray", "mypassword", "supernewpass"},
479 {false, "heroku.com", "", "octocatdodgeballchampions"},
482 bodyb, _ := n.MarshalText()
483 body := string(bodyb)
484 for _, test := range tests {
485 if test.exists && !strings.Contains(body, test.oldpassword) {
486 t.Errorf("MarshalText() before UpdatePassword() did not include %q as expected", test.oldpassword)
488 if strings.Contains(body, test.newpassword) {
489 t.Errorf("MarshalText() before UpdatePassword() contained unexpected %q", test.newpassword)
493 for _, test := range tests {
494 m := n.FindMachine(test.name)
495 if m.IsDefault() == test.exists {
496 t.Errorf("expected machine %s to not exist, but it did", test.name)
499 m = n.NewMachine(test.name, "", test.newpassword, "")
502 t.Errorf("machine %s was nil", test.name)
505 m.UpdatePassword(test.newpassword)
506 m = n.FindMachine(test.name)
507 if m.Password != test.newpassword {
508 t.Errorf("expected new password %q, got %q", test.newpassword, m.Password)
510 if m.passtoken.value != test.newpassword {
511 t.Errorf("expected m.passtoken %q, got %q", test.newpassword, m.passtoken.value)
516 bodyb, _ = n.MarshalText()
518 for _, test := range tests {
519 if test.exists && strings.Contains(body, test.oldpassword) {
520 t.Errorf("MarshalText() after UpdatePassword() contained unexpected %q", test.oldpassword)
522 if !strings.Contains(body, test.newpassword) {
523 t.Errorf("MarshalText() after UpdatePassword() did not contain %q as expected", test.newpassword)
528 func TestNewFile(t *testing.T) {
531 result, err := n.MarshalText()
535 if string(result) != "" {
536 t.Errorf("expected empty result=\"\", got %q", string(result))
539 n.NewMachine("netrctest.heroku.com", "auser", "apassword", "")
541 result, err = n.MarshalText()
545 expected := `machine netrctest.heroku.com
549 if string(result) != expected {
550 t.Errorf("expected result:\n%q\ngot:\n%q", expected, string(result))
554 func netrcReader(filename string, t *testing.T) io.Reader {
555 b, err := ioutil.ReadFile(filename)
559 return bytes.NewReader(b)