auth
2015-02-20
Child:e090a69e711f
auth/scope_test.go
Introduced scopes. Created a Scope type and a scopeStore interface, along with the memstore methods for the scopeStore. This will allow applications to define access with granularity, so users can grant access to some data, not _all_ data. We're operating on the assumption that there won't be an unreasonable number of scopes defined, so there is no paging operation included for the ListScopes method. This is a decision that may have to be revisited in the future, depending on usecases.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/scope_test.go Fri Feb 20 22:34:43 2015 -0500 1.3 @@ -0,0 +1,197 @@ 1.4 +package auth 1.5 + 1.6 +import "testing" 1.7 + 1.8 +var scopeStores = []scopeStore{NewMemstore()} 1.9 + 1.10 +func compareScopes(scope1, scope2 Scope) (success bool, field string, val1, val2 interface{}) { 1.11 + if scope1.ID != scope2.ID { 1.12 + return false, "ID", scope1.ID, scope2.ID 1.13 + } 1.14 + if scope1.Name != scope2.Name { 1.15 + return false, "Name", scope1.Name, scope2.Name 1.16 + } 1.17 + if scope1.Description != scope2.Description { 1.18 + return false, "Description", scope1.Description, scope2.Description 1.19 + } 1.20 + return true, "", nil, nil 1.21 +} 1.22 + 1.23 +func TestScopeInScopeStore(t *testing.T) { 1.24 + scope := Scope{ 1.25 + ID: "testscope", 1.26 + Name: "Test Scope", 1.27 + Description: "Access to testing data.", 1.28 + } 1.29 + scope2 := Scope{ 1.30 + ID: "testscope2", 1.31 + Name: "Test Scope 2", 1.32 + Description: "Access to minions.", 1.33 + } 1.34 + scope3 := Scope{ 1.35 + ID: "testscope3", 1.36 + Name: "Test Scope 3", 1.37 + Description: "Access to bananas.", 1.38 + } 1.39 + updatedName := "Updated Scope" 1.40 + updatedDescription := "An updated scope." 1.41 + update := ScopeChange{ 1.42 + ID: scope.ID, 1.43 + Name: &updatedName, 1.44 + } 1.45 + update2 := ScopeChange{ 1.46 + ID: scope2.ID, 1.47 + Description: &updatedDescription, 1.48 + } 1.49 + update3 := ScopeChange{ 1.50 + ID: scope3.ID, 1.51 + Name: &updatedName, 1.52 + Description: &updatedDescription, 1.53 + } 1.54 + for _, store := range scopeStores { 1.55 + context := Context{scopes: store} 1.56 + retrieved, err := context.GetScopes([]string{scope.ID}) 1.57 + if len(retrieved) != 0 { 1.58 + t.Logf("%+v", retrieved) 1.59 + t.Errorf("Expected %d results, got %d from %T", 0, len(retrieved), store) 1.60 + } 1.61 + if e, ok := err.(ErrScopeNotFound); !ok { 1.62 + t.Errorf("Expected ErrScopeNotFound, got %+v instead for %T", err, store) 1.63 + } else { 1.64 + if e.Pos != 0 { 1.65 + t.Errorf("Expected the error to be in position %d, got position %d from %T", 0, e.Pos, store) 1.66 + } 1.67 + if e.ID != scope.ID { 1.68 + t.Errorf("Expected the error to be with scope %s, got %s from %T", scope.ID, e.ID, store) 1.69 + } 1.70 + } 1.71 + err = context.CreateScopes([]Scope{scope}) 1.72 + if err != nil { 1.73 + t.Errorf("Error saving scope to %T: %s", store, err) 1.74 + } 1.75 + err = context.CreateScopes([]Scope{scope}) 1.76 + if e, ok := err.(ErrScopeAlreadyExists); !ok { 1.77 + t.Errorf("Expected ErrScopeAlreadyExists, got %s instead for %T", err, store) 1.78 + } else { 1.79 + if e.Pos != 0 { 1.80 + t.Errorf("Expected the error to be in position %d, got position %d from %T", 0, e.Pos, store) 1.81 + } 1.82 + if e.ID != scope.ID { 1.83 + t.Errorf("Expected the error to be for ID %s, got %s from %T", scope.ID, e.ID, store) 1.84 + } 1.85 + } 1.86 + retrieved, err = context.GetScopes([]string{scope.ID}) 1.87 + if err != nil { 1.88 + t.Errorf("Unexpected error retrieving scopes from %T: %+v", store, err) 1.89 + } 1.90 + if len(retrieved) != 1 { 1.91 + t.Logf("%+v", retrieved) 1.92 + t.Errorf("Expected %d results, got %d from %T", 1, len(retrieved), store) 1.93 + } 1.94 + success, field, val1, val2 := compareScopes(scope, retrieved[0]) 1.95 + if !success { 1.96 + t.Errorf("Expected %s to be %+v, got %+v from %T", field, val1, val2, store) 1.97 + } 1.98 + err = context.CreateScopes([]Scope{scope2, scope3}) 1.99 + if err != nil { 1.100 + t.Errorf("Unexpected error trying to create scope2 and scope3 in %T: %+v", store, err) 1.101 + } 1.102 + retrieved, err = context.GetScopes([]string{scope.ID, scope2.ID, scope3.ID}) 1.103 + if err != nil { 1.104 + t.Errorf("Unexpected error retrieving scopes from %T: %+v", store, err) 1.105 + } 1.106 + if len(retrieved) != 3 { 1.107 + t.Logf("%+v", retrieved) 1.108 + t.Errorf("Expected %d results, got %d from %T", 3, len(retrieved), store) 1.109 + } 1.110 + for pos, s := range []Scope{scope, scope2, scope3} { 1.111 + success, field, val1, val2 = compareScopes(s, retrieved[pos]) 1.112 + if !success { 1.113 + t.Errorf("Expected %s to be %+v for scope %s, got %+v from %T", field, val1, s.ID, val2, store) 1.114 + } 1.115 + } 1.116 + updated, err := context.UpdateScopes([]ScopeChange{update, update2, update3}) 1.117 + if err != nil { 1.118 + t.Errorf("Unexpected error updating scopes in %T: %+v", store, err) 1.119 + } 1.120 + if len(updated) != 3 { 1.121 + t.Logf("%+v", updated) 1.122 + t.Errorf("Expected %d results, got %d from %T", 3, len(updated), store) 1.123 + } 1.124 + scope.ApplyChange(update) 1.125 + scope2.ApplyChange(update2) 1.126 + scope3.ApplyChange(update3) 1.127 + for pos, s := range []Scope{scope, scope2, scope3} { 1.128 + success, field, val1, val2 = compareScopes(s, updated[pos]) 1.129 + if !success { 1.130 + t.Errorf("Expected %s to be %+v for scope %s, got %+v from %T", field, val1, s.ID, val2, store) 1.131 + } 1.132 + } 1.133 + retrieved, err = context.ListScopes() 1.134 + if err != nil { 1.135 + t.Errorf("Unexpected error retrieving scopes from %T: %+v", store, err) 1.136 + } 1.137 + if len(retrieved) != 3 { 1.138 + t.Logf("%+v", retrieved) 1.139 + t.Errorf("Expected %d results, got %d from %T", 3, len(retrieved), store) 1.140 + } 1.141 + for pos, s := range []Scope{scope, scope2, scope3} { 1.142 + success, field, val1, val2 = compareScopes(s, retrieved[pos]) 1.143 + if !success { 1.144 + t.Errorf("Expected %s to be %+v for scope %s, got $+v from %T", field, val1, s.ID, val2, store) 1.145 + } 1.146 + } 1.147 + err = context.RemoveScopes([]string{scope.ID, scope2.ID, scope3.ID}) 1.148 + if err != nil { 1.149 + t.Errorf("Unexpected error removing scopes from %T: %+v", store, err) 1.150 + } 1.151 + retrieved, err = context.ListScopes() 1.152 + if err != nil { 1.153 + t.Errorf("Unexpected error retrieving scopes from %T: %+v", store, err) 1.154 + } 1.155 + if len(retrieved) != 0 { 1.156 + t.Logf("%+v", retrieved) 1.157 + t.Errorf("Expected %d results, got %d from %T", 0, len(retrieved), store) 1.158 + } 1.159 + err = context.RemoveScopes([]string{scope.ID}) 1.160 + if err == nil { 1.161 + t.Errorf("No error returned removing non-existent scopes from %T", store) 1.162 + } 1.163 + if e, ok := err.(ErrScopeNotFound); !ok { 1.164 + t.Errorf("Unexpected error removing non-existent scopes from %T: %+v", store, err) 1.165 + } else { 1.166 + if e.Pos != 0 { 1.167 + t.Errorf("Expected error to be for scope ID in pos %d, but got %d from %T", 0, e.Pos, store) 1.168 + } 1.169 + if e.ID != scope.ID { 1.170 + t.Errorf("Expected error to be for scope ID %s, but got %s from %T", scope.ID, e.ID, store) 1.171 + } 1.172 + } 1.173 + updated, err = context.UpdateScopes([]ScopeChange{update}) 1.174 + if err == nil { 1.175 + t.Errorf("No error returned updating non-existent scopes from %T", store) 1.176 + } 1.177 + if e, ok := err.(ErrScopeNotFound); !ok { 1.178 + t.Errorf("Unexpected error updating non-existent scopes from %T: %+v", store, err) 1.179 + } else { 1.180 + if e.Pos != 0 { 1.181 + t.Errorf("Expected error to be for scope ID in pos %d, but got %d from %T", 0, e.Pos, store) 1.182 + } 1.183 + if e.ID != scope.ID { 1.184 + t.Errorf("Expected error to be for scope ID %s, but got %s from %T", scope.ID, e.ID, store) 1.185 + } 1.186 + } 1.187 + } 1.188 +} 1.189 + 1.190 +func TestScopeErrors(t *testing.T) { 1.191 + errors := map[string]error{ 1.192 + "scope test couldn't be found": ErrScopeNotFound{ID: "test", Pos: 0}, 1.193 + "scope test already exists": ErrScopeAlreadyExists{ID: "test", Pos: 0}, 1.194 + } 1.195 + for expectation, e := range errors { 1.196 + if e.Error() != expectation { 1.197 + t.Errorf("Expected %+v to produce '%s', produced '%s'", e, expectation, e.Error()) 1.198 + } 1.199 + } 1.200 +}