storage/conformance: expand transaction test suite

This commit is contained in:
Eric Chiang 2016-10-31 23:01:31 -07:00
parent 52e2a1668c
commit 786e12b15e

View file

@ -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")
}
} }
} }