datahike-browser-tests 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/.circleci/config.yml +405 -0
  2. package/.circleci/scripts/gen_ci.clj +194 -0
  3. package/.cirrus.yml +60 -0
  4. package/.clj-kondo/babashka/sci/config.edn +1 -0
  5. package/.clj-kondo/babashka/sci/sci/core.clj +9 -0
  6. package/.clj-kondo/config.edn +95 -0
  7. package/.dir-locals.el +2 -0
  8. package/.github/FUNDING.yml +3 -0
  9. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +68 -0
  10. package/.github/ISSUE_TEMPLATE/2-feature-request.yml +28 -0
  11. package/.github/ISSUE_TEMPLATE/config.yml +6 -0
  12. package/.github/pull_request_template.md +24 -0
  13. package/.github/workflows/native-image.yml +84 -0
  14. package/LICENSE +203 -0
  15. package/README.md +273 -0
  16. package/bb/deps.edn +9 -0
  17. package/bb/resources/github-fingerprints +3 -0
  18. package/bb/resources/native-image-tests/run-bb-pod-tests.clj +162 -0
  19. package/bb/resources/native-image-tests/run-libdatahike-tests +12 -0
  20. package/bb/resources/native-image-tests/run-native-image-tests +74 -0
  21. package/bb/resources/native-image-tests/run-python-tests +22 -0
  22. package/bb/resources/native-image-tests/testconfig.attr-refs.edn +6 -0
  23. package/bb/resources/native-image-tests/testconfig.edn +5 -0
  24. package/bb/resources/template/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  25. package/bb/resources/template/.settings/org.eclipse.jdt.core.prefs +9 -0
  26. package/bb/resources/template/.settings/org.eclipse.m2e.core.prefs +4 -0
  27. package/bb/resources/template/pom.xml +22 -0
  28. package/bb/src/tools/build.clj +132 -0
  29. package/bb/src/tools/clj_kondo.clj +32 -0
  30. package/bb/src/tools/deploy.clj +26 -0
  31. package/bb/src/tools/examples.clj +19 -0
  32. package/bb/src/tools/npm.clj +100 -0
  33. package/bb/src/tools/python.clj +14 -0
  34. package/bb/src/tools/release.clj +94 -0
  35. package/bb/src/tools/test.clj +148 -0
  36. package/bb/src/tools/version.clj +47 -0
  37. package/bb.edn +269 -0
  38. package/benchmark/src/benchmark/cli.clj +195 -0
  39. package/benchmark/src/benchmark/compare.clj +157 -0
  40. package/benchmark/src/benchmark/config.clj +316 -0
  41. package/benchmark/src/benchmark/measure.clj +187 -0
  42. package/benchmark/src/benchmark/store.clj +190 -0
  43. package/benchmark/test/benchmark/measure_test.clj +156 -0
  44. package/build.clj +30 -0
  45. package/config.edn +49 -0
  46. package/deps.edn +138 -0
  47. package/dev/sandbox.clj +82 -0
  48. package/dev/sandbox.cljs +127 -0
  49. package/dev/sandbox_benchmarks.clj +27 -0
  50. package/dev/sandbox_client.clj +87 -0
  51. package/dev/sandbox_transact_bench.clj +109 -0
  52. package/dev/user.clj +79 -0
  53. package/doc/README.md +96 -0
  54. package/doc/adl/README.md +6 -0
  55. package/doc/adl/adr-000-adr.org +28 -0
  56. package/doc/adl/adr-001-attribute-references.org +15 -0
  57. package/doc/adl/adr-002-build-tooling.org +54 -0
  58. package/doc/adl/adr-003-db-meta-data.md +52 -0
  59. package/doc/adl/adr-004-github-flow.md +40 -0
  60. package/doc/adl/adr-XYZ-template.md +30 -0
  61. package/doc/adl/index.org +3 -0
  62. package/doc/assets/datahike-logo.svg +3 -0
  63. package/doc/assets/datahiking-invoice.org +85 -0
  64. package/doc/assets/hhtree2.png +0 -0
  65. package/doc/assets/network_topology.svg +624 -0
  66. package/doc/assets/perf.png +0 -0
  67. package/doc/assets/schema_mindmap.mm +132 -0
  68. package/doc/assets/schema_mindmap.svg +970 -0
  69. package/doc/assets/temporal_index.mm +74 -0
  70. package/doc/backend-development.md +78 -0
  71. package/doc/bb-pod.md +89 -0
  72. package/doc/benchmarking.md +360 -0
  73. package/doc/bindings/edn-conversion.md +383 -0
  74. package/doc/cli.md +162 -0
  75. package/doc/cljdoc.edn +27 -0
  76. package/doc/cljs-support.md +133 -0
  77. package/doc/config.md +406 -0
  78. package/doc/contributing.md +114 -0
  79. package/doc/datalog-vs-sql.md +210 -0
  80. package/doc/datomic_differences.md +109 -0
  81. package/doc/development/pull-api-ns.md +186 -0
  82. package/doc/development/pull-frame-state-diagram.jpg +0 -0
  83. package/doc/distributed.md +566 -0
  84. package/doc/entity_spec.md +92 -0
  85. package/doc/gc.md +273 -0
  86. package/doc/java-api.md +808 -0
  87. package/doc/javascript-api.md +421 -0
  88. package/doc/libdatahike.md +86 -0
  89. package/doc/logging_and_error_handling.md +43 -0
  90. package/doc/norms.md +66 -0
  91. package/doc/schema-migration.md +85 -0
  92. package/doc/schema.md +287 -0
  93. package/doc/storage-backends.md +363 -0
  94. package/doc/store-id-refactoring.md +596 -0
  95. package/doc/time_variance.md +325 -0
  96. package/doc/unstructured.md +167 -0
  97. package/doc/versioning.md +261 -0
  98. package/examples/basic/README.md +19 -0
  99. package/examples/basic/deps.edn +6 -0
  100. package/examples/basic/docker-compose.yml +13 -0
  101. package/examples/basic/src/examples/core.clj +60 -0
  102. package/examples/basic/src/examples/schema.clj +155 -0
  103. package/examples/basic/src/examples/store.clj +60 -0
  104. package/examples/basic/src/examples/time_travel.clj +185 -0
  105. package/examples/java/.settings/org.eclipse.core.resources.prefs +3 -0
  106. package/examples/java/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  107. package/examples/java/.settings/org.eclipse.jdt.core.prefs +9 -0
  108. package/examples/java/.settings/org.eclipse.m2e.core.prefs +4 -0
  109. package/examples/java/README.md +162 -0
  110. package/examples/java/pom.xml +62 -0
  111. package/examples/java/src/main/java/examples/QuickStart.java +115 -0
  112. package/examples/java/src/main/java/examples/SchemaExample.java +148 -0
  113. package/examples/java/src/main/java/examples/TimeTravelExample.java +121 -0
  114. package/flake.lock +27 -0
  115. package/flake.nix +27 -0
  116. package/http-server/datahike/http/middleware.clj +75 -0
  117. package/http-server/datahike/http/server.clj +269 -0
  118. package/java/src/datahike/java/Database.java +274 -0
  119. package/java/src/datahike/java/Datahike.java +281 -0
  120. package/java/src/datahike/java/DatahikeGeneratedTest.java +349 -0
  121. package/java/src/datahike/java/DatahikeTest.java +370 -0
  122. package/java/src/datahike/java/EDN.java +170 -0
  123. package/java/src/datahike/java/IEntity.java +11 -0
  124. package/java/src/datahike/java/Keywords.java +161 -0
  125. package/java/src/datahike/java/SchemaFlexibility.java +52 -0
  126. package/java/src/datahike/java/Util.java +219 -0
  127. package/karma.conf.js +19 -0
  128. package/libdatahike/compile-cpp +7 -0
  129. package/libdatahike/src/datahike/impl/LibDatahikeBase.java +203 -0
  130. package/libdatahike/src/datahike/impl/libdatahike.clj +59 -0
  131. package/libdatahike/src/test_cpp.cpp +61 -0
  132. package/npm-package/PUBLISHING.md +140 -0
  133. package/npm-package/README.md +226 -0
  134. package/npm-package/package.template.json +34 -0
  135. package/npm-package/test-isomorphic.ts +281 -0
  136. package/npm-package/test.js +557 -0
  137. package/npm-package/typescript-test.ts +70 -0
  138. package/package.json +16 -0
  139. package/pydatahike/README.md +569 -0
  140. package/pydatahike/pyproject.toml +91 -0
  141. package/pydatahike/setup.py +42 -0
  142. package/pydatahike/src/datahike/__init__.py +134 -0
  143. package/pydatahike/src/datahike/_native.py +250 -0
  144. package/pydatahike/src/datahike/_version.py +2 -0
  145. package/pydatahike/src/datahike/database.py +722 -0
  146. package/pydatahike/src/datahike/edn.py +311 -0
  147. package/pydatahike/src/datahike/py.typed +0 -0
  148. package/pydatahike/tests/conftest.py +17 -0
  149. package/pydatahike/tests/test_basic.py +170 -0
  150. package/pydatahike/tests/test_database.py +51 -0
  151. package/pydatahike/tests/test_edn_conversion.py +299 -0
  152. package/pydatahike/tests/test_query.py +99 -0
  153. package/pydatahike/tests/test_schema.py +55 -0
  154. package/resources/clj-kondo.exports/io.replikativ/datahike/config.edn +5 -0
  155. package/resources/example_server.edn +4 -0
  156. package/shadow-cljs.edn +56 -0
  157. package/src/data_readers.clj +7 -0
  158. package/src/datahike/api/impl.cljc +176 -0
  159. package/src/datahike/api/specification.cljc +633 -0
  160. package/src/datahike/api/types.cljc +261 -0
  161. package/src/datahike/api.cljc +41 -0
  162. package/src/datahike/array.cljc +99 -0
  163. package/src/datahike/cli.clj +166 -0
  164. package/src/datahike/cljs.cljs +6 -0
  165. package/src/datahike/codegen/cli.clj +406 -0
  166. package/src/datahike/codegen/clj_kondo.clj +291 -0
  167. package/src/datahike/codegen/java.clj +403 -0
  168. package/src/datahike/codegen/naming.cljc +33 -0
  169. package/src/datahike/codegen/native.clj +559 -0
  170. package/src/datahike/codegen/pod.clj +488 -0
  171. package/src/datahike/codegen/python.clj +838 -0
  172. package/src/datahike/codegen/report.clj +55 -0
  173. package/src/datahike/codegen/typescript.clj +262 -0
  174. package/src/datahike/codegen/validation.clj +145 -0
  175. package/src/datahike/config.cljc +294 -0
  176. package/src/datahike/connections.cljc +16 -0
  177. package/src/datahike/connector.cljc +265 -0
  178. package/src/datahike/constants.cljc +142 -0
  179. package/src/datahike/core.cljc +297 -0
  180. package/src/datahike/datom.cljc +459 -0
  181. package/src/datahike/db/interface.cljc +119 -0
  182. package/src/datahike/db/search.cljc +305 -0
  183. package/src/datahike/db/transaction.cljc +937 -0
  184. package/src/datahike/db/utils.cljc +338 -0
  185. package/src/datahike/db.cljc +956 -0
  186. package/src/datahike/experimental/unstructured.cljc +126 -0
  187. package/src/datahike/experimental/versioning.cljc +172 -0
  188. package/src/datahike/externs.js +31 -0
  189. package/src/datahike/gc.cljc +69 -0
  190. package/src/datahike/http/client.clj +188 -0
  191. package/src/datahike/http/writer.clj +79 -0
  192. package/src/datahike/impl/entity.cljc +218 -0
  193. package/src/datahike/index/interface.cljc +93 -0
  194. package/src/datahike/index/persistent_set.cljc +469 -0
  195. package/src/datahike/index/utils.cljc +44 -0
  196. package/src/datahike/index.cljc +32 -0
  197. package/src/datahike/js/api.cljs +172 -0
  198. package/src/datahike/js/api_macros.clj +22 -0
  199. package/src/datahike/js.cljs +163 -0
  200. package/src/datahike/json.cljc +209 -0
  201. package/src/datahike/lru.cljc +146 -0
  202. package/src/datahike/migrate.clj +39 -0
  203. package/src/datahike/norm/norm.clj +245 -0
  204. package/src/datahike/online_gc.cljc +252 -0
  205. package/src/datahike/pod.clj +155 -0
  206. package/src/datahike/pull_api.cljc +325 -0
  207. package/src/datahike/query.cljc +1945 -0
  208. package/src/datahike/query_stats.cljc +88 -0
  209. package/src/datahike/readers.cljc +62 -0
  210. package/src/datahike/remote.cljc +218 -0
  211. package/src/datahike/schema.cljc +228 -0
  212. package/src/datahike/schema_cache.cljc +42 -0
  213. package/src/datahike/spec.cljc +101 -0
  214. package/src/datahike/store.cljc +80 -0
  215. package/src/datahike/tools.cljc +308 -0
  216. package/src/datahike/transit.cljc +80 -0
  217. package/src/datahike/writer.cljc +239 -0
  218. package/src/datahike/writing.cljc +362 -0
  219. package/src/deps.cljs +1 -0
  220. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/insert.cljc +76 -0
  221. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/upsert.cljc +128 -0
  222. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree.cljc +213 -0
  223. package/test/datahike/backward_compatibility_test/src/backward_test.clj +37 -0
  224. package/test/datahike/integration_test/config_record_file_test.clj +14 -0
  225. package/test/datahike/integration_test/config_record_test.clj +14 -0
  226. package/test/datahike/integration_test/depr_config_uri_test.clj +15 -0
  227. package/test/datahike/integration_test/return_map_test.clj +62 -0
  228. package/test/datahike/integration_test.cljc +67 -0
  229. package/test/datahike/norm/norm_test.clj +124 -0
  230. package/test/datahike/norm/resources/naming-and-sorting-test/001-a1-example.edn +5 -0
  231. package/test/datahike/norm/resources/naming-and-sorting-test/002-a2-example.edn +5 -0
  232. package/test/datahike/norm/resources/naming-and-sorting-test/003-tx-fn-test.edn +1 -0
  233. package/test/datahike/norm/resources/naming-and-sorting-test/004-tx-data-and-tx-fn-test.edn +5 -0
  234. package/test/datahike/norm/resources/naming-and-sorting-test/01-transact-basic-characters.edn +2 -0
  235. package/test/datahike/norm/resources/naming-and-sorting-test/02 add occupation.edn +5 -0
  236. package/test/datahike/norm/resources/naming-and-sorting-test/checksums.edn +12 -0
  237. package/test/datahike/norm/resources/simple-test/001-a1-example.edn +5 -0
  238. package/test/datahike/norm/resources/simple-test/002-a2-example.edn +5 -0
  239. package/test/datahike/norm/resources/simple-test/checksums.edn +4 -0
  240. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/001-a1-example.edn +5 -0
  241. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/002-a2-example.edn +5 -0
  242. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/003-tx-fn-test.edn +1 -0
  243. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/checksums.edn +6 -0
  244. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/004-tx-data-and-tx-fn-test.edn +5 -0
  245. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/checksums.edn +2 -0
  246. package/test/datahike/norm/resources/tx-fn-test/first/001-a1-example.edn +5 -0
  247. package/test/datahike/norm/resources/tx-fn-test/first/002-a2-example.edn +5 -0
  248. package/test/datahike/norm/resources/tx-fn-test/first/checksums.edn +4 -0
  249. package/test/datahike/norm/resources/tx-fn-test/second/003-tx-fn-test.edn +1 -0
  250. package/test/datahike/norm/resources/tx-fn-test/second/checksums.edn +2 -0
  251. package/test/datahike/test/api_test.cljc +895 -0
  252. package/test/datahike/test/array_test.cljc +40 -0
  253. package/test/datahike/test/attribute_refs/datoms_test.cljc +140 -0
  254. package/test/datahike/test/attribute_refs/db_test.cljc +42 -0
  255. package/test/datahike/test/attribute_refs/differences_test.cljc +515 -0
  256. package/test/datahike/test/attribute_refs/entity_test.cljc +89 -0
  257. package/test/datahike/test/attribute_refs/pull_api_test.cljc +320 -0
  258. package/test/datahike/test/attribute_refs/query_find_specs_test.cljc +59 -0
  259. package/test/datahike/test/attribute_refs/query_fns_test.cljc +130 -0
  260. package/test/datahike/test/attribute_refs/query_interop_test.cljc +47 -0
  261. package/test/datahike/test/attribute_refs/query_not_test.cljc +193 -0
  262. package/test/datahike/test/attribute_refs/query_or_test.cljc +137 -0
  263. package/test/datahike/test/attribute_refs/query_pull_test.cljc +156 -0
  264. package/test/datahike/test/attribute_refs/query_rules_test.cljc +176 -0
  265. package/test/datahike/test/attribute_refs/query_test.cljc +241 -0
  266. package/test/datahike/test/attribute_refs/temporal_search.cljc +22 -0
  267. package/test/datahike/test/attribute_refs/transact_test.cljc +220 -0
  268. package/test/datahike/test/attribute_refs/utils.cljc +128 -0
  269. package/test/datahike/test/cache_test.cljc +38 -0
  270. package/test/datahike/test/components_test.cljc +92 -0
  271. package/test/datahike/test/config_test.cljc +158 -0
  272. package/test/datahike/test/core_test.cljc +105 -0
  273. package/test/datahike/test/datom_test.cljc +44 -0
  274. package/test/datahike/test/db_test.cljc +54 -0
  275. package/test/datahike/test/entity_spec_test.cljc +159 -0
  276. package/test/datahike/test/entity_test.cljc +103 -0
  277. package/test/datahike/test/explode_test.cljc +143 -0
  278. package/test/datahike/test/filter_test.cljc +75 -0
  279. package/test/datahike/test/gc_test.cljc +159 -0
  280. package/test/datahike/test/http/server_test.clj +192 -0
  281. package/test/datahike/test/http/writer_test.clj +86 -0
  282. package/test/datahike/test/ident_test.cljc +32 -0
  283. package/test/datahike/test/index_test.cljc +345 -0
  284. package/test/datahike/test/insert.cljc +125 -0
  285. package/test/datahike/test/java_bindings_test.clj +6 -0
  286. package/test/datahike/test/listen_test.cljc +41 -0
  287. package/test/datahike/test/lookup_refs_test.cljc +266 -0
  288. package/test/datahike/test/lru_test.cljc +27 -0
  289. package/test/datahike/test/migrate_test.clj +297 -0
  290. package/test/datahike/test/model/core.cljc +376 -0
  291. package/test/datahike/test/model/invariant.cljc +142 -0
  292. package/test/datahike/test/model/rng.cljc +82 -0
  293. package/test/datahike/test/model_test.clj +217 -0
  294. package/test/datahike/test/nodejs_test.cljs +262 -0
  295. package/test/datahike/test/online_gc_test.cljc +475 -0
  296. package/test/datahike/test/pod_test.clj +369 -0
  297. package/test/datahike/test/pull_api_test.cljc +474 -0
  298. package/test/datahike/test/purge_test.cljc +144 -0
  299. package/test/datahike/test/query_aggregates_test.cljc +101 -0
  300. package/test/datahike/test/query_find_specs_test.cljc +52 -0
  301. package/test/datahike/test/query_fns_test.cljc +523 -0
  302. package/test/datahike/test/query_interop_test.cljc +47 -0
  303. package/test/datahike/test/query_not_test.cljc +189 -0
  304. package/test/datahike/test/query_or_test.cljc +158 -0
  305. package/test/datahike/test/query_pull_test.cljc +147 -0
  306. package/test/datahike/test/query_rules_test.cljc +248 -0
  307. package/test/datahike/test/query_stats_test.cljc +218 -0
  308. package/test/datahike/test/query_test.cljc +984 -0
  309. package/test/datahike/test/schema_test.cljc +424 -0
  310. package/test/datahike/test/specification_test.cljc +30 -0
  311. package/test/datahike/test/store_test.cljc +78 -0
  312. package/test/datahike/test/stress_test.cljc +57 -0
  313. package/test/datahike/test/time_variance_test.cljc +518 -0
  314. package/test/datahike/test/tools_test.clj +134 -0
  315. package/test/datahike/test/transact_test.cljc +518 -0
  316. package/test/datahike/test/tuples_test.cljc +564 -0
  317. package/test/datahike/test/unstructured_test.cljc +291 -0
  318. package/test/datahike/test/upsert_impl_test.cljc +205 -0
  319. package/test/datahike/test/upsert_test.cljc +363 -0
  320. package/test/datahike/test/utils.cljc +110 -0
  321. package/test/datahike/test/validation_test.cljc +48 -0
  322. package/test/datahike/test/versioning_test.cljc +56 -0
  323. package/test/datahike/test.cljc +66 -0
  324. package/tests.edn +24 -0
