automerge-rb 0.1.1

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 (481) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +175 -0
  4. data/ext/automerge_ext/automerge_ext.c +1805 -0
  5. data/ext/automerge_ext/extconf.rb +132 -0
  6. data/lib/automerge/version.rb +6 -0
  7. data/lib/automerge.rb +110 -0
  8. data/rust-toolchain.toml +4 -0
  9. data/vendor/automerge-rust/Cargo.lock +1909 -0
  10. data/vendor/automerge-rust/Cargo.toml +15 -0
  11. data/vendor/automerge-rust/automerge/Cargo.toml +78 -0
  12. data/vendor/automerge-rust/automerge/README.md +5 -0
  13. data/vendor/automerge-rust/automerge/benches/load_save.rs +102 -0
  14. data/vendor/automerge-rust/automerge/benches/map.rs +260 -0
  15. data/vendor/automerge-rust/automerge/benches/range.rs +37 -0
  16. data/vendor/automerge-rust/automerge/benches/sync.rs +95 -0
  17. data/vendor/automerge-rust/automerge/examples/README.md +7 -0
  18. data/vendor/automerge-rust/automerge/examples/quickstart.rs +57 -0
  19. data/vendor/automerge-rust/automerge/examples/watch.rs +94 -0
  20. data/vendor/automerge-rust/automerge/fuzz/Cargo.toml +29 -0
  21. data/vendor/automerge-rust/automerge/fuzz/fuzz_targets/load.rs +37 -0
  22. data/vendor/automerge-rust/automerge/src/autocommit.rs +1286 -0
  23. data/vendor/automerge-rust/automerge/src/automerge/current_state.rs +546 -0
  24. data/vendor/automerge-rust/automerge/src/automerge/tests.rs +2023 -0
  25. data/vendor/automerge-rust/automerge/src/automerge.rs +2071 -0
  26. data/vendor/automerge-rust/automerge/src/autoserde.rs +128 -0
  27. data/vendor/automerge-rust/automerge/src/change.rs +357 -0
  28. data/vendor/automerge-rust/automerge/src/change_graph.rs +1215 -0
  29. data/vendor/automerge-rust/automerge/src/change_queue.rs +46 -0
  30. data/vendor/automerge-rust/automerge/src/clock.rs +206 -0
  31. data/vendor/automerge-rust/automerge/src/columnar/column_range/boolean.rs +83 -0
  32. data/vendor/automerge-rust/automerge/src/columnar/column_range/delta.rs +148 -0
  33. data/vendor/automerge-rust/automerge/src/columnar/column_range/generic/group.rs +138 -0
  34. data/vendor/automerge-rust/automerge/src/columnar/column_range/generic/simple.rs +76 -0
  35. data/vendor/automerge-rust/automerge/src/columnar/column_range/generic.rs +93 -0
  36. data/vendor/automerge-rust/automerge/src/columnar/column_range/key.rs +272 -0
  37. data/vendor/automerge-rust/automerge/src/columnar/column_range/obj_id.rs +202 -0
  38. data/vendor/automerge-rust/automerge/src/columnar/column_range/opid_list.rs +329 -0
  39. data/vendor/automerge-rust/automerge/src/columnar/column_range/raw.rs +38 -0
  40. data/vendor/automerge-rust/automerge/src/columnar/column_range/rle.rs +216 -0
  41. data/vendor/automerge-rust/automerge/src/columnar/column_range/value.rs +547 -0
  42. data/vendor/automerge-rust/automerge/src/columnar/column_range.rs +17 -0
  43. data/vendor/automerge-rust/automerge/src/columnar/encoding/boolean.rs +197 -0
  44. data/vendor/automerge-rust/automerge/src/columnar/encoding/col_error.rs +88 -0
  45. data/vendor/automerge-rust/automerge/src/columnar/encoding/column_decoder.rs +133 -0
  46. data/vendor/automerge-rust/automerge/src/columnar/encoding/decodable_impls.rs +175 -0
  47. data/vendor/automerge-rust/automerge/src/columnar/encoding/delta.rs +96 -0
  48. data/vendor/automerge-rust/automerge/src/columnar/encoding/encodable_impls.rs +200 -0
  49. data/vendor/automerge-rust/automerge/src/columnar/encoding/leb128.rs +82 -0
  50. data/vendor/automerge-rust/automerge/src/columnar/encoding/properties.rs +178 -0
  51. data/vendor/automerge-rust/automerge/src/columnar/encoding/raw.rs +101 -0
  52. data/vendor/automerge-rust/automerge/src/columnar/encoding/rle.rs +239 -0
  53. data/vendor/automerge-rust/automerge/src/columnar/encoding.rs +67 -0
  54. data/vendor/automerge-rust/automerge/src/columnar/splice_error.rs +47 -0
  55. data/vendor/automerge-rust/automerge/src/columnar.rs +14 -0
  56. data/vendor/automerge-rust/automerge/src/convert.rs +112 -0
  57. data/vendor/automerge-rust/automerge/src/cursor.rs +296 -0
  58. data/vendor/automerge-rust/automerge/src/decoding.rs +475 -0
  59. data/vendor/automerge-rust/automerge/src/error.rs +159 -0
  60. data/vendor/automerge-rust/automerge/src/exid.rs +238 -0
  61. data/vendor/automerge-rust/automerge/src/hydrate/list.rs +140 -0
  62. data/vendor/automerge-rust/automerge/src/hydrate/map.rs +132 -0
  63. data/vendor/automerge-rust/automerge/src/hydrate/tests.rs +40 -0
  64. data/vendor/automerge-rust/automerge/src/hydrate/text.rs +89 -0
  65. data/vendor/automerge-rust/automerge/src/hydrate.rs +368 -0
  66. data/vendor/automerge-rust/automerge/src/indexed_cache.rs +113 -0
  67. data/vendor/automerge-rust/automerge/src/iter/doc.rs +603 -0
  68. data/vendor/automerge-rust/automerge/src/iter/keys.rs +93 -0
  69. data/vendor/automerge-rust/automerge/src/iter/list_range.rs +433 -0
  70. data/vendor/automerge-rust/automerge/src/iter/map_range.rs +316 -0
  71. data/vendor/automerge-rust/automerge/src/iter/spans.rs +601 -0
  72. data/vendor/automerge-rust/automerge/src/iter/tools.rs +427 -0
  73. data/vendor/automerge-rust/automerge/src/iter/values.rs +36 -0
  74. data/vendor/automerge-rust/automerge/src/iter.rs +25 -0
  75. data/vendor/automerge-rust/automerge/src/legacy/mod.rs +364 -0
  76. data/vendor/automerge-rust/automerge/src/legacy/serde_impls/actor_id.rs +25 -0
  77. data/vendor/automerge-rust/automerge/src/legacy/serde_impls/change_hash.rs +29 -0
  78. data/vendor/automerge-rust/automerge/src/legacy/serde_impls/element_id.rs +27 -0
  79. data/vendor/automerge-rust/automerge/src/legacy/serde_impls/mod.rs +31 -0
  80. data/vendor/automerge-rust/automerge/src/legacy/serde_impls/object_id.rs +36 -0
  81. data/vendor/automerge-rust/automerge/src/legacy/serde_impls/op.rs +668 -0
  82. data/vendor/automerge-rust/automerge/src/legacy/serde_impls/op_type.rs +26 -0
  83. data/vendor/automerge-rust/automerge/src/legacy/serde_impls/opid.rs +25 -0
  84. data/vendor/automerge-rust/automerge/src/legacy/serde_impls/scalar_value.rs +63 -0
  85. data/vendor/automerge-rust/automerge/src/legacy/utility_impls/element_id.rs +66 -0
  86. data/vendor/automerge-rust/automerge/src/legacy/utility_impls/key.rs +49 -0
  87. data/vendor/automerge-rust/automerge/src/legacy/utility_impls/mod.rs +4 -0
  88. data/vendor/automerge-rust/automerge/src/legacy/utility_impls/object_id.rs +74 -0
  89. data/vendor/automerge-rust/automerge/src/legacy/utility_impls/opid.rs +68 -0
  90. data/vendor/automerge-rust/automerge/src/lib.rs +315 -0
  91. data/vendor/automerge-rust/automerge/src/marks.rs +478 -0
  92. data/vendor/automerge-rust/automerge/src/op_set2/change/batch.rs +2002 -0
  93. data/vendor/automerge-rust/automerge/src/op_set2/change/collector.rs +974 -0
  94. data/vendor/automerge-rust/automerge/src/op_set2/change.rs +332 -0
  95. data/vendor/automerge-rust/automerge/src/op_set2/columns.rs +714 -0
  96. data/vendor/automerge-rust/automerge/src/op_set2/meta.rs +174 -0
  97. data/vendor/automerge-rust/automerge/src/op_set2/op.rs +1363 -0
  98. data/vendor/automerge-rust/automerge/src/op_set2/op_set/elems.rs +43 -0
  99. data/vendor/automerge-rust/automerge/src/op_set2/op_set/found_op.rs +60 -0
  100. data/vendor/automerge-rust/automerge/src/op_set2/op_set/index.rs +197 -0
  101. data/vendor/automerge-rust/automerge/src/op_set2/op_set/insert.rs +179 -0
  102. data/vendor/automerge-rust/automerge/src/op_set2/op_set/mark_index.rs +292 -0
  103. data/vendor/automerge-rust/automerge/src/op_set2/op_set/marks.rs +86 -0
  104. data/vendor/automerge-rust/automerge/src/op_set2/op_set/op_iter.rs +1295 -0
  105. data/vendor/automerge-rust/automerge/src/op_set2/op_set/op_query.rs +82 -0
  106. data/vendor/automerge-rust/automerge/src/op_set2/op_set/top_op.rs +50 -0
  107. data/vendor/automerge-rust/automerge/src/op_set2/op_set/visible.rs +290 -0
  108. data/vendor/automerge-rust/automerge/src/op_set2/op_set.rs +1793 -0
  109. data/vendor/automerge-rust/automerge/src/op_set2/parents.rs +133 -0
  110. data/vendor/automerge-rust/automerge/src/op_set2/skip_list.rs +714 -0
  111. data/vendor/automerge-rust/automerge/src/op_set2/types.rs +769 -0
  112. data/vendor/automerge-rust/automerge/src/op_set2.rs +18 -0
  113. data/vendor/automerge-rust/automerge/src/patches/patch.rs +95 -0
  114. data/vendor/automerge-rust/automerge/src/patches/patch_builder.rs +382 -0
  115. data/vendor/automerge-rust/automerge/src/patches/patch_log.rs +584 -0
  116. data/vendor/automerge-rust/automerge/src/patches.rs +7 -0
  117. data/vendor/automerge-rust/automerge/src/query/list_state.rs +230 -0
  118. data/vendor/automerge-rust/automerge/src/query/seek_mark.rs +142 -0
  119. data/vendor/automerge-rust/automerge/src/read.rs +326 -0
  120. data/vendor/automerge-rust/automerge/src/sequence_tree.rs +662 -0
  121. data/vendor/automerge-rust/automerge/src/storage/bundle/builder.rs +942 -0
  122. data/vendor/automerge-rust/automerge/src/storage/bundle/error.rs +42 -0
  123. data/vendor/automerge-rust/automerge/src/storage/bundle/meta.rs +23 -0
  124. data/vendor/automerge-rust/automerge/src/storage/bundle/storage.rs +146 -0
  125. data/vendor/automerge-rust/automerge/src/storage/bundle.rs +210 -0
  126. data/vendor/automerge-rust/automerge/src/storage/change/change_actors.rs +311 -0
  127. data/vendor/automerge-rust/automerge/src/storage/change/change_op_columns.rs +621 -0
  128. data/vendor/automerge-rust/automerge/src/storage/change/compressed.rs +51 -0
  129. data/vendor/automerge-rust/automerge/src/storage/change/op_with_change_actors.rs +1 -0
  130. data/vendor/automerge-rust/automerge/src/storage/change.rs +523 -0
  131. data/vendor/automerge-rust/automerge/src/storage/chunk.rs +312 -0
  132. data/vendor/automerge-rust/automerge/src/storage/columns/column.rs +42 -0
  133. data/vendor/automerge-rust/automerge/src/storage/columns/column_builder.rs +199 -0
  134. data/vendor/automerge-rust/automerge/src/storage/columns/column_specification.rs +340 -0
  135. data/vendor/automerge-rust/automerge/src/storage/columns/raw_column.rs +286 -0
  136. data/vendor/automerge-rust/automerge/src/storage/columns.rs +355 -0
  137. data/vendor/automerge-rust/automerge/src/storage/document/compression.rs +362 -0
  138. data/vendor/automerge-rust/automerge/src/storage/document.rs +411 -0
  139. data/vendor/automerge-rust/automerge/src/storage/load/change_collector.rs +15 -0
  140. data/vendor/automerge-rust/automerge/src/storage/load.rs +136 -0
  141. data/vendor/automerge-rust/automerge/src/storage/parse/leb128.rs +302 -0
  142. data/vendor/automerge-rust/automerge/src/storage/parse.rs +619 -0
  143. data/vendor/automerge-rust/automerge/src/storage/save/document.rs +27 -0
  144. data/vendor/automerge-rust/automerge/src/storage.rs +26 -0
  145. data/vendor/automerge-rust/automerge/src/sync/bloom.rs +161 -0
  146. data/vendor/automerge-rust/automerge/src/sync/message_builder.rs +118 -0
  147. data/vendor/automerge-rust/automerge/src/sync/state.rs +214 -0
  148. data/vendor/automerge-rust/automerge/src/sync/v1_compat_test/bloom.rs +162 -0
  149. data/vendor/automerge-rust/automerge/src/sync/v1_compat_test/mod.rs +625 -0
  150. data/vendor/automerge-rust/automerge/src/sync/v1_compat_test/state.rs +120 -0
  151. data/vendor/automerge-rust/automerge/src/sync.rs +2482 -0
  152. data/vendor/automerge-rust/automerge/src/text_diff/LICENSE +201 -0
  153. data/vendor/automerge-rust/automerge/src/text_diff/myers.rs +332 -0
  154. data/vendor/automerge-rust/automerge/src/text_diff/replace.rs +139 -0
  155. data/vendor/automerge-rust/automerge/src/text_diff/utils.rs +119 -0
  156. data/vendor/automerge-rust/automerge/src/text_diff.rs +515 -0
  157. data/vendor/automerge-rust/automerge/src/text_value.rs +276 -0
  158. data/vendor/automerge-rust/automerge/src/transaction/commit.rs +34 -0
  159. data/vendor/automerge-rust/automerge/src/transaction/inner.rs +1403 -0
  160. data/vendor/automerge-rust/automerge/src/transaction/manual_transaction.rs +147 -0
  161. data/vendor/automerge-rust/automerge/src/transaction/owned_transaction.rs +266 -0
  162. data/vendor/automerge-rust/automerge/src/transaction/result.rs +21 -0
  163. data/vendor/automerge-rust/automerge/src/transaction/transactable.rs +203 -0
  164. data/vendor/automerge-rust/automerge/src/transaction.rs +513 -0
  165. data/vendor/automerge-rust/automerge/src/types.rs +749 -0
  166. data/vendor/automerge-rust/automerge/src/validation.rs +29 -0
  167. data/vendor/automerge-rust/automerge/src/value.rs +763 -0
  168. data/vendor/automerge-rust/automerge/tests/batch_insert.rs +1034 -0
  169. data/vendor/automerge-rust/automerge/tests/block_tests.rs +887 -0
  170. data/vendor/automerge-rust/automerge/tests/convert_string_to_text.rs +72 -0
  171. data/vendor/automerge-rust/automerge/tests/diff_marks.rs +1508 -0
  172. data/vendor/automerge-rust/automerge/tests/fixtures/64bit_obj_id_change.automerge +0 -0
  173. data/vendor/automerge-rust/automerge/tests/fixtures/64bit_obj_id_doc.automerge +0 -0
  174. data/vendor/automerge-rust/automerge/tests/fixtures/counter_value_has_incorrect_meta.automerge +0 -0
  175. data/vendor/automerge-rust/automerge/tests/fixtures/counter_value_is_ok.automerge +0 -0
  176. data/vendor/automerge-rust/automerge/tests/fixtures/counter_value_is_overlong.automerge +0 -0
  177. data/vendor/automerge-rust/automerge/tests/fixtures/two_change_chunks.automerge +0 -0
  178. data/vendor/automerge-rust/automerge/tests/fixtures/two_change_chunks_compressed.automerge +0 -0
  179. data/vendor/automerge-rust/automerge/tests/fixtures/two_change_chunks_out_of_order.automerge +0 -0
  180. data/vendor/automerge-rust/automerge/tests/fuzz-crashers/action-is-48.automerge +0 -0
  181. data/vendor/automerge-rust/automerge/tests/fuzz-crashers/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 +0 -0
  182. data/vendor/automerge-rust/automerge/tests/fuzz-crashers/incorrect_max_op.automerge +0 -0
  183. data/vendor/automerge-rust/automerge/tests/fuzz-crashers/invalid_deflate_stream.automerge +0 -0
  184. data/vendor/automerge-rust/automerge/tests/fuzz-crashers/missing_actor.automerge +0 -0
  185. data/vendor/automerge-rust/automerge/tests/fuzz-crashers/overflow_in_length.automerge +0 -0
  186. data/vendor/automerge-rust/automerge/tests/fuzz-crashers/too_many_deps.automerge +0 -0
  187. data/vendor/automerge-rust/automerge/tests/fuzz-crashers/too_many_ops.automerge +0 -0
  188. data/vendor/automerge-rust/automerge/tests/test.rs +2668 -0
  189. data/vendor/automerge-rust/automerge/tests/test_mark_patches.rs +41 -0
  190. data/vendor/automerge-rust/automerge/tests/test_save_load_orphans.rs +84 -0
  191. data/vendor/automerge-rust/automerge/tests/text.rs +1098 -0
  192. data/vendor/automerge-rust/automerge/tests/text_encoding.rs +640 -0
  193. data/vendor/automerge-rust/automerge-c/CMakeLists.txt +439 -0
  194. data/vendor/automerge-rust/automerge-c/Cargo.toml +22 -0
  195. data/vendor/automerge-rust/automerge-c/README.md +233 -0
  196. data/vendor/automerge-rust/automerge-c/build.rs +21 -0
  197. data/vendor/automerge-rust/automerge-c/cbindgen.toml +48 -0
  198. data/vendor/automerge-rust/automerge-c/cmake/Cargo.toml.in +22 -0
  199. data/vendor/automerge-rust/automerge-c/cmake/automerge-c-config.cmake.in +99 -0
  200. data/vendor/automerge-rust/automerge-c/cmake/cbindgen.toml.in +48 -0
  201. data/vendor/automerge-rust/automerge-c/cmake/config.h.in +58 -0
  202. data/vendor/automerge-rust/automerge-c/cmake/enum-string-functions-gen.cmake +183 -0
  203. data/vendor/automerge-rust/automerge-c/cmake/file-regex-replace.cmake +33 -0
  204. data/vendor/automerge-rust/automerge-c/cmake/file-touch.cmake +35 -0
  205. data/vendor/automerge-rust/automerge-c/docs/CMakeLists.txt +39 -0
  206. data/vendor/automerge-rust/automerge-c/docs/img/brandmark.png +0 -0
  207. data/vendor/automerge-rust/automerge-c/examples/CMakeLists.txt +42 -0
  208. data/vendor/automerge-rust/automerge-c/examples/README.md +9 -0
  209. data/vendor/automerge-rust/automerge-c/examples/quickstart.c +131 -0
  210. data/vendor/automerge-rust/automerge-c/include/automerge-c/utils/result.h +30 -0
  211. data/vendor/automerge-rust/automerge-c/include/automerge-c/utils/stack.h +130 -0
  212. data/vendor/automerge-rust/automerge-c/include/automerge-c/utils/stack_callback_data.h +53 -0
  213. data/vendor/automerge-rust/automerge-c/include/automerge-c/utils/string.h +29 -0
  214. data/vendor/automerge-rust/automerge-c/src/actor_id.rs +193 -0
  215. data/vendor/automerge-rust/automerge-c/src/byte_span.rs +227 -0
  216. data/vendor/automerge-rust/automerge-c/src/change.rs +356 -0
  217. data/vendor/automerge-rust/automerge-c/src/cursor.rs +168 -0
  218. data/vendor/automerge-rust/automerge-c/src/doc/list.rs +636 -0
  219. data/vendor/automerge-rust/automerge-c/src/doc/map.rs +556 -0
  220. data/vendor/automerge-rust/automerge-c/src/doc/mark.rs +296 -0
  221. data/vendor/automerge-rust/automerge-c/src/doc/utils.rs +46 -0
  222. data/vendor/automerge-rust/automerge-c/src/doc.rs +1009 -0
  223. data/vendor/automerge-rust/automerge-c/src/index.rs +84 -0
  224. data/vendor/automerge-rust/automerge-c/src/item.rs +2177 -0
  225. data/vendor/automerge-rust/automerge-c/src/items.rs +401 -0
  226. data/vendor/automerge-rust/automerge-c/src/lib.rs +11 -0
  227. data/vendor/automerge-rust/automerge-c/src/obj.rs +216 -0
  228. data/vendor/automerge-rust/automerge-c/src/result.rs +653 -0
  229. data/vendor/automerge-rust/automerge-c/src/sync/have.rs +42 -0
  230. data/vendor/automerge-rust/automerge-c/src/sync/message.rs +146 -0
  231. data/vendor/automerge-rust/automerge-c/src/sync/state.rs +262 -0
  232. data/vendor/automerge-rust/automerge-c/src/sync.rs +7 -0
  233. data/vendor/automerge-rust/automerge-c/src/utils/result.c +33 -0
  234. data/vendor/automerge-rust/automerge-c/src/utils/stack.c +106 -0
  235. data/vendor/automerge-rust/automerge-c/src/utils/stack_callback_data.c +9 -0
  236. data/vendor/automerge-rust/automerge-c/src/utils/string.c +46 -0
  237. data/vendor/automerge-rust/automerge-c/test/CMakeLists.txt +67 -0
  238. data/vendor/automerge-rust/automerge-c/test/actor_id_tests.c +140 -0
  239. data/vendor/automerge-rust/automerge-c/test/base_state.c +17 -0
  240. data/vendor/automerge-rust/automerge-c/test/base_state.h +39 -0
  241. data/vendor/automerge-rust/automerge-c/test/byte_span_tests.c +119 -0
  242. data/vendor/automerge-rust/automerge-c/test/cmocka_utils.c +91 -0
  243. data/vendor/automerge-rust/automerge-c/test/cmocka_utils.h +42 -0
  244. data/vendor/automerge-rust/automerge-c/test/cursor_tests.c +263 -0
  245. data/vendor/automerge-rust/automerge-c/test/doc_state.c +27 -0
  246. data/vendor/automerge-rust/automerge-c/test/doc_state.h +17 -0
  247. data/vendor/automerge-rust/automerge-c/test/doc_tests.c +335 -0
  248. data/vendor/automerge-rust/automerge-c/test/enum_string_tests.c +148 -0
  249. data/vendor/automerge-rust/automerge-c/test/files/brave-ape-49.automerge +0 -0
  250. data/vendor/automerge-rust/automerge-c/test/item_tests.c +313 -0
  251. data/vendor/automerge-rust/automerge-c/test/list_tests.c +544 -0
  252. data/vendor/automerge-rust/automerge-c/test/macro_utils.c +38 -0
  253. data/vendor/automerge-rust/automerge-c/test/macro_utils.h +23 -0
  254. data/vendor/automerge-rust/automerge-c/test/main.c +33 -0
  255. data/vendor/automerge-rust/automerge-c/test/map_tests.c +1610 -0
  256. data/vendor/automerge-rust/automerge-c/test/mark_tests.c +124 -0
  257. data/vendor/automerge-rust/automerge-c/test/ported_wasm/basic_tests.c +1642 -0
  258. data/vendor/automerge-rust/automerge-c/test/ported_wasm/cursor_tests.c +108 -0
  259. data/vendor/automerge-rust/automerge-c/test/ported_wasm/suite.c +17 -0
  260. data/vendor/automerge-rust/automerge-c/test/ported_wasm/sync_tests.c +1280 -0
  261. data/vendor/automerge-rust/automerge-c/test/str_utils.c +15 -0
  262. data/vendor/automerge-rust/automerge-c/test/str_utils.h +17 -0
  263. data/vendor/automerge-rust/automerge-test/Cargo.toml +17 -0
  264. data/vendor/automerge-rust/automerge-test/README.md +3 -0
  265. data/vendor/automerge-rust/automerge-test/src/lib.rs +487 -0
  266. data/vendor/automerge-rust/hexane/CHANGELOG.md +34 -0
  267. data/vendor/automerge-rust/hexane/Cargo.toml +47 -0
  268. data/vendor/automerge-rust/hexane/README.md +292 -0
  269. data/vendor/automerge-rust/hexane/RESULTS.txt +20 -0
  270. data/vendor/automerge-rust/hexane/TODO +18 -0
  271. data/vendor/automerge-rust/hexane/benches/insert.rs +82 -0
  272. data/vendor/automerge-rust/hexane/benches/seek.rs +77 -0
  273. data/vendor/automerge-rust/hexane/benches/splice.rs +82 -0
  274. data/vendor/automerge-rust/hexane/src/aggregate.rs +288 -0
  275. data/vendor/automerge-rust/hexane/src/boolean.rs +478 -0
  276. data/vendor/automerge-rust/hexane/src/columndata.rs +2540 -0
  277. data/vendor/automerge-rust/hexane/src/cursor.rs +756 -0
  278. data/vendor/automerge-rust/hexane/src/delta.rs +793 -0
  279. data/vendor/automerge-rust/hexane/src/encoder.rs +639 -0
  280. data/vendor/automerge-rust/hexane/src/leb128.rs +82 -0
  281. data/vendor/automerge-rust/hexane/src/lib.rs +95 -0
  282. data/vendor/automerge-rust/hexane/src/pack.rs +325 -0
  283. data/vendor/automerge-rust/hexane/src/raw.rs +314 -0
  284. data/vendor/automerge-rust/hexane/src/rle.rs +928 -0
  285. data/vendor/automerge-rust/hexane/src/slab/tree.rs +1373 -0
  286. data/vendor/automerge-rust/hexane/src/slab/writer.rs +535 -0
  287. data/vendor/automerge-rust/hexane/src/slab.rs +224 -0
  288. data/vendor/automerge-rust/hexane/src/test.rs +108 -0
  289. data/vendor/bundle/ruby/3.3.0/bin/rake +29 -0
  290. data/vendor/bundle/ruby/3.3.0/bin/rake-compiler +29 -0
  291. data/vendor/bundle/ruby/3.3.0/bin/rake-compiler-dock +29 -0
  292. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/History.rdoc +1732 -0
  293. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/Manifest.txt +32 -0
  294. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/README.rdoc +845 -0
  295. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/Rakefile +97 -0
  296. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/design_rationale.rb +54 -0
  297. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/hoe/minitest.rb +30 -0
  298. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/assertions.rb +850 -0
  299. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/autorun.rb +6 -0
  300. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/benchmark.rb +452 -0
  301. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/compress.rb +94 -0
  302. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/error_on_warning.rb +11 -0
  303. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/expectations.rb +321 -0
  304. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/hell.rb +11 -0
  305. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/manual_plugins.rb +16 -0
  306. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/mock.rb +327 -0
  307. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/parallel.rb +72 -0
  308. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/pride.rb +4 -0
  309. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/pride_plugin.rb +135 -0
  310. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/spec.rb +353 -0
  311. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/test.rb +238 -0
  312. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/test_task.rb +324 -0
  313. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest/unit.rb +42 -0
  314. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/lib/minitest.rb +1250 -0
  315. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/test/minitest/metametameta.rb +150 -0
  316. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/test/minitest/test_minitest_assertions.rb +1677 -0
  317. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/test/minitest/test_minitest_benchmark.rb +137 -0
  318. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/test/minitest/test_minitest_mock.rb +1213 -0
  319. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/test/minitest/test_minitest_reporter.rb +437 -0
  320. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/test/minitest/test_minitest_spec.rb +1159 -0
  321. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/test/minitest/test_minitest_test.rb +1374 -0
  322. data/vendor/bundle/ruby/3.3.0/gems/minitest-5.27.0/test/minitest/test_minitest_test_task.rb +57 -0
  323. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/History.rdoc +2454 -0
  324. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/MIT-LICENSE +21 -0
  325. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/README.rdoc +155 -0
  326. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/command_line_usage.rdoc +171 -0
  327. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/example/Rakefile1 +38 -0
  328. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/example/Rakefile2 +35 -0
  329. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/example/a.c +6 -0
  330. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/example/b.c +6 -0
  331. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/example/main.c +11 -0
  332. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/glossary.rdoc +42 -0
  333. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/jamis.rb +592 -0
  334. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/proto_rake.rdoc +127 -0
  335. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/rake.1 +156 -0
  336. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/rakefile.rdoc +635 -0
  337. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/doc/rational.rdoc +151 -0
  338. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/exe/rake +27 -0
  339. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/application.rb +847 -0
  340. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/backtrace.rb +25 -0
  341. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/clean.rb +78 -0
  342. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/cloneable.rb +17 -0
  343. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/cpu_counter.rb +122 -0
  344. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/default_loader.rb +15 -0
  345. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/dsl_definition.rb +196 -0
  346. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/early_time.rb +22 -0
  347. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/ext/core.rb +26 -0
  348. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/ext/string.rb +176 -0
  349. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/file_creation_task.rb +25 -0
  350. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/file_list.rb +435 -0
  351. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/file_task.rb +58 -0
  352. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/file_utils.rb +137 -0
  353. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/file_utils_ext.rb +135 -0
  354. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/invocation_chain.rb +57 -0
  355. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/invocation_exception_mixin.rb +17 -0
  356. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/late_time.rb +18 -0
  357. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/linked_list.rb +112 -0
  358. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/loaders/makefile.rb +54 -0
  359. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/multi_task.rb +14 -0
  360. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/name_space.rb +38 -0
  361. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/options.rb +31 -0
  362. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/packagetask.rb +222 -0
  363. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/phony.rb +16 -0
  364. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/private_reader.rb +21 -0
  365. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/promise.rb +100 -0
  366. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/pseudo_status.rb +30 -0
  367. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/rake_module.rb +67 -0
  368. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/rake_test_loader.rb +27 -0
  369. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/rule_recursion_overflow_error.rb +20 -0
  370. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/scope.rb +43 -0
  371. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/task.rb +434 -0
  372. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/task_argument_error.rb +8 -0
  373. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/task_arguments.rb +113 -0
  374. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/task_manager.rb +333 -0
  375. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/tasklib.rb +12 -0
  376. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/testtask.rb +192 -0
  377. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/thread_history_display.rb +49 -0
  378. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/thread_pool.rb +157 -0
  379. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/trace_output.rb +23 -0
  380. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/version.rb +10 -0
  381. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake/win32.rb +17 -0
  382. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/lib/rake.rb +69 -0
  383. data/vendor/bundle/ruby/3.3.0/gems/rake-13.4.2/rake.gemspec +102 -0
  384. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/Gemfile +8 -0
  385. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/History.md +695 -0
  386. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/LICENSE.txt +20 -0
  387. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/README.md +476 -0
  388. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/Rakefile +15 -0
  389. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/appveyor.yml +22 -0
  390. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/bin/rake-compiler +24 -0
  391. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/cucumber.yml +4 -0
  392. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/compile.feature +79 -0
  393. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/cross-compile.feature +23 -0
  394. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/cross-package-multi.feature +15 -0
  395. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/cross-package.feature +14 -0
  396. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/java-compile.feature +22 -0
  397. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/java-no-native-compile.feature +33 -0
  398. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/java-package.feature +24 -0
  399. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/package.feature +40 -0
  400. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/step_definitions/compilation.rb +70 -0
  401. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/step_definitions/cross_compilation.rb +27 -0
  402. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/step_definitions/execution.rb +52 -0
  403. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/step_definitions/folders.rb +32 -0
  404. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/step_definitions/gem.rb +46 -0
  405. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/step_definitions/java_compilation.rb +7 -0
  406. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/support/env.rb +10 -0
  407. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/support/file_template_helpers.rb +137 -0
  408. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/support/generator_helpers.rb +123 -0
  409. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/features/support/platform_extension_helpers.rb +27 -0
  410. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/lib/rake/baseextensiontask.rb +90 -0
  411. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/lib/rake/compiler_config.rb +38 -0
  412. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/lib/rake/extensioncompiler.rb +51 -0
  413. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/lib/rake/extensiontask.rb +589 -0
  414. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/lib/rake/javaextensiontask.rb +321 -0
  415. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/tasks/bin/cross-ruby.rake +189 -0
  416. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/tasks/bootstrap.rake +11 -0
  417. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/tasks/common.rake +10 -0
  418. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/tasks/cucumber.rake +23 -0
  419. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/tasks/gem.rake +15 -0
  420. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-1.3.1/tasks/rspec.rake +9 -0
  421. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/CHANGELOG.md +446 -0
  422. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/CONTRIBUTING.md +109 -0
  423. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/Dockerfile.jruby +79 -0
  424. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/Dockerfile.mri.erb +282 -0
  425. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/Gemfile +8 -0
  426. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/LICENSE.txt +22 -0
  427. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/README.md +447 -0
  428. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/Rakefile +246 -0
  429. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/bin/rake-compiler-dock +18 -0
  430. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/buildkitd.toml +2 -0
  431. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/gem_helper.rb +54 -0
  432. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/mk_i686.rb +18 -0
  433. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/mk_musl_cross.sh +37 -0
  434. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/mk_osxcross.sh +45 -0
  435. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/mk_pkg_config.sh +24 -0
  436. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/parallel_docker_build.rb +169 -0
  437. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/patches/rake-compiler-1.3.1/0004-Enable-build-of-static-libruby.patch +38 -0
  438. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/patches/rake-compiler-1.3.1/0005-build-miniruby-first.patch +16 -0
  439. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/patches/rake-compiler-1.3.1/0006-ruby-4-rubyspec-capiext.patch +16 -0
  440. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/rcd-env.sh +6 -0
  441. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/runas +7 -0
  442. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/sigfw.c +45 -0
  443. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/strip_wrapper_codesign +17 -0
  444. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/strip_wrapper_vbox +30 -0
  445. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/build/sudoers +1 -0
  446. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock/colors.rb +43 -0
  447. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock/docker_check.rb +356 -0
  448. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock/predefined_user_group.rb +5 -0
  449. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock/starter.rb +206 -0
  450. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock/version.rb +4 -0
  451. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock.rb +151 -0
  452. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/mingw64-ucrt/Dockerfile +66 -0
  453. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/mingw64-ucrt/README.md +14 -0
  454. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/mingw64-ucrt/binutils-mingw-w64-ignore-check-errors.patch +13 -0
  455. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/mingw64-ucrt/gcc-mingw-w64-only-c-c++.patch +13 -0
  456. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/mingw64-ucrt/mingw-w64-enable-ucrt.patch +22 -0
  457. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/rake-compiler-dock.gemspec +34 -0
  458. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/env/Dockerfile.alpine +17 -0
  459. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/env/Dockerfile.debian +24 -0
  460. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/fixtures/mig_test_rpc.defs +8 -0
  461. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/Gemfile +11 -0
  462. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/Rakefile +97 -0
  463. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/ext/java/RcdTestExtService.java +19 -0
  464. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/ext/java/RubyRcdTest.java +16 -0
  465. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/ext/mri/extconf.rb +111 -0
  466. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/ext/mri/rcd_test_ext.c +65 -0
  467. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/ext/mri/rcd_test_ext.h +11 -0
  468. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/lib/rcd_test.rb +6 -0
  469. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/rcd_test.gemspec +28 -0
  470. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/test/test_basic.rb +49 -0
  471. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/test_environment_variables.rb +108 -0
  472. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/test_mig.rb +18 -0
  473. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/test_parallel_docker_build.rb +95 -0
  474. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/test_rubygems_plugins.rb +12 -0
  475. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/test_starter.rb +158 -0
  476. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.12.0/test/test_versions.rb +82 -0
  477. data/vendor/bundle/ruby/3.3.0/specifications/minitest-5.27.0.gemspec +32 -0
  478. data/vendor/bundle/ruby/3.3.0/specifications/rake-13.4.2.gemspec +26 -0
  479. data/vendor/bundle/ruby/3.3.0/specifications/rake-compiler-1.3.1.gemspec +33 -0
  480. data/vendor/bundle/ruby/3.3.0/specifications/rake-compiler-dock-1.12.0.gemspec +28 -0
  481. metadata +584 -0
