Monorepo for Tangled
tangled.org
1package db
2
3import (
4 "context"
5 "fmt"
6 "path/filepath"
7 "sync"
8 "testing"
9)
10
11// TestGetOrAssignOwnerUID_Concurrent verifies that concurrent calls for
12// distinct DIDs each get a unique UID, with no duplicates from a race on
13// the uid_counter table.
14func TestGetOrAssignOwnerUID_Concurrent(t *testing.T) {
15 d := newTestDB(t)
16
17 const n = 50
18 results := make([]uint32, n)
19 var wg sync.WaitGroup
20 wg.Add(n)
21 for i := 0; i < n; i++ {
22 go func(i int) {
23 defer wg.Done()
24 uid, err := d.GetOrAssignOwnerUID(fmt.Sprintf("did:plc:test-%03d", i))
25 if err != nil {
26 t.Errorf("GetOrAssignOwnerUID(%d): %v", i, err)
27 return
28 }
29 results[i] = uid
30 }(i)
31 }
32 wg.Wait()
33
34 seen := map[uint32]int{}
35 for i, uid := range results {
36 if uid == 0 {
37 t.Errorf("result[%d] is zero (probably an error above)", i)
38 continue
39 }
40 if prev, ok := seen[uid]; ok {
41 t.Errorf("uid %d was returned for both index %d and %d", uid, prev, i)
42 }
43 seen[uid] = i
44 }
45
46 if len(seen) != n {
47 t.Errorf("got %d unique UIDs, want %d", len(seen), n)
48 }
49}
50
51// TestGetOrAssignOwnerUID_Idempotent verifies that repeated calls for the
52// same DID return the same UID.
53func TestGetOrAssignOwnerUID_Idempotent(t *testing.T) {
54 d := newTestDB(t)
55 const did = "did:plc:stable"
56
57 first, err := d.GetOrAssignOwnerUID(did)
58 if err != nil {
59 t.Fatalf("first call: %v", err)
60 }
61 for i := 0; i < 5; i++ {
62 uid, err := d.GetOrAssignOwnerUID(did)
63 if err != nil {
64 t.Fatalf("repeat call %d: %v", i, err)
65 }
66 if uid != first {
67 t.Errorf("repeat call %d returned %d, want %d", i, uid, first)
68 }
69 }
70}
71
72// TestGetOrAssignOwnerUID_StartsAt100000 verifies the counter seeds correctly.
73func TestGetOrAssignOwnerUID_StartsAt100000(t *testing.T) {
74 d := newTestDB(t)
75 uid, err := d.GetOrAssignOwnerUID("did:plc:first")
76 if err != nil {
77 t.Fatalf("first call: %v", err)
78 }
79 if uid != 100000 {
80 t.Errorf("first UID = %d, want 100000", uid)
81 }
82}
83
84func newTestDB(t *testing.T) *DB {
85 t.Helper()
86 d, err := Setup(context.Background(), filepath.Join(t.TempDir(), "test.db"))
87 if err != nil {
88 t.Fatalf("db.Setup: %v", err)
89 }
90 return d
91}