@@ -0,0 +1,103 @@
1
+ (ns datahike.test.entity-test
2
+ (:require
3
+ [#?(:cljs cljs.reader :clj clojure.edn) :as edn]
4
+ #?(:cljs [cljs.test :as t :refer-macros [is deftest testing]]
5
+ :clj [clojure.test :as t :refer [is deftest testing]])
6
+ [clojure.walk]
7
+ [datahike.api :as d]
8
+ [datahike.db :as db]
9
+ [datahike.impl.entity :as de]
10
+ [datahike.test.core-test :as tdc]))
11
+
12
+ #?(:cljs (def Throwable js/Error))
13
+
14
+ (t/use-fixtures :once tdc/no-namespace-maps)
15
+
16
+ (deftest test-entity
17
+ (let [db (-> (db/empty-db {:aka {:db/cardinality :db.cardinality/many}})
18
+ (d/db-with [{:db/id 1, :name "Ivan", :age 19, :aka ["X" "Y"]}
19
+ {:db/id 2, :name "Ivan", :sex "male", :aka ["Z"]}
20
+ [:db/add 3 :huh? false]]))
21
+ e (d/entity db 1)]
22
+ (is (= (:db/id e) 1))
23
+ (is (identical? (d/entity-db e) db))
24
+ (is (= (:name e) "Ivan"))
25
+ (is (= (e :name) "Ivan")) ; IFn form
26
+ (is (= (:age e) 19))
27
+ (is (= (:aka e) #{"X" "Y"}))
28
+ (is (= true (contains? e :age)))
29
+ (is (= false (contains? e :not-found)))
30
+ (is (= (into {} e)
31
+ {:name "Ivan", :age 19, :aka #{"X" "Y"}}))
32
+ (is (= (into {} (d/entity db 1))
33
+ {:name "Ivan", :age 19, :aka #{"X" "Y"}}))
34
+ (is (= (into {} (d/entity db 2))
35
+ {:name "Ivan", :sex "male", :aka #{"Z"}}))
36
+ (let [e3 (d/entity db 3)]
37
+ (is (= (into {} e3) {:huh? false})) ; Force caching.
38
+ (is (false? (:huh? e3))))
39
+
40
+ (is (= (pr-str (d/entity db 1)) "{:db/id 1}"))
41
+ (is (= (pr-str (let [e (d/entity db 1)] (:unknown e) e)) "{:db/id 1}"))
42
+ ;; read back in to account for unordered-ness
43
+ (is (= (edn/read-string (pr-str (let [e (d/entity db 1)] (:name e) e)))
44
+ (edn/read-string "{:name \"Ivan\", :db/id 1}")))))
45
+
46
+ (deftest test-entity-refs
47
+ (let [db (-> (db/empty-db {:father {:db/valueType :db.type/ref}
48
+ :children {:db/valueType :db.type/ref
49
+ :db/cardinality :db.cardinality/many}})
50
+ (d/db-with
51
+ [{:db/id 1, :children [10]}
52
+ {:db/id 10, :father 1, :children [100 101]}
53
+ {:db/id 100, :father 10}
54
+ {:db/id 101, :father 10}]))
55
+ e #(d/entity db %)]
56
+
57
+ (is (= (:children (e 1)) #{(e 10)}))
58
+ (is (= (:children (e 10)) #{(e 100) (e 101)}))
59
+
60
+ (testing "empty attribute"
61
+ (is (= (:children (e 100)) nil)))
62
+
63
+ (testing "nested navigation"
64
+ (is (= (-> (e 1) :children first :children) #{(e 100) (e 101)}))
65
+ (is (= (-> (e 10) :children first :father) (e 10)))
66
+ (is (= (-> (e 10) :father :children) #{(e 10)}))
67
+
68
+ (testing "after touch"
69
+ (let [e1 (e 1)
70
+ e10 (e 10)]
71
+ (de/touch e1)
72
+ (de/touch e10)
73
+ (is (= (-> e1 :children first :children) #{(e 100) (e 101)}))
74
+ (is (= (-> e10 :children first :father) (e 10)))
75
+ (is (= (-> e10 :father :children) #{(e 10)})))))
76
+
77
+ (testing "backward navigation"
78
+ (is (= (:_children (e 1)) nil))
79
+ (is (= (:_father (e 1)) #{(e 10)}))
80
+ (is (= (:_children (e 10)) #{(e 1)}))
81
+ (is (= (:_father (e 10)) #{(e 100) (e 101)}))
82
+ (is (= (-> (e 100) :_children first :_children) #{(e 1)})))))
83
+
84
+ (deftest test-entity-misses
85
+ (let [db (-> (db/empty-db {:name {:db/unique :db.unique/identity}})
86
+ (d/db-with [{:db/id 1, :name "Ivan"}
87
+ {:db/id 2, :name "Oleg"}]))]
88
+ (is (nil? (d/entity db nil)))
89
+ (is (nil? (d/entity db "abc")))
90
+ (is (nil? (d/entity db :keyword)))
91
+ (is (nil? (d/entity db [:name "Petr"])))
92
+ (is (= 777 (:db/id (d/entity db 777))))
93
+ (is (thrown-with-msg? Throwable #"Lookup ref attribute should be marked as :db/unique: \[:not-an-attr 777\]"
94
+ (d/entity db [:not-an-attr 777])))))
95
+
96
+ (deftest test-entity-walk
97
+ (let [ivan {:name "Ivan", :age 19, :aka #{"X" "Y"}}
98
+ db (-> (db/empty-db {:aka {:db/cardinality :db.cardinality/many}})
99
+ (d/db-with [(assoc ivan :db/id 1)]))
100
+ e (d/entity db 1)]
101
+ (is (= (clojure.walk/walk identity identity e) ivan))
102
+ (is (= (clojure.walk/postwalk identity e) ivan))
103
+ (is (= (clojure.walk/prewalk identity e) ivan))))
@@ -0,0 +1,143 @@
1
+ (ns datahike.test.explode-test
2
+ (:require
3
+ #?(:cljs [cljs.test :as t :refer-macros [is are deftest testing]]
4
+ :clj [clojure.test :as t :refer [is are deftest testing]])
5
+ [datahike.api :as d]
6
+ [datahike.db :as db]
7
+ [datahike.test.utils :as dtu]
8
+ [datahike.test.core-test]))
9
+
10
+ #?(:cljs
11
+ (def Throwable js/Error))
12
+
13
+ (deftest test-explode
14
+ (doseq [coll [["Devil" "Tupen"]
15
+ #{"Devil" "Tupen"}
16
+ '("Devil" "Tupen")
17
+ (to-array ["Devil" "Tupen"])]]
18
+ (testing coll
19
+ (let [conn (dtu/setup-db {:initial-tx [{:db/ident :aka
20
+ :db/valueType :db.type/string
21
+ :db/cardinality :db.cardinality/many}
22
+ {:db/ident :also
23
+ :db/valueType :db.type/string
24
+ :db/cardinality :db.cardinality/many}]})]
25
+ (d/transact conn {:tx-data [{:db/id -1
26
+ :name "Ivan"
27
+ :age 16
28
+ :aka coll
29
+ :also "ok"}]})
30
+ (is (= (d/q '[:find ?n ?a
31
+ :where
32
+ [3 :name ?n]
33
+ [3 :age ?a]]
34
+ @conn)
35
+ #{["Ivan" 16]}))
36
+ (is (= (d/q '[:find ?v
37
+ :where [3 :also ?v]]
38
+ @conn)
39
+ #{["ok"]}))
40
+ (is (= (d/q '[:find ?v
41
+ :where [3 :aka ?v]]
42
+ @conn)
43
+ #{["Devil"] ["Tupen"]}))))))
44
+
45
+ (deftest test-explode-ref
46
+ (let [db0 (db/empty-db {:children {:db/valueType :db.type/ref
47
+ :db/cardinality :db.cardinality/many}})]
48
+ (let [db (d/db-with db0 [{:db/id -1, :name "Ivan", :children [-2 -3]}
49
+ {:db/id -2, :name "Petr"}
50
+ {:db/id -3, :name "Evgeny"}])]
51
+ (is (= (d/q '[:find ?n
52
+ :where [_ :children ?e]
53
+ [?e :name ?n]] db)
54
+ #{["Petr"] ["Evgeny"]})))
55
+
56
+ (let [db (d/db-with db0 [{:db/id -1, :name "Ivan"}
57
+ {:db/id -2, :name "Petr", :_children -1}
58
+ {:db/id -3, :name "Evgeny", :_children -1}])]
59
+ (is (= (d/q '[:find ?n
60
+ :where [_ :children ?e]
61
+ [?e :name ?n]] db)
62
+ #{["Petr"] ["Evgeny"]})))
63
+
64
+ (is (thrown-with-msg? Throwable
65
+ #"Bad attribute :_parent: reverse attribute name requires \{:db/valueType :db.type/ref\} in schema"
66
+ (d/db-with db0 [{:name "Sergey" :_parent 1}])))))
67
+
68
+ (deftest test-explode-nested-maps
69
+ (let [schema {:profile {:db/valueType :db.type/ref}}
70
+ db (db/empty-db schema)]
71
+ (are [tx res] (= (d/q '[:find ?e ?a ?v
72
+ :where [?e ?a ?v]]
73
+ (d/db-with db tx)) res)
74
+ [{:db/id 5 :name "Ivan" :profile {:db/id 7 :email "@2"}}]
75
+ #{[5 :name "Ivan"] [5 :profile 7] [7 :email "@2"]}
76
+
77
+ [{:name "Ivan" :profile {:email "@2"}}]
78
+ #{[1 :name "Ivan"] [1 :profile 2] [2 :email "@2"]}
79
+
80
+ [{:profile {:email "@2"}}] ;; issue #59
81
+ #{[1 :profile 2] [2 :email "@2"]}
82
+
83
+ [{:email "@2" :_profile {:name "Ivan"}}]
84
+ #{[1 :email "@2"] [2 :name "Ivan"] [2 :profile 1]}))
85
+
86
+ (testing "multi-valued"
87
+ (let [schema {:profile {:db/valueType :db.type/ref
88
+ :db/cardinality :db.cardinality/many}}
89
+ db (db/empty-db schema)]
90
+ (are [tx res] (= (d/q '[:find ?e ?a ?v
91
+ :where [?e ?a ?v]]
92
+ (d/db-with db tx)) res)
93
+ [{:db/id 5 :name "Ivan" :profile {:db/id 7 :email "@2"}}]
94
+ #{[5 :name "Ivan"] [5 :profile 7] [7 :email "@2"]}
95
+
96
+ [{:db/id 5 :name "Ivan" :profile [{:db/id 7 :email "@2"} {:db/id 8 :email "@3"}]}]
97
+ #{[5 :name "Ivan"] [5 :profile 7] [7 :email "@2"] [5 :profile 8] [8 :email "@3"]}
98
+
99
+ [{:name "Ivan" :profile {:email "@2"}}]
100
+ #{[1 :name "Ivan"] [1 :profile 2] [2 :email "@2"]}
101
+
102
+ [{:name "Ivan" :profile [{:email "@2"} {:email "@3"}]}]
103
+ #{[1 :name "Ivan"] [1 :profile 2] [2 :email "@2"] [1 :profile 3] [3 :email "@3"]}
104
+
105
+ [{:email "@2" :_profile {:name "Ivan"}}]
106
+ #{[1 :email "@2"] [2 :name "Ivan"] [2 :profile 1]}
107
+
108
+ [{:email "@2" :_profile [{:name "Ivan"} {:name "Petr"}]}]
109
+ #{[1 :email "@2"] [2 :name "Ivan"] [2 :profile 1] [3 :name "Petr"] [3 :profile 1]}))))
110
+
111
+ (deftest test-circular-refs
112
+ (let [schema {:comp {:db/valueType :db.type/ref
113
+ :db/cardinality :db.cardinality/many
114
+ :db/isComponent true}}
115
+ db (d/db-with (db/empty-db schema)
116
+ [{:db/id 1, :comp [{:name "C"}]}])]
117
+ (is (= (mapv (juxt :e :a :v) (d/datoms db :eavt))
118
+ [[1 :comp 2]
119
+ [2 :name "C"]])))
120
+
121
+ (let [schema {:comp {:db/valueType :db.type/ref
122
+ :db/cardinality :db.cardinality/many}}
123
+ db (d/db-with (db/empty-db schema)
124
+ [{:db/id 1, :comp [{:name "C"}]}])]
125
+ (is (= (mapv (juxt :e :a :v) (d/datoms db :eavt))
126
+ [[1 :comp 2]
127
+ [2 :name "C"]])))
128
+
129
+ (let [schema {:comp {:db/valueType :db.type/ref
130
+ :db/isComponent true}}
131
+ db (d/db-with (db/empty-db schema)
132
+ [{:db/id 1, :comp {:name "C"}}])]
133
+ (is (= (mapv (juxt :e :a :v) (d/datoms db :eavt))
134
+ [[1 :comp 2]
135
+ [2 :name "C"]])))
136
+
137
+ (let [schema {:comp {:db/valueType :db.type/ref}}
138
+ db (d/db-with (db/empty-db schema)
139
+ [{:db/id 1, :comp {:name "C"}}])]
140
+ (is (= (mapv (juxt :e :a :v) (d/datoms db :eavt))
141
+ [[1 :comp 2]
142
+ [2 :name "C"]]))))
143
+
@@ -0,0 +1,75 @@
1
+ (ns datahike.test.filter-test
2
+ (:require
3
+ #?(:cljs [cljs.test :as t :refer-macros [is are deftest testing]]
4
+ :clj [clojure.test :as t :refer [is are deftest testing]])
5
+ [datahike.api :as d]
6
+ [datahike.db :as db]))
7
+
8
+ (deftest test-filter-db
9
+ (let [empty-db (db/empty-db {:aka {:db/cardinality :db.cardinality/many}})
10
+ db (-> empty-db
11
+ (d/db-with [{:db/id 1
12
+ :name "Petr"
13
+ :email "petya@spb.ru"
14
+ :aka ["I" "Great"]
15
+ :password "<SECRET>"}
16
+ {:db/id 2
17
+ :name "Ivan"
18
+ :aka ["Terrible" "IV"]
19
+ :password "<PROTECTED>"}
20
+ {:db/id 3
21
+ :name "Nikolai"
22
+ :aka ["II"]
23
+ :password "<UNKNOWN>"}]))
24
+ remove-pass (fn [_ datom] (not= :password (:a datom)))
25
+ remove-ivan (fn [_ datom] (not= 2 (:e datom)))
26
+ long-akas (fn [udb datom] (or (not= :aka (:a datom))
27
+ ;; has just 1 aka
28
+ (<= (count (:aka (d/entity udb (:e datom)))) 1)
29
+ ;; or aka longer than 4 chars
30
+ (>= (count (:v datom)) 4)))]
31
+
32
+ (are [_db _res] (= (d/q '[:find ?v :where [_ :password ?v]] _db) _res)
33
+ db #{["<SECRET>"] ["<PROTECTED>"] ["<UNKNOWN>"]}
34
+ (d/filter db remove-pass) #{}
35
+ (d/filter db remove-ivan) #{["<SECRET>"] ["<UNKNOWN>"]}
36
+ (-> db (d/filter remove-ivan) (d/filter remove-pass)) #{})
37
+
38
+ (are [_db _res] (= (d/q '[:find ?v :where [_ :aka ?v]] _db) _res)
39
+ db #{["I"] ["Great"] ["Terrible"] ["IV"] ["II"]}
40
+ (d/filter db remove-pass) #{["I"] ["Great"] ["Terrible"] ["IV"] ["II"]}
41
+ (d/filter db remove-ivan) #{["I"] ["Great"] ["II"]}
42
+ (d/filter db long-akas) #{["Great"] ["Terrible"] ["II"]}
43
+ (-> db (d/filter remove-ivan) (d/filter long-akas)) #{["Great"] ["II"]}
44
+ (-> db (d/filter long-akas) (d/filter remove-ivan)) #{["Great"] ["II"]})
45
+
46
+ (testing "Entities"
47
+ (is (= (:password (d/entity db 1)) "<SECRET>"))
48
+ (is (= (:password (d/entity (d/filter db remove-pass) 1) ::not-found) ::not-found))
49
+ (is (= (:aka (d/entity db 2)) #{"Terrible" "IV"}))
50
+ (is (= (:aka (d/entity (d/filter db long-akas) 2)) #{"Terrible"})))
51
+
52
+ (testing "Index access"
53
+ (is (= (map :v (d/datoms db :aevt :password))
54
+ ["<SECRET>" "<PROTECTED>" "<UNKNOWN>"]))
55
+ (is (= (map :v (d/datoms (d/filter db remove-pass) :aevt :password))
56
+ [])))
57
+
58
+ (testing "equiv"
59
+ (is (= (d/db-with db [[:db.fn/retractEntity 2]])
60
+ (d/filter db remove-ivan)))
61
+ (is (= empty-db
62
+ (d/filter empty-db (constantly true))
63
+ (d/filter db (constantly false))))))
64
+
65
+ (testing "double filtering"
66
+ (let [db (d/db-with (db/empty-db {})
67
+ [{:db/id 1, :name "Petr", :age 32}
68
+ {:db/id 2, :name "Oleg"}
69
+ {:db/id 3, :name "Ivan", :age 12}])
70
+ has-age? (fn [db datom] (some? (:age (d/entity db (:e datom)))))
71
+ adult? (fn [db datom] (>= (:age (d/entity db (:e datom))) 18))
72
+ names (fn [db] (map :v (d/datoms db :aevt :name)))]
73
+ (is (= ["Petr" "Oleg" "Ivan"] (names db)))
74
+ (is (= ["Petr" "Ivan"] (names (-> db (d/filter has-age?)))))
75
+ (is (= ["Petr"] (names (-> db (d/filter has-age?) (d/filter adult?))))))))
@@ -0,0 +1,159 @@
1
+ (ns datahike.test.gc-test
2
+ (:require
3
+ #?(:cljs [cljs.test :as t :refer-macros [is deftest testing]]
4
+ :clj [clojure.test :as t :refer [is deftest testing]])
5
+ [clojure.set :as set]
6
+ [superv.async :refer [<?? S]]
7
+ [datahike.api :as d]
8
+ [datahike.index.interface :refer [-mark]]
9
+ [datahike.experimental.versioning :refer [branch! delete-branch! merge!
10
+ branch-history]]
11
+ [konserve.core :as k]
12
+ [datahike.test.core-test])
13
+ (:import [java.util Date]))
14
+
15
+ #?(:cljs (def Throwable js/Error))
16
+
17
+ (defn- count-store [db]
18
+ (count (k/keys (:store db) {:sync? true})))
19
+
20
+ (def count-query '[:find (count ?e) .
21
+ :where
22
+ [?e :age _]])
23
+
24
+ (def txs (vec (for [i (range 1000)] {:age i})))
25
+
26
+ (def cfg {:store {:backend :file
27
+ :path "/tmp/gc-test"
28
+ :id #uuid "9c000000-0000-0000-0000-000000000001"}
29
+ :keep-history? true
30
+ :schema-flexibility :write
31
+ :index :datahike.index/persistent-set})
32
+
33
+ (def schema [{:db/ident :age
34
+ :db/cardinality :db.cardinality/one
35
+ :db/valueType :db.type/long}])
36
+
37
+ (deftest datahike-gc-test
38
+ (let [cfg (assoc-in cfg [:store :path] "/tmp/dh-gc-test")
39
+ conn (do
40
+ (d/delete-database cfg)
41
+ (d/create-database cfg)
42
+ (d/connect cfg))
43
+ ;; everything will fit into the root nodes of each index here
44
+ num-roots 3
45
+ fresh-count (+ num-roots 4) ;; :branches + :db + cid + roots + schema-meta
46
+ history-count 3]
47
+ (testing "Test initial store counts."
48
+ (is (= 1 (count (-mark (:eavt @conn)))))
49
+ (is (= fresh-count (count-store @conn)))
50
+ (d/transact conn schema)
51
+ (is (= 1 (count (-mark (:eavt @conn)))))
52
+ (is (= (+ 2 history-count fresh-count num-roots) (count-store @conn))))
53
+ (testing "Delete old db with roots."
54
+ (is (= (+ num-roots 2) (count (<?? S (d/gc-storage conn (Date.))))))
55
+ (is (= (+ history-count fresh-count) (count-store @conn))))
56
+ (testing "Try to run on dirty index and fail."
57
+ (is (thrown-with-msg? Throwable #"Index needs to be properly flushed before marking."
58
+ (-mark (:eavt
59
+ (:db-after
60
+ (d/with @conn [{:db/id 100
61
+ :age 5}])))))))
62
+
63
+ (testing "Check that we can still read the data."
64
+ (let [new-conn (d/connect cfg)]
65
+ (d/transact conn txs)
66
+ (<?? S (d/gc-storage conn (Date.)))
67
+ (is (= 1000 (d/q count-query @new-conn)))
68
+ (d/release new-conn)))
69
+ (d/release conn)))
70
+
71
+ (deftest datahike-gc-versioning-test
72
+ (let [cfg (assoc-in cfg [:store :path] "/tmp/dh-gc-versioning-test")
73
+ conn (do
74
+ (d/delete-database cfg)
75
+ (d/create-database cfg)
76
+ (d/connect cfg))
77
+ _ (d/transact conn schema)
78
+ ;; create two more branches
79
+ _ (branch! conn :db :branch1)
80
+ cfg1 (assoc cfg :branch :branch1)
81
+ conn-branch1 (d/connect cfg1)
82
+ _ (branch! conn :db :branch2)
83
+ cfg2 (assoc cfg :branch :branch2)
84
+ conn-branch2 (d/connect cfg2)]
85
+ (testing "Check branches."
86
+ (d/transact conn-branch1 txs)
87
+ (d/transact conn-branch2 txs)
88
+ (<?? S (d/gc-storage conn (Date.)))
89
+ (is (nil? (d/q count-query @conn)))
90
+ (is (= 1000 (d/q count-query @conn-branch1)))
91
+ (is (= 1000 (d/q count-query @conn-branch2)))
92
+ (delete-branch! conn :branch2)
93
+ (<?? S (d/gc-storage conn (Date.))))
94
+
95
+ (d/release conn)
96
+ (d/release conn-branch1)
97
+ (d/release conn-branch2)
98
+
99
+ (testing "Removed branch and after gc check."
100
+ (let [cfg (assoc-in cfg [:store :path] "/tmp/dh-gc-versioning-test")
101
+ conn (d/connect cfg)
102
+ ;; create two more branches
103
+ cfg1 (assoc cfg :branch :branch1)
104
+ conn-branch1 (d/connect cfg1)
105
+ cfg2 (assoc cfg :branch :branch2)]
106
+ (is (nil? (d/q count-query @conn)))
107
+ (is (= 1000 (d/q count-query @conn-branch1)))
108
+ (is (thrown-with-msg? Throwable #"Database does not exist."
109
+ (d/connect cfg2)))
110
+ (d/release conn)
111
+ (d/release conn-branch1)))))
112
+
113
+ (deftest datahike-gc-range-test
114
+ (let [cfg (assoc-in cfg [:store :path] "/tmp/dh-gc-range-test")
115
+ conn (do
116
+ (d/delete-database cfg)
117
+ (d/create-database cfg)
118
+ (d/connect cfg))
119
+ _ (d/transact conn schema)
120
+ ;; create a branch
121
+ _ (branch! conn :db :branch1)
122
+ conn-branch1 (d/connect (assoc cfg :branch :branch1))
123
+ ;; transact on each
124
+ _ (d/transact conn txs)
125
+ _ (d/transact conn-branch1 txs)
126
+ ;; record before-date for gc
127
+ _ (Thread/sleep 100)
128
+ remove-before (Date.)]
129
+ (Thread/sleep 100)
130
+ ;; transact
131
+ (d/transact conn [{:age 42}])
132
+ (d/transact conn-branch1 [{:age 42}])
133
+ ;; transact again
134
+ (d/transact conn [{:age 42}])
135
+ (d/transact conn-branch1 [{:age 42}])
136
+ ;; merge back
137
+ (merge! conn #{:branch1} [])
138
+ (let [db-history (<?? S (branch-history conn))
139
+ branch1-history (<?? S (branch-history conn-branch1))
140
+ _ (delete-branch! conn :branch1)
141
+ _ (testing "Check branch counts"
142
+ (is (= 9 (count db-history)))
143
+ (is (= 5 (count branch1-history)))
144
+ (is (= 9 (count (set/union (set db-history) (set branch1-history))))))
145
+ new-history (set (filter (fn [db]
146
+ (let [db-date ^Date (or (get-in db [:meta :datahike/updated-at])
147
+ (get-in db [:meta :datahike/created-at]))]
148
+ (> (.getTime db-date)
149
+ (.getTime remove-before))))
150
+ (concat db-history branch1-history)))
151
+ ;; gc
152
+ _ (<?? S (d/gc-storage conn remove-before))
153
+ history-after-gc (set (<?? S (branch-history conn)))]
154
+ (testing "Check that newer db roots are still there and counts after gc."
155
+ (is (set/subset? new-history history-after-gc))
156
+ (is (= 5 (count new-history)))
157
+ (is (= 7 (count history-after-gc)))))
158
+ (d/release conn)
159
+ (d/release conn-branch1)))
@@ -0,0 +1,192 @@
1
+ (ns datahike.test.http.server-test
2
+ (:require
3
+ [clojure.test :as t :refer [is deftest testing]]
4
+ [datahike.http.server :refer [start-server stop-server]]
5
+ [datahike.http.client :as api]))
6
+
7
+ (defn run-server-tests [server-config client-config]
8
+ (let [{:keys [format]} client-config
9
+ server (start-server server-config)]
10
+ (try
11
+ (let [new-config (api/create-database {:store {:backend :memory :id #uuid "de110000-0000-0000-0000-000000000001"}
12
+ :schema-flexibility :read
13
+ :remote-peer client-config})
14
+ _ (is (map? new-config))
15
+
16
+ conn (api/connect new-config)
17
+ {:keys [db-before db-after tx-data]} (api/transact conn [{:name "Peter" :age 42}])
18
+
19
+ _ (is (seq tx-data))
20
+
21
+ _ (is (not= (:commit-id db-before)
22
+ (:commit-id db-after)))
23
+
24
+ test-db @conn
25
+ _ (is (= test-db (api/db conn) db-after))
26
+
27
+ query '[:find ?n ?a
28
+ :in $
29
+ :where
30
+ [$ ?e :age ?a]
31
+ [$ ?e :name ?n]]
32
+
33
+ _ (is (= (api/q query test-db)
34
+ #{["Peter" 42]}))
35
+
36
+ _ (is (map? (api/query-stats query test-db)))
37
+
38
+ _ (is (= (api/pull test-db '[:*] 1)
39
+ {:db/id 1, :age 42, :name "Peter"}))
40
+
41
+ _ (is (= 3 (count (api/datoms test-db :eavt))))
42
+
43
+ _ (is (= 3 (count (api/seek-datoms test-db :eavt))))
44
+
45
+ _ (is (map? (api/metrics test-db)))
46
+
47
+ _ (is (map? (api/schema test-db)))
48
+
49
+ _ (is (map? (api/reverse-schema test-db)))
50
+
51
+ _ (is (map? (api/entity test-db 1)))
52
+
53
+ _ (when-not (= format :edn)
54
+ (is (= test-db (api/entity-db (api/entity test-db 1)))))
55
+
56
+ _ (is (instance? datahike.remote.RemoteSinceDB (api/since test-db (java.util.Date.))))
57
+
58
+ _ (is (instance? datahike.remote.RemoteAsOfDB (api/as-of test-db (java.util.Date.))))
59
+
60
+ _ (is (nil? (api/release conn)))
61
+
62
+ _ (is (nil? (api/delete-database new-config)))
63
+
64
+ _ (is (false? (api/database-exists? new-config)))
65
+
66
+ new-config (api/create-database {:store {:backend :memory :id #uuid "de110000-0000-0000-0000-000000000002"}
67
+ :schema-flexibility :write
68
+ :remote-peer client-config})
69
+
70
+ conn (api/connect new-config)
71
+
72
+ schema [{:db/ident :name
73
+ :db/valueType :db.type/string
74
+ :db/cardinality :db.cardinality/one}
75
+ {:db/ident :age
76
+ :db/valueType :db.type/number
77
+ :db/cardinality :db.cardinality/one}]
78
+
79
+ _ (api/transact conn schema)
80
+
81
+ _ (api/transact conn [{:name "Peter" :age 42}])
82
+
83
+ test-db @conn
84
+ _ (is (= (api/q query test-db)
85
+ #{["Peter" 42]}))]
86
+
87
+ (is (nil? (api/release conn)))
88
+ (is (nil? (api/delete-database new-config)))
89
+ (stop-server server))
90
+ (finally
91
+ (stop-server server)))))
92
+
93
+ (deftest test-server
94
+ (testing "Test transit binding."
95
+ (let [port 23189]
96
+ (run-server-tests {:port port
97
+ :join? false
98
+ :dev-mode false
99
+ :token "securerandompassword"}
100
+ {:backend :datahike-server
101
+ :url (str "http://localhost:" port)
102
+ :token "securerandompassword"
103
+ :format :transit})))
104
+ (testing "Test edn binding."
105
+ (let [port 23190]
106
+ (run-server-tests {:port port
107
+ :join? false
108
+ :dev-mode false
109
+ :token "securerandompassword"}
110
+ {:backend :datahike-server
111
+ :url (str "http://localhost:" port)
112
+ :token "securerandompassword"
113
+ :format :edn})))
114
+ (testing "Test JSON binding."
115
+ (let [port 23191]
116
+ (run-server-tests {:port port
117
+ :join? false
118
+ :dev-mode false
119
+ :token "securerandompassword"}
120
+ {:backend :datahike-server
121
+ :url (str "http://localhost:" port)
122
+ :token "securerandompassword"
123
+ :format :json}))))
124
+
125
+ (deftest test-authentication
126
+ (testing "Password tokens must match."
127
+ (let [port 23194
128
+ server (start-server {:port port
129
+ :join? false
130
+ :dev-mode false
131
+ :token "securerandompassword"})]
132
+ (try
133
+ (is (thrown-with-msg? Exception #"Exceptional status code: 401"
134
+ (api/create-database {:store {:backend :memory :id #uuid "de110000-0000-0000-0000-000000000003"}
135
+ :schema-flexibility :read
136
+ :remote-peer {:backend :datahike-server
137
+ :url (str "http://localhost:" port)
138
+ :token "wrong"
139
+ :format :edn}})))
140
+ (finally
141
+ (stop-server server)))))
142
+ (testing "Dev-mode overrides password authentication."
143
+ (let [port 23195
144
+ server (start-server {:port port
145
+ :join? false
146
+ :dev-mode true
147
+ :token "securerandompassword"})
148
+ cfg {:store {:backend :memory :id #uuid "de110000-0000-0000-0000-000000000004"}
149
+ :schema-flexibility :read
150
+ :remote-peer {:backend :datahike-server
151
+ :url (str "http://localhost:" port)
152
+ :token "wrong"
153
+ :format :edn}}]
154
+ (try
155
+ (api/delete-database cfg) ; Clean up any existing database
156
+ (is (map? (api/create-database cfg)))
157
+ (finally
158
+ (api/delete-database cfg)
159
+ (stop-server server))))))
160
+
161
+ (deftest test-json-interface
162
+ (testing "Direct JSON interaction"
163
+ (let [port 23196
164
+ server (start-server {:port port
165
+ :join? false
166
+ :dev-mode true
167
+ :token "securerandompassword"})
168
+ remote {:backend :datahike-server
169
+ :url (str "http://localhost:" port)
170
+ :token "securerandompassword"
171
+ :format :json}
172
+ _ (try (api/request-json-raw :post "delete-database" remote
173
+ "[\"{:store {:backend :memory :id #uuid \\\"23196000-0000-0000-0000-000000000001\\\"}}\"]")
174
+ (catch Exception _))] ; Ignore if database doesn't exist
175
+ (try
176
+ (let [raw-cfg (api/request-json-raw :post "create-database" remote
177
+ "[\"{:store {:backend :memory :id #uuid \\\"23196000-0000-0000-0000-000000000001\\\"} :schema-flexibility :read}\"]")
178
+ raw-conn (api/request-json-raw :post "connect" remote
179
+ (str "[" raw-cfg "]"))
180
+ _ (api/request-json-raw :post "transact" remote
181
+ (str "[" raw-conn ", [{\"name\": \"Peter\", \"age\": 42}]]"))
182
+ raw-db (api/request-json-raw :post "db" remote
183
+ (str "[" raw-conn "]"))]
184
+ (is (= (api/request-json-raw :get "q" remote
185
+ (str "[\"[:find ?n ?a :in $1 :where [$1 ?e :age ?a] [$1 ?e :name ?n]]\","
186
+ raw-db "]"))
187
+ "[\"!set\",[[\"Peter\",42]]]")))
188
+ (finally
189
+ (try (api/request-json-raw :post "delete-database" remote
190
+ "[\"{:store {:backend :memory :id #uuid \\\"23196000-0000-0000-0000-000000000001\\\"}}\"]")
191
+ (catch Exception _))
192
+ (stop-server server))))))