@@ -0,0 +1,2668 @@
1
+ use automerge::marks::{ExpandMark, Mark};
2
+ //use automerge::op_tree::B;
3
+ use automerge::transaction::{CommitOptions, Transactable};
4
+ use automerge::{
5
+ sync::SyncDoc, ActorId, AutoCommit, Automerge, AutomergeError, Change, ExpandedChange, ObjId,
6
+ ObjType, Patch, PatchAction, PatchLog, Prop, ReadDoc, ScalarValue, SequenceTree, Value, ROOT,
7
+ };
8
+
9
+ const B: usize = 16;
10
+
11
+ fn patch_log_from_actor(actor: &[u8]) -> PatchLog {
12
+ let mut source = AutoCommit::new();
13
+ source.set_actor(ActorId::from(actor));
14
+ source.put(ROOT, "source", "value").unwrap();
15
+ let source_changes = source.get_changes(&[]);
16
+
17
+ let mut patch_log = PatchLog::active();
18
+ let mut doc = Automerge::new();
19
+ doc.apply_changes_log_patches(source_changes, &mut patch_log)
20
+ .unwrap();
21
+ patch_log
22
+ }
23
+
24
+ fn doc_with_actor(actor: &[u8]) -> Automerge {
25
+ let mut source = AutoCommit::new();
26
+ source.set_actor(ActorId::from(actor));
27
+ source.put(ROOT, "key", "value").unwrap();
28
+ let changes = source.get_changes(&[]);
29
+
30
+ let mut doc = Automerge::new();
31
+ doc.apply_changes(changes).unwrap();
32
+ doc
33
+ }
34
+
35
+ #[test]
36
+ fn applying_changes_with_patch_log_from_another_document_returns_error_not_panic() {
37
+ let mut patch_log = patch_log_from_actor(b"bbbbbb");
38
+ let mut source = AutoCommit::new();
39
+ source.set_actor(ActorId::from(b"cccccc" as &[u8]));
40
+ source.put(ROOT, "source", "value").unwrap();
41
+ let changes = source.get_changes(&[]);
42
+
43
+ let mut doc = Automerge::new();
44
+ let result = doc.apply_changes_log_patches(changes, &mut patch_log);
45
+
46
+ assert!(matches!(result, Err(AutomergeError::PatchLogMismatch(_))));
47
+ }
48
+
49
+ #[test]
50
+ fn transaction_with_patch_log_from_another_document_does_not_panic() {
51
+ let patch_log = patch_log_from_actor(b"bbbbbb");
52
+ let mut doc = doc_with_actor(b"cccccc");
53
+
54
+ let result = doc.transaction_log_patches(patch_log);
55
+
56
+ assert!(matches!(result, Err(automerge::PatchLogMismatch)));
57
+ }
58
+
59
+ #[test]
60
+ fn transaction_at_with_patch_log_from_another_document_does_not_panic() {
61
+ let patch_log = patch_log_from_actor(b"bbbbbb");
62
+ let mut doc = doc_with_actor(b"cccccc");
63
+ let heads = doc.get_heads();
64
+
65
+ let result = doc.transaction_at(patch_log, &heads);
66
+
67
+ assert!(matches!(result, Err(automerge::PatchLogMismatch)));
68
+ }
69
+
70
+ #[test]
71
+ fn owned_transaction_with_patch_log_from_another_document_does_not_panic() {
72
+ let patch_log = patch_log_from_actor(b"bbbbbb");
73
+ let doc = doc_with_actor(b"cccccc");
74
+
75
+ let result = doc.into_transaction(Some(patch_log), None);
76
+
77
+ assert!(matches!(result, Err(automerge::PatchLogMismatch)));
78
+ }
79
+
80
+ use std::fs;
81
+
82
+ // set up logging for all the tests
83
+ use test_log::test;
84
+
85
+ #[allow(unused_imports)]
86
+ use automerge_test::{
87
+ assert_doc, assert_obj, list, map, mk_counter, new_doc, new_doc_with_actor, pretty_print,
88
+ realize, realize_obj, sorted_actors, RealizedObject,
89
+ };
90
+ use pretty_assertions::assert_eq;
91
+
92
+ #[test]
93
+ fn no_conflict_on_repeated_assignment() {
94
+ let mut doc = AutoCommit::new();
95
+ doc.put(&automerge::ROOT, "foo", 1).unwrap();
96
+ doc.put(&automerge::ROOT, "foo", 2).unwrap();
97
+ assert_doc!(
98
+ &doc,
99
+ map! {
100
+ "foo" => { 2 },
101
+ }
102
+ );
103
+ }
104
+
105
+ #[test]
106
+ fn repeated_map_assignment_which_resolves_conflict_not_ignored() {
107
+ let mut doc1 = new_doc();
108
+ let mut doc2 = new_doc();
109
+ doc1.put(&automerge::ROOT, "field", 123).unwrap();
110
+ doc2.merge(&mut doc1).unwrap();
111
+ doc2.put(&automerge::ROOT, "field", 456).unwrap();
112
+ doc1.put(&automerge::ROOT, "field", 789).unwrap();
113
+ doc1.merge(&mut doc2).unwrap();
114
+ assert_eq!(doc1.get_all(&automerge::ROOT, "field").unwrap().len(), 2);
115
+
116
+ doc1.put(&automerge::ROOT, "field", 123).unwrap();
117
+ assert_doc!(
118
+ &doc1,
119
+ map! {
120
+ "field" => { 123 }
121
+ }
122
+ );
123
+ }
124
+
125
+ #[test]
126
+ fn repeated_list_assignment_which_resolves_conflict_not_ignored() {
127
+ let mut doc1 = new_doc();
128
+ let mut doc2 = new_doc();
129
+ let list_id = doc1
130
+ .put_object(&automerge::ROOT, "list", ObjType::List)
131
+ .unwrap();
132
+ doc1.insert(&list_id, 0, 123).unwrap();
133
+ doc2.merge(&mut doc1).unwrap();
134
+ doc2.put(&list_id, 0, 456).unwrap();
135
+ doc1.merge(&mut doc2).unwrap();
136
+ doc1.put(&list_id, 0, 789).unwrap();
137
+
138
+ assert_doc!(
139
+ &doc1,
140
+ map! {
141
+ "list" => {
142
+ list![
143
+ { 789 },
144
+ ]
145
+ }
146
+ }
147
+ );
148
+ }
149
+
150
+ #[test]
151
+ fn list_deletion() {
152
+ let mut doc = new_doc();
153
+ let list_id = doc
154
+ .put_object(&automerge::ROOT, "list", ObjType::List)
155
+ .unwrap();
156
+ doc.insert(&list_id, 0, 123).unwrap();
157
+ doc.insert(&list_id, 1, 456).unwrap();
158
+ doc.insert(&list_id, 2, 789).unwrap();
159
+ doc.delete(&list_id, 1).unwrap();
160
+ assert_doc!(
161
+ &doc,
162
+ map! {
163
+ "list" => { list![
164
+ { 123 },
165
+ { 789 },
166
+ ]}
167
+ }
168
+ )
169
+ }
170
+
171
+ #[test]
172
+ fn merge_concurrent_map_prop_updates() {
173
+ let mut doc1 = new_doc();
174
+ let mut doc2 = new_doc();
175
+ doc1.put(&automerge::ROOT, "foo", "bar").unwrap();
176
+ doc2.put(&automerge::ROOT, "hello", "world").unwrap();
177
+ doc1.merge(&mut doc2).unwrap();
178
+ assert_eq!(
179
+ doc1.get(&automerge::ROOT, "foo").unwrap().unwrap().0,
180
+ "bar".into()
181
+ );
182
+ assert_doc!(
183
+ &doc1,
184
+ map! {
185
+ "foo" => { "bar" },
186
+ "hello" => { "world" },
187
+ }
188
+ );
189
+ doc2.merge(&mut doc1).unwrap();
190
+ assert_doc!(
191
+ &doc2,
192
+ map! {
193
+ "foo" => { "bar" },
194
+ "hello" => { "world" },
195
+ }
196
+ );
197
+ assert_eq!(realize(doc1.document()), realize(doc2.document()));
198
+ }
199
+
200
+ #[test]
201
+ fn add_concurrent_increments_of_same_property() {
202
+ let mut doc1 = new_doc();
203
+ let mut doc2 = new_doc();
204
+ doc1.put(&automerge::ROOT, "counter", mk_counter(0))
205
+ .unwrap();
206
+ doc2.merge(&mut doc1).unwrap();
207
+ doc1.increment(&automerge::ROOT, "counter", 1).unwrap();
208
+ doc2.increment(&automerge::ROOT, "counter", 2).unwrap();
209
+ doc1.merge(&mut doc2).unwrap();
210
+ assert_doc!(
211
+ &doc1,
212
+ map! {
213
+ "counter" => {
214
+ mk_counter(3)
215
+ }
216
+ }
217
+ );
218
+ }
219
+
220
+ #[test]
221
+ fn add_increments_only_to_preceeded_values() {
222
+ let mut doc1 = new_doc();
223
+ let mut doc2 = new_doc();
224
+
225
+ doc1.put(&automerge::ROOT, "counter", mk_counter(0))
226
+ .unwrap();
227
+ doc1.increment(&automerge::ROOT, "counter", 1).unwrap();
228
+
229
+ // create a counter in doc2
230
+ doc2.put(&automerge::ROOT, "counter", mk_counter(0))
231
+ .unwrap();
232
+ doc2.increment(&automerge::ROOT, "counter", 3).unwrap();
233
+
234
+ // The two values should be conflicting rather than added
235
+ doc1.merge(&mut doc2).unwrap();
236
+
237
+ assert_doc!(
238
+ &doc1,
239
+ map! {
240
+ "counter" => {
241
+ mk_counter(1),
242
+ mk_counter(3),
243
+ }
244
+ }
245
+ );
246
+ }
247
+
248
+ #[test]
249
+ fn concurrent_updates_of_same_field() {
250
+ let mut doc1 = new_doc();
251
+ let mut doc2 = new_doc();
252
+ doc1.put(&automerge::ROOT, "field", "one").unwrap();
253
+ doc2.put(&automerge::ROOT, "field", "two").unwrap();
254
+
255
+ doc1.merge(&mut doc2).unwrap();
256
+
257
+ assert_doc!(
258
+ &doc1,
259
+ map! {
260
+ "field" => {
261
+ "one",
262
+ "two",
263
+ }
264
+ }
265
+ );
266
+ }
267
+
268
+ #[test]
269
+ fn concurrent_updates_of_same_list_element() {
270
+ let mut doc1 = new_doc();
271
+ let mut doc2 = new_doc();
272
+ let list_id = doc1
273
+ .put_object(&automerge::ROOT, "birds", ObjType::List)
274
+ .unwrap();
275
+ doc1.insert(&list_id, 0, "finch").unwrap();
276
+ doc2.merge(&mut doc1).unwrap();
277
+ doc1.put(&list_id, 0, "greenfinch").unwrap();
278
+ doc2.put(&list_id, 0, "goldfinch").unwrap();
279
+
280
+ doc1.merge(&mut doc2).unwrap();
281
+
282
+ assert_doc!(
283
+ &doc1,
284
+ map! {
285
+ "birds" => {
286
+ list![{
287
+ "greenfinch",
288
+ "goldfinch",
289
+ }]
290
+ }
291
+ }
292
+ );
293
+ }
294
+
295
+ #[test]
296
+ fn assignment_conflicts_of_different_types() {
297
+ let mut doc1 = new_doc();
298
+ let mut doc2 = new_doc();
299
+ let mut doc3 = new_doc();
300
+ doc1.put(&automerge::ROOT, "field", "string").unwrap();
301
+ doc2.put_object(&automerge::ROOT, "field", ObjType::List)
302
+ .unwrap();
303
+ doc3.put_object(&automerge::ROOT, "field", ObjType::Map)
304
+ .unwrap();
305
+ doc1.merge(&mut doc2).unwrap();
306
+ doc1.merge(&mut doc3).unwrap();
307
+
308
+ assert_doc!(
309
+ &doc1,
310
+ map! {
311
+ "field" => {
312
+ "string",
313
+ list!{},
314
+ map!{},
315
+ }
316
+ }
317
+ );
318
+ }
319
+
320
+ #[test]
321
+ fn changes_within_conflicting_map_field() {
322
+ let mut doc1 = new_doc();
323
+ let mut doc2 = new_doc();
324
+ doc1.put(&automerge::ROOT, "field", "string").unwrap();
325
+ let map_id = doc2
326
+ .put_object(&automerge::ROOT, "field", ObjType::Map)
327
+ .unwrap();
328
+ doc2.put(&map_id, "innerKey", 42).unwrap();
329
+ doc1.merge(&mut doc2).unwrap();
330
+
331
+ assert_doc!(
332
+ &doc1,
333
+ map! {
334
+ "field" => {
335
+ "string",
336
+ map!{
337
+ "innerKey" => {
338
+ 42,
339
+ }
340
+ }
341
+ }
342
+ }
343
+ );
344
+ }
345
+
346
+ #[test]
347
+ fn changes_within_conflicting_list_element() {
348
+ let (actor1, actor2) = sorted_actors();
349
+ let mut doc1 = new_doc_with_actor(actor1);
350
+ let mut doc2 = new_doc_with_actor(actor2);
351
+ let list_id = doc1
352
+ .put_object(&automerge::ROOT, "list", ObjType::List)
353
+ .unwrap();
354
+ doc1.insert(&list_id, 0, "hello").unwrap();
355
+ doc2.merge(&mut doc1).unwrap();
356
+
357
+ let map_in_doc1 = doc1.put_object(&list_id, 0, ObjType::Map).unwrap();
358
+ doc1.put(&map_in_doc1, "map1", true).unwrap();
359
+ doc1.put(&map_in_doc1, "key", 1).unwrap();
360
+
361
+ let map_in_doc2 = doc2.put_object(&list_id, 0, ObjType::Map).unwrap();
362
+ doc1.merge(&mut doc2).unwrap();
363
+ doc2.put(&map_in_doc2, "map2", true).unwrap();
364
+ doc2.put(&map_in_doc2, "key", 2).unwrap();
365
+
366
+ doc1.merge(&mut doc2).unwrap();
367
+
368
+ assert_doc!(
369
+ &doc1,
370
+ map! {
371
+ "list" => {
372
+ list![
373
+ {
374
+ map!{
375
+ "map2" => { true },
376
+ "key" => { 2 },
377
+ },
378
+ map!{
379
+ "key" => { 1 },
380
+ "map1" => { true },
381
+ }
382
+ }
383
+ ]
384
+ }
385
+ }
386
+ );
387
+ }
388
+
389
+ #[test]
390
+ fn concurrently_assigned_nested_maps_should_not_merge() {
391
+ let mut doc1 = new_doc();
392
+ let mut doc2 = new_doc();
393
+
394
+ let doc1_map_id = doc1
395
+ .put_object(&automerge::ROOT, "config", ObjType::Map)
396
+ .unwrap();
397
+ doc1.put(&doc1_map_id, "background", "blue").unwrap();
398
+
399
+ let doc2_map_id = doc2
400
+ .put_object(&automerge::ROOT, "config", ObjType::Map)
401
+ .unwrap();
402
+ doc2.put(&doc2_map_id, "logo_url", "logo.png").unwrap();
403
+
404
+ doc1.merge(&mut doc2).unwrap();
405
+
406
+ assert_doc!(
407
+ &doc1,
408
+ map! {
409
+ "config" => {
410
+ map!{
411
+ "background" => {"blue"}
412
+ },
413
+ map!{
414
+ "logo_url" => {"logo.png"}
415
+ }
416
+ }
417
+ }
418
+ );
419
+ }
420
+
421
+ #[test]
422
+ fn concurrent_insertions_at_different_list_positions() {
423
+ let (actor1, actor2) = sorted_actors();
424
+ let mut doc1 = new_doc_with_actor(actor1);
425
+ let mut doc2 = new_doc_with_actor(actor2);
426
+ assert!(doc1.get_actor() < doc2.get_actor());
427
+
428
+ let list_id = doc1
429
+ .put_object(&automerge::ROOT, "list", ObjType::List)
430
+ .unwrap();
431
+
432
+ doc1.insert(&list_id, 0, "one").unwrap();
433
+ doc1.insert(&list_id, 1, "three").unwrap();
434
+ doc2.merge(&mut doc1).unwrap();
435
+ doc1.splice(&list_id, 1, 0, vec![ScalarValue::from("two")])
436
+ .unwrap();
437
+ doc2.insert(&list_id, 2, "four").unwrap();
438
+
439
+ doc1.merge(&mut doc2).unwrap();
440
+
441
+ assert_doc!(
442
+ &doc1,
443
+ map! {
444
+ "list" => {
445
+ list![
446
+ {"one"},
447
+ {"two"},
448
+ {"three"},
449
+ {"four"},
450
+ ]
451
+ }
452
+ }
453
+ );
454
+ }
455
+
456
+ #[test]
457
+ fn concurrent_insertions_at_same_list_position() {
458
+ let (actor1, actor2) = sorted_actors();
459
+ let mut doc1 = new_doc_with_actor(actor1);
460
+ let mut doc2 = new_doc_with_actor(actor2);
461
+ assert!(doc1.get_actor() < doc2.get_actor());
462
+
463
+ let list_id = doc1
464
+ .put_object(&automerge::ROOT, "birds", ObjType::List)
465
+ .unwrap();
466
+ doc1.insert(&list_id, 0, "parakeet").unwrap();
467
+
468
+ doc2.merge(&mut doc1).unwrap();
469
+ doc1.insert(&list_id, 1, "starling").unwrap();
470
+ doc2.insert(&list_id, 1, "chaffinch").unwrap();
471
+ doc1.merge(&mut doc2).unwrap();
472
+
473
+ assert_doc!(
474
+ &doc1,
475
+ map! {
476
+ "birds" => {
477
+ list![
478
+ {
479
+ "parakeet",
480
+ },
481
+ {
482
+ "chaffinch",
483
+ },
484
+ {
485
+ "starling",
486
+ },
487
+ ]
488
+ },
489
+ }
490
+ );
491
+ }
492
+
493
+ #[test]
494
+ fn concurrent_assignment_and_deletion_of_a_map_entry() {
495
+ let mut doc1 = new_doc();
496
+ let mut doc2 = new_doc();
497
+ doc1.put(&automerge::ROOT, "bestBird", "robin").unwrap();
498
+ doc2.merge(&mut doc1).unwrap();
499
+ doc1.delete(&automerge::ROOT, "bestBird").unwrap();
500
+ doc2.put(&automerge::ROOT, "bestBird", "magpie").unwrap();
501
+
502
+ doc1.merge(&mut doc2).unwrap();
503
+
504
+ assert_doc!(
505
+ &doc1,
506
+ map! {
507
+ "bestBird" => {
508
+ "magpie",
509
+ }
510
+ }
511
+ );
512
+ }
513
+
514
+ #[test]
515
+ fn concurrent_assignment_and_deletion_of_list_entry() {
516
+ let mut doc1 = new_doc();
517
+ let mut doc2 = new_doc();
518
+ let list_id = doc1
519
+ .put_object(&automerge::ROOT, "birds", ObjType::List)
520
+ .unwrap();
521
+ doc1.insert(&list_id, 0, "blackbird").unwrap();
522
+ doc1.insert(&list_id, 1, "thrush").unwrap();
523
+ doc1.insert(&list_id, 2, "goldfinch").unwrap();
524
+ doc2.merge(&mut doc1).unwrap();
525
+ doc1.put(&list_id, 1, "starling").unwrap();
526
+ doc2.delete(&list_id, 1).unwrap();
527
+
528
+ assert_doc!(
529
+ &doc2,
530
+ map! {
531
+ "birds" => {list![
532
+ {"blackbird"},
533
+ {"goldfinch"},
534
+ ]}
535
+ }
536
+ );
537
+
538
+ assert_doc!(
539
+ &doc1,
540
+ map! {
541
+ "birds" => {list![
542
+ { "blackbird" },
543
+ { "starling" },
544
+ { "goldfinch" },
545
+ ]}
546
+ }
547
+ );
548
+
549
+ doc1.merge(&mut doc2).unwrap();
550
+
551
+ assert_doc!(
552
+ &doc1,
553
+ map! {
554
+ "birds" => {list![
555
+ { "blackbird" },
556
+ { "starling" },
557
+ { "goldfinch" },
558
+ ]}
559
+ }
560
+ );
561
+ }
562
+
563
+ #[test]
564
+ fn insertion_after_a_deleted_list_element() {
565
+ let mut doc1 = new_doc();
566
+ let mut doc2 = new_doc();
567
+ let list_id = doc1
568
+ .put_object(&automerge::ROOT, "birds", ObjType::List)
569
+ .unwrap();
570
+
571
+ doc1.insert(&list_id, 0, "blackbird").unwrap();
572
+ doc1.insert(&list_id, 1, "thrush").unwrap();
573
+ doc1.insert(&list_id, 2, "goldfinch").unwrap();
574
+
575
+ doc2.merge(&mut doc1).unwrap();
576
+
577
+ doc1.splice(&list_id, 1, 2, Vec::<ScalarValue>::new())
578
+ .unwrap();
579
+
580
+ doc2.splice(&list_id, 2, 0, vec![ScalarValue::from("starling")])
581
+ .unwrap();
582
+
583
+ doc1.merge(&mut doc2).unwrap();
584
+
585
+ assert_doc!(
586
+ &doc1,
587
+ map! {
588
+ "birds" => {list![
589
+ { "blackbird" },
590
+ { "starling" }
591
+ ]}
592
+ }
593
+ );
594
+
595
+ doc2.merge(&mut doc1).unwrap();
596
+ assert_doc!(
597
+ &doc2,
598
+ map! {
599
+ "birds" => {list![
600
+ { "blackbird" },
601
+ { "starling" }
602
+ ]}
603
+ }
604
+ );
605
+ }
606
+
607
+ #[test]
608
+ fn concurrent_deletion_of_same_list_element() {
609
+ let mut doc1 = new_doc();
610
+ let mut doc2 = new_doc();
611
+ let list_id = doc1
612
+ .put_object(&automerge::ROOT, "birds", ObjType::List)
613
+ .unwrap();
614
+
615
+ doc1.insert(&list_id, 0, "albatross").unwrap();
616
+ doc1.insert(&list_id, 1, "buzzard").unwrap();
617
+ doc1.insert(&list_id, 2, "cormorant").unwrap();
618
+
619
+ doc2.merge(&mut doc1).unwrap();
620
+
621
+ doc1.delete(&list_id, 1).unwrap();
622
+
623
+ doc2.delete(&list_id, 1).unwrap();
624
+
625
+ doc1.merge(&mut doc2).unwrap();
626
+
627
+ assert_doc!(
628
+ &doc1,
629
+ map! {
630
+ "birds" => {list![
631
+ { "albatross" },
632
+ { "cormorant" }
633
+ ]}
634
+ }
635
+ );
636
+
637
+ doc2.merge(&mut doc1).unwrap();
638
+ assert_doc!(
639
+ &doc2,
640
+ map! {
641
+ "birds" => {list![
642
+ { "albatross" },
643
+ { "cormorant" }
644
+ ]}
645
+ }
646
+ );
647
+ }
648
+
649
+ #[test]
650
+ fn concurrent_updates_at_different_levels() {
651
+ let mut doc1 = new_doc();
652
+ let mut doc2 = new_doc();
653
+
654
+ let animals = doc1
655
+ .put_object(&automerge::ROOT, "animals", ObjType::Map)
656
+ .unwrap();
657
+ let birds = doc1.put_object(&animals, "birds", ObjType::Map).unwrap();
658
+ doc1.put(&birds, "pink", "flamingo").unwrap();
659
+ doc1.put(&birds, "black", "starling").unwrap();
660
+
661
+ let mammals = doc1.put_object(&animals, "mammals", ObjType::List).unwrap();
662
+ doc1.insert(&mammals, 0, "badger").unwrap();
663
+
664
+ doc2.merge(&mut doc1).unwrap();
665
+
666
+ doc1.put(&birds, "brown", "sparrow").unwrap();
667
+
668
+ doc2.delete(&animals, "birds").unwrap();
669
+ doc1.merge(&mut doc2).unwrap();
670
+
671
+ assert_obj!(
672
+ &doc1,
673
+ &automerge::ROOT,
674
+ "animals",
675
+ map! {
676
+ "mammals" => {
677
+ list![{ "badger" }],
678
+ }
679
+ }
680
+ );
681
+
682
+ assert_obj!(
683
+ doc2.document(),
684
+ &automerge::ROOT,
685
+ "animals",
686
+ map! {
687
+ "mammals" => {
688
+ list![{ "badger" }],
689
+ }
690
+ }
691
+ );
692
+ }
693
+
694
+ #[test]
695
+ fn concurrent_updates_of_concurrently_deleted_objects() {
696
+ let mut doc1 = new_doc();
697
+ let mut doc2 = new_doc();
698
+
699
+ let birds = doc1
700
+ .put_object(&automerge::ROOT, "birds", ObjType::Map)
701
+ .unwrap();
702
+ let blackbird = doc1.put_object(&birds, "blackbird", ObjType::Map).unwrap();
703
+ doc1.put(&blackbird, "feathers", "black").unwrap();
704
+
705
+ doc2.merge(&mut doc1).unwrap();
706
+
707
+ doc1.delete(&birds, "blackbird").unwrap();
708
+
709
+ doc2.put(&blackbird, "beak", "orange").unwrap();
710
+
711
+ doc1.merge(&mut doc2).unwrap();
712
+
713
+ assert_doc!(
714
+ &doc1,
715
+ map! {
716
+ "birds" => {
717
+ map!{},
718
+ }
719
+ }
720
+ );
721
+ }
722
+
723
+ #[test]
724
+ fn does_not_interleave_sequence_insertions_at_same_position() {
725
+ let (actor1, actor2) = sorted_actors();
726
+ let mut doc1 = new_doc_with_actor(actor1);
727
+ let mut doc2 = new_doc_with_actor(actor2);
728
+
729
+ let wisdom = doc1
730
+ .put_object(&automerge::ROOT, "wisdom", ObjType::List)
731
+ .unwrap();
732
+ doc2.merge(&mut doc1).unwrap();
733
+
734
+ doc1.splice(
735
+ &wisdom,
736
+ 0,
737
+ 0,
738
+ vec![
739
+ ScalarValue::from("to"),
740
+ ScalarValue::from("be"),
741
+ ScalarValue::from("is"),
742
+ ScalarValue::from("to"),
743
+ ScalarValue::from("do"),
744
+ ],
745
+ )
746
+ .unwrap();
747
+
748
+ doc2.splice(
749
+ &wisdom,
750
+ 0,
751
+ 0,
752
+ vec![
753
+ ScalarValue::from("to"),
754
+ ScalarValue::from("do"),
755
+ ScalarValue::from("is"),
756
+ ScalarValue::from("to"),
757
+ ScalarValue::from("be"),
758
+ ],
759
+ )
760
+ .unwrap();
761
+
762
+ doc1.merge(&mut doc2).unwrap();
763
+
764
+ assert_doc!(
765
+ &doc1,
766
+ map! {
767
+ "wisdom" => {list![
768
+ {"to"},
769
+ {"do"},
770
+ {"is"},
771
+ {"to"},
772
+ {"be"},
773
+ {"to"},
774
+ {"be"},
775
+ {"is"},
776
+ {"to"},
777
+ {"do"},
778
+ ]}
779
+ }
780
+ );
781
+ }
782
+
783
+ #[test]
784
+ fn mutliple_insertions_at_same_list_position_with_insertion_by_greater_actor_id() {
785
+ let (actor1, actor2) = sorted_actors();
786
+ assert!(actor2 > actor1);
787
+ let mut doc1 = new_doc_with_actor(actor1);
788
+ let mut doc2 = new_doc_with_actor(actor2);
789
+
790
+ let list = doc1
791
+ .put_object(&automerge::ROOT, "list", ObjType::List)
792
+ .unwrap();
793
+ doc1.insert(&list, 0, "two").unwrap();
794
+ doc2.merge(&mut doc1).unwrap();
795
+
796
+ doc2.insert(&list, 0, "one").unwrap();
797
+ assert_doc!(
798
+ &doc2,
799
+ map! {
800
+ "list" => { list![
801
+ { "one" },
802
+ { "two" },
803
+ ]}
804
+ }
805
+ );
806
+ }
807
+
808
+ #[test]
809
+ fn mutliple_insertions_at_same_list_position_with_insertion_by_lesser_actor_id() {
810
+ let (actor2, actor1) = sorted_actors();
811
+ assert!(actor2 < actor1);
812
+ let mut doc1 = new_doc_with_actor(actor1);
813
+ let mut doc2 = new_doc_with_actor(actor2);
814
+
815
+ let list = doc1
816
+ .put_object(&automerge::ROOT, "list", ObjType::List)
817
+ .unwrap();
818
+ doc1.insert(&list, 0, "two").unwrap();
819
+ doc2.merge(&mut doc1).unwrap();
820
+
821
+ doc2.insert(&list, 0, "one").unwrap();
822
+ assert_doc!(
823
+ &doc2,
824
+ map! {
825
+ "list" => { list![
826
+ { "one" },
827
+ { "two" },
828
+ ]}
829
+ }
830
+ );
831
+ }
832
+
833
+ #[test]
834
+ fn insertion_consistent_with_causality() {
835
+ let mut doc1 = new_doc();
836
+ let mut doc2 = new_doc();
837
+
838
+ let list = doc1
839
+ .put_object(&automerge::ROOT, "list", ObjType::List)
840
+ .unwrap();
841
+ doc1.insert(&list, 0, "four").unwrap();
842
+ doc2.merge(&mut doc1).unwrap();
843
+ doc2.insert(&list, 0, "three").unwrap();
844
+ doc1.merge(&mut doc2).unwrap();
845
+ doc1.insert(&list, 0, "two").unwrap();
846
+ doc2.merge(&mut doc1).unwrap();
847
+ doc2.insert(&list, 0, "one").unwrap();
848
+
849
+ assert_doc!(
850
+ &doc2,
851
+ map! {
852
+ "list" => { list![
853
+ {"one"},
854
+ {"two"},
855
+ {"three" },
856
+ {"four"},
857
+ ]}
858
+ }
859
+ );
860
+ }
861
+
862
+ #[test]
863
+ fn save_and_restore_empty() {
864
+ let mut doc = new_doc();
865
+ let loaded = Automerge::load(&doc.save()).unwrap();
866
+
867
+ assert_doc!(&loaded, map! {});
868
+ }
869
+
870
+ #[test]
871
+ fn save_restore_complex1() {
872
+ let mut doc1 = new_doc();
873
+ let todos = doc1
874
+ .put_object(&automerge::ROOT, "todos", ObjType::List)
875
+ .unwrap();
876
+
877
+ let first_todo = doc1.insert_object(&todos, 0, ObjType::Map).unwrap();
878
+ doc1.put(&first_todo, "title", "water plants").unwrap();
879
+ doc1.put(&first_todo, "done", false).unwrap();
880
+
881
+ let mut doc2 = new_doc();
882
+ doc2.merge(&mut doc1).unwrap();
883
+ doc2.put(&first_todo, "title", "weed plants").unwrap();
884
+
885
+ doc1.put(&first_todo, "title", "kill plants").unwrap();
886
+ doc1.merge(&mut doc2).unwrap();
887
+
888
+ let reloaded = Automerge::load(&doc1.save()).unwrap();
889
+
890
+ assert_doc!(
891
+ &reloaded,
892
+ map! {
893
+ "todos" => {list![
894
+ {map!{
895
+ "title" => {
896
+ "weed plants",
897
+ "kill plants",
898
+ },
899
+ "done" => {false},
900
+ }}
901
+ ]}
902
+ }
903
+ );
904
+ }
905
+
906
+ #[test]
907
+ fn handle_repeated_out_of_order_changes() -> Result<(), automerge::AutomergeError> {
908
+ let mut doc1 = new_doc();
909
+ let list = doc1.put_object(ROOT, "list", ObjType::List)?;
910
+ doc1.insert(&list, 0, "a")?;
911
+ let mut doc2 = doc1.fork();
912
+ doc1.insert(&list, 1, "b")?;
913
+ doc1.commit();
914
+ doc1.insert(&list, 2, "c")?;
915
+ doc1.commit();
916
+ doc1.insert(&list, 3, "d")?;
917
+ doc1.commit();
918
+ let changes = doc1.get_changes(&[]).into_iter().collect::<Vec<_>>();
919
+ doc2.apply_changes(changes[2..].to_vec())?;
920
+ doc2.apply_changes(changes[2..].to_vec())?;
921
+ doc2.apply_changes(changes)?;
922
+ assert_eq!(doc1.save(), doc2.save());
923
+ Ok(())
924
+ }
925
+
926
+ #[test]
927
+ fn save_restore_complex_transactional() {
928
+ let mut doc1 = Automerge::new();
929
+ let first_todo = doc1
930
+ .transact::<_, _, automerge::AutomergeError>(|d| {
931
+ let todos = d.put_object(&automerge::ROOT, "todos", ObjType::List)?;
932
+ let first_todo = d.insert_object(&todos, 0, ObjType::Map)?;
933
+ d.put(&first_todo, "title", "water plants")?;
934
+ d.put(&first_todo, "done", false)?;
935
+ Ok(first_todo)
936
+ })
937
+ .unwrap()
938
+ .result;
939
+
940
+ let mut doc2 = Automerge::new();
941
+ doc2.merge(&mut doc1).unwrap();
942
+ doc2.transact::<_, _, automerge::AutomergeError>(|tx| {
943
+ tx.put(&first_todo, "title", "weed plants")?;
944
+ Ok(())
945
+ })
946
+ .unwrap();
947
+
948
+ doc1.transact::<_, _, automerge::AutomergeError>(|tx| {
949
+ tx.put(&first_todo, "title", "kill plants")?;
950
+ Ok(())
951
+ })
952
+ .unwrap();
953
+ doc1.merge(&mut doc2).unwrap();
954
+
955
+ let reloaded = Automerge::load(&doc1.save()).unwrap();
956
+
957
+ assert_doc!(
958
+ &reloaded,
959
+ map! {
960
+ "todos" => {list![
961
+ {map!{
962
+ "title" => {
963
+ "weed plants",
964
+ "kill plants",
965
+ },
966
+ "done" => {false},
967
+ }}
968
+ ]}
969
+ }
970
+ );
971
+ }
972
+
973
+ #[test]
974
+ fn list_counter_del() -> Result<(), automerge::AutomergeError> {
975
+ let mut v = [ActorId::random(), ActorId::random(), ActorId::random()];
976
+ v.sort();
977
+ let actor1 = v[0].clone();
978
+ let actor2 = v[1].clone();
979
+ let actor3 = v[2].clone();
980
+
981
+ let mut doc1 = new_doc_with_actor(actor1);
982
+
983
+ let list = doc1.put_object(ROOT, "list", ObjType::List)?;
984
+ doc1.insert(&list, 0, "a")?;
985
+ doc1.insert(&list, 1, "b")?;
986
+ doc1.insert(&list, 2, "c")?;
987
+
988
+ let mut doc2 = AutoCommit::load(&doc1.save())?;
989
+ doc2.set_actor(actor2);
990
+
991
+ let mut doc3 = AutoCommit::load(&doc1.save())?;
992
+ doc3.set_actor(actor3);
993
+
994
+ doc1.put(&list, 1, ScalarValue::counter(0))?;
995
+ doc2.put(&list, 1, ScalarValue::counter(10))?;
996
+ doc3.put(&list, 1, ScalarValue::counter(100))?;
997
+
998
+ doc1.put(&list, 2, ScalarValue::counter(0))?;
999
+ doc2.put(&list, 2, ScalarValue::counter(10))?;
1000
+ doc3.put(&list, 2, 100)?;
1001
+
1002
+ doc1.increment(&list, 1, 1)?;
1003
+ doc1.increment(&list, 2, 1)?;
1004
+
1005
+ doc1.merge(&mut doc2).unwrap();
1006
+ doc1.merge(&mut doc3).unwrap();
1007
+
1008
+ assert_obj!(
1009
+ doc1.document(),
1010
+ &automerge::ROOT,
1011
+ "list",
1012
+ list![
1013
+ {
1014
+ "a",
1015
+ },
1016
+ {
1017
+ ScalarValue::counter(1),
1018
+ ScalarValue::counter(10),
1019
+ ScalarValue::counter(100)
1020
+ },
1021
+ {
1022
+ ScalarValue::Int(100),
1023
+ ScalarValue::counter(1),
1024
+ ScalarValue::counter(10),
1025
+ }
1026
+ ]
1027
+ );
1028
+
1029
+ doc1.increment(&list, 1, 1)?;
1030
+ doc1.increment(&list, 2, 1)?;
1031
+
1032
+ assert_obj!(
1033
+ doc1.document(),
1034
+ &automerge::ROOT,
1035
+ "list",
1036
+ list![
1037
+ {
1038
+ "a",
1039
+ },
1040
+ {
1041
+ ScalarValue::counter(2),
1042
+ ScalarValue::counter(11),
1043
+ ScalarValue::counter(101)
1044
+ },
1045
+ {
1046
+ ScalarValue::counter(2),
1047
+ ScalarValue::counter(11),
1048
+ }
1049
+ ]
1050
+ );
1051
+
1052
+ doc1.delete(&list, 2)?;
1053
+
1054
+ assert_eq!(doc1.length(&list), 2);
1055
+
1056
+ let doc4 = AutoCommit::load(&doc1.save())?;
1057
+
1058
+ assert_eq!(doc4.length(&list), 2);
1059
+
1060
+ doc1.delete(&list, 1)?;
1061
+
1062
+ assert_eq!(doc1.length(&list), 1);
1063
+
1064
+ doc1.dump();
1065
+ let doc5 = AutoCommit::load(&doc1.save())?;
1066
+
1067
+ assert_eq!(doc5.length(&list), 1);
1068
+
1069
+ Ok(())
1070
+ }
1071
+
1072
+ #[test]
1073
+ fn observe_counter_change_application() {
1074
+ let mut doc = AutoCommit::new();
1075
+ doc.put(ROOT, "counter", ScalarValue::counter(1)).unwrap();
1076
+ doc.increment(ROOT, "counter", 2).unwrap();
1077
+ doc.increment(ROOT, "counter", 5).unwrap();
1078
+ let changes = doc.get_changes(&[]).into_iter();
1079
+
1080
+ let mut doc = AutoCommit::new();
1081
+ doc.apply_changes(changes).unwrap();
1082
+ }
1083
+
1084
+ #[test]
1085
+ fn increment_non_counter_map() {
1086
+ let mut doc = AutoCommit::new();
1087
+ // can't increment nothing
1088
+ assert!(matches!(
1089
+ doc.increment(ROOT, "nothing", 2),
1090
+ Err(AutomergeError::MissingCounter)
1091
+ ));
1092
+
1093
+ // can't increment a non-counter
1094
+ doc.put(ROOT, "non-counter", "mystring").unwrap();
1095
+ assert!(matches!(
1096
+ doc.increment(ROOT, "non-counter", 2),
1097
+ Err(AutomergeError::MissingCounter)
1098
+ ));
1099
+
1100
+ // can increment a counter still
1101
+ doc.put(ROOT, "counter", ScalarValue::counter(1)).unwrap();
1102
+ assert!(matches!(doc.increment(ROOT, "counter", 2), Ok(())));
1103
+
1104
+ // can increment a counter that is part of a conflict
1105
+ let mut doc1 = AutoCommit::new();
1106
+ doc1.set_actor(ActorId::from([1]));
1107
+ let mut doc2 = AutoCommit::new();
1108
+ doc2.set_actor(ActorId::from([2]));
1109
+
1110
+ doc1.put(ROOT, "key", ScalarValue::counter(1)).unwrap();
1111
+ doc2.put(ROOT, "key", "mystring").unwrap();
1112
+ doc1.merge(&mut doc2).unwrap();
1113
+
1114
+ assert!(matches!(doc1.increment(ROOT, "key", 2), Ok(())));
1115
+ }
1116
+
1117
+ #[test]
1118
+ fn increment_non_counter_list() {
1119
+ let mut doc = AutoCommit::new();
1120
+ let list = doc.put_object(ROOT, "list", ObjType::List).unwrap();
1121
+
1122
+ // can't increment a non-counter
1123
+ doc.insert(&list, 0, "mystring").unwrap();
1124
+ assert!(matches!(
1125
+ doc.increment(&list, 0, 2),
1126
+ Err(AutomergeError::MissingCounter)
1127
+ ));
1128
+
1129
+ // can increment a counter
1130
+ doc.insert(&list, 0, ScalarValue::counter(1)).unwrap();
1131
+ assert!(matches!(doc.increment(&list, 0, 2), Ok(())));
1132
+
1133
+ // can increment a counter that is part of a conflict
1134
+ let mut doc1 = AutoCommit::new();
1135
+ doc1.set_actor(ActorId::from([1]));
1136
+ let list = doc1.put_object(ROOT, "list", ObjType::List).unwrap();
1137
+ doc1.insert(&list, 0, ()).unwrap();
1138
+ let mut doc2 = doc1.fork();
1139
+ doc2.set_actor(ActorId::from([2]));
1140
+
1141
+ doc1.put(&list, 0, ScalarValue::counter(1)).unwrap();
1142
+ doc2.put(&list, 0, "mystring").unwrap();
1143
+ doc1.merge(&mut doc2).unwrap();
1144
+
1145
+ assert!(matches!(doc1.increment(&list, 0, 2), Ok(())));
1146
+ }
1147
+
1148
+ #[test]
1149
+ fn test_local_inc_in_map() {
1150
+ let mut v = [ActorId::random(), ActorId::random(), ActorId::random()];
1151
+ v.sort();
1152
+ let actor1 = v[0].clone();
1153
+ let actor2 = v[1].clone();
1154
+ let actor3 = v[2].clone();
1155
+
1156
+ let mut doc1 = new_doc_with_actor(actor1);
1157
+ doc1.put(&automerge::ROOT, "hello", "world").unwrap();
1158
+
1159
+ let mut doc2 = AutoCommit::load(&doc1.save()).unwrap();
1160
+ doc2.set_actor(actor2);
1161
+
1162
+ let mut doc3 = AutoCommit::load(&doc1.save()).unwrap();
1163
+ doc3.set_actor(actor3);
1164
+
1165
+ doc1.put(ROOT, "cnt", 20_u64).unwrap();
1166
+ doc2.put(ROOT, "cnt", ScalarValue::counter(0)).unwrap();
1167
+ doc3.put(ROOT, "cnt", ScalarValue::counter(10)).unwrap();
1168
+ doc1.merge(&mut doc2).unwrap();
1169
+ doc1.merge(&mut doc3).unwrap();
1170
+
1171
+ assert_doc! {doc1.document(), map!{
1172
+ "cnt" => {
1173
+ 20_u64,
1174
+ ScalarValue::counter(0),
1175
+ ScalarValue::counter(10),
1176
+ },
1177
+ "hello" => {"world"},
1178
+ }};
1179
+
1180
+ doc1.increment(ROOT, "cnt", 5).unwrap();
1181
+
1182
+ assert_doc! {doc1.document(), map!{
1183
+ "cnt" => {
1184
+ ScalarValue::counter(5),
1185
+ ScalarValue::counter(15),
1186
+ },
1187
+ "hello" => {"world"},
1188
+ }};
1189
+ let mut doc4 = AutoCommit::load(&doc1.save()).unwrap();
1190
+ assert_eq!(doc4.save(), doc1.save());
1191
+ }
1192
+
1193
+ #[test]
1194
+ fn test_merging_test_conflicts_then_saving_and_loading() {
1195
+ let (actor1, actor2) = sorted_actors();
1196
+
1197
+ let mut doc1 = new_doc_with_actor(actor1);
1198
+ let text = doc1.put_object(ROOT, "text", ObjType::Text).unwrap();
1199
+ doc1.splice_text(&text, 0, 0, "hello").unwrap();
1200
+
1201
+ let mut doc2 = AutoCommit::load(&doc1.save()).unwrap();
1202
+ doc2.set_actor(actor2);
1203
+
1204
+ assert_doc! {&doc2, map!{
1205
+ "text" => { list![{"h"}, {"e"}, {"l"}, {"l"}, {"o"}]},
1206
+ }};
1207
+
1208
+ doc2.splice_text(&text, 4, 1, "").unwrap();
1209
+ doc2.splice_text(&text, 4, 0, "!").unwrap();
1210
+ doc2.splice_text(&text, 5, 0, " ").unwrap();
1211
+ doc2.splice_text(&text, 6, 0, "world").unwrap();
1212
+
1213
+ assert_doc!(
1214
+ &doc2,
1215
+ map! {
1216
+ "text" => { list![{"h"}, {"e"}, {"l"}, {"l"}, {"!"}, {" "}, {"w"} , {"o"}, {"r"}, {"l"}, {"d"}]}
1217
+ }
1218
+ );
1219
+
1220
+ let doc3 = AutoCommit::load(&doc2.save()).unwrap();
1221
+
1222
+ assert_doc!(
1223
+ &doc3,
1224
+ map! {
1225
+ "text" => { list![{"h"}, {"e"}, {"l"}, {"l"}, {"!"}, {" "}, {"w"} , {"o"}, {"r"}, {"l"}, {"d"}]}
1226
+ }
1227
+ );
1228
+ }
1229
+
1230
+ /// Surfaces an error which occurs when loading a document with a change which only contains a
1231
+ /// delete operation. In this case the delete operation doesn't appear in the encoded document
1232
+ /// operations except as a succ, so the max_op was calculated incorectly.
1233
+ #[test]
1234
+ fn delete_only_change() {
1235
+ let actor = automerge::ActorId::random();
1236
+ let mut doc1 = automerge::Automerge::new().with_actor(actor.clone());
1237
+ let list = doc1
1238
+ .transact::<_, _, automerge::AutomergeError>(|d| {
1239
+ let l = d.put_object(&automerge::ROOT, "list", ObjType::List)?;
1240
+ d.insert(&l, 0, 'a')?;
1241
+ Ok(l)
1242
+ })
1243
+ .unwrap()
1244
+ .result;
1245
+
1246
+ let mut doc2 = automerge::Automerge::load(&doc1.save())
1247
+ .unwrap()
1248
+ .with_actor(actor.clone());
1249
+ doc2.transact::<_, _, automerge::AutomergeError>(|d| d.delete(&list, 0))
1250
+ .unwrap();
1251
+
1252
+ let mut doc3 = automerge::Automerge::load(&doc2.save())
1253
+ .unwrap()
1254
+ .with_actor(actor.clone());
1255
+ doc3.transact(|d| d.insert(&list, 0, "b")).unwrap();
1256
+
1257
+ let doc4 = automerge::Automerge::load(&doc3.save())
1258
+ .unwrap()
1259
+ .with_actor(actor);
1260
+
1261
+ let changes = doc4.get_changes(&[]);
1262
+ assert_eq!(changes.len(), 3);
1263
+ let c = &changes[2];
1264
+ assert_eq!(c.start_op().get(), 4);
1265
+ }
1266
+
1267
+ /// Expose an error where a document which contained a create operation without any subsequent
1268
+ /// operations targeting the created object did not load the object correctly.
1269
+ #[test]
1270
+ fn save_and_reload_create_object() {
1271
+ let actor = automerge::ActorId::random();
1272
+ let mut doc = automerge::Automerge::new().with_actor(actor);
1273
+
1274
+ // Create a change containing an object but no other operations
1275
+ let list = doc
1276
+ .transact::<_, _, automerge::AutomergeError>(|d| {
1277
+ d.put_object(&automerge::ROOT, "foo", ObjType::List)
1278
+ })
1279
+ .unwrap()
1280
+ .result;
1281
+
1282
+ // Save and load the change
1283
+ let mut doc2 = automerge::Automerge::load(&doc.save()).unwrap();
1284
+ doc2.transact::<_, _, automerge::AutomergeError>(|d| {
1285
+ d.insert(&list, 0, 1_u64)?;
1286
+ Ok(())
1287
+ })
1288
+ .unwrap();
1289
+
1290
+ assert_doc!(&doc2, map! {"foo" => { list! [{1_u64}]}});
1291
+
1292
+ let _doc3 = automerge::Automerge::load(&doc2.save()).unwrap();
1293
+ }
1294
+
1295
+ #[test]
1296
+ fn test_compressed_changes() {
1297
+ let mut doc = new_doc();
1298
+ // crate::storage::DEFLATE_MIN_SIZE is 250, so this should trigger compression
1299
+ doc.put(ROOT, "bytes", ScalarValue::Bytes(vec![10; 300]))
1300
+ .unwrap();
1301
+ let mut change = doc.get_last_local_change().unwrap().clone();
1302
+ let uncompressed = change.raw_bytes().to_vec();
1303
+ assert!(uncompressed.len() > 256);
1304
+ let compressed = change.bytes().to_vec();
1305
+ assert!(compressed.len() < uncompressed.len());
1306
+
1307
+ let reloaded = automerge::Change::try_from(&compressed[..]).unwrap();
1308
+ assert_eq!(change.raw_bytes(), reloaded.raw_bytes());
1309
+ }
1310
+
1311
+ #[test]
1312
+ fn test_compressed_doc_cols() {
1313
+ // In this test, the keyCtr column is long enough for deflate compression to kick in, but the
1314
+ // keyStr column is short. Thus, the deflate bit gets set for keyCtr but not for keyStr.
1315
+ // When checking whether the columns appear in ascending order, we must ignore the deflate bit.
1316
+ let mut doc = new_doc();
1317
+ let list = doc.put_object(ROOT, "list", ObjType::List).unwrap();
1318
+ let mut expected = Vec::new();
1319
+ for i in 0..200 {
1320
+ doc.insert(&list, i, i as u64).unwrap();
1321
+ expected.push(i as u64);
1322
+ }
1323
+ let uncompressed = doc.save_nocompress();
1324
+ let compressed = doc.save();
1325
+ assert!(compressed.len() < uncompressed.len());
1326
+ let loaded = automerge::Automerge::load(&compressed).unwrap();
1327
+ assert_doc!(
1328
+ &loaded,
1329
+ map! {
1330
+ "list" => { expected}
1331
+ }
1332
+ );
1333
+ }
1334
+
1335
+ #[test]
1336
+ fn test_change_encoding_expanded_change_round_trip() {
1337
+ let change_bytes: Vec<u8> = vec![
1338
+ 0x85, 0x6f, 0x4a, 0x83, // magic bytes
1339
+ 0xb2, 0x98, 0x9e, 0xa9, // checksum
1340
+ 1, 61, 0, 2, 0x12, 0x34, // chunkType: change, length, deps, actor '1234'
1341
+ 1, 1, 252, 250, 220, 255, 5, // seq, startOp, time
1342
+ 14, 73, 110, 105, 116, 105, 97, 108, 105, 122, 97, 116, 105, 111,
1343
+ 110, // message: 'Initialization'
1344
+ 0, 6, // actor list, column count
1345
+ 0x15, 3, 0x34, 1, 0x42, 2, // keyStr, insert, action
1346
+ 0x56, 2, 0x57, 1, 0x70, 2, // valLen, valRaw, predNum
1347
+ 0x7f, 1, 0x78, // keyStr: 'x'
1348
+ 1, // insert: false
1349
+ 0x7f, 1, // action: set
1350
+ 0x7f, 19, // valLen: 1 byte of type uint
1351
+ 1, // valRaw: 1
1352
+ 0x7f, 0, // predNum: 0
1353
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // 10 trailing bytes
1354
+ ];
1355
+ let change = automerge::Change::try_from(&change_bytes[..]).unwrap();
1356
+ assert_eq!(change.raw_bytes(), change_bytes);
1357
+ let expanded = automerge::ExpandedChange::from(&change);
1358
+ let unexpanded: automerge::Change = expanded.into();
1359
+ assert_eq!(unexpanded.raw_bytes(), change_bytes);
1360
+ }
1361
+
1362
+ #[test]
1363
+ fn save_and_load_incremented_counter() {
1364
+ let mut doc = AutoCommit::new();
1365
+ doc.put(ROOT, "counter", ScalarValue::counter(1)).unwrap();
1366
+ doc.commit();
1367
+ doc.increment(ROOT, "counter", 1).unwrap();
1368
+ doc.commit();
1369
+ let changes1: Vec<Change> = doc.get_changes(&[]).into_iter().collect();
1370
+ let json: Vec<_> = changes1
1371
+ .iter()
1372
+ .map(|c| serde_json::to_string(&c.decode()).unwrap())
1373
+ .collect();
1374
+ let changes2: Vec<Change> = json
1375
+ .iter()
1376
+ .map(|j| serde_json::from_str::<ExpandedChange>(j).unwrap().into())
1377
+ .collect();
1378
+
1379
+ assert_eq!(changes1, changes2);
1380
+ }
1381
+
1382
+ #[test]
1383
+ fn load_incremental_with_corrupted_tail() {
1384
+ let mut doc = AutoCommit::new();
1385
+ doc.put(ROOT, "key", ScalarValue::Str("value".into()))
1386
+ .unwrap();
1387
+ doc.commit();
1388
+ let mut bytes = doc.save();
1389
+ bytes.extend_from_slice(&[1, 2, 3, 4]);
1390
+ let mut loaded = Automerge::new();
1391
+ let loaded_len = loaded.load_incremental(&bytes).unwrap();
1392
+ assert_eq!(loaded_len, 1);
1393
+ assert_doc!(
1394
+ &loaded,
1395
+ map! {
1396
+ "key" => { "value" },
1397
+ }
1398
+ );
1399
+ }
1400
+
1401
+ #[test]
1402
+ fn load_doc_with_deleted_objects() {
1403
+ // Reproduces an issue where a document with deleted objects failed to load
1404
+ let mut doc = AutoCommit::new();
1405
+ doc.put_object(ROOT, "list", ObjType::List).unwrap();
1406
+ doc.put_object(ROOT, "text", ObjType::Text).unwrap();
1407
+ doc.put_object(ROOT, "map", ObjType::Map).unwrap();
1408
+ doc.put_object(ROOT, "table", ObjType::Table).unwrap();
1409
+ doc.delete(&ROOT, "list").unwrap();
1410
+ doc.delete(&ROOT, "text").unwrap();
1411
+ doc.delete(&ROOT, "map").unwrap();
1412
+ doc.delete(&ROOT, "table").unwrap();
1413
+ let saved = doc.save();
1414
+ Automerge::load(&saved).unwrap();
1415
+ }
1416
+
1417
+ #[test]
1418
+ fn insert_after_many_deletes() {
1419
+ let mut doc = AutoCommit::new();
1420
+ let obj = doc.put_object(&ROOT, "object", ObjType::Map).unwrap();
1421
+ for i in 0..100 {
1422
+ doc.put(&obj, i.to_string(), i).unwrap();
1423
+ doc.delete(&obj, i.to_string()).unwrap();
1424
+ }
1425
+ }
1426
+
1427
+ #[test]
1428
+ fn simple_bad_saveload() {
1429
+ let mut doc = Automerge::new();
1430
+ doc.transact::<_, _, AutomergeError>(|d| {
1431
+ d.put(ROOT, "count", 0)?;
1432
+ Ok(())
1433
+ })
1434
+ .unwrap();
1435
+
1436
+ doc.transact::<_, _, AutomergeError>(|_d| Ok(())).unwrap();
1437
+
1438
+ doc.transact::<_, _, AutomergeError>(|d| {
1439
+ d.put(ROOT, "count", 0)?;
1440
+ Ok(())
1441
+ })
1442
+ .unwrap();
1443
+
1444
+ let bytes = doc.save();
1445
+ Automerge::load(&bytes).unwrap();
1446
+ }
1447
+
1448
+ #[test]
1449
+ fn ops_on_wrong_objets() -> Result<(), AutomergeError> {
1450
+ let mut doc = AutoCommit::new();
1451
+ let list = doc.put_object(&automerge::ROOT, "list", ObjType::List)?;
1452
+ doc.insert(&list, 0, "a")?;
1453
+ doc.insert(&list, 1, "b")?;
1454
+ let e1 = doc.put(&list, "a", "AAA");
1455
+ assert_eq!(e1, Err(AutomergeError::InvalidOp(ObjType::List)));
1456
+ let e2 = doc.splice_text(&list, 0, 0, "hello world");
1457
+ assert_eq!(e2, Err(AutomergeError::InvalidOp(ObjType::List)));
1458
+ let map = doc.put_object(&automerge::ROOT, "map", ObjType::Map)?;
1459
+ doc.put(&map, "a", "AAA")?;
1460
+ doc.put(&map, "b", "BBB")?;
1461
+ let e3 = doc.insert(&map, 0, "b");
1462
+ assert_eq!(e3, Err(AutomergeError::InvalidOp(ObjType::Map)));
1463
+ let e4 = doc.splice_text(&map, 0, 0, "hello world");
1464
+ assert_eq!(e4, Err(AutomergeError::InvalidOp(ObjType::Map)));
1465
+ let text = doc.put_object(&automerge::ROOT, "text", ObjType::Text)?;
1466
+ doc.splice_text(&text, 0, 0, "hello world")?;
1467
+ let e5 = doc.put(&text, "a", "AAA");
1468
+ assert_eq!(e5, Err(AutomergeError::InvalidOp(ObjType::Text)));
1469
+ //let e6 = doc.insert(&text, 0, "b");
1470
+ //assert_eq!(e6, Err(AutomergeError::InvalidOp(ObjType::Text)));
1471
+ Ok(())
1472
+ }
1473
+
1474
+ #[test]
1475
+ fn fuzz_crashers() {
1476
+ let paths = fs::read_dir("./tests/fuzz-crashers").unwrap();
1477
+
1478
+ for path in paths {
1479
+ // uncomment this line to figure out which fixture is crashing:
1480
+ println!("{:?}", path.as_ref().unwrap().path().display());
1481
+ let bytes = fs::read(path.as_ref().unwrap().path());
1482
+ let res = Automerge::load(&bytes.unwrap());
1483
+ assert!(res.is_err());
1484
+ }
1485
+ }
1486
+
1487
+ fn fixture(name: &str) -> Vec<u8> {
1488
+ fs::read("./tests/fixtures/".to_owned() + name).unwrap()
1489
+ }
1490
+
1491
+ #[test]
1492
+ fn overlong_leb() {
1493
+ // the value metadata says "2", but the LEB is only 1-byte long and there's an extra 0
1494
+ assert!(Automerge::load(&fixture("counter_value_has_incorrect_meta.automerge")).is_err());
1495
+ // the LEB is overlong (using 2 bytes where one would have sufficed)
1496
+ assert!(Automerge::load(&fixture("counter_value_is_overlong.automerge")).is_err());
1497
+ // the LEB is correct
1498
+ assert!(Automerge::load(&fixture("counter_value_is_ok.automerge")).is_ok());
1499
+ }
1500
+
1501
+ #[test]
1502
+ fn load() {
1503
+ fn check_fixture(name: &str) {
1504
+ let doc = Automerge::load(&fixture(name)).unwrap();
1505
+ let map_id = doc.get(ROOT, "a").unwrap().unwrap().1;
1506
+ assert_eq!(doc.get(map_id, "a").unwrap().unwrap().0, "b".into());
1507
+ }
1508
+
1509
+ check_fixture("two_change_chunks.automerge");
1510
+ check_fixture("two_change_chunks_compressed.automerge");
1511
+ check_fixture("two_change_chunks_out_of_order.automerge");
1512
+ }
1513
+
1514
+ #[test]
1515
+ fn negative_64() {
1516
+ let mut doc = Automerge::new();
1517
+ assert!(doc.transact(|d| { d.put(ROOT, "a", -64_i64) }).is_ok())
1518
+ }
1519
+
1520
+ #[test]
1521
+ fn obj_id_64bits() {
1522
+ // this change has an opId of 2**42, which when cast to a 32-bit int gives 0.
1523
+ // The file should either fail to load (a limit of ~4 billion ops per doc seems reasonable), or be handled correctly.
1524
+ if let Ok(doc) = Automerge::load(&fixture("64bit_obj_id_change.automerge")) {
1525
+ let map_id = doc.get(ROOT, "a").unwrap().unwrap().1;
1526
+ assert!(map_id != ROOT)
1527
+ }
1528
+
1529
+ // this fixture is the same as the above, but as a document chunk.
1530
+ if let Ok(doc) = Automerge::load(&fixture("64bit_obj_id_doc.automerge")) {
1531
+ let map_id = doc.get(ROOT, "a").unwrap().unwrap().1;
1532
+ assert!(map_id != ROOT)
1533
+ }
1534
+ }
1535
+
1536
+ #[test]
1537
+ fn bad_change_on_optree_node_boundary() {
1538
+ let mut doc = Automerge::new();
1539
+ doc.transact::<_, _, AutomergeError>(|d| {
1540
+ d.put(ROOT, "a", "z")?;
1541
+ d.put(ROOT, "b", 0)?;
1542
+ d.put(ROOT, "c", 0)?;
1543
+ Ok(())
1544
+ })
1545
+ .unwrap();
1546
+ let iterations = 15_u64;
1547
+ for i in 0_u64..iterations {
1548
+ doc.transact::<_, _, AutomergeError>(|d| {
1549
+ let s = "a".repeat(i as usize);
1550
+ d.put(ROOT, "a", s)?;
1551
+ d.put(ROOT, "b", i + 1)?;
1552
+ d.put(ROOT, "c", i + 1)?;
1553
+ Ok(())
1554
+ })
1555
+ .unwrap();
1556
+ }
1557
+ let mut doc2 = Automerge::load(doc.save().as_slice()).unwrap();
1558
+ doc.transact::<_, _, AutomergeError>(|d| {
1559
+ let i = iterations + 2;
1560
+ let s = "a".repeat(i as usize);
1561
+ d.put(ROOT, "a", s)?;
1562
+ d.put(ROOT, "b", i)?;
1563
+ d.put(ROOT, "c", i)?;
1564
+ Ok(())
1565
+ })
1566
+ .unwrap();
1567
+ let change = doc.get_changes(&doc2.get_heads());
1568
+ doc2.apply_changes(change.into_iter().collect::<Vec<_>>())
1569
+ .unwrap();
1570
+ Automerge::load(doc2.save().as_slice()).unwrap();
1571
+ }
1572
+
1573
+ #[test]
1574
+ fn regression_nth_miscount() {
1575
+ let mut doc = Automerge::new();
1576
+ doc.transact::<_, _, AutomergeError>(|d| {
1577
+ let list_id = d.put_object(ROOT, "listval", ObjType::List).unwrap();
1578
+ for i in 0..30 {
1579
+ d.insert(&list_id, i, ScalarValue::Null).unwrap();
1580
+ let map = d.put_object(&list_id, i, ObjType::Map).unwrap();
1581
+ d.put(map, "test", ScalarValue::Int(i.try_into().unwrap()))
1582
+ .unwrap();
1583
+ }
1584
+ Ok(())
1585
+ })
1586
+ .unwrap();
1587
+ for i in 0..30 {
1588
+ let (obj_type, list_id) = doc.get(ROOT, "listval").unwrap().unwrap();
1589
+ assert_eq!(obj_type, Value::Object(ObjType::List));
1590
+ let (obj_type, map_id) = doc.get(&list_id, i).unwrap().unwrap();
1591
+ assert_eq!(obj_type, Value::Object(ObjType::Map));
1592
+ let (obj_type, _) = doc.get(map_id, "test").unwrap().unwrap();
1593
+ assert_eq!(
1594
+ obj_type,
1595
+ Value::Scalar(std::borrow::Cow::Borrowed(&ScalarValue::Int(
1596
+ i.try_into().unwrap()
1597
+ )))
1598
+ )
1599
+ }
1600
+ }
1601
+
1602
+ #[test]
1603
+ fn regression_nth_miscount_smaller() {
1604
+ let mut doc = Automerge::new();
1605
+ doc.transact::<_, _, AutomergeError>(|d| {
1606
+ let list_id = d.put_object(ROOT, "listval", ObjType::List).unwrap();
1607
+ for i in 0..B * 4 {
1608
+ d.insert(&list_id, i, ScalarValue::Null).unwrap();
1609
+ d.put(&list_id, i, ScalarValue::Int(i.try_into().unwrap()))
1610
+ .unwrap();
1611
+ }
1612
+ Ok(())
1613
+ })
1614
+ .unwrap();
1615
+ for i in 0..B * 4 {
1616
+ let (obj_type, list_id) = doc.get(ROOT, "listval").unwrap().unwrap();
1617
+ assert_eq!(obj_type, Value::Object(ObjType::List));
1618
+ let (obj_type, _) = doc.get(list_id, i).unwrap().unwrap();
1619
+ assert_eq!(
1620
+ obj_type,
1621
+ Value::Scalar(std::borrow::Cow::Borrowed(&ScalarValue::Int(
1622
+ i.try_into().unwrap()
1623
+ )))
1624
+ )
1625
+ }
1626
+ }
1627
+
1628
+ #[test]
1629
+ fn regression_insert_opid() {
1630
+ let mut doc = Automerge::new();
1631
+ let mut tx = doc.transaction();
1632
+ let list_id = tx
1633
+ .put_object(&automerge::ROOT, "list", ObjType::List)
1634
+ .unwrap();
1635
+ tx.commit();
1636
+
1637
+ let change1 = doc.get_last_local_change().unwrap().clone();
1638
+ let mut tx = doc.transaction();
1639
+
1640
+ const N: usize = 30;
1641
+ for i in 0..=N {
1642
+ tx.insert(&list_id, i, ScalarValue::Null).unwrap();
1643
+ tx.put(&list_id, i, ScalarValue::Int(i as i64)).unwrap();
1644
+ }
1645
+ tx.commit();
1646
+
1647
+ let change2 = doc.get_last_local_change().unwrap().clone();
1648
+ let mut new_doc = Automerge::new();
1649
+ let mut patch_log = PatchLog::active();
1650
+ new_doc
1651
+ .apply_changes_log_patches(vec![change1], &mut patch_log)
1652
+ .unwrap();
1653
+ new_doc
1654
+ .apply_changes_log_patches(vec![change2], &mut patch_log)
1655
+ .unwrap();
1656
+
1657
+ for i in 0..=N {
1658
+ let (doc_val, _) = doc.get(&list_id, i).unwrap().unwrap();
1659
+ let (new_doc_val, _) = new_doc.get(&list_id, i).unwrap().unwrap();
1660
+
1661
+ assert_eq!(
1662
+ doc_val,
1663
+ Value::Scalar(std::borrow::Cow::Owned(ScalarValue::Int(i as i64)))
1664
+ );
1665
+ assert_eq!(
1666
+ new_doc_val,
1667
+ Value::Scalar(std::borrow::Cow::Owned(ScalarValue::Int(i as i64)))
1668
+ );
1669
+ }
1670
+
1671
+ let patches = new_doc.make_patches(&mut patch_log);
1672
+ let mut values = SequenceTree::new();
1673
+ for i in 0..=N {
1674
+ values.push((
1675
+ Value::Scalar(std::borrow::Cow::Owned(ScalarValue::Int(i as i64))),
1676
+ ObjId::Id((2 * (i + 1) + 1) as u64, doc.get_actor().clone(), 0),
1677
+ false,
1678
+ ));
1679
+ }
1680
+ let expected_patches = vec![
1681
+ Patch {
1682
+ obj: ROOT,
1683
+ path: vec![],
1684
+ action: PatchAction::PutMap {
1685
+ key: "list".to_string(),
1686
+ value: (
1687
+ Value::Object(ObjType::List),
1688
+ ObjId::Id(1, doc.get_actor().clone(), 0),
1689
+ ),
1690
+ conflict: false,
1691
+ },
1692
+ },
1693
+ Patch {
1694
+ obj: ObjId::Id(1, doc.get_actor().clone(), 0),
1695
+ path: vec![(ROOT, Prop::Map("list".into()))],
1696
+ action: PatchAction::Insert { index: 0, values },
1697
+ },
1698
+ ];
1699
+ assert_eq!(patches, expected_patches);
1700
+ }
1701
+
1702
+ #[test]
1703
+ fn big_list() {
1704
+ let mut doc = Automerge::new();
1705
+ let mut tx = doc.transaction();
1706
+ let list_id = tx.put_object(&ROOT, "list", ObjType::List).unwrap();
1707
+ tx.commit();
1708
+
1709
+ let change1 = doc.get_last_local_change().unwrap().clone();
1710
+ let mut tx = doc.transaction();
1711
+
1712
+ const N: usize = B;
1713
+ for i in 0..=N {
1714
+ tx.insert(&list_id, i, ScalarValue::Null).unwrap();
1715
+ }
1716
+ for i in 0..=N {
1717
+ tx.put_object(&list_id, i, ObjType::Map).unwrap();
1718
+ }
1719
+ tx.commit();
1720
+
1721
+ let change2 = doc.get_last_local_change().unwrap().clone();
1722
+ let mut new_doc = Automerge::new();
1723
+ let mut patch_log = PatchLog::active();
1724
+ new_doc
1725
+ .apply_changes_log_patches(vec![change1], &mut patch_log)
1726
+ .unwrap();
1727
+ new_doc
1728
+ .apply_changes_log_patches(vec![change2], &mut patch_log)
1729
+ .unwrap();
1730
+
1731
+ let patches = new_doc.make_patches(&mut patch_log);
1732
+ println!("PATCH = {:?}", patches.last());
1733
+ let matches = match &patches.last().unwrap().action {
1734
+ PatchAction::PutSeq { index: N, .. } => true,
1735
+ PatchAction::Insert { index: 0, values } if values.len() == N + 1 => true,
1736
+ _ => false,
1737
+ };
1738
+ assert!(matches);
1739
+ }
1740
+
1741
+ #[test]
1742
+ fn marks() {
1743
+ let mut doc = Automerge::new();
1744
+ let mut tx = doc.transaction();
1745
+
1746
+ let text_id = tx.put_object(&ROOT, "text", ObjType::Text).unwrap();
1747
+
1748
+ tx.splice_text(&text_id, 0, 0, "hello world").unwrap();
1749
+
1750
+ let mark = Mark::new("bold".to_string(), true, 0, "hello".len());
1751
+ tx.mark(&text_id, mark, ExpandMark::Both).unwrap();
1752
+
1753
+ // add " cool" (it will be bold because ExpandMark::Both)
1754
+ tx.splice_text(&text_id, "hello".len(), 0, " cool").unwrap();
1755
+
1756
+ // unbold "hello"
1757
+ tx.unmark(&text_id, "bold", 0, "hello".len(), ExpandMark::Before)
1758
+ .unwrap();
1759
+
1760
+ // insert "why " before hello.
1761
+ tx.splice_text(&text_id, 0, 0, "why ").unwrap();
1762
+
1763
+ let marks = tx.marks(&text_id).unwrap();
1764
+
1765
+ assert_eq!(marks[0].start, 9);
1766
+ assert_eq!(marks[0].end, 14);
1767
+ assert_eq!(marks[0].name(), "bold");
1768
+ assert_eq!(marks[0].value(), &ScalarValue::from(true));
1769
+ }
1770
+
1771
+ #[test]
1772
+ fn can_transaction_at() -> Result<(), AutomergeError> {
1773
+ let mut doc1 = Automerge::new();
1774
+ let mut tx = doc1.transaction();
1775
+ let txt = tx.put_object(&ROOT, "text", ObjType::Text).unwrap();
1776
+ tx.put(&ROOT, "size", 100).unwrap();
1777
+ tx.splice_text(&txt, 0, 0, "aaabbbccc")?;
1778
+ tx.commit();
1779
+ let heads1 = doc1.get_heads();
1780
+ let mut tx = doc1.transaction();
1781
+ assert_eq!(tx.text(&txt).unwrap(), "aaabbbccc");
1782
+ assert_eq!(tx.get(&ROOT, "size").unwrap().unwrap().0, Value::int(100));
1783
+ tx.splice_text(&txt, 3, 3, "QQQ")?;
1784
+ tx.put(&ROOT, "size", 200)?;
1785
+ assert_eq!(tx.text(&txt).unwrap(), "aaaQQQccc");
1786
+ assert_eq!(tx.get(&ROOT, "size").unwrap().unwrap().0, Value::int(200));
1787
+ tx.commit();
1788
+
1789
+ let mut tx = doc1.transaction_at(PatchLog::null(), &heads1)?;
1790
+ assert_eq!(tx.text(&txt).unwrap(), "aaabbbccc");
1791
+ assert_eq!(tx.get(&ROOT, "size").unwrap().unwrap().0, Value::int(100));
1792
+ tx.splice_text(&txt, 3, 3, "ZZZ")?;
1793
+ tx.put(&ROOT, "size", 300)?;
1794
+ assert_eq!(tx.text(&txt).unwrap(), "aaaZZZccc");
1795
+ assert_eq!(tx.get(&ROOT, "size").unwrap().unwrap().0, Value::int(300));
1796
+ tx.commit();
1797
+ assert_eq!(doc1.text(&txt).unwrap(), "aaaZZZQQQccc");
1798
+ assert_eq!(doc1.get(&ROOT, "size").unwrap().unwrap().0, Value::int(300));
1799
+
1800
+ let mut tx = doc1.transaction_at(PatchLog::null(), &heads1)?;
1801
+ assert_eq!(tx.text(&txt).unwrap(), "aaabbbccc");
1802
+ assert_eq!(tx.get(&ROOT, "size").unwrap().unwrap().0, Value::int(100));
1803
+ tx.splice_text(&txt, 3, 3, "TTT")?;
1804
+ tx.put(&ROOT, "size", 400)?;
1805
+ assert_eq!(tx.text(&txt).unwrap(), "aaaTTTccc");
1806
+ assert_eq!(tx.get(&ROOT, "size").unwrap().unwrap().0, Value::int(400));
1807
+ tx.commit();
1808
+ assert_eq!(doc1.text(&txt).unwrap(), "aaaTTTZZZQQQccc");
1809
+ assert_eq!(doc1.get(&ROOT, "size").unwrap().unwrap().0, Value::int(400));
1810
+ Ok(())
1811
+ }
1812
+
1813
+ #[test]
1814
+ fn can_isolate() -> Result<(), AutomergeError> {
1815
+ let mut doc1 = AutoCommit::new();
1816
+ let txt = doc1.put_object(&ROOT, "text", ObjType::Text).unwrap();
1817
+ doc1.put(&ROOT, "size", 100).unwrap();
1818
+ doc1.splice_text(&txt, 0, 0, "aaabbbccc")?;
1819
+ let heads1 = doc1.get_heads();
1820
+ doc1.put(&ROOT, "size", 150)?;
1821
+
1822
+ doc1.isolate(&heads1);
1823
+
1824
+ let mut doc2 = doc1.fork();
1825
+ doc2.put(&ROOT, "other", 999)?;
1826
+ doc2.splice_text(&txt, 9, 0, "111")?;
1827
+
1828
+ assert_eq!(doc1.text(&txt).unwrap(), "aaabbbccc");
1829
+ assert_eq!(doc1.get(&ROOT, "size").unwrap().unwrap().0, Value::int(100));
1830
+ doc1.splice_text(&txt, 3, 3, "QQQ")?;
1831
+ println!("---- A ");
1832
+ doc1.put(&ROOT, "size", 200)?;
1833
+ println!("---- N ");
1834
+ assert_eq!(doc1.text(&txt).unwrap(), "aaaQQQccc");
1835
+ assert_eq!(doc1.get(&ROOT, "size").unwrap().unwrap().0, Value::int(200));
1836
+
1837
+ let heads2 = doc1.get_heads();
1838
+ assert_eq!(doc1.text(&txt).unwrap(), "aaaQQQccc");
1839
+
1840
+ doc1.merge(&mut doc2)?;
1841
+ assert_eq!(doc1.get(&ROOT, "size").unwrap().unwrap().0, Value::int(200));
1842
+ assert_eq!(doc1.get(&ROOT, "other").unwrap(), None);
1843
+
1844
+ doc1.isolate(&heads1);
1845
+
1846
+ assert_ne!(heads1, heads2);
1847
+
1848
+ assert_eq!(doc1.text(&txt).unwrap(), "aaabbbccc");
1849
+ assert_eq!(doc1.get(&ROOT, "size").unwrap().unwrap().0, Value::int(100));
1850
+ doc1.splice_text(&txt, 3, 3, "ZZZ")?;
1851
+ doc1.put(&ROOT, "size", 300)?;
1852
+ assert_eq!(doc1.text(&txt).unwrap(), "aaaZZZccc");
1853
+ assert_eq!(doc1.get(&ROOT, "size").unwrap().unwrap().0, Value::int(300));
1854
+
1855
+ let _heads3 = doc1.get_heads(); // commit
1856
+ assert_eq!(doc1.text(&txt).unwrap(), "aaaZZZccc");
1857
+
1858
+ doc1.integrate();
1859
+ assert_eq!(doc1.text(&txt).unwrap(), "aaaZZZQQQccc111");
1860
+ assert_eq!(
1861
+ doc1.get(&ROOT, "other").unwrap().unwrap().0,
1862
+ Value::int(999)
1863
+ );
1864
+
1865
+ doc1.isolate(&heads1);
1866
+
1867
+ assert_eq!(doc1.text(&txt).unwrap(), "aaabbbccc");
1868
+ assert_eq!(doc1.get(&ROOT, "size").unwrap().unwrap().0, Value::int(100));
1869
+ doc1.splice_text(&txt, 3, 3, "TTT")?;
1870
+ doc1.put(&ROOT, "size", 400)?;
1871
+ assert_eq!(doc1.text(&txt).unwrap(), "aaaTTTccc");
1872
+ assert_eq!(doc1.get(&ROOT, "size").unwrap().unwrap().0, Value::int(400));
1873
+
1874
+ let _heads4 = doc1.get_heads(); // commit
1875
+ assert_eq!(doc1.text(&txt).unwrap(), "aaaTTTccc");
1876
+ doc1.integrate();
1877
+
1878
+ assert_eq!(doc1.text(&txt).unwrap(), "aaaTTTZZZQQQccc111");
1879
+ assert_eq!(doc1.get(&ROOT, "size").unwrap().unwrap().0, Value::int(400));
1880
+ Ok(())
1881
+ }
1882
+
1883
+ #[test]
1884
+ fn inserting_text_near_deleted_marks() {
1885
+ let mut doc = Automerge::new();
1886
+ let mut tx = doc.transaction();
1887
+ let text_id = tx.put_object(&ROOT, "text", ObjType::Text).unwrap();
1888
+ tx.splice_text(&text_id, 0, 0, "hello world").unwrap();
1889
+ let mark = Mark::new("bold".to_string(), true, 2, 8);
1890
+ tx.mark(&text_id, mark, ExpandMark::After).unwrap();
1891
+ let mark = Mark::new("link".to_string(), true, 3, 6);
1892
+ tx.mark(&text_id, mark, ExpandMark::None).unwrap();
1893
+
1894
+ tx.splice_text(&text_id, 1, 10, "").unwrap(); // 'h'
1895
+ dbg!(tx.text(&text_id).unwrap(), tx.marks(&text_id).unwrap());
1896
+ tx.splice_text(&text_id, 0, 0, "a").unwrap(); // 'ah'
1897
+ dbg!(tx.text(&text_id).unwrap(), tx.marks(&text_id).unwrap());
1898
+ tx.splice_text(&text_id, 2, 0, "a").unwrap(); // 'ah<bold>a</bold>'
1899
+ dbg!(tx.text(&text_id).unwrap(), tx.marks(&text_id).unwrap());
1900
+ }
1901
+
1902
+ #[test]
1903
+ fn test_load_incremental_partial_load() {
1904
+ let mut doc = Automerge::new();
1905
+
1906
+ let mut tx = doc.transaction();
1907
+ tx.put(&ROOT, "a", 1).unwrap();
1908
+ tx.commit();
1909
+
1910
+ let start_heads = doc.get_heads();
1911
+ let mut tx = doc.transaction();
1912
+ tx.put(&ROOT, "b", 2).unwrap();
1913
+ tx.commit();
1914
+
1915
+ let changes = doc.get_changes(&start_heads);
1916
+
1917
+ let encoded = changes.into_iter().fold(Vec::new(), |mut acc, mut change| {
1918
+ acc.extend_from_slice(change.bytes().as_ref());
1919
+ acc
1920
+ });
1921
+
1922
+ let mut doc2 = Automerge::new();
1923
+ doc2.load_incremental(&encoded).unwrap();
1924
+ }
1925
+
1926
+ #[test]
1927
+ fn test_get_change_meta() {
1928
+ let mut doc = Automerge::new();
1929
+
1930
+ let mut tx = doc.transaction();
1931
+ tx.put(&ROOT, "a", 1).unwrap();
1932
+ tx.commit();
1933
+
1934
+ let start_heads = doc.get_heads();
1935
+ let mut tx = doc.transaction();
1936
+ tx.put(&ROOT, "b", 2).unwrap();
1937
+ tx.commit();
1938
+
1939
+ let changes = doc.get_changes_meta(&start_heads);
1940
+
1941
+ assert_eq!(changes.len(), 1);
1942
+ assert_eq!(*changes[0].actor, *doc.get_actor());
1943
+ assert_eq!(changes[0].seq, 2);
1944
+ }
1945
+
1946
+ #[test]
1947
+ fn get_marks_at_heads() {
1948
+ let mut doc = Automerge::new();
1949
+ let mut tx = doc.transaction();
1950
+ let text_id = tx.put_object(&ROOT, "text", ObjType::Text).unwrap();
1951
+ tx.splice_text(&text_id, 0, 0, "hello world").unwrap();
1952
+ let mark = Mark::new("bold".to_string(), true, 0, 10);
1953
+ tx.mark(&text_id, mark, ExpandMark::After).unwrap();
1954
+ tx.commit();
1955
+
1956
+ let heads = doc.get_heads();
1957
+
1958
+ let mut tx = doc.transaction();
1959
+ tx.mark(
1960
+ &text_id,
1961
+ Mark::new("bold".to_string(), ScalarValue::Null, 0, 10),
1962
+ ExpandMark::None,
1963
+ )
1964
+ .unwrap();
1965
+ let mark_map = tx.get_marks(&text_id, 1, Some(&heads)).unwrap();
1966
+ assert_eq!(mark_map.len(), 1);
1967
+ let (mark_name, mark_value) = mark_map.iter().next().unwrap();
1968
+ assert_eq!(mark_name, "bold");
1969
+ assert_eq!(mark_value, &ScalarValue::Boolean(true));
1970
+
1971
+ tx.commit();
1972
+
1973
+ let mark_map = doc.get_marks(&text_id, 1, Some(&heads)).unwrap();
1974
+ assert_eq!(mark_map.len(), 1);
1975
+ let (mark_name, mark_value) = mark_map.iter().next().unwrap();
1976
+ assert_eq!(mark_name, "bold");
1977
+ assert_eq!(mark_value, &ScalarValue::Boolean(true));
1978
+ }
1979
+
1980
+ /*
1981
+ #[test]
1982
+ fn conflicting_unicode_text_with_different_widths() -> Result<(), AutomergeError> {
1983
+ let mut doc1 = AutoCommit::new();
1984
+ let txt = doc1.put_object(&ROOT, "text", ObjType::Text).unwrap();
1985
+ doc1.splice_text(&txt, 0, 0, "abc")?;
1986
+
1987
+ let mut doc2 = doc1.fork();
1988
+
1989
+ doc1.put(&txt, 1, "B")?;
1990
+ doc2.put(&txt, 1, "🐻")?;
1991
+
1992
+ assert_eq!(doc1.length(&txt), 3);
1993
+ assert_eq!(doc2.length(&txt), 4);
1994
+
1995
+ doc1.merge(&mut doc2)?;
1996
+ doc2.merge(&mut doc1)?;
1997
+
1998
+ let length = doc1.length(&txt);
1999
+ let last_value = doc1.get(&txt, length - 1)?;
2000
+ for n in 0..length {
2001
+ assert_eq!(doc1.get(&txt, n), doc2.get(&txt, n));
2002
+ }
2003
+ assert_eq!(last_value.unwrap().0, Value::from("c"));
2004
+
2005
+ println!("list.len() == {:?}", length);
2006
+ assert_eq!(doc1.length(&txt), doc2.length(&txt));
2007
+ Ok(())
2008
+ }
2009
+ */
2010
+
2011
+ #[test]
2012
+ fn rollback_with_no_ops() {
2013
+ let mut doc = Automerge::new();
2014
+
2015
+ doc.transact::<_, _, AutomergeError>(|tx| {
2016
+ tx.put(ROOT, "a", 1)?;
2017
+ Ok::<_, AutomergeError>(())
2018
+ })
2019
+ .unwrap();
2020
+
2021
+ let mut doc2 = doc.fork();
2022
+
2023
+ let tx = doc2.transaction();
2024
+ tx.commit();
2025
+
2026
+ let mut doc3 = doc.fork();
2027
+ doc3.transact::<_, _, AutomergeError>(|tx| {
2028
+ tx.put(ROOT, "b", 2)?;
2029
+ Ok::<_, AutomergeError>(())
2030
+ })
2031
+ .unwrap();
2032
+
2033
+ doc2.merge(&mut doc3).unwrap();
2034
+
2035
+ let tx = doc2.transaction();
2036
+ tx.rollback();
2037
+ }
2038
+
2039
+ #[test]
2040
+ fn rollback_with_several_actors() {
2041
+ let mut doc1 = AutoCommit::new().with_actor("aaaaaa".try_into().unwrap());
2042
+ let text = doc1.put_object(&ROOT, "text", ObjType::Text).unwrap();
2043
+ doc1.splice_text(&text, 0, 0, "the sly fox jumped over the lazy dog")
2044
+ .unwrap();
2045
+ let map_a = doc1.put_object(&ROOT, "map_a", ObjType::Map).unwrap();
2046
+ doc1.put(&map_a, "key1", "value1a").unwrap();
2047
+ doc1.put(&map_a, "key2", "value2a").unwrap();
2048
+
2049
+ let mut doc2 = doc1.fork().with_actor("cccccc".try_into().unwrap());
2050
+ doc2.splice_text(&text, 8, 3, "monkey").unwrap();
2051
+ doc2.splice_text(&text, 36, 3, "pig").unwrap();
2052
+ let map_c = doc2.put_object(&ROOT, "map_c", ObjType::Map).unwrap();
2053
+ doc2.put(&map_a, "key2", "value2c").unwrap();
2054
+ doc2.put(&map_a, "key3", "value3c").unwrap();
2055
+ doc2.put(&map_c, "key1", "value").unwrap();
2056
+
2057
+ let mut doc3 = doc2.fork().with_actor("bbbbbb".try_into().unwrap());
2058
+ doc3.splice_text(&text, 8, 5, "zebra").unwrap();
2059
+ let map_b = doc3.put_object(&ROOT, "map_b", ObjType::Map).unwrap();
2060
+ doc3.put(&map_a, "key1", "value3b").unwrap();
2061
+ doc3.put(&map_a, "key3", "value3b").unwrap();
2062
+ doc3.put(&map_b, "key1", "value").unwrap();
2063
+ doc3.rollback();
2064
+
2065
+ assert_eq!(doc3.save(), doc2.save());
2066
+ }
2067
+
2068
+ #[test]
2069
+ fn save_with_ops_which_reference_actors_only_via_delete() {
2070
+ let mut doc = Automerge::new();
2071
+
2072
+ doc.transact::<_, _, AutomergeError>(|tx| {
2073
+ tx.put(ROOT, "a", 1)?;
2074
+ Ok::<_, AutomergeError>(())
2075
+ })
2076
+ .unwrap();
2077
+
2078
+ let mut forked = doc.fork();
2079
+ forked
2080
+ .transact::<_, _, AutomergeError>(|tx| {
2081
+ tx.delete(ROOT, "a")?;
2082
+ Ok::<_, AutomergeError>(())
2083
+ })
2084
+ .unwrap();
2085
+
2086
+ doc.merge(&mut forked).unwrap();
2087
+
2088
+ // `doc` now contains a delete op which uses the actor of the fork. Delete
2089
+ // ops don't exist explicitly in the document ops, they are referenced in
2090
+ // the "successors" of the encoded ops. This means that when we're encoding
2091
+ // actor IDs into the document we need to check that any actor IDs which
2092
+ // are referenced in the `successors` of an op are encoded as well.
2093
+
2094
+ let saved = doc.save();
2095
+ // This will panic if we failed to encode the referenced actor ID
2096
+ let _ = Automerge::load(&saved).unwrap();
2097
+ }
2098
+
2099
+ #[test]
2100
+ fn save_with_empty_commits() {
2101
+ let mut doc = Automerge::new();
2102
+
2103
+ doc.transact::<_, _, AutomergeError>(|tx| {
2104
+ tx.put(ROOT, "a", 1)?;
2105
+ Ok::<_, AutomergeError>(())
2106
+ })
2107
+ .unwrap();
2108
+
2109
+ let mut forked = doc.fork();
2110
+ forked.empty_commit(CommitOptions::default());
2111
+
2112
+ doc.merge(&mut forked).unwrap();
2113
+
2114
+ let saved = doc.save();
2115
+ // This will panic if we failed to encode the referenced actor ID
2116
+ let _ = Automerge::load(&saved).unwrap();
2117
+ }
2118
+
2119
+ #[test]
2120
+ fn large_patches_in_lists_are_correct() {
2121
+ // Reproduces a bug caused by an incorrect use of ListEncoding in Automerge::live_obj_paths.
2122
+ // This is a function which precalculates the path of every visible object in the document.
2123
+ // The problem was that when calculating the index into a sequence it was using
2124
+ // ListEncoding::List to determine the index, which meant that when a string was inserted into
2125
+ // a list then the index of elements following the list was based on the number of elements in
2126
+ // the string, when it should just increase the index by one for the whole string.
2127
+ //
2128
+ // This bug was a little tricky to track down because it was only triggered by an optimization
2129
+ // which kicks in when there are > 100 patches to render.
2130
+
2131
+ let mut doc = Automerge::new();
2132
+ let heads_before = doc.get_heads();
2133
+ let list = doc
2134
+ .transact::<_, _, AutomergeError>(|tx| {
2135
+ let list = tx.put_object(ROOT, "list", ObjType::List)?;
2136
+ // This should just count as one
2137
+ tx.insert(&list, 0, "123456")?;
2138
+ for i in 1..501 {
2139
+ let inner = tx.insert_object(&list, i, ObjType::Map)?;
2140
+ tx.put(&inner, "a", i as i64)?;
2141
+ }
2142
+ Ok(list)
2143
+ })
2144
+ .unwrap()
2145
+ .result;
2146
+ let heads_after = doc.get_heads();
2147
+ let patches = doc.diff(&heads_before, &heads_after);
2148
+ let final_patch = patches.last().unwrap();
2149
+ assert_eq!(
2150
+ final_patch.path,
2151
+ vec![
2152
+ (ROOT, Prop::Map("list".into())),
2153
+ (list, Prop::Seq(500)) // In the buggy code this was incorrectly coming out as 505 due to
2154
+ // the counting of "123456" as 6 elements rather than 1
2155
+ ]
2156
+ );
2157
+ let PatchAction::PutMap { .. } = &final_patch.action else {
2158
+ panic!("Expected PutMap, got {:?}", final_patch.action);
2159
+ };
2160
+ }
2161
+
2162
+ #[test]
2163
+ fn diff_should_reverse_deletion_of_object_in_list_correctly() {
2164
+ let mut doc = AutoCommit::new();
2165
+ let list = doc.put_object(ROOT, "list", ObjType::List).unwrap();
2166
+ doc.insert(&list, 0, "a").unwrap();
2167
+ let text = doc
2168
+ .insert_object(&list, 1, automerge::ObjType::Text)
2169
+ .unwrap();
2170
+ doc.splice_text(&text, 0, 0, "b").unwrap();
2171
+ doc.insert(&list, 2, "c").unwrap();
2172
+
2173
+ let heads_before = doc.get_heads();
2174
+ doc.delete(&list, 1).unwrap();
2175
+ let heads_after = doc.get_heads();
2176
+
2177
+ doc.update_diff_cursor();
2178
+ let patches = doc.diff(&heads_after, &heads_before);
2179
+
2180
+ assert_eq!(patches.len(), 2);
2181
+ let patch = patches[0].clone();
2182
+ let PatchAction::Insert { index, values } = &patch.action else {
2183
+ panic!("Expected Insert, got {:?}", patch.action);
2184
+ };
2185
+ assert_eq!(*index, 1);
2186
+ assert_eq!(values.len(), 1);
2187
+ let (value, _, _) = values.into_iter().next().unwrap();
2188
+ assert_eq!(value, &Value::Object(ObjType::Text));
2189
+
2190
+ let patch = patches[1].clone();
2191
+ let PatchAction::SpliceText { index, value, .. } = patch.action else {
2192
+ panic!("Expected SpliceText, got {:?}", patch.action);
2193
+ };
2194
+ assert_eq!(index, 0);
2195
+ assert_eq!(value.make_string(), "b");
2196
+ }
2197
+
2198
+ #[test]
2199
+ fn diff_should_reverse_deletion_of_object_in_map_correctly() {
2200
+ let mut doc = AutoCommit::new();
2201
+
2202
+ let map = doc.put_object(ROOT, "map", ObjType::Map).unwrap();
2203
+ doc.put_object(&map, "text", ObjType::Text).unwrap();
2204
+
2205
+ doc.put(&map, "a", "a").unwrap();
2206
+ let text = doc.put_object(&map, "b", automerge::ObjType::Text).unwrap();
2207
+ doc.splice_text(&text, 0, 0, "b").unwrap();
2208
+ doc.put(&map, "c", "c").unwrap();
2209
+
2210
+ let heads_before = doc.get_heads();
2211
+ doc.delete(&map, "b").unwrap();
2212
+ let heads_after = doc.get_heads();
2213
+
2214
+ doc.update_diff_cursor();
2215
+ let patches = doc.diff(&heads_after, &heads_before);
2216
+
2217
+ assert_eq!(patches.len(), 2);
2218
+ let patch = patches[0].clone();
2219
+ let PatchAction::PutMap { key, value, .. } = &patch.action else {
2220
+ panic!("Expected putmap, got {:?}", patch.action);
2221
+ };
2222
+ assert_eq!(key, "b");
2223
+ assert_eq!(value.0, Value::Object(ObjType::Text));
2224
+
2225
+ let patch = patches[1].clone();
2226
+ let PatchAction::SpliceText { index, value, .. } = patch.action else {
2227
+ panic!("Expected SpliceText, got {:?}", patch.action);
2228
+ };
2229
+ assert_eq!(index, 0);
2230
+ assert_eq!(value.make_string(), "b");
2231
+ }
2232
+
2233
+ #[test]
2234
+ fn diff_should_reverse_deletion_of_block_in_text_correctly() {
2235
+ let mut doc = AutoCommit::new();
2236
+ let text = doc.put_object(ROOT, "text", ObjType::Text).unwrap();
2237
+ doc.splice_text(&text, 0, 0, "a").unwrap();
2238
+ let block = doc.split_block(&text, 1).unwrap();
2239
+ doc.splice_text(&text, 2, 0, "b").unwrap();
2240
+ doc.put(&block, "key", "value").unwrap();
2241
+
2242
+ let heads_before = doc.get_heads();
2243
+ doc.delete(&text, 1).unwrap();
2244
+ let heads_after = doc.get_heads();
2245
+
2246
+ doc.update_diff_cursor();
2247
+ let patches = doc.diff(&heads_after, &heads_before);
2248
+
2249
+ assert_eq!(patches.len(), 2);
2250
+ let patch = patches[0].clone();
2251
+ let PatchAction::Insert { index, values } = &patch.action else {
2252
+ panic!("Expected Insert, got {:?}", patch.action);
2253
+ };
2254
+ assert_eq!(*index, 1);
2255
+ assert_eq!(values.len(), 1);
2256
+ let (value, _, _) = values.into_iter().next().unwrap();
2257
+ assert_eq!(value, &Value::Object(ObjType::Map));
2258
+
2259
+ let patch = patches[1].clone();
2260
+ let PatchAction::PutMap { key, value, .. } = patch.action else {
2261
+ panic!("Expected PutMap, got {:?}", patch.action);
2262
+ };
2263
+ assert_eq!(key, "key");
2264
+ let Value::Scalar(s) = value.0 else {
2265
+ panic!("Expected Scalar, got {:?}", value.0);
2266
+ };
2267
+ assert_eq!(s.as_ref(), &ScalarValue::Str("value".into()));
2268
+ }
2269
+
2270
+ #[test]
2271
+ fn missing_actors_when_docs_are_forked() {
2272
+ // Reproduces https://github.com/automerge/automerge/issues/897
2273
+ //
2274
+ // The problem was a result of these things interacting:
2275
+ //
2276
+ // 1. When we create a transaction we add the actor ID of the document
2277
+ // creating the transaction to the IndexedCache of actor IDs that
2278
+ // document stores
2279
+ // 2. When we fork a document we copy the IndexedCache from the source
2280
+ // document to the forked document
2281
+ // 3. When we save a document we must encode all the actor IDs in the saved
2282
+ // document in lexicographic order. To do this we first enumerate all
2283
+ // the actor IDs in the change graph and then encode this in the
2284
+ // document
2285
+ // 4. We assume that the IndexedCache of actor IDs on the document only
2286
+ // contains actor IDs which are in the change graph
2287
+ //
2288
+ // What can happen is that we create a new actor ID somehow (by forking or
2289
+ // loading). Then we create a transaction with the new actor ID but never
2290
+ // actually make any changes. Then, we create another actor ID in the
2291
+ // same document - by forking it typically. This means that this last
2292
+ // document has an IndexedCache with an actor ID in it which will never
2293
+ // be saved to the document, but which is followed by an actor ID which
2294
+ // will be saved. This in turn means that the indexes we save to the
2295
+ // document are off by one and so we get load errors.
2296
+ //
2297
+ // The solution was to create the lookup table from actor index to actor
2298
+ // ID directly from the actor IDs in the change graph rather than from the
2299
+ // IndexedCache.
2300
+ let actor0 = ActorId::from(&[0]);
2301
+ let actor1 = ActorId::from(&[1]);
2302
+ let actor2 = ActorId::from(&[2]);
2303
+
2304
+ let mut doc0 = AutoCommit::new().with_actor(actor0);
2305
+ doc0.put(ROOT, "a", 1).unwrap();
2306
+
2307
+ // swap these actors and no error occurs
2308
+ let mut doc1 = doc0.fork().with_actor(actor2);
2309
+ let mut doc2 = doc0.fork().with_actor(actor1);
2310
+
2311
+ doc1.put(ROOT, "b", 2).unwrap();
2312
+ doc2.merge(&mut doc1).unwrap();
2313
+
2314
+ let s1 = doc2.save();
2315
+
2316
+ // This call creates a transaction which doesn't do anything (because the
2317
+ // "c" key doesn't exist) and so the actor ID (actor1) gets added to the
2318
+ // IndexedCache of doc2
2319
+ doc2.delete(ROOT, "c").unwrap();
2320
+
2321
+ // error occurs here
2322
+ let s2 = doc2.save_and_verify().unwrap();
2323
+
2324
+ assert_eq!(s1, s2);
2325
+ }
2326
+
2327
+ #[test]
2328
+ fn allows_empty_keys_in_mappings() {
2329
+ let mut doc = AutoCommit::new();
2330
+ doc.put(&automerge::ROOT, "", 1).unwrap();
2331
+ assert_doc!(
2332
+ &doc,
2333
+ map! {
2334
+ "" => { 1 },
2335
+ }
2336
+ );
2337
+ }
2338
+
2339
+ #[test]
2340
+ fn has_our_changes() {
2341
+ let mut left = AutoCommit::new();
2342
+ left.put(&automerge::ROOT, "a", 1).unwrap();
2343
+
2344
+ let mut right = AutoCommit::new();
2345
+ right.put(&automerge::ROOT, "b", 2).unwrap();
2346
+
2347
+ let mut left_to_right = automerge::sync::State::new();
2348
+ let mut right_to_left = automerge::sync::State::new();
2349
+
2350
+ assert!(!left.has_our_changes(&left_to_right));
2351
+ assert!(!right.has_our_changes(&right_to_left));
2352
+
2353
+ while !left.has_our_changes(&left_to_right) || !right.has_our_changes(&right_to_left) {
2354
+ let mut quiet = true;
2355
+ if let Some(msg) = left.sync().generate_sync_message(&mut left_to_right) {
2356
+ quiet = false;
2357
+ right
2358
+ .sync()
2359
+ .receive_sync_message(&mut right_to_left, msg)
2360
+ .unwrap();
2361
+ }
2362
+ if let Some(msg) = right.sync().generate_sync_message(&mut right_to_left) {
2363
+ quiet = false;
2364
+ left.sync()
2365
+ .receive_sync_message(&mut left_to_right, msg)
2366
+ .unwrap();
2367
+ }
2368
+ if quiet {
2369
+ panic!("no messages sent but the sync state says we're not in sync");
2370
+ }
2371
+ }
2372
+ assert!(right.has_our_changes(&right_to_left));
2373
+ }
2374
+
2375
+ #[test]
2376
+ fn stats_smoke_test() {
2377
+ let mut doc = AutoCommit::new();
2378
+ doc.put(&automerge::ROOT, "a", 1).unwrap();
2379
+ doc.commit();
2380
+ doc.put(&automerge::ROOT, "b", 2).unwrap();
2381
+ doc.commit();
2382
+ let stats = doc.stats();
2383
+ assert_eq!(stats.num_changes, 2);
2384
+ assert_eq!(stats.num_ops, 2);
2385
+ }
2386
+
2387
+ #[test]
2388
+ fn invalid_index() {
2389
+ let mut doc = AutoCommit::new();
2390
+ let obj = doc
2391
+ .put_object(&automerge::ROOT, "a", ObjType::List)
2392
+ .unwrap();
2393
+ doc.insert(&obj, 0, 1).unwrap();
2394
+ doc.put(&obj, 0, 2).unwrap();
2395
+ assert_eq!(doc.get(&obj, 0).unwrap().unwrap().0, 2.into());
2396
+ assert_eq!(doc.insert(&obj, 2, 1), Err(AutomergeError::InvalidIndex(2)));
2397
+ assert_eq!(doc.put(&obj, 2, 2), Err(AutomergeError::InvalidIndex(2)));
2398
+ assert_eq!(
2399
+ doc.insert(&obj, 100, 1),
2400
+ Err(AutomergeError::InvalidIndex(100))
2401
+ );
2402
+ assert_eq!(
2403
+ doc.put(&obj, 100, 2),
2404
+ Err(AutomergeError::InvalidIndex(100))
2405
+ );
2406
+ }
2407
+
2408
+ #[test]
2409
+ fn zero_length_data() {
2410
+ let mut doc = AutoCommit::new();
2411
+ doc.put(&ROOT, "string", "").unwrap();
2412
+ doc.put(&ROOT, "bytes", vec![]).unwrap();
2413
+ doc.commit();
2414
+ assert_eq!(
2415
+ doc.get(&ROOT, "string").unwrap().unwrap().0,
2416
+ Value::from("")
2417
+ );
2418
+ assert_eq!(
2419
+ doc.get(&ROOT, "bytes").unwrap().unwrap().0,
2420
+ Value::from(vec![])
2421
+ );
2422
+ }
2423
+
2424
+ #[test]
2425
+ fn make_sure_load_incremental_doesnt_skip_a_load_with_a_common_head() {
2426
+ let mut doc1 = AutoCommit::new();
2427
+ doc1.put(&ROOT, "string", "hello").unwrap();
2428
+ let mut doc2 = doc1.fork();
2429
+ let mut doc3 = doc1.fork();
2430
+
2431
+ assert!(doc1.get_heads().len() == 1);
2432
+
2433
+ doc1.put(&ROOT, "concurrent1", "123").unwrap();
2434
+ assert!(doc1.get_heads().len() == 1);
2435
+ let hash_b = doc1.get_heads()[0];
2436
+
2437
+ doc3.load_incremental(&doc1.save()).unwrap();
2438
+ assert!(doc3.get_heads().len() == 1);
2439
+ let hash_c = doc3.get_heads()[0];
2440
+
2441
+ assert_eq!(hash_b, hash_c);
2442
+
2443
+ doc2.put(&ROOT, "concurrent2", "abc").unwrap();
2444
+ assert!(doc2.get_heads().len() == 1);
2445
+ let hash_d = doc2.get_heads()[0];
2446
+
2447
+ doc2.merge(&mut doc1).unwrap();
2448
+ let heads = doc2.get_heads();
2449
+
2450
+ assert!(heads.len() == 2);
2451
+ assert!(heads.contains(&hash_d));
2452
+ assert!(heads.contains(&hash_b));
2453
+
2454
+ doc3.load_incremental(&doc2.save()).unwrap();
2455
+
2456
+ assert!(doc3.get_heads() == doc2.get_heads());
2457
+ }
2458
+
2459
+ #[test]
2460
+ fn test_get_last_local_change_generation() {
2461
+ let mut doc = AutoCommit::new();
2462
+ let text = doc.put_object(&ROOT, "text", ObjType::Text).unwrap();
2463
+ doc.splice_text(&text, 0, 0, "hello world").unwrap();
2464
+ confirm_last_change(&mut doc);
2465
+ doc.splice_text(&text, 5, 1, "X").unwrap();
2466
+ confirm_last_change(&mut doc);
2467
+ doc.splice_text(&text, 6, 1, "").unwrap();
2468
+ confirm_last_change(&mut doc);
2469
+ doc.splice_text(&text, 0, 0, "ten thousand and five hundred")
2470
+ .unwrap();
2471
+ confirm_last_change(&mut doc);
2472
+ }
2473
+
2474
+ fn confirm_last_change(doc: &mut AutoCommit) {
2475
+ let heads = doc.get_heads();
2476
+ let change = doc.get_last_local_change().unwrap();
2477
+ assert_eq!(vec![change.hash()], heads);
2478
+ }
2479
+
2480
+ #[test]
2481
+ fn test_overwriting_a_conflict() {
2482
+ let mut doc1 = AutoCommit::new();
2483
+ let mut doc2 = doc1.fork();
2484
+
2485
+ // put the same values
2486
+ doc1.put(&ROOT, "key", "value").unwrap();
2487
+ doc2.put(&ROOT, "key", "value").unwrap();
2488
+ doc1.merge(&mut doc2).unwrap();
2489
+ doc2.merge(&mut doc1).unwrap();
2490
+
2491
+ assert_eq!(doc1.get_all(&ROOT, "key").unwrap().len(), 2);
2492
+ assert_eq!(doc2.get_all(&ROOT, "key").unwrap().len(), 2);
2493
+
2494
+ doc1.put(&ROOT, "key", "value").unwrap();
2495
+ doc2.put(&ROOT, "key", "value").unwrap();
2496
+ doc1.merge(&mut doc2).unwrap();
2497
+ doc2.merge(&mut doc1).unwrap();
2498
+
2499
+ assert_eq!(doc1.get_all(&ROOT, "key").unwrap().len(), 1);
2500
+ assert_eq!(doc2.get_all(&ROOT, "key").unwrap().len(), 1);
2501
+ }
2502
+
2503
+ #[test]
2504
+ fn get_changes_with_hash_of_empty_change_produces_correct_result() {
2505
+ // This test reproduces an issue where if you create an empty change, then
2506
+ // call Automerge::get_changes(&[hash_of_empty_change]) the result would
2507
+ // include the hash of the change just created but it should be empty. The
2508
+ // reason this happend was that `get_changes` works by walking the change
2509
+ // graph and combining all the (actor, seq) pairs to form a vector clock
2510
+ // which represents the ancestors which should be filtered out. The logic
2511
+ // which performed this walking combined clocks by comparing the `max_op` of
2512
+ // two changes, but in the case of an empty change the `max_op` didn't
2513
+ // change and this meant that the clock was not updated with the sequence
2514
+ // number of the empty change. This meant that the clock did not include the
2515
+ // empty change seq and so the empty change was not filtered out.
2516
+ let mut doc = AutoCommit::new();
2517
+ let head = doc.empty_change(CommitOptions::default());
2518
+ let changes = doc.get_changes(&[head]);
2519
+ assert!(changes.is_empty());
2520
+ }
2521
+
2522
+ #[test]
2523
+ fn reproduce_clock_cache_bug() {
2524
+ // This test exercises an issue with clock caching. The problem manifested
2525
+ // as two documents which have common history returning different results
2526
+ // for `Automerge::get_changes(&common_heads)` where `common_heads` is a
2527
+ // set of change hashes which are in both documents.
2528
+ // `Automerge::get_changes(&heads)` returns everything in a document which
2529
+ // is _not_ an ancestor of the heads specified. In two documents which
2530
+ // contain `heads`, `get_changes(&heads)` should therefore return the same
2531
+ // thing.
2532
+ //
2533
+ // In order to compute the ancestors of the common heads, automerge converts
2534
+ // the heads to a vector clock. Every commit in an Automerge document has an
2535
+ // (actor ID, sequence number) pair (a lamport timestamp) which identifies
2536
+ // the commit. We can walk the commit graph accumulating these pairs to form
2537
+ // a vector clock. This vector clock can then be used to determine if any
2538
+ // given commit is an ancestor of the given heads.
2539
+ //
2540
+ // E.g. imagine this graph where I denote the lamport timestamp as (actor
2541
+ // ID, sequence number):
2542
+ //
2543
+ // * (a, 1)
2544
+ // |
2545
+ // * (a, 2)
2546
+ // / \
2547
+ // / \
2548
+ // * (b, 1) * (c, 1)
2549
+ // \ /
2550
+ // \ /
2551
+ // * (d, 1)
2552
+ //
2553
+ // Then say we have the heads for (b, 1), we can walk from (b,1) to the root
2554
+ // and we will end up with a vector clock of [(a, 2), (b, 1)]. We can then
2555
+ // use this vector clock to determine that (b,1) is an ancestor of (a,1)
2556
+ // because the clock for (b,1) contains (a,2), which is greater than (a,1)
2557
+ //
2558
+ // Creating these clocks for large documents is expensive, so we cache
2559
+ // clocks for every 16 commits in the document. The problem this test
2560
+ // exposes is that the logic for the clock caching was incorrect. When
2561
+ // walking the graph, the cache logic could accidentally omit some
2562
+ // commits from the cached clock.
2563
+ //
2564
+ // The caching logic was expressed by starting with the end node and then
2565
+ // walking backwards in a depth first search until the cache limit is
2566
+ // reached, it looked something like this:
2567
+ //
2568
+ // let limit = CACHE_STEP * 2
2569
+ // let clock = new_clock()
2570
+ // let to_visit = [start node]
2571
+ // let visited = []
2572
+ // while let Some(node) = to_visit.pop() {
2573
+ // // Process node
2574
+ // if let Some(cached) = get_cache(node) {
2575
+ // merge(cached, clock)
2576
+ // } else if visited.len() <= limit {
2577
+ // to_visit.extend(parents_of(node))
2578
+ // } else {
2579
+ // break;
2580
+ // }
2581
+ // }
2582
+ //
2583
+ // The logic would then restart from the remaining nodes in the to_visit queue.
2584
+ //
2585
+ // The bug is that in some scenarios we would not add the parents of the
2586
+ // node which causes us to reach the cache limit to the to_visit queue.
2587
+ //
2588
+ // The easiest way to observe this bug is to create a document where there
2589
+ // is a commit which has a large number of parents (i.e. a merge commit
2590
+ // from many branches). E.g imagine a document like this:
2591
+ //
2592
+ // A
2593
+ // |
2594
+ // .--.--.--.--.--.--.--.--.
2595
+ // B C D E F G H I J
2596
+ // | | | | | | | | |
2597
+ // K L M N O P Q R S
2598
+ // '--'--'--'--'--'--'--'--'
2599
+ // |
2600
+ // T
2601
+ // |
2602
+ // U
2603
+ //
2604
+ // Now, let's say our CACHE_STEP is 3. Then every third change which is
2605
+ // applied is cached. U is the 21st change and so it will be cached. The
2606
+ // cache logic will now step backwards through the graph until 6 (CACHE_STEP
2607
+ // * 2) nodes have been visited, and then it will stop. In this case that
2608
+ // would mean that we add T to the list of nodes to visit, then pop it and
2609
+ // process it, adding all of T's parents to the list of nodes to visit.
2610
+ // Then we continue processing until we reach O so the final order is
2611
+ // T, K, L, M, N, O. Here's where the bug is, the cache logic now returns
2612
+ // and says "now keep going with the rest of the to_visit list", but it
2613
+ // didn't add the parents of O to the list and so F never gets processed.
2614
+ //
2615
+ // This is only a problem if F is a commit with a different actor ID then
2616
+ // O, otherwise the (actor_id, seq) if O covers F.
2617
+ //
2618
+ // So, to reproduce this error, we create a lot of branches, and on each
2619
+ // branch make a lot of commits - each commit with a different actor.
2620
+ // Then we merge the branches together and observe that `get_changes(&heads)`
2621
+ // returns empty. If the caching logic is incorrect the heads will be
2622
+ // converted into a clock which doesn't cover commits like F and then
2623
+ // `get_changes(&heads)` will be non empty.
2624
+
2625
+ let mut base = AutoCommit::new();
2626
+
2627
+ // Add some number of initial commits
2628
+ for i in 0..100 {
2629
+ base.put(ROOT, format!("initial_commit_{}", i), true)
2630
+ .unwrap();
2631
+ base.commit();
2632
+ }
2633
+
2634
+ const NUM_BRANCHES: usize = 20;
2635
+ const COMMITS_PER_BRANCH: usize = 2;
2636
+
2637
+ let mut branches = (0..NUM_BRANCHES - 1)
2638
+ .map(|_| base.fork())
2639
+ .collect::<Vec<_>>();
2640
+ branches.push(base);
2641
+
2642
+ for (branch_no, branch) in branches.iter_mut().enumerate() {
2643
+ for commit_no in 0..COMMITS_PER_BRANCH {
2644
+ branch
2645
+ .put(ROOT, format!("branch_{}-{}", branch_no, commit_no), true)
2646
+ .unwrap();
2647
+ branch.commit();
2648
+ // Make a new actor for the next commit
2649
+ *branch = branch.fork();
2650
+ }
2651
+ }
2652
+
2653
+ let mut base = branches.pop().unwrap();
2654
+
2655
+ for branch in &mut branches {
2656
+ base.merge(branch).unwrap();
2657
+ }
2658
+
2659
+ // Create a bunch of commits after the merge to ensure a clock is cached
2660
+ // between the document heads and the branches
2661
+ for i in 0..100 {
2662
+ base.put(ROOT, format!("after-merge-{}", i), true).unwrap();
2663
+ base.commit();
2664
+ }
2665
+ let heads = base.get_heads();
2666
+
2667
+ assert!(base.get_changes(&heads).is_empty());
2668
+ }