package store import ( "sync" "sync/atomic" "testing" ) // TestConcurrentReadWrite تأیید می‌کند که با pool چند-اتصالی + WAL + busy_timeout، // خواندن و نوشتنِ هم‌زمان بدونِ خطای «database is locked» انجام می‌شود. func TestConcurrentReadWrite(t *testing.T) { s, err := Open(t.TempDir() + "/c.db") if err != nil { t.Fatal(err) } defer s.Close() if _, err := s.DB.Exec(`CREATE TABLE t(id INTEGER PRIMARY KEY, v INTEGER)`); err != nil { t.Fatal(err) } const workers = 40 // ۲۰ نویسنده + ۲۰ خواننده هم‌زمان const iters = 50 var wg sync.WaitGroup var writeErr, readErr int64 for w := 0; w < workers; w++ { wg.Add(1) go func(w int) { defer wg.Done() for i := 0; i < iters; i++ { if w%2 == 0 { if _, err := s.DB.Exec(`INSERT INTO t(v) VALUES(?)`, i); err != nil { atomic.AddInt64(&writeErr, 1) t.Logf("write err: %v", err) } } else { var n int if err := s.DB.QueryRow(`SELECT COUNT(*) FROM t`).Scan(&n); err != nil { atomic.AddInt64(&readErr, 1) t.Logf("read err: %v", err) } } } }(w) } wg.Wait() if writeErr != 0 || readErr != 0 { t.Fatalf("concurrency errors: writes=%d reads=%d (expected 0)", writeErr, readErr) } var total int _ = s.DB.QueryRow(`SELECT COUNT(*) FROM t`).Scan(&total) if want := (workers / 2) * iters; total != want { t.Fatalf("expected %d rows written, got %d", want, total) } }