storage/conformance: expand transaction test suite
This commit is contained in:
		@@ -4,6 +4,9 @@ package conformance
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/crypto/bcrypt"
 | 
			
		||||
 | 
			
		||||
	"github.com/coreos/dex/storage"
 | 
			
		||||
)
 | 
			
		||||
@@ -17,7 +20,10 @@ import (
 | 
			
		||||
// conformance.
 | 
			
		||||
func RunTransactionTests(t *testing.T, newStorage func() storage.Storage) {
 | 
			
		||||
	runTests(t, newStorage, []subTest{
 | 
			
		||||
		{"AuthRequestConcurrentUpdate", testAuthRequestConcurrentUpdate},
 | 
			
		||||
		{"ClientConcurrentUpdate", testClientConcurrentUpdate},
 | 
			
		||||
		{"PasswordConcurrentUpdate", testPasswordConcurrentUpdate},
 | 
			
		||||
		{"KeysConcurrentUpdate", testKeysConcurrentUpdate},
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -45,10 +51,124 @@ func testClientConcurrentUpdate(t *testing.T, s storage.Storage) {
 | 
			
		||||
		return old, nil
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Logf("update1: %v", err1)
 | 
			
		||||
	t.Logf("update2: %v", err2)
 | 
			
		||||
 | 
			
		||||
	if err1 == nil && err2 == nil {
 | 
			
		||||
		t.Errorf("update client: concurrent updates both returned no error")
 | 
			
		||||
	if (err1 == nil) == (err2 == nil) {
 | 
			
		||||
		t.Errorf("update client:\nupdate1: %v\nupdate2: %v\n", err1, err2)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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