package db import ( "path" "sync" "testing" ) // TestKVInc tests that the KVInc function behaves correctly under concurrent access func TestKVInc(t *testing.T) { posternDB, err := OpenDB(&Config{ DBPath: path.Join(t.TempDir(), "meta.db"), }) if err != nil { t.Fatal(err) } defer func(posternDB *DB) { err := posternDB.Close() if err != nil { t.Fatal(err) } }(posternDB) key := "test-concurrency-key" if err := posternDB.KVSet(t.Context(), key, 0); err != nil { t.Fatalf("KVSet setup failed: %v", err) } const numGoroutines = 50 const incsPerGoroutine = 200 var wg sync.WaitGroup wg.Add(numGoroutines) for range numGoroutines { go func(db *DB) { defer wg.Done() for range incsPerGoroutine { _, err := db.KVInc(t.Context(), key, 1) if err != nil { t.Errorf("KVInc failed during execution: %v", err) return } } }(posternDB) } wg.Wait() // Retrieve the final count val, err := posternDB.KVGet(t.Context(), key) if err != nil { t.Fatalf("KVGet failed to fetch final value: %v", err) } got, ok := val.(int64) if !ok { t.Fatalf("KVGet returned unexpected type: %T, expected int", val) } // Catch race conditions expected := int64(numGoroutines * incsPerGoroutine) if got != expected { t.Errorf("Race condition detected! Expected final value %d, got %d", expected, got) } // Check return value of next increment res, err := posternDB.KVInc(t.Context(), key, 1) if err != nil { t.Errorf("KVInc failed during execution: %v", err) return } if res != expected+1 { t.Errorf("Incrementation mismatch! Expected final value %d, got %d", expected+1, res) } } // TestKVIncString tests that the KVInc function does not increment invalid values func TestKVIncString(t *testing.T) { posternDB, err := OpenDB(&Config{ DBPath: path.Join(t.TempDir(), "meta.db"), }) if err != nil { t.Fatal(err) } defer func(posternDB *DB) { err := posternDB.Close() if err != nil { t.Fatal(err) } }(posternDB) key := "test-key" if err := posternDB.KVSet(t.Context(), key, "value"); err != nil { t.Fatalf("KVSet setup failed: %v", err) } _, err = posternDB.KVInc(t.Context(), key, 1) if err == nil { t.Fatalf("KVInc should have failed during execution due to attempt incrementing a non-integer value") } } // TestKVDelete tests the KVDelete function func TestKVDelete(t *testing.T) { posternDB, err := OpenDB(&Config{ DBPath: path.Join(t.TempDir(), "meta.db"), }) if err != nil { t.Fatal(err) } defer func(posternDB *DB) { err := posternDB.Close() if err != nil { t.Fatal(err) } }(posternDB) key := "test-key" var testVal int64 = 42 if err := posternDB.KVSet(t.Context(), key, testVal); err != nil { t.Fatalf("KVSet setup failed: %v", err) } val, err := posternDB.KVPop(t.Context(), key) if err != nil { t.Fatalf("KVGet failed to fetch final value: %v", err) } if val != testVal { t.Errorf("Expected value %d, got %d", testVal, val) } _, err = posternDB.KVPop(t.Context(), key) if err == nil { t.Fatalf("KVDelete should have failed during execution due to missing key") } }