CMakeLists.txt 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. # Tests for smartbotic-database
  2. # yyjson (v1.10+) — Phase A swaps nlohmann::json::parse for parse_to_nlohmann
  3. # at hot paths in wal.cpp, snapshot.cpp, history_store.cpp, etc. Any test
  4. # target that compiles those files now also needs json_parse.cpp linked and
  5. # yyjson linked. Resolve once at file scope so every test target below can
  6. # use ${yyjson_LIBRARIES} / ${yyjson_INCLUDE_DIRS}.
  7. if(NOT yyjson_FOUND)
  8. find_package(PkgConfig REQUIRED)
  9. pkg_check_modules(yyjson REQUIRED yyjson)
  10. endif()
  11. # LMDB (v2.0 storage substrate) — resolve once at file scope, mirroring the
  12. # yyjson pattern. liblmdb does not ship pkg-config on Debian 13, so use
  13. # find_path/find_library. Each test target that pulls in storage/ sources
  14. # adds ${LMDB_INCLUDE_DIR} / ${LMDB_LIBRARY} to its link/include flags.
  15. if(NOT LMDB_INCLUDE_DIR OR NOT LMDB_LIBRARY)
  16. find_path(LMDB_INCLUDE_DIR lmdb.h)
  17. find_library(LMDB_LIBRARY NAMES lmdb)
  18. if(NOT LMDB_INCLUDE_DIR OR NOT LMDB_LIBRARY)
  19. message(FATAL_ERROR "LMDB not found. Install liblmdb-dev.")
  20. endif()
  21. endif()
  22. # Vector storage integration test
  23. # Compiles memory_store.cpp directly — no dependency on the full service executable.
  24. set(TEST_VECTOR_SOURCES
  25. test_vector_storage.cpp
  26. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/memory_store.cpp
  27. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/config/collection_config_manager.cpp
  28. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/history_store.cpp
  29. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/wal.cpp
  30. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  31. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  32. )
  33. add_executable(test_vector_storage ${TEST_VECTOR_SOURCES})
  34. target_include_directories(test_vector_storage PRIVATE
  35. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  36. )
  37. # nlohmann/json
  38. if(TARGET nlohmann_json::nlohmann_json)
  39. target_link_libraries(test_vector_storage PRIVATE nlohmann_json::nlohmann_json)
  40. else()
  41. target_include_directories(test_vector_storage PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  42. endif()
  43. # spdlog
  44. if(TARGET spdlog::spdlog)
  45. target_link_libraries(test_vector_storage PRIVATE spdlog::spdlog)
  46. else()
  47. target_link_libraries(test_vector_storage PRIVATE ${SPDLOG_LIBRARIES})
  48. target_include_directories(test_vector_storage PRIVATE ${SPDLOG_INCLUDE_DIRS})
  49. endif()
  50. # Threads (required by MemoryStore background threads)
  51. find_package(Threads REQUIRED)
  52. target_link_libraries(test_vector_storage PRIVATE Threads::Threads)
  53. # yyjson (wal.cpp uses parse_to_nlohmann from v1.10+)
  54. target_link_libraries(test_vector_storage PRIVATE ${yyjson_LIBRARIES})
  55. target_include_directories(test_vector_storage PRIVATE ${yyjson_INCLUDE_DIRS})
  56. # View projection unit test
  57. set(TEST_VIEWS_SOURCES
  58. test_views.cpp
  59. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/views/projection.cpp
  60. )
  61. add_executable(test_views ${TEST_VIEWS_SOURCES})
  62. target_include_directories(test_views PRIVATE
  63. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  64. )
  65. # nlohmann/json
  66. if(TARGET nlohmann_json::nlohmann_json)
  67. target_link_libraries(test_views PRIVATE nlohmann_json::nlohmann_json)
  68. else()
  69. target_include_directories(test_views PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  70. endif()
  71. # Per-collection timestamp precision test
  72. set(TEST_TIMESTAMP_PRECISION_SOURCES
  73. test_timestamp_precision.cpp
  74. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/memory_store.cpp
  75. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/config/collection_config_manager.cpp
  76. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/history_store.cpp
  77. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/wal.cpp
  78. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  79. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  80. )
  81. add_executable(test_timestamp_precision ${TEST_TIMESTAMP_PRECISION_SOURCES})
  82. target_include_directories(test_timestamp_precision PRIVATE
  83. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  84. )
  85. if(TARGET nlohmann_json::nlohmann_json)
  86. target_link_libraries(test_timestamp_precision PRIVATE nlohmann_json::nlohmann_json)
  87. else()
  88. target_include_directories(test_timestamp_precision PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  89. endif()
  90. if(TARGET spdlog::spdlog)
  91. target_link_libraries(test_timestamp_precision PRIVATE spdlog::spdlog)
  92. else()
  93. target_link_libraries(test_timestamp_precision PRIVATE ${SPDLOG_LIBRARIES})
  94. target_include_directories(test_timestamp_precision PRIVATE ${SPDLOG_INCLUDE_DIRS})
  95. endif()
  96. find_package(Threads REQUIRED)
  97. target_link_libraries(test_timestamp_precision PRIVATE Threads::Threads)
  98. # yyjson (wal.cpp uses parse_to_nlohmann from v1.10+)
  99. target_link_libraries(test_timestamp_precision PRIVATE ${yyjson_LIBRARIES})
  100. target_include_directories(test_timestamp_precision PRIVATE ${yyjson_INCLUDE_DIRS})
  101. # Snapshot durability + fallback integration test
  102. # Exercises SnapshotManager directly; pulls in memory_store.cpp, snapshot.cpp,
  103. # and wal.cpp (for the crc32 helpers used by snapshot.cpp).
  104. set(TEST_SNAPSHOT_DURABILITY_SOURCES
  105. test_snapshot_durability.cpp
  106. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/memory_store.cpp
  107. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/config/collection_config_manager.cpp
  108. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/snapshot.cpp
  109. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/wal.cpp
  110. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/history_store.cpp
  111. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  112. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  113. )
  114. add_executable(test_snapshot_durability ${TEST_SNAPSHOT_DURABILITY_SOURCES})
  115. target_include_directories(test_snapshot_durability PRIVATE
  116. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  117. )
  118. if(TARGET nlohmann_json::nlohmann_json)
  119. target_link_libraries(test_snapshot_durability PRIVATE nlohmann_json::nlohmann_json)
  120. else()
  121. target_include_directories(test_snapshot_durability PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  122. endif()
  123. if(TARGET spdlog::spdlog)
  124. target_link_libraries(test_snapshot_durability PRIVATE spdlog::spdlog)
  125. else()
  126. target_link_libraries(test_snapshot_durability PRIVATE ${SPDLOG_LIBRARIES})
  127. target_include_directories(test_snapshot_durability PRIVATE ${SPDLOG_INCLUDE_DIRS})
  128. endif()
  129. find_package(Threads REQUIRED)
  130. target_link_libraries(test_snapshot_durability PRIVATE Threads::Threads)
  131. # yyjson (wal.cpp/snapshot.cpp use parse_to_nlohmann from v1.10+)
  132. target_link_libraries(test_snapshot_durability PRIVATE ${yyjson_LIBRARIES})
  133. target_include_directories(test_snapshot_durability PRIVATE ${yyjson_INCLUDE_DIRS})
  134. # LZ4 — snapshot.cpp #includes <lz4.h> unless DISABLE_LZ4 is defined, so link it.
  135. find_package(PkgConfig QUIET)
  136. if(PKG_CONFIG_FOUND)
  137. pkg_check_modules(TEST_LZ4 QUIET liblz4)
  138. endif()
  139. if(TEST_LZ4_FOUND)
  140. target_link_libraries(test_snapshot_durability PRIVATE ${TEST_LZ4_LIBRARIES})
  141. target_include_directories(test_snapshot_durability PRIVATE ${TEST_LZ4_INCLUDE_DIRS})
  142. else()
  143. # Fallback: assume liblz4 is installed at a standard location
  144. target_link_libraries(test_snapshot_durability PRIVATE lz4)
  145. endif()
  146. # Config drop-in loader test (v1.7.0 T1 → T12)
  147. # Exercises loadLayeredConfig() in isolation.
  148. set(TEST_CONFIG_DROPINS_SOURCES
  149. test_config_dropins.cpp
  150. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/config/config_loader.cpp
  151. )
  152. add_executable(test_config_dropins ${TEST_CONFIG_DROPINS_SOURCES})
  153. target_include_directories(test_config_dropins PRIVATE
  154. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  155. )
  156. if(TARGET nlohmann_json::nlohmann_json)
  157. target_link_libraries(test_config_dropins PRIVATE nlohmann_json::nlohmann_json)
  158. else()
  159. target_include_directories(test_config_dropins PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  160. endif()
  161. if(TARGET spdlog::spdlog)
  162. target_link_libraries(test_config_dropins PRIVATE spdlog::spdlog)
  163. else()
  164. target_link_libraries(test_config_dropins PRIVATE ${SPDLOG_LIBRARIES})
  165. target_include_directories(test_config_dropins PRIVATE ${SPDLOG_INCLUDE_DIRS})
  166. endif()
  167. # Eviction test (v1.7.0 T4+T5+T6 → T12)
  168. # Exercises chunked eviction, per-collection priorities, and the hot-write
  169. # floor directly through MemoryStore. Mirrors the link deps of test_timestamp_precision.
  170. set(TEST_EVICTION_SOURCES
  171. test_eviction.cpp
  172. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/memory_store.cpp
  173. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/config/collection_config_manager.cpp
  174. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/history_store.cpp
  175. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/wal.cpp
  176. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  177. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  178. )
  179. add_executable(test_eviction ${TEST_EVICTION_SOURCES})
  180. target_include_directories(test_eviction PRIVATE
  181. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  182. )
  183. if(TARGET nlohmann_json::nlohmann_json)
  184. target_link_libraries(test_eviction PRIVATE nlohmann_json::nlohmann_json)
  185. else()
  186. target_include_directories(test_eviction PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  187. endif()
  188. if(TARGET spdlog::spdlog)
  189. target_link_libraries(test_eviction PRIVATE spdlog::spdlog)
  190. else()
  191. target_link_libraries(test_eviction PRIVATE ${SPDLOG_LIBRARIES})
  192. target_include_directories(test_eviction PRIVATE ${SPDLOG_INCLUDE_DIRS})
  193. endif()
  194. find_package(Threads REQUIRED)
  195. target_link_libraries(test_eviction PRIVATE Threads::Threads)
  196. # yyjson (wal.cpp uses parse_to_nlohmann from v1.10+)
  197. target_link_libraries(test_eviction PRIVATE ${yyjson_LIBRARIES})
  198. target_include_directories(test_eviction PRIVATE ${yyjson_INCLUDE_DIRS})
  199. # yyjson → nlohmann bridge helper test (v1.10 Phase A T2)
  200. # Exercises parse_to_nlohmann() in isolation against nlohmann::json::parse
  201. # for a corpus of production-shaped docs. yyjson is configured at the
  202. # service/ scope; re-resolve it here so the test target can find it
  203. # independently of the service build.
  204. if(NOT yyjson_FOUND)
  205. find_package(PkgConfig REQUIRED)
  206. pkg_check_modules(yyjson REQUIRED yyjson)
  207. endif()
  208. add_executable(test_json_parse
  209. test_json_parse.cpp
  210. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  211. )
  212. target_include_directories(test_json_parse PRIVATE
  213. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  214. ${yyjson_INCLUDE_DIRS}
  215. )
  216. if(TARGET nlohmann_json::nlohmann_json)
  217. target_link_libraries(test_json_parse PRIVATE nlohmann_json::nlohmann_json)
  218. else()
  219. target_include_directories(test_json_parse PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  220. endif()
  221. target_link_libraries(test_json_parse PRIVATE ${yyjson_LIBRARIES})
  222. # Binary doc encoder/decoder test (v1.11 Phase B T2)
  223. # Exercises doc_binary::Doc, encode, decode, get_field, to_json_text against
  224. # nlohmann::json round-trips. yyjson resolution is shared at file scope above.
  225. add_executable(test_doc_binary
  226. test_doc_binary.cpp
  227. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  228. )
  229. target_include_directories(test_doc_binary PRIVATE
  230. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  231. ${yyjson_INCLUDE_DIRS}
  232. )
  233. if(TARGET nlohmann_json::nlohmann_json)
  234. target_link_libraries(test_doc_binary PRIVATE nlohmann_json::nlohmann_json)
  235. else()
  236. target_include_directories(test_doc_binary PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  237. endif()
  238. target_link_libraries(test_doc_binary PRIVATE ${yyjson_LIBRARIES})
  239. # Parse-time micro-benchmark (v1.10 Phase A T8) — manual bench, NOT
  240. # registered with CTest. Run as ./build/tests/bench_json_parse <corpus>.
  241. add_executable(bench_json_parse
  242. bench_json_parse.cpp
  243. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  244. )
  245. target_include_directories(bench_json_parse PRIVATE
  246. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  247. ${yyjson_INCLUDE_DIRS}
  248. )
  249. if(TARGET nlohmann_json::nlohmann_json)
  250. target_link_libraries(bench_json_parse PRIVATE nlohmann_json::nlohmann_json)
  251. else()
  252. target_include_directories(bench_json_parse PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  253. endif()
  254. target_link_libraries(bench_json_parse PRIVATE ${yyjson_LIBRARIES})
  255. # RSS bench (v1.11 Phase B T8) — manual bench, NOT registered with CTest.
  256. # Run as ./build/tests/bench_doc_memory [N].
  257. add_executable(bench_doc_memory
  258. bench_doc_memory.cpp
  259. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  260. )
  261. target_include_directories(bench_doc_memory PRIVATE
  262. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  263. ${yyjson_INCLUDE_DIRS}
  264. )
  265. if(TARGET nlohmann_json::nlohmann_json)
  266. target_link_libraries(bench_doc_memory PRIVATE nlohmann_json::nlohmann_json)
  267. else()
  268. target_include_directories(bench_doc_memory PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  269. endif()
  270. target_link_libraries(bench_doc_memory PRIVATE ${yyjson_LIBRARIES})
  271. # LMDB environment unit test (v2.0 storage Phase C Stage 1, Tasks 1.2 / 1.3).
  272. # Compiles the storage/ sources directly — no dependency on the service
  273. # executable.
  274. add_executable(test_lmdb_env
  275. test_lmdb_env.cpp
  276. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_env.cpp
  277. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_txn.cpp
  278. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_dbi.cpp
  279. )
  280. target_include_directories(test_lmdb_env PRIVATE
  281. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  282. ${LMDB_INCLUDE_DIR}
  283. )
  284. target_link_libraries(test_lmdb_env PRIVATE ${LMDB_LIBRARY})
  285. # DocumentStore + LmdbDocumentStore unit test (v2.0 storage Phase C Stage 2).
  286. # Same shape as test_lmdb_env: links the storage/ sources and a couple of
  287. # helpers (doc_binary, json_parse) directly. No dependency on the full
  288. # service executable.
  289. add_executable(test_document_store
  290. test_document_store.cpp
  291. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_env.cpp
  292. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_txn.cpp
  293. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_dbi.cpp
  294. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/document_store_lmdb.cpp
  295. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/subdb_identity.cpp
  296. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  297. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  298. )
  299. target_include_directories(test_document_store PRIVATE
  300. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  301. ${LMDB_INCLUDE_DIR}
  302. ${yyjson_INCLUDE_DIRS}
  303. )
  304. target_link_libraries(test_document_store PRIVATE ${LMDB_LIBRARY})
  305. target_link_libraries(test_document_store PRIVATE ${yyjson_LIBRARIES})
  306. if(TARGET nlohmann_json::nlohmann_json)
  307. target_link_libraries(test_document_store PRIVATE nlohmann_json::nlohmann_json)
  308. else()
  309. target_include_directories(test_document_store PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  310. endif()
  311. # v1.x → v2.0 migration tool unit test (v2.0 storage Phase C Stage 3).
  312. # Pulls in both the v1.x persistence stack (snapshot.cpp, wal.cpp, history_store.cpp,
  313. # memory_store.cpp) and the v2.0 storage stack (LMDB primitives + DocumentStore +
  314. # migrate_v1_to_v2). Each side is independent of the other at link time except
  315. # for the migration .cpp itself, which is the bridge.
  316. add_executable(test_migrate_v1_to_v2
  317. test_migrate_v1_to_v2.cpp
  318. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/memory_store.cpp
  319. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/config/collection_config_manager.cpp
  320. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/snapshot.cpp
  321. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/wal.cpp
  322. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/history_store.cpp
  323. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  324. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  325. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_env.cpp
  326. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_txn.cpp
  327. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_dbi.cpp
  328. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/document_store_lmdb.cpp
  329. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/subdb_identity.cpp
  330. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/migrate_v1_to_v2.cpp
  331. )
  332. target_include_directories(test_migrate_v1_to_v2 PRIVATE
  333. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  334. ${LMDB_INCLUDE_DIR}
  335. ${yyjson_INCLUDE_DIRS}
  336. )
  337. target_link_libraries(test_migrate_v1_to_v2 PRIVATE ${LMDB_LIBRARY})
  338. target_link_libraries(test_migrate_v1_to_v2 PRIVATE ${yyjson_LIBRARIES})
  339. if(TARGET nlohmann_json::nlohmann_json)
  340. target_link_libraries(test_migrate_v1_to_v2 PRIVATE nlohmann_json::nlohmann_json)
  341. else()
  342. target_include_directories(test_migrate_v1_to_v2 PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  343. endif()
  344. if(TARGET spdlog::spdlog)
  345. target_link_libraries(test_migrate_v1_to_v2 PRIVATE spdlog::spdlog)
  346. else()
  347. target_link_libraries(test_migrate_v1_to_v2 PRIVATE ${SPDLOG_LIBRARIES})
  348. target_include_directories(test_migrate_v1_to_v2 PRIVATE ${SPDLOG_INCLUDE_DIRS})
  349. endif()
  350. find_package(Threads REQUIRED)
  351. target_link_libraries(test_migrate_v1_to_v2 PRIVATE Threads::Threads)
  352. # LZ4 — snapshot.cpp uses LZ4 compression
  353. if(PKG_CONFIG_FOUND)
  354. pkg_check_modules(MIGRATE_LZ4 QUIET liblz4)
  355. endif()
  356. if(MIGRATE_LZ4_FOUND)
  357. target_link_libraries(test_migrate_v1_to_v2 PRIVATE ${MIGRATE_LZ4_LIBRARIES})
  358. target_include_directories(test_migrate_v1_to_v2 PRIVATE ${MIGRATE_LZ4_INCLUDE_DIRS})
  359. else()
  360. target_link_libraries(test_migrate_v1_to_v2 PRIVATE lz4)
  361. endif()
  362. # v2.0 Stage 4 — dual-write mirror unit + integration test.
  363. # Links the MemoryStore + LMDB substrate the same way test_migrate_v1_to_v2 does,
  364. # but skips persistence/snapshot/wal since the mirror helper does not touch them.
  365. add_executable(test_dual_write_mirror
  366. test_dual_write_mirror.cpp
  367. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/memory_store.cpp
  368. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/config/collection_config_manager.cpp
  369. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/history_store.cpp
  370. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/wal.cpp
  371. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  372. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  373. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_env.cpp
  374. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_txn.cpp
  375. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_dbi.cpp
  376. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/document_store_lmdb.cpp
  377. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/subdb_identity.cpp
  378. )
  379. target_include_directories(test_dual_write_mirror PRIVATE
  380. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  381. ${LMDB_INCLUDE_DIR}
  382. ${yyjson_INCLUDE_DIRS}
  383. )
  384. target_link_libraries(test_dual_write_mirror PRIVATE ${LMDB_LIBRARY})
  385. target_link_libraries(test_dual_write_mirror PRIVATE ${yyjson_LIBRARIES})
  386. if(TARGET nlohmann_json::nlohmann_json)
  387. target_link_libraries(test_dual_write_mirror PRIVATE nlohmann_json::nlohmann_json)
  388. else()
  389. target_include_directories(test_dual_write_mirror PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  390. endif()
  391. if(TARGET spdlog::spdlog)
  392. target_link_libraries(test_dual_write_mirror PRIVATE spdlog::spdlog)
  393. else()
  394. target_link_libraries(test_dual_write_mirror PRIVATE ${SPDLOG_LIBRARIES})
  395. target_include_directories(test_dual_write_mirror PRIVATE ${SPDLOG_INCLUDE_DIRS})
  396. endif()
  397. find_package(Threads REQUIRED)
  398. target_link_libraries(test_dual_write_mirror PRIVATE Threads::Threads)
  399. # Five test files assert via assert(), which CMAKE_BUILD_TYPE=Release compiles
  400. # out via -DNDEBUG. That silently reduced 104 assertions across test_views,
  401. # test_eviction, test_snapshot_durability, test_timestamp_precision and
  402. # test_config_dropins to no-ops: the suites ran, printed PASS, and checked
  403. # nothing. Strip NDEBUG from test targets so assertions are live in every
  404. # build type. Production targets are unaffected.
  405. foreach(_t
  406. test_vector_storage test_views test_timestamp_precision
  407. test_snapshot_durability test_config_dropins test_eviction
  408. test_json_parse test_doc_binary test_lmdb_env test_document_store
  409. test_migrate_v1_to_v2 test_dual_write_mirror)
  410. target_compile_options(${_t} PRIVATE -UNDEBUG)
  411. endforeach()
  412. # Register with CTest
  413. enable_testing()
  414. add_test(NAME vector_storage COMMAND test_vector_storage)
  415. add_test(NAME views COMMAND test_views)
  416. add_test(NAME timestamp_precision COMMAND test_timestamp_precision)
  417. add_test(NAME snapshot_durability COMMAND test_snapshot_durability)
  418. add_test(NAME config_dropins COMMAND test_config_dropins)
  419. add_test(NAME eviction COMMAND test_eviction)
  420. add_test(NAME json_parse COMMAND test_json_parse)
  421. add_test(NAME doc_binary COMMAND test_doc_binary)
  422. add_test(NAME lmdb_env COMMAND test_lmdb_env)
  423. add_test(NAME document_store COMMAND test_document_store)
  424. add_test(NAME migrate_v1_to_v2 COMMAND test_migrate_v1_to_v2)
  425. add_test(NAME dual_write_mirror COMMAND test_dual_write_mirror)
  426. # v2.3 — project addressing (header-only parser; no link deps).
  427. add_executable(test_project_addressing test_project_addressing.cpp)
  428. target_include_directories(test_project_addressing PRIVATE
  429. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  430. )
  431. add_test(NAME project_addressing COMMAND test_project_addressing)
  432. # v2.3 Stage F — project CRUD placeholders (header-only filesystem helpers;
  433. # no link deps beyond std::filesystem). Exercises listProjects /
  434. # createProject / dropProject against a tmp data dir. Stage B replaces the
  435. # placeholder with a project-registry-backed implementation; this test
  436. # will be retargeted then.
  437. add_executable(test_project_crud test_project_crud.cpp)
  438. target_include_directories(test_project_crud PRIVATE
  439. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  440. )
  441. add_test(NAME project_crud COMMAND test_project_crud)
  442. # v2.4.4 — sub-db identity sentinel. Regression cover for the misbound-MDB_dbi
  443. # incident in which writes for one collection landed in another's sub-db.
  444. add_executable(test_subdb_identity
  445. test_subdb_identity.cpp
  446. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_env.cpp
  447. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_txn.cpp
  448. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/lmdb_dbi.cpp
  449. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/subdb_identity.cpp
  450. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/storage/document_store_lmdb.cpp
  451. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  452. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  453. )
  454. target_include_directories(test_subdb_identity PRIVATE
  455. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  456. ${LMDB_INCLUDE_DIR}
  457. ${yyjson_INCLUDE_DIRS}
  458. )
  459. target_link_libraries(test_subdb_identity PRIVATE ${LMDB_LIBRARY})
  460. target_link_libraries(test_subdb_identity PRIVATE ${yyjson_LIBRARIES})
  461. if(TARGET nlohmann_json::nlohmann_json)
  462. target_link_libraries(test_subdb_identity PRIVATE nlohmann_json::nlohmann_json)
  463. else()
  464. target_include_directories(test_subdb_identity PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  465. endif()
  466. add_test(NAME test_subdb_identity COMMAND test_subdb_identity)
  467. # v2.6.0 — project-scoped file storage. Covers cross-project id isolation and
  468. # the per-project deduplicated flag (global dedup would otherwise be a
  469. # cross-project existence oracle).
  470. add_executable(test_file_project_scope
  471. test_file_project_scope.cpp
  472. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/files/file_manager.cpp
  473. )
  474. target_include_directories(test_file_project_scope PRIVATE
  475. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  476. )
  477. find_package(OpenSSL REQUIRED)
  478. target_link_libraries(test_file_project_scope PRIVATE OpenSSL::SSL OpenSSL::Crypto)
  479. if(TARGET nlohmann_json::nlohmann_json)
  480. target_link_libraries(test_file_project_scope PRIVATE nlohmann_json::nlohmann_json)
  481. else()
  482. target_include_directories(test_file_project_scope PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  483. endif()
  484. if(TARGET spdlog::spdlog)
  485. target_link_libraries(test_file_project_scope PRIVATE spdlog::spdlog)
  486. else()
  487. target_link_libraries(test_file_project_scope PRIVATE ${SPDLOG_LIBRARIES})
  488. target_include_directories(test_file_project_scope PRIVATE ${SPDLOG_INCLUDE_DIRS})
  489. endif()
  490. find_package(Threads REQUIRED)
  491. target_link_libraries(test_file_project_scope PRIVATE Threads::Threads)
  492. add_test(NAME test_file_project_scope COMMAND test_file_project_scope)
  493. # v2.8.0 — access policy engine. The critical assertions are the safety ones:
  494. # security off allows everything (so upgrades are inert), enabling is refused
  495. # without an admin policy, the last admin cannot be removed, and audit mode
  496. # evaluates honestly but allows.
  497. add_executable(test_policy_manager
  498. test_policy_manager.cpp
  499. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/security/policy_manager.cpp
  500. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/memory_store.cpp
  501. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/config/collection_config_manager.cpp
  502. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/history_store.cpp
  503. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/wal.cpp
  504. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  505. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  506. )
  507. target_include_directories(test_policy_manager PRIVATE
  508. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  509. ${yyjson_INCLUDE_DIRS}
  510. )
  511. target_link_libraries(test_policy_manager PRIVATE ${yyjson_LIBRARIES})
  512. if(TARGET nlohmann_json::nlohmann_json)
  513. target_link_libraries(test_policy_manager PRIVATE nlohmann_json::nlohmann_json)
  514. else()
  515. target_include_directories(test_policy_manager PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  516. endif()
  517. if(TARGET spdlog::spdlog)
  518. target_link_libraries(test_policy_manager PRIVATE spdlog::spdlog)
  519. else()
  520. target_link_libraries(test_policy_manager PRIVATE ${SPDLOG_LIBRARIES})
  521. target_include_directories(test_policy_manager PRIVATE ${SPDLOG_INCLUDE_DIRS})
  522. endif()
  523. find_package(Threads REQUIRED)
  524. target_link_libraries(test_policy_manager PRIVATE Threads::Threads)
  525. add_test(NAME test_policy_manager COMMAND test_policy_manager)
  526. # v2.8.0 — document TTL across write paths. Pins that update() preserves an
  527. # existing expiry: it used to wipe it, so any TTL'd document that was ever
  528. # updated became permanent.
  529. add_executable(test_document_ttl
  530. test_document_ttl.cpp
  531. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/memory_store.cpp
  532. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/config/collection_config_manager.cpp
  533. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/history_store.cpp
  534. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/wal.cpp
  535. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  536. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  537. )
  538. target_include_directories(test_document_ttl PRIVATE
  539. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  540. ${yyjson_INCLUDE_DIRS}
  541. )
  542. target_link_libraries(test_document_ttl PRIVATE ${yyjson_LIBRARIES})
  543. if(TARGET nlohmann_json::nlohmann_json)
  544. target_link_libraries(test_document_ttl PRIVATE nlohmann_json::nlohmann_json)
  545. else()
  546. target_include_directories(test_document_ttl PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  547. endif()
  548. if(TARGET spdlog::spdlog)
  549. target_link_libraries(test_document_ttl PRIVATE spdlog::spdlog)
  550. else()
  551. target_link_libraries(test_document_ttl PRIVATE ${SPDLOG_LIBRARIES})
  552. target_include_directories(test_document_ttl PRIVATE ${SPDLOG_INCLUDE_DIRS})
  553. endif()
  554. find_package(Threads REQUIRED)
  555. target_link_libraries(test_document_ttl PRIVATE Threads::Threads)
  556. add_test(NAME test_document_ttl COMMAND test_document_ttl)
  557. # v2.8.0 — ViewManager persistence. test_views only exercises applyProjection()
  558. # in-process, so nothing covered loadFromStore's paging: a bare Query stops at
  559. # 100 views and silently loses the rest.
  560. add_executable(test_view_manager_paging
  561. test_view_manager_paging.cpp
  562. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/views/view_manager.cpp
  563. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/views/projection.cpp
  564. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/memory_store.cpp
  565. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/config/collection_config_manager.cpp
  566. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/history_store.cpp
  567. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/persistence/wal.cpp
  568. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
  569. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/doc_binary.cpp
  570. )
  571. target_include_directories(test_view_manager_paging PRIVATE
  572. ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
  573. ${yyjson_INCLUDE_DIRS}
  574. )
  575. target_link_libraries(test_view_manager_paging PRIVATE ${yyjson_LIBRARIES})
  576. if(TARGET nlohmann_json::nlohmann_json)
  577. target_link_libraries(test_view_manager_paging PRIVATE nlohmann_json::nlohmann_json)
  578. else()
  579. target_include_directories(test_view_manager_paging PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
  580. endif()
  581. if(TARGET spdlog::spdlog)
  582. target_link_libraries(test_view_manager_paging PRIVATE spdlog::spdlog)
  583. else()
  584. target_link_libraries(test_view_manager_paging PRIVATE ${SPDLOG_LIBRARIES})
  585. target_include_directories(test_view_manager_paging PRIVATE ${SPDLOG_INCLUDE_DIRS})
  586. endif()
  587. find_package(Threads REQUIRED)
  588. target_link_libraries(test_view_manager_paging PRIVATE Threads::Threads)
  589. add_test(NAME test_view_manager_paging COMMAND test_view_manager_paging)