storage/conformance: expand transaction test suite
This commit is contained in:
		| @@ -4,6 +4,9 @@ package conformance | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/crypto/bcrypt" | ||||||
|  |  | ||||||
| 	"github.com/coreos/dex/storage" | 	"github.com/coreos/dex/storage" | ||||||
| ) | ) | ||||||
| @@ -17,7 +20,10 @@ import ( | |||||||
| // conformance. | // conformance. | ||||||
| func RunTransactionTests(t *testing.T, newStorage func() storage.Storage) { | func RunTransactionTests(t *testing.T, newStorage func() storage.Storage) { | ||||||
| 	runTests(t, newStorage, []subTest{ | 	runTests(t, newStorage, []subTest{ | ||||||
|  | 		{"AuthRequestConcurrentUpdate", testAuthRequestConcurrentUpdate}, | ||||||
| 		{"ClientConcurrentUpdate", testClientConcurrentUpdate}, | 		{"ClientConcurrentUpdate", testClientConcurrentUpdate}, | ||||||
|  | 		{"PasswordConcurrentUpdate", testPasswordConcurrentUpdate}, | ||||||
|  | 		{"KeysConcurrentUpdate", testKeysConcurrentUpdate}, | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -45,10 +51,124 @@ func testClientConcurrentUpdate(t *testing.T, s storage.Storage) { | |||||||
| 		return old, nil | 		return old, nil | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Logf("update1: %v", err1) | 	if (err1 == nil) == (err2 == nil) { | ||||||
| 	t.Logf("update2: %v", err2) | 		t.Errorf("update client:\nupdate1: %v\nupdate2: %v\n", err1, err2) | ||||||
|  | 	} | ||||||
| 	if err1 == nil && err2 == nil { | } | ||||||
| 		t.Errorf("update client: concurrent updates both returned no error") |  | ||||||
|  | func testAuthRequestConcurrentUpdate(t *testing.T, s storage.Storage) { | ||||||
|  | 	a := storage.AuthRequest{ | ||||||
|  | 		ID:                  storage.NewID(), | ||||||
|  | 		ClientID:            "foobar", | ||||||
|  | 		ResponseTypes:       []string{"code"}, | ||||||
|  | 		Scopes:              []string{"openid", "email"}, | ||||||
|  | 		RedirectURI:         "https://localhost:80/callback", | ||||||
|  | 		Nonce:               "foo", | ||||||
|  | 		State:               "bar", | ||||||
|  | 		ForceApprovalPrompt: true, | ||||||
|  | 		LoggedIn:            true, | ||||||
|  | 		Expiry:              neverExpire, | ||||||
|  | 		ConnectorID:         "ldap", | ||||||
|  | 		ConnectorData:       []byte(`{"some":"data"}`), | ||||||
|  | 		Claims: storage.Claims{ | ||||||
|  | 			UserID:        "1", | ||||||
|  | 			Username:      "jane", | ||||||
|  | 			Email:         "jane.doe@example.com", | ||||||
|  | 			EmailVerified: true, | ||||||
|  | 			Groups:        []string{"a", "b"}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := s.CreateAuthRequest(a); err != nil { | ||||||
|  | 		t.Fatalf("failed creating auth request: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var err1, err2 error | ||||||
|  |  | ||||||
|  | 	err1 = s.UpdateAuthRequest(a.ID, func(old storage.AuthRequest) (storage.AuthRequest, error) { | ||||||
|  | 		old.State = "state 1" | ||||||
|  | 		err2 = s.UpdateAuthRequest(a.ID, func(old storage.AuthRequest) (storage.AuthRequest, error) { | ||||||
|  | 			old.State = "state 2" | ||||||
|  | 			return old, nil | ||||||
|  | 		}) | ||||||
|  | 		return old, nil | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	if (err1 == nil) == (err2 == nil) { | ||||||
|  | 		t.Errorf("update auth request:\nupdate1: %v\nupdate2: %v\n", err1, err2) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func testPasswordConcurrentUpdate(t *testing.T, s storage.Storage) { | ||||||
|  | 	// Use bcrypt.MinCost to keep the tests short. | ||||||
|  | 	passwordHash, err := bcrypt.GenerateFromPassword([]byte("secret"), bcrypt.MinCost) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	password := storage.Password{ | ||||||
|  | 		Email:    "jane@example.com", | ||||||
|  | 		Hash:     passwordHash, | ||||||
|  | 		Username: "jane", | ||||||
|  | 		UserID:   "foobar", | ||||||
|  | 	} | ||||||
|  | 	if err := s.CreatePassword(password); err != nil { | ||||||
|  | 		t.Fatalf("create password token: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var err1, err2 error | ||||||
|  |  | ||||||
|  | 	err1 = s.UpdatePassword(password.Email, func(old storage.Password) (storage.Password, error) { | ||||||
|  | 		old.Username = "user 1" | ||||||
|  | 		err2 = s.UpdatePassword(password.Email, func(old storage.Password) (storage.Password, error) { | ||||||
|  | 			old.Username = "user 2" | ||||||
|  | 			return old, nil | ||||||
|  | 		}) | ||||||
|  | 		return old, nil | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	if (err1 == nil) == (err2 == nil) { | ||||||
|  | 		t.Errorf("update password: concurrent updates both returned no error") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func testKeysConcurrentUpdate(t *testing.T, s storage.Storage) { | ||||||
|  | 	// Test twice. Once for a create, once for an update. | ||||||
|  | 	for i := 0; i < 2; i++ { | ||||||
|  | 		n := time.Now().UTC().Round(time.Second) | ||||||
|  | 		keys1 := storage.Keys{ | ||||||
|  | 			SigningKey:    jsonWebKeys[0].Private, | ||||||
|  | 			SigningKeyPub: jsonWebKeys[0].Public, | ||||||
|  | 			NextRotation:  n, | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		keys2 := storage.Keys{ | ||||||
|  | 			SigningKey:    jsonWebKeys[2].Private, | ||||||
|  | 			SigningKeyPub: jsonWebKeys[2].Public, | ||||||
|  | 			NextRotation:  n.Add(time.Hour), | ||||||
|  | 			VerificationKeys: []storage.VerificationKey{ | ||||||
|  | 				{ | ||||||
|  | 					PublicKey: jsonWebKeys[0].Public, | ||||||
|  | 					Expiry:    n.Add(time.Hour), | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					PublicKey: jsonWebKeys[1].Public, | ||||||
|  | 					Expiry:    n.Add(time.Hour * 2), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var err1, err2 error | ||||||
|  |  | ||||||
|  | 		err1 = s.UpdateKeys(func(old storage.Keys) (storage.Keys, error) { | ||||||
|  | 			err2 = s.UpdateKeys(func(old storage.Keys) (storage.Keys, error) { | ||||||
|  | 				return keys1, nil | ||||||
|  | 			}) | ||||||
|  | 			return keys2, nil | ||||||
|  | 		}) | ||||||
|  |  | ||||||
|  | 		if (err1 == nil) == (err2 == nil) { | ||||||
|  | 			t.Errorf("update keys: concurrent updates both returned no error") | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user