all repos — postern

@ 0c62cb9eb1848e5d4ab12ede27ed1b3b70f586f2

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