all repos — postern

@ e38fd17b290eded83d0d6080554cb90d4d911b31

Modern mail management

clone
git clone https:///postern.git

internal/db/kv_test.go (view raw)

  1package db
  2
  3import (
  4	"path"
  5	"sync"
  6	"testing"
  7)
  8
  9// TestKVInc tests that the KVInc function behaves correctly under concurrent access
 10func TestKVInc(t *testing.T) {
 11	posternDB, err := OpenDB(&Config{
 12		DBPath: path.Join(t.TempDir(), "meta.db"),
 13	})
 14	if err != nil {
 15		t.Fatal(err)
 16	}
 17
 18	defer func(posternDB *DB) {
 19		err := posternDB.Close()
 20		if err != nil {
 21			t.Fatal(err)
 22		}
 23	}(posternDB)
 24
 25	key := "test-concurrency-key"
 26	if err := posternDB.KVSet(t.Context(), key, 0); err != nil {
 27		t.Fatalf("KVSet setup failed: %v", err)
 28	}
 29
 30	const numGoroutines = 50
 31	const incsPerGoroutine = 200
 32
 33	var wg sync.WaitGroup
 34	wg.Add(numGoroutines)
 35
 36	for range numGoroutines {
 37		go func(db *DB) {
 38			defer wg.Done()
 39			for range incsPerGoroutine {
 40				_, err := db.KVInc(t.Context(), key, 1)
 41				if err != nil {
 42					t.Errorf("KVInc failed during execution: %v", err)
 43					return
 44				}
 45			}
 46		}(posternDB)
 47	}
 48
 49	wg.Wait()
 50
 51	// Retrieve the final count
 52	val, err := posternDB.KVGet(t.Context(), key)
 53	if err != nil {
 54		t.Fatalf("KVGet failed to fetch final value: %v", err)
 55	}
 56
 57	got, ok := val.(int64)
 58	if !ok {
 59		t.Fatalf("KVGet returned unexpected type: %T, expected int", val)
 60	}
 61
 62	// Catch race conditions
 63	expected := int64(numGoroutines * incsPerGoroutine)
 64	if got != expected {
 65		t.Errorf("Race condition detected! Expected final value %d, got %d", expected, got)
 66	}
 67
 68	// Check return value of next increment
 69	res, err := posternDB.KVInc(t.Context(), key, 1)
 70	if err != nil {
 71		t.Errorf("KVInc failed during execution: %v", err)
 72		return
 73	}
 74
 75	if res != expected+1 {
 76		t.Errorf("Incrementation mismatch! Expected final value %d, got %d", expected+1, res)
 77	}
 78}
 79
 80// TestKVIncString tests that the KVInc function does not increment invalid values
 81func TestKVIncString(t *testing.T) {
 82	posternDB, err := OpenDB(&Config{
 83		DBPath: path.Join(t.TempDir(), "meta.db"),
 84	})
 85	if err != nil {
 86		t.Fatal(err)
 87	}
 88
 89	defer func(posternDB *DB) {
 90		err := posternDB.Close()
 91		if err != nil {
 92			t.Fatal(err)
 93		}
 94	}(posternDB)
 95
 96	key := "test-key"
 97	if err := posternDB.KVSet(t.Context(), key, "value"); err != nil {
 98		t.Fatalf("KVSet setup failed: %v", err)
 99	}
100
101	_, err = posternDB.KVInc(t.Context(), key, 1)
102	if err == nil {
103		t.Fatalf("KVInc should have failed during execution due to attempt incrementing a non-integer value")
104	}
105}
106
107// TestKVDelete tests the KVDelete function
108func TestKVDelete(t *testing.T) {
109	posternDB, err := OpenDB(&Config{
110		DBPath: path.Join(t.TempDir(), "meta.db"),
111	})
112	if err != nil {
113		t.Fatal(err)
114	}
115
116	defer func(posternDB *DB) {
117		err := posternDB.Close()
118		if err != nil {
119			t.Fatal(err)
120		}
121	}(posternDB)
122
123	key := "test-key"
124	var testVal int64 = 42
125	if err := posternDB.KVSet(t.Context(), key, testVal); err != nil {
126		t.Fatalf("KVSet setup failed: %v", err)
127	}
128
129	val, err := posternDB.KVPop(t.Context(), key)
130	if err != nil {
131		t.Fatalf("KVGet failed to fetch final value: %v", err)
132	}
133	if val != testVal {
134		t.Errorf("Expected value %d, got %d", testVal, val)
135	}
136
137	_, err = posternDB.KVPop(t.Context(), key)
138	if err == nil {
139		t.Fatalf("KVDelete should have failed during execution due to missing key")
140	}
141}