github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/cliconfig/credentials/native_store_test.go (about) 1 package credentials 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "strings" 9 "testing" 10 11 "github.com/docker/engine-api/types" 12 ) 13 14 const ( 15 validServerAddress = "https://index.docker.io/v1" 16 validServerAddress2 = "https://example.com:5002" 17 invalidServerAddress = "https://foobar.example.com" 18 missingCredsAddress = "https://missing.docker.io/v1" 19 ) 20 21 var errCommandExited = fmt.Errorf("exited 1") 22 23 // mockCommand simulates interactions between the docker client and a remote 24 // credentials helper. 25 // Unit tests inject this mocked command into the remote to control execution. 26 type mockCommand struct { 27 arg string 28 input io.Reader 29 } 30 31 // Output returns responses from the remote credentials helper. 32 // It mocks those reponses based in the input in the mock. 33 func (m *mockCommand) Output() ([]byte, error) { 34 in, err := ioutil.ReadAll(m.input) 35 if err != nil { 36 return nil, err 37 } 38 inS := string(in) 39 40 switch m.arg { 41 case "erase": 42 switch inS { 43 case validServerAddress: 44 return nil, nil 45 default: 46 return []byte("error erasing credentials"), errCommandExited 47 } 48 case "get": 49 switch inS { 50 case validServerAddress, validServerAddress2: 51 return []byte(`{"Username": "foo", "Password": "bar"}`), nil 52 case missingCredsAddress: 53 return []byte(errCredentialsNotFound.Error()), errCommandExited 54 case invalidServerAddress: 55 return []byte("error getting credentials"), errCommandExited 56 } 57 case "store": 58 var c credentialsRequest 59 err := json.NewDecoder(strings.NewReader(inS)).Decode(&c) 60 if err != nil { 61 return []byte("error storing credentials"), errCommandExited 62 } 63 switch c.ServerURL { 64 case validServerAddress: 65 return nil, nil 66 default: 67 return []byte("error storing credentials"), errCommandExited 68 } 69 } 70 71 return []byte(fmt.Sprintf("unknown argument %q with %q", m.arg, inS)), errCommandExited 72 } 73 74 // Input sets the input to send to a remote credentials helper. 75 func (m *mockCommand) Input(in io.Reader) { 76 m.input = in 77 } 78 79 func mockCommandFn(args ...string) command { 80 return &mockCommand{ 81 arg: args[0], 82 } 83 } 84 85 func TestNativeStoreAddCredentials(t *testing.T) { 86 f := newConfigFile(make(map[string]types.AuthConfig)) 87 f.CredentialsStore = "mock" 88 89 s := &nativeStore{ 90 commandFn: mockCommandFn, 91 fileStore: NewFileStore(f), 92 } 93 err := s.Store(types.AuthConfig{ 94 Username: "foo", 95 Password: "bar", 96 Email: "foo@example.com", 97 ServerAddress: validServerAddress, 98 }) 99 100 if err != nil { 101 t.Fatal(err) 102 } 103 104 if len(f.AuthConfigs) != 1 { 105 t.Fatalf("expected 1 auth config, got %d", len(f.AuthConfigs)) 106 } 107 108 a, ok := f.AuthConfigs[validServerAddress] 109 if !ok { 110 t.Fatalf("expected auth for %s, got %v", validServerAddress, f.AuthConfigs) 111 } 112 if a.Auth != "" { 113 t.Fatalf("expected auth to be empty, got %s", a.Auth) 114 } 115 if a.Username != "" { 116 t.Fatalf("expected username to be empty, got %s", a.Username) 117 } 118 if a.Password != "" { 119 t.Fatalf("expected password to be empty, got %s", a.Password) 120 } 121 if a.Email != "foo@example.com" { 122 t.Fatalf("expected email `foo@example.com`, got %s", a.Email) 123 } 124 } 125 126 func TestNativeStoreAddInvalidCredentials(t *testing.T) { 127 f := newConfigFile(make(map[string]types.AuthConfig)) 128 f.CredentialsStore = "mock" 129 130 s := &nativeStore{ 131 commandFn: mockCommandFn, 132 fileStore: NewFileStore(f), 133 } 134 err := s.Store(types.AuthConfig{ 135 Username: "foo", 136 Password: "bar", 137 Email: "foo@example.com", 138 ServerAddress: invalidServerAddress, 139 }) 140 141 if err == nil { 142 t.Fatal("expected error, got nil") 143 } 144 145 if err.Error() != "error storing credentials" { 146 t.Fatalf("expected `error storing credentials`, got %v", err) 147 } 148 149 if len(f.AuthConfigs) != 0 { 150 t.Fatalf("expected 0 auth config, got %d", len(f.AuthConfigs)) 151 } 152 } 153 154 func TestNativeStoreGet(t *testing.T) { 155 f := newConfigFile(map[string]types.AuthConfig{ 156 validServerAddress: { 157 Email: "foo@example.com", 158 }, 159 }) 160 f.CredentialsStore = "mock" 161 162 s := &nativeStore{ 163 commandFn: mockCommandFn, 164 fileStore: NewFileStore(f), 165 } 166 a, err := s.Get(validServerAddress) 167 if err != nil { 168 t.Fatal(err) 169 } 170 171 if a.Username != "foo" { 172 t.Fatalf("expected username `foo`, got %s", a.Username) 173 } 174 if a.Password != "bar" { 175 t.Fatalf("expected password `bar`, got %s", a.Password) 176 } 177 if a.Email != "foo@example.com" { 178 t.Fatalf("expected email `foo@example.com`, got %s", a.Email) 179 } 180 } 181 182 func TestNativeStoreGetAll(t *testing.T) { 183 f := newConfigFile(map[string]types.AuthConfig{ 184 validServerAddress: { 185 Email: "foo@example.com", 186 }, 187 validServerAddress2: { 188 Email: "foo@example2.com", 189 }, 190 }) 191 f.CredentialsStore = "mock" 192 193 s := &nativeStore{ 194 commandFn: mockCommandFn, 195 fileStore: NewFileStore(f), 196 } 197 as, err := s.GetAll() 198 if err != nil { 199 t.Fatal(err) 200 } 201 202 if len(as) != 2 { 203 t.Fatalf("wanted 2, got %d", len(as)) 204 } 205 206 if as[validServerAddress].Username != "foo" { 207 t.Fatalf("expected username `foo` for %s, got %s", validServerAddress, as[validServerAddress].Username) 208 } 209 if as[validServerAddress].Password != "bar" { 210 t.Fatalf("expected password `bar` for %s, got %s", validServerAddress, as[validServerAddress].Password) 211 } 212 if as[validServerAddress].Email != "foo@example.com" { 213 t.Fatalf("expected email `foo@example.com` for %s, got %s", validServerAddress, as[validServerAddress].Email) 214 } 215 if as[validServerAddress2].Username != "foo" { 216 t.Fatalf("expected username `foo` for %s, got %s", validServerAddress2, as[validServerAddress2].Username) 217 } 218 if as[validServerAddress2].Password != "bar" { 219 t.Fatalf("expected password `bar` for %s, got %s", validServerAddress2, as[validServerAddress2].Password) 220 } 221 if as[validServerAddress2].Email != "foo@example2.com" { 222 t.Fatalf("expected email `foo@example2.com` for %s, got %s", validServerAddress2, as[validServerAddress2].Email) 223 } 224 } 225 226 func TestNativeStoreGetMissingCredentials(t *testing.T) { 227 f := newConfigFile(map[string]types.AuthConfig{ 228 validServerAddress: { 229 Email: "foo@example.com", 230 }, 231 }) 232 f.CredentialsStore = "mock" 233 234 s := &nativeStore{ 235 commandFn: mockCommandFn, 236 fileStore: NewFileStore(f), 237 } 238 _, err := s.Get(missingCredsAddress) 239 if err != nil { 240 // missing credentials do not produce an error 241 t.Fatal(err) 242 } 243 } 244 245 func TestNativeStoreGetInvalidAddress(t *testing.T) { 246 f := newConfigFile(map[string]types.AuthConfig{ 247 validServerAddress: { 248 Email: "foo@example.com", 249 }, 250 }) 251 f.CredentialsStore = "mock" 252 253 s := &nativeStore{ 254 commandFn: mockCommandFn, 255 fileStore: NewFileStore(f), 256 } 257 _, err := s.Get(invalidServerAddress) 258 if err == nil { 259 t.Fatal("expected error, got nil") 260 } 261 262 if err.Error() != "error getting credentials" { 263 t.Fatalf("expected `error getting credentials`, got %v", err) 264 } 265 } 266 267 func TestNativeStoreErase(t *testing.T) { 268 f := newConfigFile(map[string]types.AuthConfig{ 269 validServerAddress: { 270 Email: "foo@example.com", 271 }, 272 }) 273 f.CredentialsStore = "mock" 274 275 s := &nativeStore{ 276 commandFn: mockCommandFn, 277 fileStore: NewFileStore(f), 278 } 279 err := s.Erase(validServerAddress) 280 if err != nil { 281 t.Fatal(err) 282 } 283 284 if len(f.AuthConfigs) != 0 { 285 t.Fatalf("expected 0 auth configs, got %d", len(f.AuthConfigs)) 286 } 287 } 288 289 func TestNativeStoreEraseInvalidAddress(t *testing.T) { 290 f := newConfigFile(map[string]types.AuthConfig{ 291 validServerAddress: { 292 Email: "foo@example.com", 293 }, 294 }) 295 f.CredentialsStore = "mock" 296 297 s := &nativeStore{ 298 commandFn: mockCommandFn, 299 fileStore: NewFileStore(f), 300 } 301 err := s.Erase(invalidServerAddress) 302 if err == nil { 303 t.Fatal("expected error, got nil") 304 } 305 306 if err.Error() != "error erasing credentials" { 307 t.Fatalf("expected `error erasing credentials`, got %v", err) 308 } 309 }