Files
Baradb/clients/nim/tests/test_client.nim
T
dimgigov f9f77b3a18 feat: production blockers — JOINs, deadlock detection, TLS, parameterized queries
- JOIN execution: INNER/LEFT/RIGHT/FULL/CROSS with column disambiguation
- Deadlock detection: wait-for graph wired into TxnManager.write()
- TLS/SSL: OpenSSL via std/net for TCP wire protocol, auto self-signed certs
- Parameterized queries: ? placeholders with WireValue binding
- Wire protocol: mkQueryParams message support
- HTTP /query endpoint accepts JSON params array
- Nim client: query(sql, params) overload
- Tests: 262 passing (15 new)

All PLAN.md production blockers resolved.
2026-05-06 16:42:53 +03:00

185 lines
5.7 KiB
Nim

## BaraDB Nim Client — Tests
import std/unittest
import std/strutils
import baradb/client
suite "QueryBuilder":
test "Simple SELECT":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("name", "age").from("users").build()
check sql == "SELECT name, age FROM users"
test "SELECT with WHERE":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("name").from("users").where("age > 18").build()
check sql == "SELECT name FROM users WHERE age > 18"
test "SELECT with JOIN":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("u.name", "o.total").from("users u")
.join("orders o", "u.id = o.user_id").build()
check "JOIN" in sql
check "ON" in sql
test "SELECT with GROUP BY and HAVING":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("dept", "count(*)").from("employees")
.groupBy("dept").having("count(*) > 5").build()
check "GROUP BY" in sql
check "HAVING" in sql
test "SELECT with ORDER BY and LIMIT":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("name").from("users")
.orderBy("name", "DESC").limit(10).offset(5).build()
check "ORDER BY name DESC" in sql
check "LIMIT 10" in sql
check "OFFSET 5" in sql
test "Full complex query":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("u.name", "count(*) as cnt")
.from("users u")
.leftJoin("orders o", "u.id = o.user_id")
.where("u.age > 18")
.groupBy("u.name")
.having("cnt > 3")
.orderBy("cnt", "DESC")
.limit(50)
.build()
check sql.startsWith("SELECT")
check "LEFT JOIN" in sql
check "WHERE" in sql
check "GROUP BY" in sql
check "HAVING" in sql
check "ORDER BY" in sql
check "LIMIT 50" in sql
suite "Client Config":
test "Default config":
let config = defaultConfig()
check config.host == "127.0.0.1"
check config.port == 5432
check config.database == "default"
test "Custom config":
let config = ClientConfig(host: "db.example.com", port: 9999,
database: "production", username: "app")
check config.host == "db.example.com"
check config.port == 9999
test "Client creation":
let client = newClient()
check not client.isConnected
suite "Wire Protocol":
test "Build query message":
let msg = makeQueryMessage(1, "SELECT 1")
check msg.len > 0
# First 4 bytes: mkQuery (0x02) in big-endian uint32
check msg[3] == 2'u8
test "Wire value serialization":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkString, strVal: "hello")
buf.serializeValue(val)
var pos = 0
let decoded = buf.deserializeValue(pos)
check decoded.kind == fkString
check decoded.strVal == "hello"
test "Null value roundtrip":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkNull)
buf.serializeValue(val)
check buf.len == 1
check buf[0] == 0x00'u8
test "Int64 value roundtrip":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkInt64, int64Val: 123456789)
buf.serializeValue(val)
var pos = 0
let decoded = buf.deserializeValue(pos)
check decoded.kind == fkInt64
check decoded.int64Val == 123456789
test "Array value roundtrip":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkArray, arrayVal: @[
WireValue(kind: fkString, strVal: "a"),
WireValue(kind: fkString, strVal: "b"),
])
buf.serializeValue(val)
var pos = 0
let decoded = buf.deserializeValue(pos)
check decoded.kind == fkArray
check decoded.arrayVal.len == 2
check decoded.arrayVal[0].strVal == "a"
suite "Client async":
test "Client nextId":
let client = newClient()
check not client.isConnected
suite "Wire Protocol Extended":
test "Int8 value roundtrip":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkInt8, int8Val: -42)
buf.serializeValue(val)
var pos = 0
let decoded = buf.deserializeValue(pos)
check decoded.kind == fkInt8
check decoded.int8Val == -42
test "Int16 value roundtrip":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkInt16, int16Val: -1000)
buf.serializeValue(val)
var pos = 0
let decoded = buf.deserializeValue(pos)
check decoded.kind == fkInt16
check decoded.int16Val == -1000
test "Float32 value roundtrip":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkFloat32, float32Val: 3.14'f32)
buf.serializeValue(val)
var pos = 0
let decoded = buf.deserializeValue(pos)
check decoded.kind == fkFloat32
check decoded.float32Val == 3.14'f32
test "Bytes value roundtrip":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkBytes, bytesVal: @[1'u8, 2'u8, 3'u8])
buf.serializeValue(val)
var pos = 0
let decoded = buf.deserializeValue(pos)
check decoded.kind == fkBytes
check decoded.bytesVal == @[1'u8, 2'u8, 3'u8]
test "Vector value roundtrip":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkVector, vecVal: @[1.0'f32, 2.0'f32, 3.0'f32])
buf.serializeValue(val)
var pos = 0
let decoded = buf.deserializeValue(pos)
check decoded.kind == fkVector
check decoded.vecVal.len == 3
check decoded.vecVal[0] == 1.0'f32
test "WireValue to string":
check wireValueToString(WireValue(kind: fkNull)) == ""
check wireValueToString(WireValue(kind: fkBool, boolVal: true)) == "true"
check wireValueToString(WireValue(kind: fkInt32, int32Val: 42)) == "42"
check wireValueToString(WireValue(kind: fkString, strVal: "hello")) == "hello"
check wireValueToString(WireValue(kind: fkVector, vecVal: @[1.0'f32])) == "<vector:1>"