1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package kvstore_test
4
5import (
6 "context"
7 "sync"
8 "testing"
9
10 "github.com/stretchr/testify/assert"
11 "github.com/stretchr/testify/require"
12)
13
14// The key is generated once and survives a restart; the epoch counts up and
15// survives it too.
16func TestSessionsPersist(t *testing.T) {
17 ctx := context.Background()
18 dir := t.TempDir()
19 s := openStore(t, dir)
20
21 key, err := s.Sessions().Key(ctx)
22 require.NoError(t, err)
23 assert.Len(t, key, 32)
24 again, err := s.Sessions().Key(ctx)
25 require.NoError(t, err)
26 assert.Equal(t, key, again)
27
28 e, err := s.Sessions().Epoch(ctx)
29 require.NoError(t, err)
30 assert.Zero(t, e)
31 for want := uint64(1); want <= 3; want++ {
32 got, err := s.Sessions().BumpEpoch(ctx)
33 require.NoError(t, err)
34 assert.Equal(t, want, got)
35 }
36 require.NoError(t, s.Close(ctx))
37
38 s = openStore(t, dir)
39 reopened, err := s.Sessions().Key(ctx)
40 require.NoError(t, err)
41 assert.Equal(t, key, reopened, "a restart keeps the key")
42 e, err = s.Sessions().Epoch(ctx)
43 require.NoError(t, err)
44 assert.Equal(t, uint64(3), e)
45}
46
47// Concurrent bumps never give the same epoch twice, and concurrent first
48// reads agree on one key.
49func TestSessionsConcurrent(t *testing.T) {
50 ctx := context.Background()
51 s := openStore(t, t.TempDir())
52 var wg sync.WaitGroup
53 keys := make([][]byte, 8)
54 epochs := make(chan uint64, 8)
55 for i := range 8 {
56 wg.Add(1)
57 go func() {
58 defer wg.Done()
59 k, err := s.Sessions().Key(ctx)
60 assert.NoError(t, err)
61 keys[i] = k
62 if e, err := s.Sessions().BumpEpoch(ctx); err == nil {
63 epochs <- e
64 }
65 }()
66 }
67 wg.Wait()
68 close(epochs)
69 for _, k := range keys[1:] {
70 assert.Equal(t, keys[0], k)
71 }
72 seen := map[uint64]bool{}
73 for e := range epochs {
74 assert.False(t, seen[e], "epoch %d twice", e)
75 seen[e] = true
76 }
77}