Week 4: Production Hardening — Thread Safety, Fuzz Tests, Property-Based Tests, NimForum Smoke Test
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled
Thread Safety: - Add lock to BTreeIndex (insert/get/scan/remove/contains) - Add lock to InvertedIndex (addDocument/removeDocument/search/bm25/tfidf/fuzzy/regex) - Add ctxLock to ExecutionContext for DDL/schema metadata, autoIncCounters, sequences - Deep-copy sessionVars in cloneForConnection() to isolate per-connection state - Fix activeConnections check-then-act race with Lock Wire Protocol Hardening: - Fix RangeDefect in deserializeValue for invalid FieldKind bytes - Fix IndexDefect in fkFloat32/fkFloat64 by reusing readUint32/readUint64 - Fix int32/int64 cast from uint32/uint64 to use cast[] instead of constructor - Fix parseHeader to validate MsgKind instead of holey enum cast Property-Based Tests (tests/prop_test.nim): - 8 invariants for evalExprValue: literal types, commutativity, identity, double negation, NULL propagation Wire Protocol Fuzz (tests/fuzz_test.nim): - 7 fuzz tests: random bytes deserialization, truncated buffers, MsgKind casts, parseHeader logic, message roundtrips NimForum Adapter Smoke Test (tests/nimforum_smoke_test.nim): - Full TCP server lifecycle with adapter CRUD and parameterized queries Test Results: 423 tests pass, 0 failures
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
## Property-Based Tests — evalExprValue invariants
|
||||
import std/unittest
|
||||
import std/tables
|
||||
import std/random
|
||||
import std/os
|
||||
import std/monotimes
|
||||
import std/math
|
||||
|
||||
import barabadb/core/types
|
||||
import barabadb/storage/lsm
|
||||
import barabadb/query/ir as qir
|
||||
import barabadb/query/executor as qexec
|
||||
|
||||
suite "Property-Based — evalExprValue Invariants":
|
||||
setup:
|
||||
var testDir = getTempDir() / "baradb_prop_test_" & $getCurrentProcessId() & "_" & $getMonoTime().ticks
|
||||
createDir(testDir)
|
||||
var db = newLSMTree(testDir)
|
||||
var ctx = qexec.newExecutionContext(db)
|
||||
|
||||
teardown:
|
||||
removeDir(testDir)
|
||||
|
||||
proc randIntLit(rng: var Rand, minVal: int = -1000, maxVal: int = 1000): IRExpr =
|
||||
result = IRExpr(kind: irekLiteral, valueKind: vkInt64)
|
||||
result.literal = IRLiteral(kind: vkInt64, int64Val: int64(rng.rand(minVal..maxVal)))
|
||||
|
||||
proc randFloatLit(rng: var Rand, minVal: float = -1000.0, maxVal: float = 1000.0): IRExpr =
|
||||
result = IRExpr(kind: irekLiteral, valueKind: vkFloat64)
|
||||
result.literal = IRLiteral(kind: vkFloat64, float64Val: minVal + rng.rand(maxVal - minVal))
|
||||
|
||||
proc randBinaryExpr(rng: var Rand, left, right: IRExpr, op: IROperator): IRExpr =
|
||||
result = IRExpr(kind: irekBinary)
|
||||
result.binOp = op
|
||||
result.binLeft = left
|
||||
result.binRight = right
|
||||
if left.valueKind == vkInt64 and right.valueKind == vkInt64 and op != irDiv:
|
||||
result.valueKind = vkInt64
|
||||
else:
|
||||
result.valueKind = vkFloat64
|
||||
|
||||
proc randUnaryExpr(rng: var Rand, expr: IRExpr, op: IROperator): IRExpr =
|
||||
result = IRExpr(kind: irekUnary)
|
||||
result.unOp = op
|
||||
result.unExpr = expr
|
||||
result.valueKind = expr.valueKind
|
||||
|
||||
test "Literal eval returns correct ValueKind (INT)":
|
||||
var rng = initRand(42)
|
||||
for i in 0..<100:
|
||||
let lit = randIntLit(rng)
|
||||
let v = evalExprValue(lit, initTable[string, string](), nil)
|
||||
check v.kind == vkInt64
|
||||
|
||||
test "Literal eval returns correct ValueKind (FLOAT)":
|
||||
var rng = initRand(43)
|
||||
for i in 0..<100:
|
||||
let lit = randFloatLit(rng)
|
||||
let v = evalExprValue(lit, initTable[string, string](), nil)
|
||||
check v.kind == vkFloat64
|
||||
|
||||
test "INT addition is commutative":
|
||||
var rng = initRand(44)
|
||||
for i in 0..<100:
|
||||
let a = randIntLit(rng)
|
||||
let b = randIntLit(rng)
|
||||
let sum1 = evalExprValue(randBinaryExpr(rng, a, b, irAdd), initTable[string, string](), nil)
|
||||
let sum2 = evalExprValue(randBinaryExpr(rng, b, a, irAdd), initTable[string, string](), nil)
|
||||
if sum1.kind == vkInt64 and sum2.kind == vkInt64:
|
||||
check sum1.int64Val == sum2.int64Val
|
||||
|
||||
test "FLOAT addition is commutative":
|
||||
var rng = initRand(45)
|
||||
for i in 0..<100:
|
||||
let a = randFloatLit(rng)
|
||||
let b = randFloatLit(rng)
|
||||
let sum1 = evalExprValue(randBinaryExpr(rng, a, b, irAdd), initTable[string, string](), nil)
|
||||
let sum2 = evalExprValue(randBinaryExpr(rng, b, a, irAdd), initTable[string, string](), nil)
|
||||
if sum1.kind == vkFloat64 and sum2.kind == vkFloat64:
|
||||
check abs(sum1.float64Val - sum2.float64Val) < 1e-9
|
||||
|
||||
test "INT multiplication by 1 is identity":
|
||||
var rng = initRand(46)
|
||||
for i in 0..<100:
|
||||
let a = randIntLit(rng)
|
||||
let one = IRExpr(kind: irekLiteral, valueKind: vkInt64)
|
||||
one.literal = IRLiteral(kind: vkInt64, int64Val: 1)
|
||||
let prod = evalExprValue(randBinaryExpr(rng, a, one, irMul), initTable[string, string](), nil)
|
||||
if prod.kind == vkInt64:
|
||||
check prod.int64Val == a.literal.int64Val
|
||||
|
||||
test "Double negation of INT is identity":
|
||||
var rng = initRand(47)
|
||||
for i in 0..<100:
|
||||
let a = randIntLit(rng)
|
||||
let neg = randUnaryExpr(rng, a, irNeg)
|
||||
let negNeg = randUnaryExpr(rng, neg, irNeg)
|
||||
let v = evalExprValue(negNeg, initTable[string, string](), nil)
|
||||
if v.kind == vkInt64:
|
||||
check v.int64Val == a.literal.int64Val
|
||||
|
||||
test "Double negation of FLOAT is identity":
|
||||
var rng = initRand(48)
|
||||
for i in 0..<100:
|
||||
let a = randFloatLit(rng)
|
||||
let neg = randUnaryExpr(rng, a, irNeg)
|
||||
let negNeg = randUnaryExpr(rng, neg, irNeg)
|
||||
let v = evalExprValue(negNeg, initTable[string, string](), nil)
|
||||
if v.kind == vkFloat64:
|
||||
check abs(v.float64Val - a.literal.float64Val) < 1e-9
|
||||
|
||||
test "NULL literal propagates through arithmetic":
|
||||
let nullLit = IRExpr(kind: irekLiteral, valueKind: vkNull)
|
||||
nullLit.literal = IRLiteral(kind: vkNull)
|
||||
let intLit = IRExpr(kind: irekLiteral, valueKind: vkInt64)
|
||||
intLit.literal = IRLiteral(kind: vkInt64, int64Val: 5)
|
||||
for op in [irAdd, irSub, irMul, irDiv]:
|
||||
let expr = IRExpr(kind: irekBinary)
|
||||
expr.binOp = op
|
||||
expr.binLeft = nullLit
|
||||
expr.binRight = intLit
|
||||
let v = evalExprValue(expr, initTable[string, string](), nil)
|
||||
check v.kind == vkNull
|
||||
Reference in New Issue
Block a user