- MemoryQueriesAndModelTests: hybrid SQL shape, FactRef/TurnRow Codable, ReplayEvent.memoryRetrieval kind round-trip - SingleEmissionSiteGrepTests: testMemoryRetrievalHasSingleEmissionSite symmetric to the 07-02 memoryMutation gate RED gate: tests reference MemoryQueries, FactRef.score/triggerTurnId, TurnRow, ReplayEvent.memoryRetrieval — none of which exist yet.
64 lines
2.5 KiB
Swift
64 lines
2.5 KiB
Swift
import XCTest
|
|
import Replay
|
|
@testable import Memory
|
|
|
|
/// Plan 07-03 Task 1 — unit tests for the new SQL constants and value types.
|
|
///
|
|
/// These tests do NOT touch SQLite. They exercise the static SQL strings,
|
|
/// the Codable conformance for FactRef and TurnRow, and the
|
|
/// ReplayEvent.memoryRetrieval round-trip.
|
|
final class MemoryQueriesAndModelTests: XCTestCase {
|
|
|
|
func testHybridSearchSQLContainsRRFExpression() {
|
|
let sql = MemoryQueries.hybridSearchSQL(k: 50)
|
|
XCTAssertTrue(sql.contains("SUM(1.0/(60+rank))"),
|
|
"RRF expression must use rrfK=60")
|
|
XCTAssertTrue(sql.contains("f.valid_to IS NULL AND f.forgotten_at IS NULL"))
|
|
XCTAssertTrue(sql.contains("AND k = 50"),
|
|
"vec0 cohort must template k as a literal (RESEARCH P9)")
|
|
XCTAssertTrue(sql.contains("bm25(facts_fts)"))
|
|
XCTAssertTrue(sql.contains("embedding MATCH"))
|
|
XCTAssertTrue(sql.contains("ORDER BY fused.rrf DESC"))
|
|
}
|
|
|
|
func testHybridSearchSQLRRFKConstant() {
|
|
XCTAssertEqual(MemoryQueries.rrfK, 60)
|
|
}
|
|
|
|
func testHybridSearchSQLHasNoSessionIdPredicate() {
|
|
let sql = MemoryQueries.hybridSearchSQL(k: 10)
|
|
XCTAssertFalse(sql.contains("session_id"),
|
|
"D-07 invariant: search_memory must be unscoped.")
|
|
}
|
|
|
|
func testForgetFactSQLUsesUpdateNotDelete() {
|
|
let sql = MemoryQueries.forgetFactSQL
|
|
XCTAssertTrue(sql.contains("UPDATE facts"))
|
|
XCTAssertFalse(sql.contains("DELETE FROM facts"))
|
|
}
|
|
|
|
func testFactRefIsCodable() throws {
|
|
let ref = FactRef(factId: 42, summary: "S P O", score: 0.5,
|
|
triggerTurnId: 7, timestamp: 1000)
|
|
let encoded = try JSONEncoder().encode(ref)
|
|
let decoded = try JSONDecoder().decode(FactRef.self, from: encoded)
|
|
XCTAssertEqual(decoded, ref)
|
|
}
|
|
|
|
func testTurnRowIsCodable() throws {
|
|
let row = TurnRow(id: 1, sessionId: "A", role: "user",
|
|
content: "hi", source: "userText", createdAt: 100)
|
|
let encoded = try JSONEncoder().encode(row)
|
|
let decoded = try JSONDecoder().decode(TurnRow.self, from: encoded)
|
|
XCTAssertEqual(decoded, row)
|
|
}
|
|
|
|
func testReplayEventMemoryRetrievalRoundtrip() {
|
|
let bytes = "{\"factId\":1}".data(using: .utf8)!
|
|
let ev: ReplayEvent = .memoryRetrieval(bytes)
|
|
let (kind, payload) = ev.encoded()
|
|
XCTAssertEqual(kind, "memory_retrieval")
|
|
XCTAssertEqual(payload, bytes)
|
|
}
|
|
}
|