Skip to content

Commit

Permalink
Add random seed to tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mpalmi committed Jan 31, 2025
1 parent 14f5f5a commit a5d0025
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 38 deletions.
56 changes: 35 additions & 21 deletions vault/identity_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"fmt"
"math/rand"
"os"
"regexp"
"slices"
"strconv"
Expand All @@ -19,9 +20,7 @@ import (
"github.com/hashicorp/go-hclog"
uuid "github.com/hashicorp/go-uuid"
credGithub "github.com/hashicorp/vault/builtin/credential/github"
"github.com/hashicorp/vault/builtin/credential/userpass"
credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
"github.com/hashicorp/vault/helper/activationflags"
"github.com/hashicorp/vault/helper/identity"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/helper/storagepacker"
Expand Down Expand Up @@ -1456,7 +1455,7 @@ func identityStoreLoadingIsDeterministic(t *testing.T, identityDeduplication boo
Logger: logger,
BuiltinRegistry: corehelpers.NewMockBuiltinRegistry(),
CredentialBackends: map[string]logical.Factory{
"userpass": userpass.Factory,
"userpass": credUserpass.Factory,
},
}

Expand All @@ -1470,6 +1469,14 @@ func identityStoreLoadingIsDeterministic(t *testing.T, identityDeduplication boo

ctx := context.Background()

seedval := rand.Int63()
if os.Getenv("VAULT_TEST_IDENTITY_STORE_DETERMINISTIC_SEED") != "" {
seedval, err = strconv.ParseInt(os.Getenv("VAULT_TEST_IDENTITY_STORE_DETERMINISTIC_SEED"), 10, 64)
require.NoError(t, err)
}
seed := rand.New(rand.NewSource(seedval)) // Seed for deterministic test
defer t.Logf("Test generated with with seed %d", seedval)

// We create 100 entities each with 1 non-local alias and 1 local alias. We
// then randomly create duplicate alias or local alias entries with a
// probability that is unrealistic but ensures we have duplicates on every
Expand All @@ -1478,9 +1485,9 @@ func identityStoreLoadingIsDeterministic(t *testing.T, identityDeduplication boo
name := fmt.Sprintf("entity-%d", i)
alias := fmt.Sprintf("alias-%d", i)
localAlias := fmt.Sprintf("localalias-%d", i)
e := makeEntityForPacker(t, name, c.identityStore.entityPacker)
attachAlias(t, e, alias, upme)
attachAlias(t, e, localAlias, localMe)
e := makeEntityForPacker(t, name, c.identityStore.entityPacker, seed)
attachAlias(t, e, alias, upme, seed)
attachAlias(t, e, localAlias, localMe, seed)
err = TestHelperWriteToStoragePacker(ctx, c.identityStore.entityPacker, e.ID, e)
require.NoError(t, err)

Expand All @@ -1489,35 +1496,35 @@ func identityStoreLoadingIsDeterministic(t *testing.T, identityDeduplication boo
// few double and maybe triple duplicates of each type every few test runs
// and may have duplicates of both types or neither etc.
pDup := 0.3
rnd := rand.Float64()
rnd := seed.Float64()
dupeNum := 1
for rnd < pDup && dupeNum < 10 {
e := makeEntityForPacker(t, fmt.Sprintf("entity-%d-dup-%d", i, dupeNum), c.identityStore.entityPacker)
attachAlias(t, e, alias, upme)
e := makeEntityForPacker(t, fmt.Sprintf("entity-%d-dup-%d", i, dupeNum), c.identityStore.entityPacker, seed)
attachAlias(t, e, alias, upme, seed)
err = TestHelperWriteToStoragePacker(ctx, c.identityStore.entityPacker, e.ID, e)
require.NoError(t, err)
// Toss again to see if we continue
rnd = rand.Float64()
rnd = seed.Float64()
dupeNum++
}
// Toss the coin again to see if there are any local dupes
dupeNum = 1
rnd = rand.Float64()
rnd = seed.Float64()
for rnd < pDup && dupeNum < 10 {
e := makeEntityForPacker(t, fmt.Sprintf("entity-%d-localdup-%d", i, dupeNum), c.identityStore.entityPacker)
attachAlias(t, e, localAlias, localMe)
e := makeEntityForPacker(t, fmt.Sprintf("entity-%d-localdup-%d", i, dupeNum), c.identityStore.entityPacker, seed)
attachAlias(t, e, localAlias, localMe, seed)
err = TestHelperWriteToStoragePacker(ctx, c.identityStore.entityPacker, e.ID, e)
require.NoError(t, err)
rnd = rand.Float64()
rnd = seed.Float64()
dupeNum++
}
// See if we should add entity _name_ duplicates too (with no aliases)
rnd = rand.Float64()
rnd = seed.Float64()
for rnd < pDup {
e := makeEntityForPacker(t, name, c.identityStore.entityPacker)
e := makeEntityForPacker(t, name, c.identityStore.entityPacker, seed)
err = TestHelperWriteToStoragePacker(ctx, c.identityStore.entityPacker, e.ID, e)
require.NoError(t, err)
rnd = rand.Float64()
rnd = seed.Float64()
}
// One more edge case is that it's currently possible as of the time of
// writing for a failure during entity invalidation to result in a permanent
Expand All @@ -1543,21 +1550,21 @@ func identityStoreLoadingIsDeterministic(t *testing.T, identityDeduplication boo
if i%2 == 0 {
alias = fmt.Sprintf("groupalias-%d", i)
}
e := makeGroupWithNameAndAlias(t, name, alias, c.identityStore.groupPacker, upme)
e := makeGroupWithNameAndAlias(t, name, alias, c.identityStore.groupPacker, upme, seed)
err = TestHelperWriteToStoragePacker(ctx, c.identityStore.groupPacker, e.ID, e)
require.NoError(t, err)
}
// Now add 10 groups with the same alias to ensure duplicates don't cause
// non-deterministic behavior.
for i := 0; i <= 10; i++ {
name := fmt.Sprintf("group-dup-%d", i)
e := makeGroupWithNameAndAlias(t, name, "groupalias-dup", c.identityStore.groupPacker, upme)
e := makeGroupWithNameAndAlias(t, name, "groupalias-dup", c.identityStore.groupPacker, upme, seed)
err = TestHelperWriteToStoragePacker(ctx, c.identityStore.groupPacker, e.ID, e)
require.NoError(t, err)
}
// Add a second and third groups with duplicate names too.
for _, name := range []string{"group-0", "group-1", "group-1"} {
e := makeGroupWithNameAndAlias(t, name, "", c.identityStore.groupPacker, upme)
e := makeGroupWithNameAndAlias(t, name, "", c.identityStore.groupPacker, upme, seed)
err = TestHelperWriteToStoragePacker(ctx, c.identityStore.groupPacker, e.ID, e)
require.NoError(t, err)
}
Expand Down Expand Up @@ -1690,7 +1697,14 @@ func TestIdentityStoreLoadingDuplicateReporting(t *testing.T) {

ctx := namespace.RootContext(nil)

identityCreateCaseDuplicates(t, ctx, c, upme, localMe)
seedval := rand.Int63()
if os.Getenv("VAULT_TEST_IDENTITY_STORE_DETERMINISTIC_SEED") != "" {
seedval, err = strconv.ParseInt(os.Getenv("VAULT_TEST_IDENTITY_STORE_DETERMINISTIC_SEED"), 10, 64)
require.NoError(t, err)
}
seed := rand.New(rand.NewSource(seedval)) // Seed for deterministic test
defer t.Logf("Test generated with with seed %d", seedval)
identityCreateCaseDuplicates(t, ctx, c, upme, localMe, seed)

entIdentityStoreDuplicateReportTestSetup(t, ctx, c, rootToken)

Expand Down
36 changes: 19 additions & 17 deletions vault/identity_store_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"errors"
"fmt"
"math/rand"
"strings"
"sync"
"testing"
Expand Down Expand Up @@ -2826,14 +2827,14 @@ func (i *IdentityStore) countEntitiesByMountAccessor(ctx context.Context) (map[s
return byMountAccessor, nil
}

func makeEntityForPacker(t *testing.T, name string, p *storagepacker.StoragePacker) *identity.Entity {
func makeEntityForPacker(t *testing.T, name string, p *storagepacker.StoragePacker, seed *rand.Rand) *identity.Entity {
t.Helper()
return makeEntityForPackerWithNamespace(t, namespace.RootNamespaceID, name, p)
return makeEntityForPackerWithNamespace(t, namespace.RootNamespaceID, name, p, seed)
}

func makeEntityForPackerWithNamespace(t *testing.T, namespaceID, name string, p *storagepacker.StoragePacker) *identity.Entity {
func makeEntityForPackerWithNamespace(t *testing.T, namespaceID, name string, p *storagepacker.StoragePacker, seed *rand.Rand) *identity.Entity {
t.Helper()
id, err := uuid.GenerateUUID()
id, err := uuid.GenerateUUIDWithReader(seed)
require.NoError(t, err)
return &identity.Entity{
ID: id,
Expand All @@ -2843,9 +2844,10 @@ func makeEntityForPackerWithNamespace(t *testing.T, namespaceID, name string, p
}
}

func attachAlias(t *testing.T, e *identity.Entity, name string, me *MountEntry) *identity.Alias {
func attachAlias(t *testing.T, e *identity.Entity, name string, me *MountEntry, seed *rand.Rand) *identity.Alias {
t.Helper()
id, err := uuid.GenerateUUID()

id, err := uuid.GenerateUUIDWithReader(seed)
require.NoError(t, err)
if e.NamespaceID != me.NamespaceID {
panic("mount and entity in different namespaces")
Expand All @@ -2864,7 +2866,7 @@ func attachAlias(t *testing.T, e *identity.Entity, name string, me *MountEntry)
return a
}

func identityCreateCaseDuplicates(t *testing.T, ctx context.Context, c *Core, upme, localme *MountEntry) {
func identityCreateCaseDuplicates(t *testing.T, ctx context.Context, c *Core, upme, localme *MountEntry, seed *rand.Rand) {
t.Helper()

if upme.NamespaceID != localme.NamespaceID {
Expand All @@ -2875,31 +2877,31 @@ func identityCreateCaseDuplicates(t *testing.T, ctx context.Context, c *Core, up
// suffixes.
for i, suffix := range []string{"-case", "-case", "-cAsE"} {
// Entity duplicated by name
e := makeEntityForPackerWithNamespace(t, upme.NamespaceID, "entity"+suffix, c.identityStore.entityPacker)
e := makeEntityForPackerWithNamespace(t, upme.NamespaceID, "entity"+suffix, c.identityStore.entityPacker, seed)
err := TestHelperWriteToStoragePacker(ctx, c.identityStore.entityPacker, e.ID, e)
require.NoError(t, err)

// Entity that isn't a dupe itself but has duplicated aliases
e2 := makeEntityForPackerWithNamespace(t, upme.NamespaceID, fmt.Sprintf("entity-%d", i), c.identityStore.entityPacker)
e2 := makeEntityForPackerWithNamespace(t, upme.NamespaceID, fmt.Sprintf("entity-%d", i), c.identityStore.entityPacker, seed)
// Add local and non-local aliases for this entity (which will also be
// duplicated)
attachAlias(t, e2, "alias"+suffix, upme)
attachAlias(t, e2, "local-alias"+suffix, localme)
attachAlias(t, e2, "alias"+suffix, upme, seed)
attachAlias(t, e2, "local-alias"+suffix, localme, seed)
err = TestHelperWriteToStoragePacker(ctx, c.identityStore.entityPacker, e2.ID, e2)
require.NoError(t, err)

// Group duplicated by name
g := makeGroupWithNameAndAlias(t, "group"+suffix, "", c.identityStore.groupPacker, upme)
g := makeGroupWithNameAndAlias(t, "group"+suffix, "", c.identityStore.groupPacker, upme, seed)
err = TestHelperWriteToStoragePacker(ctx, c.identityStore.groupPacker, g.ID, g)
require.NoError(t, err)
}
}

func makeGroupWithNameAndAlias(t *testing.T, name, alias string, p *storagepacker.StoragePacker, me *MountEntry) *identity.Group {
func makeGroupWithNameAndAlias(t *testing.T, name, alias string, p *storagepacker.StoragePacker, me *MountEntry, seed *rand.Rand) *identity.Group {
t.Helper()
id, err := uuid.GenerateUUID()
id, err := uuid.GenerateUUIDWithReader(seed)
require.NoError(t, err)
id2, err := uuid.GenerateUUID()
id2, err := uuid.GenerateUUIDWithReader(seed)
require.NoError(t, err)
g := &identity.Group{
ID: id,
Expand All @@ -2920,9 +2922,9 @@ func makeGroupWithNameAndAlias(t *testing.T, name, alias string, p *storagepacke
return g
}

func makeLocalAliasWithName(t *testing.T, name, entityID string, bucketKey string, me *MountEntry) *identity.LocalAliases {
func makeLocalAliasWithName(t *testing.T, name, entityID string, bucketKey string, me *MountEntry, seed *rand.Rand) *identity.LocalAliases {
t.Helper()
id, err := uuid.GenerateUUID()
id, err := uuid.GenerateUUIDWithReader(seed)
require.NoError(t, err)
return &identity.LocalAliases{
Aliases: []*identity.Alias{
Expand Down

0 comments on commit a5d0025

Please sign in to comment.