tigerbeetle 0.0.34 → 0.0.37
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/ext/tb_client/extconf.rb +13 -13
- data/ext/tb_client/tigerbeetle/LICENSE +177 -0
- data/ext/tb_client/tigerbeetle/build.zig +2327 -0
- data/ext/tb_client/tigerbeetle/src/aof.zig +1000 -0
- data/ext/tb_client/tigerbeetle/src/build_multiversion.zig +808 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp/protocol.zig +1283 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp/spec.zig +1704 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp/types.zig +341 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp.zig +1450 -0
- data/ext/tb_client/tigerbeetle/src/cdc/runner.zig +1659 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/samples/main.c +406 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/context.zig +1084 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/echo_client.zig +286 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/packet.zig +158 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal.zig +229 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal_fuzz.zig +110 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.h +386 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.zig +34 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_exports.zig +281 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header.zig +312 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header_test.zig +138 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/test.zig +466 -0
- data/ext/tb_client/tigerbeetle/src/clients/docs_samples.zig +157 -0
- data/ext/tb_client/tigerbeetle/src/clients/docs_types.zig +90 -0
- data/ext/tb_client/tigerbeetle/src/clients/dotnet/ci.zig +203 -0
- data/ext/tb_client/tigerbeetle/src/clients/dotnet/docs.zig +79 -0
- data/ext/tb_client/tigerbeetle/src/clients/dotnet/dotnet_bindings.zig +542 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/ci.zig +109 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/docs.zig +86 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/go_bindings.zig +370 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/pkg/native/tb_client.h +386 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/ci.zig +167 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/docs.zig +126 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/java_bindings.zig +996 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/client.zig +748 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/jni.zig +3238 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_tests.zig +1718 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_thread_cleaner.zig +190 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/ci.zig +104 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/docs.zig +75 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/node.zig +522 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/node_bindings.zig +267 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/src/c.zig +3 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/src/translate.zig +379 -0
- data/ext/tb_client/tigerbeetle/src/clients/python/ci.zig +131 -0
- data/ext/tb_client/tigerbeetle/src/clients/python/docs.zig +63 -0
- data/ext/tb_client/tigerbeetle/src/clients/python/python_bindings.zig +588 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/assets/tb_client.h +386 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/ci.zig +73 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/docs.zig +106 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/rust_bindings.zig +305 -0
- data/ext/tb_client/tigerbeetle/src/config.zig +296 -0
- data/ext/tb_client/tigerbeetle/src/constants.zig +790 -0
- data/ext/tb_client/tigerbeetle/src/copyhound.zig +202 -0
- data/ext/tb_client/tigerbeetle/src/counting_allocator.zig +72 -0
- data/ext/tb_client/tigerbeetle/src/direction.zig +11 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/build.zig +158 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/content.zig +156 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/docs.zig +252 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/file_checker.zig +313 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/html.zig +87 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/page_writer.zig +63 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/redirects.zig +47 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/search_index_writer.zig +28 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/service_worker_writer.zig +61 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/single_page_writer.zig +169 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/website.zig +46 -0
- data/ext/tb_client/tigerbeetle/src/ewah.zig +445 -0
- data/ext/tb_client/tigerbeetle/src/ewah_benchmark.zig +128 -0
- data/ext/tb_client/tigerbeetle/src/ewah_fuzz.zig +171 -0
- data/ext/tb_client/tigerbeetle/src/fuzz_tests.zig +179 -0
- data/ext/tb_client/tigerbeetle/src/integration_tests.zig +662 -0
- data/ext/tb_client/tigerbeetle/src/io/common.zig +155 -0
- data/ext/tb_client/tigerbeetle/src/io/darwin.zig +1093 -0
- data/ext/tb_client/tigerbeetle/src/io/linux.zig +1880 -0
- data/ext/tb_client/tigerbeetle/src/io/test.zig +1005 -0
- data/ext/tb_client/tigerbeetle/src/io/windows.zig +1598 -0
- data/ext/tb_client/tigerbeetle/src/io.zig +34 -0
- data/ext/tb_client/tigerbeetle/src/iops.zig +134 -0
- data/ext/tb_client/tigerbeetle/src/list.zig +236 -0
- data/ext/tb_client/tigerbeetle/src/lsm/binary_search.zig +848 -0
- data/ext/tb_client/tigerbeetle/src/lsm/binary_search_benchmark.zig +179 -0
- data/ext/tb_client/tigerbeetle/src/lsm/cache_map.zig +424 -0
- data/ext/tb_client/tigerbeetle/src/lsm/cache_map_fuzz.zig +420 -0
- data/ext/tb_client/tigerbeetle/src/lsm/compaction.zig +2117 -0
- data/ext/tb_client/tigerbeetle/src/lsm/composite_key.zig +182 -0
- data/ext/tb_client/tigerbeetle/src/lsm/forest.zig +1119 -0
- data/ext/tb_client/tigerbeetle/src/lsm/forest_fuzz.zig +1102 -0
- data/ext/tb_client/tigerbeetle/src/lsm/forest_table_iterator.zig +200 -0
- data/ext/tb_client/tigerbeetle/src/lsm/groove.zig +1495 -0
- data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge.zig +739 -0
- data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge_benchmark.zig +166 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest.zig +754 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_level.zig +1294 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_level_fuzz.zig +510 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_log.zig +1263 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_log_fuzz.zig +628 -0
- data/ext/tb_client/tigerbeetle/src/lsm/node_pool.zig +247 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_buffer.zig +116 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_builder.zig +543 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_fuzz.zig +938 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_lookup.zig +293 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_merge.zig +362 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_range.zig +99 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_state.zig +17 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_tree.zig +1036 -0
- data/ext/tb_client/tigerbeetle/src/lsm/schema.zig +617 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scratch_memory.zig +84 -0
- data/ext/tb_client/tigerbeetle/src/lsm/segmented_array.zig +1500 -0
- data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_benchmark.zig +149 -0
- data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_fuzz.zig +7 -0
- data/ext/tb_client/tigerbeetle/src/lsm/set_associative_cache.zig +865 -0
- data/ext/tb_client/tigerbeetle/src/lsm/table.zig +607 -0
- data/ext/tb_client/tigerbeetle/src/lsm/table_memory.zig +843 -0
- data/ext/tb_client/tigerbeetle/src/lsm/table_value_iterator.zig +105 -0
- data/ext/tb_client/tigerbeetle/src/lsm/timestamp_range.zig +40 -0
- data/ext/tb_client/tigerbeetle/src/lsm/tree.zig +630 -0
- data/ext/tb_client/tigerbeetle/src/lsm/tree_fuzz.zig +933 -0
- data/ext/tb_client/tigerbeetle/src/lsm/zig_zag_merge.zig +557 -0
- data/ext/tb_client/tigerbeetle/src/message_buffer.zig +469 -0
- data/ext/tb_client/tigerbeetle/src/message_bus.zig +1214 -0
- data/ext/tb_client/tigerbeetle/src/message_bus_fuzz.zig +936 -0
- data/ext/tb_client/tigerbeetle/src/message_pool.zig +343 -0
- data/ext/tb_client/tigerbeetle/src/multiversion.zig +2195 -0
- data/ext/tb_client/tigerbeetle/src/queue.zig +390 -0
- data/ext/tb_client/tigerbeetle/src/repl/completion.zig +201 -0
- data/ext/tb_client/tigerbeetle/src/repl/parser.zig +1356 -0
- data/ext/tb_client/tigerbeetle/src/repl/terminal.zig +496 -0
- data/ext/tb_client/tigerbeetle/src/repl.zig +1034 -0
- data/ext/tb_client/tigerbeetle/src/scripts/amqp.zig +973 -0
- data/ext/tb_client/tigerbeetle/src/scripts/cfo.zig +1866 -0
- data/ext/tb_client/tigerbeetle/src/scripts/changelog.zig +304 -0
- data/ext/tb_client/tigerbeetle/src/scripts/ci.zig +227 -0
- data/ext/tb_client/tigerbeetle/src/scripts/client_readmes.zig +658 -0
- data/ext/tb_client/tigerbeetle/src/scripts/devhub.zig +466 -0
- data/ext/tb_client/tigerbeetle/src/scripts/release.zig +1058 -0
- data/ext/tb_client/tigerbeetle/src/scripts.zig +105 -0
- data/ext/tb_client/tigerbeetle/src/shell.zig +1195 -0
- data/ext/tb_client/tigerbeetle/src/stack.zig +260 -0
- data/ext/tb_client/tigerbeetle/src/state_machine/auditor.zig +911 -0
- data/ext/tb_client/tigerbeetle/src/state_machine/workload.zig +2079 -0
- data/ext/tb_client/tigerbeetle/src/state_machine.zig +4872 -0
- data/ext/tb_client/tigerbeetle/src/state_machine_fuzz.zig +288 -0
- data/ext/tb_client/tigerbeetle/src/state_machine_tests.zig +3128 -0
- data/ext/tb_client/tigerbeetle/src/static_allocator.zig +82 -0
- data/ext/tb_client/tigerbeetle/src/stdx/bit_set.zig +157 -0
- data/ext/tb_client/tigerbeetle/src/stdx/bounded_array.zig +292 -0
- data/ext/tb_client/tigerbeetle/src/stdx/debug.zig +65 -0
- data/ext/tb_client/tigerbeetle/src/stdx/flags.zig +1414 -0
- data/ext/tb_client/tigerbeetle/src/stdx/mlock.zig +92 -0
- data/ext/tb_client/tigerbeetle/src/stdx/prng.zig +677 -0
- data/ext/tb_client/tigerbeetle/src/stdx/radix.zig +336 -0
- data/ext/tb_client/tigerbeetle/src/stdx/ring_buffer.zig +511 -0
- data/ext/tb_client/tigerbeetle/src/stdx/sort_test.zig +112 -0
- data/ext/tb_client/tigerbeetle/src/stdx/stdx.zig +1160 -0
- data/ext/tb_client/tigerbeetle/src/stdx/testing/low_level_hash_vectors.zig +142 -0
- data/ext/tb_client/tigerbeetle/src/stdx/testing/snaptest.zig +361 -0
- data/ext/tb_client/tigerbeetle/src/stdx/time_units.zig +275 -0
- data/ext/tb_client/tigerbeetle/src/stdx/unshare.zig +295 -0
- data/ext/tb_client/tigerbeetle/src/stdx/vendored/aegis.zig +436 -0
- data/ext/tb_client/tigerbeetle/src/stdx/windows.zig +48 -0
- data/ext/tb_client/tigerbeetle/src/stdx/zipfian.zig +402 -0
- data/ext/tb_client/tigerbeetle/src/storage.zig +489 -0
- data/ext/tb_client/tigerbeetle/src/storage_fuzz.zig +180 -0
- data/ext/tb_client/tigerbeetle/src/testing/bench.zig +146 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/grid_checker.zig +53 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/journal_checker.zig +61 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/manifest_checker.zig +76 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/message_bus.zig +110 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/network.zig +412 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/state_checker.zig +331 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/storage_checker.zig +458 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster.zig +1198 -0
- data/ext/tb_client/tigerbeetle/src/testing/exhaustigen.zig +128 -0
- data/ext/tb_client/tigerbeetle/src/testing/fixtures.zig +181 -0
- data/ext/tb_client/tigerbeetle/src/testing/fuzz.zig +144 -0
- data/ext/tb_client/tigerbeetle/src/testing/id.zig +97 -0
- data/ext/tb_client/tigerbeetle/src/testing/io.zig +317 -0
- data/ext/tb_client/tigerbeetle/src/testing/marks.zig +126 -0
- data/ext/tb_client/tigerbeetle/src/testing/packet_simulator.zig +533 -0
- data/ext/tb_client/tigerbeetle/src/testing/reply_sequence.zig +154 -0
- data/ext/tb_client/tigerbeetle/src/testing/state_machine.zig +389 -0
- data/ext/tb_client/tigerbeetle/src/testing/storage.zig +1247 -0
- data/ext/tb_client/tigerbeetle/src/testing/table.zig +249 -0
- data/ext/tb_client/tigerbeetle/src/testing/time.zig +98 -0
- data/ext/tb_client/tigerbeetle/src/testing/tmp_tigerbeetle.zig +212 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/constants.zig +26 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/faulty_network.zig +580 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/java_driver/ci.zig +39 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/logged_process.zig +214 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/rust_driver/ci.zig +34 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/supervisor.zig +766 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/workload.zig +543 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/zig_driver.zig +181 -0
- data/ext/tb_client/tigerbeetle/src/tidy.zig +1448 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_driver.zig +227 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_load.zig +1069 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/cli.zig +1422 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect.zig +1658 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect_integrity.zig +518 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/libtb_client.zig +36 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/main.zig +646 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle.zig +958 -0
- data/ext/tb_client/tigerbeetle/src/time.zig +236 -0
- data/ext/tb_client/tigerbeetle/src/trace/event.zig +745 -0
- data/ext/tb_client/tigerbeetle/src/trace/statsd.zig +462 -0
- data/ext/tb_client/tigerbeetle/src/trace.zig +556 -0
- data/ext/tb_client/tigerbeetle/src/unit_tests.zig +321 -0
- data/ext/tb_client/tigerbeetle/src/vopr.zig +1785 -0
- data/ext/tb_client/tigerbeetle/src/vortex.zig +101 -0
- data/ext/tb_client/tigerbeetle/src/vsr/checkpoint_trailer.zig +473 -0
- data/ext/tb_client/tigerbeetle/src/vsr/checksum.zig +208 -0
- data/ext/tb_client/tigerbeetle/src/vsr/checksum_benchmark.zig +43 -0
- data/ext/tb_client/tigerbeetle/src/vsr/client.zig +768 -0
- data/ext/tb_client/tigerbeetle/src/vsr/client_replies.zig +532 -0
- data/ext/tb_client/tigerbeetle/src/vsr/client_sessions.zig +338 -0
- data/ext/tb_client/tigerbeetle/src/vsr/clock.zig +1019 -0
- data/ext/tb_client/tigerbeetle/src/vsr/fault_detector.zig +279 -0
- data/ext/tb_client/tigerbeetle/src/vsr/free_set.zig +1381 -0
- data/ext/tb_client/tigerbeetle/src/vsr/free_set_fuzz.zig +315 -0
- data/ext/tb_client/tigerbeetle/src/vsr/grid.zig +1460 -0
- data/ext/tb_client/tigerbeetle/src/vsr/grid_blocks_missing.zig +757 -0
- data/ext/tb_client/tigerbeetle/src/vsr/grid_scrubber.zig +797 -0
- data/ext/tb_client/tigerbeetle/src/vsr/journal.zig +2586 -0
- data/ext/tb_client/tigerbeetle/src/vsr/marzullo.zig +308 -0
- data/ext/tb_client/tigerbeetle/src/vsr/message_header.zig +1777 -0
- data/ext/tb_client/tigerbeetle/src/vsr/multi_batch.zig +715 -0
- data/ext/tb_client/tigerbeetle/src/vsr/multi_batch_fuzz.zig +185 -0
- data/ext/tb_client/tigerbeetle/src/vsr/repair_budget.zig +333 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica.zig +12355 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica_format.zig +416 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica_reformat.zig +165 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica_test.zig +2910 -0
- data/ext/tb_client/tigerbeetle/src/vsr/routing.zig +1075 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock.zig +1603 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock_fuzz.zig +484 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums.zig +405 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +355 -0
- data/ext/tb_client/tigerbeetle/src/vsr/sync.zig +29 -0
- data/ext/tb_client/tigerbeetle/src/vsr.zig +1727 -0
- data/lib/tb_client/shared_lib.rb +12 -5
- data/lib/tigerbeetle/client.rb +1 -1
- data/lib/tigerbeetle/platforms.rb +9 -0
- data/lib/tigerbeetle/version.rb +2 -2
- data/tigerbeetle.gemspec +22 -5
- metadata +242 -3
- data/ext/tb_client/pkg.tar.gz +0 -0
|
@@ -0,0 +1,3128 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
const assert = std.debug.assert;
|
|
3
|
+
const math = std.math;
|
|
4
|
+
const mem = std.mem;
|
|
5
|
+
|
|
6
|
+
const stdx = @import("stdx");
|
|
7
|
+
const maybe = stdx.maybe;
|
|
8
|
+
|
|
9
|
+
const tb = @import("tigerbeetle.zig");
|
|
10
|
+
const vsr = @import("vsr.zig");
|
|
11
|
+
const constants = vsr.constants;
|
|
12
|
+
|
|
13
|
+
const MultiBatchEncoder = vsr.multi_batch.MultiBatchEncoder;
|
|
14
|
+
const MultiBatchDecoder = vsr.multi_batch.MultiBatchDecoder;
|
|
15
|
+
|
|
16
|
+
const TimestampRange = @import("lsm/timestamp_range.zig").TimestampRange;
|
|
17
|
+
|
|
18
|
+
const Account = tb.Account;
|
|
19
|
+
const AccountBalance = tb.AccountBalance;
|
|
20
|
+
const Transfer = tb.Transfer;
|
|
21
|
+
const CreateAccountsResult = tb.CreateAccountsResult;
|
|
22
|
+
const CreateTransfersResult = tb.CreateTransfersResult;
|
|
23
|
+
|
|
24
|
+
const CreateAccountResult = tb.CreateAccountResult;
|
|
25
|
+
const CreateTransferResult = tb.CreateTransferResult;
|
|
26
|
+
|
|
27
|
+
const AccountFilter = tb.AccountFilter;
|
|
28
|
+
const QueryFilter = tb.QueryFilter;
|
|
29
|
+
const ChangeEventsFilter = tb.ChangeEventsFilter;
|
|
30
|
+
const ChangeEvent = tb.ChangeEvent;
|
|
31
|
+
const ChangeEventType = tb.ChangeEventType;
|
|
32
|
+
|
|
33
|
+
const StateMachineType = @import("state_machine.zig").StateMachineType;
|
|
34
|
+
|
|
35
|
+
const testing = std.testing;
|
|
36
|
+
|
|
37
|
+
pub const TestContext = struct {
|
|
38
|
+
const TimeSim = @import("testing/time.zig").TimeSim;
|
|
39
|
+
const Storage = @import("testing/storage.zig").Storage;
|
|
40
|
+
const Tracer = Storage.Tracer;
|
|
41
|
+
const data_file_size_min = @import("vsr/superblock.zig").data_file_size_min;
|
|
42
|
+
const SuperBlock = @import("vsr/superblock.zig").SuperBlockType(Storage);
|
|
43
|
+
const Grid = @import("vsr/grid.zig").GridType(Storage);
|
|
44
|
+
const fixtures = @import("testing/fixtures.zig");
|
|
45
|
+
|
|
46
|
+
pub const StateMachine = StateMachineType(Storage);
|
|
47
|
+
|
|
48
|
+
pub const Operation = enum {
|
|
49
|
+
create_accounts,
|
|
50
|
+
create_transfers,
|
|
51
|
+
lookup_accounts,
|
|
52
|
+
lookup_transfers,
|
|
53
|
+
get_account_transfers,
|
|
54
|
+
get_account_balances,
|
|
55
|
+
query_accounts,
|
|
56
|
+
query_transfers,
|
|
57
|
+
get_change_events,
|
|
58
|
+
|
|
59
|
+
const VersionMap = std.EnumArray(Operation, StateMachine.Operation);
|
|
60
|
+
/// Variations of operations supported by the state machine,
|
|
61
|
+
/// including deprecated ones used by old clients.
|
|
62
|
+
const versions: []const VersionMap = &.{
|
|
63
|
+
.init(.{
|
|
64
|
+
.create_accounts = .create_accounts,
|
|
65
|
+
.create_transfers = .create_transfers,
|
|
66
|
+
.lookup_accounts = .lookup_accounts,
|
|
67
|
+
.lookup_transfers = .lookup_transfers,
|
|
68
|
+
.get_account_transfers = .get_account_transfers,
|
|
69
|
+
.get_account_balances = .get_account_balances,
|
|
70
|
+
.query_accounts = .query_accounts,
|
|
71
|
+
.query_transfers = .query_transfers,
|
|
72
|
+
.get_change_events = .get_change_events,
|
|
73
|
+
}),
|
|
74
|
+
.init(.{
|
|
75
|
+
.create_accounts = .deprecated_create_accounts_unbatched,
|
|
76
|
+
.create_transfers = .deprecated_create_transfers_unbatched,
|
|
77
|
+
.lookup_accounts = .deprecated_lookup_accounts_unbatched,
|
|
78
|
+
.lookup_transfers = .deprecated_lookup_transfers_unbatched,
|
|
79
|
+
.get_account_transfers = .deprecated_get_account_transfers_unbatched,
|
|
80
|
+
.get_account_balances = .deprecated_get_account_balances_unbatched,
|
|
81
|
+
.query_accounts = .deprecated_query_accounts_unbatched,
|
|
82
|
+
.query_transfers = .deprecated_query_transfers_unbatched,
|
|
83
|
+
.get_change_events = .get_change_events,
|
|
84
|
+
}),
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
storage: Storage,
|
|
89
|
+
time_sim: TimeSim,
|
|
90
|
+
trace: Tracer,
|
|
91
|
+
superblock: SuperBlock,
|
|
92
|
+
grid: Grid,
|
|
93
|
+
state_machine: StateMachine,
|
|
94
|
+
op: u64,
|
|
95
|
+
busy: bool,
|
|
96
|
+
|
|
97
|
+
pub fn init(ctx: *TestContext, allocator: mem.Allocator) !void {
|
|
98
|
+
ctx.storage = try fixtures.init_storage(allocator, .{ .size = 4096 });
|
|
99
|
+
errdefer ctx.storage.deinit(allocator);
|
|
100
|
+
|
|
101
|
+
ctx.time_sim = fixtures.init_time(.{});
|
|
102
|
+
|
|
103
|
+
ctx.trace = try fixtures.init_tracer(allocator, ctx.time_sim.time(), .{});
|
|
104
|
+
errdefer ctx.trace.deinit(allocator);
|
|
105
|
+
|
|
106
|
+
ctx.superblock = try fixtures.init_superblock(allocator, &ctx.storage, .{
|
|
107
|
+
.storage_size_limit = data_file_size_min,
|
|
108
|
+
});
|
|
109
|
+
errdefer ctx.superblock.deinit(allocator);
|
|
110
|
+
|
|
111
|
+
// Pretend that the superblock is open so that the Forest can initialize.
|
|
112
|
+
ctx.superblock.opened = true;
|
|
113
|
+
ctx.superblock.working.vsr_state.checkpoint.header.op = 0;
|
|
114
|
+
|
|
115
|
+
ctx.grid = try fixtures.init_grid(allocator, &ctx.trace, &ctx.superblock, .{});
|
|
116
|
+
errdefer ctx.grid.deinit(allocator);
|
|
117
|
+
|
|
118
|
+
const batch_size_limit = 30 * @max(@sizeOf(Account), @sizeOf(Transfer));
|
|
119
|
+
assert(batch_size_limit <= constants.message_body_size_max);
|
|
120
|
+
try ctx.state_machine.init(
|
|
121
|
+
allocator,
|
|
122
|
+
ctx.time_sim.time(),
|
|
123
|
+
&ctx.grid,
|
|
124
|
+
.{
|
|
125
|
+
.batch_size_limit = batch_size_limit,
|
|
126
|
+
.lsm_forest_compaction_block_count = StateMachine.Forest.Options
|
|
127
|
+
.compaction_block_count_min,
|
|
128
|
+
.lsm_forest_node_count = 1,
|
|
129
|
+
.cache_entries_accounts = 0,
|
|
130
|
+
.cache_entries_transfers = 0,
|
|
131
|
+
.cache_entries_transfers_pending = 0,
|
|
132
|
+
.log_trace = true,
|
|
133
|
+
.aof_recovery = false,
|
|
134
|
+
},
|
|
135
|
+
);
|
|
136
|
+
errdefer ctx.state_machine.deinit(allocator);
|
|
137
|
+
// Usually, `pulse_next_timestamp` starts in an unknown state, signaling that the state
|
|
138
|
+
// machine needs a `pulse` to scan for pending transfers and correctly determine when to
|
|
139
|
+
// process the next expiry. However, this initial `pulse` unnecessarily bumps time, making
|
|
140
|
+
// unit tests that depend on the `timestamp` harder to reason about.
|
|
141
|
+
//
|
|
142
|
+
// Since this is a newly created state machine, we can bypass the initial check, ensuring
|
|
143
|
+
// that there will be no `timestamp` bumps between operations unless actual pending
|
|
144
|
+
// transfers get expired.
|
|
145
|
+
ctx.state_machine.expire_pending_transfers
|
|
146
|
+
.pulse_next_timestamp = TimestampRange.timestamp_max;
|
|
147
|
+
|
|
148
|
+
ctx.op = 1;
|
|
149
|
+
ctx.busy = false;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
pub fn deinit(ctx: *TestContext, allocator: mem.Allocator) void {
|
|
153
|
+
ctx.state_machine.deinit(allocator);
|
|
154
|
+
ctx.grid.deinit(allocator);
|
|
155
|
+
ctx.superblock.deinit(allocator);
|
|
156
|
+
ctx.trace.deinit(allocator);
|
|
157
|
+
ctx.storage.deinit(allocator);
|
|
158
|
+
ctx.* = undefined;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
fn callback(state_machine: *StateMachine) void {
|
|
162
|
+
const ctx: *TestContext = @fieldParentPtr("state_machine", state_machine);
|
|
163
|
+
assert(ctx.busy);
|
|
164
|
+
ctx.busy = false;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
fn submit(
|
|
168
|
+
context: *TestContext,
|
|
169
|
+
operation: TestContext.StateMachine.Operation,
|
|
170
|
+
input_buffer: []align(16) u8,
|
|
171
|
+
input_size: u32,
|
|
172
|
+
output_buffer: *align(16) [constants.message_body_size_max]u8,
|
|
173
|
+
) []const u8 {
|
|
174
|
+
const message_body: []align(16) const u8 = message_body: {
|
|
175
|
+
if (!operation.is_multi_batch()) {
|
|
176
|
+
break :message_body input_buffer[0..input_size];
|
|
177
|
+
}
|
|
178
|
+
assert(operation.is_multi_batch());
|
|
179
|
+
const event_size = operation.event_size();
|
|
180
|
+
var body_encoder = MultiBatchEncoder.init(input_buffer, .{
|
|
181
|
+
.element_size = event_size,
|
|
182
|
+
});
|
|
183
|
+
body_encoder.add(input_size);
|
|
184
|
+
const bytes_written = body_encoder.finish();
|
|
185
|
+
assert(bytes_written > 0);
|
|
186
|
+
break :message_body input_buffer[0..bytes_written];
|
|
187
|
+
};
|
|
188
|
+
context.prepare(operation, message_body);
|
|
189
|
+
|
|
190
|
+
const pulse_needed = context.state_machine.pulse_needed(
|
|
191
|
+
context.state_machine.prepare_timestamp,
|
|
192
|
+
);
|
|
193
|
+
maybe(pulse_needed);
|
|
194
|
+
// Pulse is executed in a best-effort manner
|
|
195
|
+
// after committing the current pipelined operation.
|
|
196
|
+
defer if (pulse_needed) context.pulse();
|
|
197
|
+
|
|
198
|
+
const reply_actual_size = context.execute(
|
|
199
|
+
context.op,
|
|
200
|
+
operation,
|
|
201
|
+
message_body,
|
|
202
|
+
output_buffer,
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
if (!operation.is_multi_batch()) {
|
|
206
|
+
return output_buffer[0..reply_actual_size];
|
|
207
|
+
}
|
|
208
|
+
assert(operation.is_multi_batch());
|
|
209
|
+
|
|
210
|
+
const result_size = operation.result_size();
|
|
211
|
+
var reply_decoder = MultiBatchDecoder.init(
|
|
212
|
+
output_buffer[0..reply_actual_size],
|
|
213
|
+
.{ .element_size = result_size },
|
|
214
|
+
) catch unreachable;
|
|
215
|
+
assert(reply_decoder.batch_count() == 1);
|
|
216
|
+
return reply_decoder.peek();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
pub fn prepare(
|
|
220
|
+
context: *TestContext,
|
|
221
|
+
operation: TestContext.StateMachine.Operation,
|
|
222
|
+
message_body_used: []align(16) const u8,
|
|
223
|
+
) void {
|
|
224
|
+
context.state_machine.commit_timestamp = context.state_machine.prepare_timestamp;
|
|
225
|
+
context.state_machine.prepare_timestamp += 1;
|
|
226
|
+
context.state_machine.prepare(
|
|
227
|
+
operation,
|
|
228
|
+
message_body_used,
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
fn pulse(context: *TestContext) void {
|
|
233
|
+
if (context.state_machine.pulse_needed(context.state_machine.prepare_timestamp)) {
|
|
234
|
+
const operation = vsr.Operation.pulse.cast(TestContext.StateMachine.Operation);
|
|
235
|
+
context.prepare(operation, &.{});
|
|
236
|
+
const pulse_size = context.execute(
|
|
237
|
+
context.op,
|
|
238
|
+
operation,
|
|
239
|
+
&.{},
|
|
240
|
+
undefined, // Output is never used for pulse.
|
|
241
|
+
);
|
|
242
|
+
assert(pulse_size == 0);
|
|
243
|
+
context.op += 1;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
pub fn execute(
|
|
248
|
+
context: *TestContext,
|
|
249
|
+
op: u64,
|
|
250
|
+
operation: TestContext.StateMachine.Operation,
|
|
251
|
+
message_body_used: []align(16) const u8,
|
|
252
|
+
output_buffer: *align(16) [constants.message_body_size_max]u8,
|
|
253
|
+
) usize {
|
|
254
|
+
const timestamp = context.state_machine.prepare_timestamp;
|
|
255
|
+
context.busy = true;
|
|
256
|
+
context.state_machine.prefetch_timestamp = timestamp;
|
|
257
|
+
context.state_machine.prefetch(
|
|
258
|
+
TestContext.callback,
|
|
259
|
+
op,
|
|
260
|
+
op,
|
|
261
|
+
operation,
|
|
262
|
+
message_body_used,
|
|
263
|
+
);
|
|
264
|
+
while (context.busy) context.storage.run();
|
|
265
|
+
|
|
266
|
+
return context.state_machine.commit(
|
|
267
|
+
1,
|
|
268
|
+
op,
|
|
269
|
+
timestamp,
|
|
270
|
+
operation,
|
|
271
|
+
message_body_used,
|
|
272
|
+
output_buffer,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
fn get_account_from_cache(context: *TestContext, id: u128) ?Account {
|
|
277
|
+
return switch (context.state_machine.forest.grooves.accounts.get(id)) {
|
|
278
|
+
.found_object => |a| a,
|
|
279
|
+
.found_orphaned_id => unreachable,
|
|
280
|
+
.not_found => null,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const TestAction = union(enum) {
|
|
286
|
+
// Set the account's balance.
|
|
287
|
+
setup: struct {
|
|
288
|
+
account: u128,
|
|
289
|
+
debits_pending: u128,
|
|
290
|
+
debits_posted: u128,
|
|
291
|
+
credits_pending: u128,
|
|
292
|
+
credits_posted: u128,
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
tick: struct {
|
|
296
|
+
value: i64,
|
|
297
|
+
unit: enum { nanoseconds, seconds },
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
commit: TestContext.Operation,
|
|
301
|
+
account: TestCreateAccount,
|
|
302
|
+
transfer: TestCreateTransfer,
|
|
303
|
+
|
|
304
|
+
lookup_account: struct {
|
|
305
|
+
id: u128,
|
|
306
|
+
data: ?struct {
|
|
307
|
+
debits_pending: u128,
|
|
308
|
+
debits_posted: u128,
|
|
309
|
+
credits_pending: u128,
|
|
310
|
+
credits_posted: u128,
|
|
311
|
+
flag_closed: ?enum { CLSD } = null,
|
|
312
|
+
} = null,
|
|
313
|
+
},
|
|
314
|
+
lookup_transfer: struct {
|
|
315
|
+
id: u128,
|
|
316
|
+
data: union(enum) {
|
|
317
|
+
exists: bool,
|
|
318
|
+
amount: u128,
|
|
319
|
+
timestamp: u64,
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
|
|
323
|
+
get_account_balances: TestGetAccountBalances,
|
|
324
|
+
get_account_balances_result: struct {
|
|
325
|
+
transfer_id: u128,
|
|
326
|
+
debits_pending: u128,
|
|
327
|
+
debits_posted: u128,
|
|
328
|
+
credits_pending: u128,
|
|
329
|
+
credits_posted: u128,
|
|
330
|
+
},
|
|
331
|
+
|
|
332
|
+
get_account_transfers: TestGetAccountTransfers,
|
|
333
|
+
get_account_transfers_result: u128,
|
|
334
|
+
|
|
335
|
+
query_accounts: TestQueryAccounts,
|
|
336
|
+
query_accounts_result: struct {
|
|
337
|
+
id: u128,
|
|
338
|
+
data: ?struct {
|
|
339
|
+
debits_pending: u128,
|
|
340
|
+
debits_posted: u128,
|
|
341
|
+
credits_pending: u128,
|
|
342
|
+
credits_posted: u128,
|
|
343
|
+
flag_closed: ?enum { CLSD } = null,
|
|
344
|
+
} = null,
|
|
345
|
+
},
|
|
346
|
+
|
|
347
|
+
query_transfers: TestQueryTransfers,
|
|
348
|
+
query_transfers_result: u128,
|
|
349
|
+
|
|
350
|
+
get_change_events: TestGetChangeEventsFilter,
|
|
351
|
+
get_change_events_result: TestGetChangeEventsResult,
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
const TestCreateAccount = struct {
|
|
355
|
+
id: u128,
|
|
356
|
+
debits_pending: u128 = 0,
|
|
357
|
+
debits_posted: u128 = 0,
|
|
358
|
+
credits_pending: u128 = 0,
|
|
359
|
+
credits_posted: u128 = 0,
|
|
360
|
+
user_data_128: u128 = 0,
|
|
361
|
+
user_data_64: u64 = 0,
|
|
362
|
+
user_data_32: u32 = 0,
|
|
363
|
+
reserved: u1 = 0,
|
|
364
|
+
ledger: u32,
|
|
365
|
+
code: u16,
|
|
366
|
+
flags_linked: ?enum { LNK } = null,
|
|
367
|
+
flags_debits_must_not_exceed_credits: ?enum { @"D<C" } = null,
|
|
368
|
+
flags_credits_must_not_exceed_debits: ?enum { @"C<D" } = null,
|
|
369
|
+
flags_history: ?enum { HIST } = null,
|
|
370
|
+
flags_imported: ?enum { IMP } = null,
|
|
371
|
+
flags_closed: ?enum { CLSD } = null,
|
|
372
|
+
flags_padding: u10 = 0,
|
|
373
|
+
timestamp: u64 = 0,
|
|
374
|
+
result: CreateAccountResult,
|
|
375
|
+
|
|
376
|
+
fn event(a: TestCreateAccount) Account {
|
|
377
|
+
return .{
|
|
378
|
+
.id = a.id,
|
|
379
|
+
.debits_pending = a.debits_pending,
|
|
380
|
+
.debits_posted = a.debits_posted,
|
|
381
|
+
.credits_pending = a.credits_pending,
|
|
382
|
+
.credits_posted = a.credits_posted,
|
|
383
|
+
.user_data_128 = a.user_data_128,
|
|
384
|
+
.user_data_64 = a.user_data_64,
|
|
385
|
+
.user_data_32 = a.user_data_32,
|
|
386
|
+
.reserved = a.reserved,
|
|
387
|
+
.ledger = a.ledger,
|
|
388
|
+
.code = a.code,
|
|
389
|
+
.flags = .{
|
|
390
|
+
.linked = a.flags_linked != null,
|
|
391
|
+
.debits_must_not_exceed_credits = a.flags_debits_must_not_exceed_credits != null,
|
|
392
|
+
.credits_must_not_exceed_debits = a.flags_credits_must_not_exceed_debits != null,
|
|
393
|
+
.history = a.flags_history != null,
|
|
394
|
+
.imported = a.flags_imported != null,
|
|
395
|
+
.closed = a.flags_closed != null,
|
|
396
|
+
.padding = a.flags_padding,
|
|
397
|
+
},
|
|
398
|
+
.timestamp = a.timestamp,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
const TestCreateTransfer = struct {
|
|
404
|
+
id: u128,
|
|
405
|
+
debit_account_id: u128,
|
|
406
|
+
credit_account_id: u128,
|
|
407
|
+
amount: u128 = 0,
|
|
408
|
+
pending_id: u128 = 0,
|
|
409
|
+
user_data_128: u128 = 0,
|
|
410
|
+
user_data_64: u64 = 0,
|
|
411
|
+
user_data_32: u32 = 0,
|
|
412
|
+
timeout: u32 = 0,
|
|
413
|
+
ledger: u32,
|
|
414
|
+
code: u16,
|
|
415
|
+
flags_linked: ?enum { LNK } = null,
|
|
416
|
+
flags_pending: ?enum { PEN } = null,
|
|
417
|
+
flags_post_pending_transfer: ?enum { POS } = null,
|
|
418
|
+
flags_void_pending_transfer: ?enum { VOI } = null,
|
|
419
|
+
flags_balancing_debit: ?enum { BDR } = null,
|
|
420
|
+
flags_balancing_credit: ?enum { BCR } = null,
|
|
421
|
+
flags_imported: ?enum { IMP } = null,
|
|
422
|
+
flags_closing_debit: ?enum { CDR } = null,
|
|
423
|
+
flags_closing_credit: ?enum { CCR } = null,
|
|
424
|
+
flags_padding: u5 = 0,
|
|
425
|
+
timestamp: u64 = 0,
|
|
426
|
+
result: CreateTransferResult,
|
|
427
|
+
|
|
428
|
+
fn event(t: TestCreateTransfer) Transfer {
|
|
429
|
+
return .{
|
|
430
|
+
.id = t.id,
|
|
431
|
+
.debit_account_id = t.debit_account_id,
|
|
432
|
+
.credit_account_id = t.credit_account_id,
|
|
433
|
+
.amount = t.amount,
|
|
434
|
+
.pending_id = t.pending_id,
|
|
435
|
+
.user_data_128 = t.user_data_128,
|
|
436
|
+
.user_data_64 = t.user_data_64,
|
|
437
|
+
.user_data_32 = t.user_data_32,
|
|
438
|
+
.timeout = t.timeout,
|
|
439
|
+
.ledger = t.ledger,
|
|
440
|
+
.code = t.code,
|
|
441
|
+
.flags = .{
|
|
442
|
+
.linked = t.flags_linked != null,
|
|
443
|
+
.pending = t.flags_pending != null,
|
|
444
|
+
.post_pending_transfer = t.flags_post_pending_transfer != null,
|
|
445
|
+
.void_pending_transfer = t.flags_void_pending_transfer != null,
|
|
446
|
+
.balancing_debit = t.flags_balancing_debit != null,
|
|
447
|
+
.balancing_credit = t.flags_balancing_credit != null,
|
|
448
|
+
.imported = t.flags_imported != null,
|
|
449
|
+
.closing_debit = t.flags_closing_debit != null,
|
|
450
|
+
.closing_credit = t.flags_closing_credit != null,
|
|
451
|
+
.padding = t.flags_padding,
|
|
452
|
+
},
|
|
453
|
+
.timestamp = t.timestamp,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
const TestAccountFilter = struct {
|
|
459
|
+
account_id: u128,
|
|
460
|
+
user_data_128: ?u128 = null,
|
|
461
|
+
user_data_64: ?u64 = null,
|
|
462
|
+
user_data_32: ?u32 = null,
|
|
463
|
+
code: ?u16 = null,
|
|
464
|
+
// When non-null, the filter is set to the timestamp at which the specified transfer (by id) was
|
|
465
|
+
// created.
|
|
466
|
+
timestamp_min_transfer_id: ?u128 = null,
|
|
467
|
+
timestamp_max_transfer_id: ?u128 = null,
|
|
468
|
+
limit: u32,
|
|
469
|
+
flags_debits: ?enum { DR } = null,
|
|
470
|
+
flags_credits: ?enum { CR } = null,
|
|
471
|
+
flags_reversed: ?enum { REV } = null,
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
const TestQueryFilter = struct {
|
|
475
|
+
user_data_128: u128,
|
|
476
|
+
user_data_64: u64,
|
|
477
|
+
user_data_32: u32,
|
|
478
|
+
ledger: u32,
|
|
479
|
+
code: u16,
|
|
480
|
+
timestamp_min_transfer_id: ?u128 = null,
|
|
481
|
+
timestamp_max_transfer_id: ?u128 = null,
|
|
482
|
+
limit: u32,
|
|
483
|
+
flags_reversed: ?enum { REV } = null,
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
const TestGetChangeEventsFilter = struct {
|
|
487
|
+
timestamp_min_transfer_id: ?u128 = null,
|
|
488
|
+
timestamp_max_transfer_id: ?u128 = null,
|
|
489
|
+
limit: u32,
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
const TestGetChangeEventsResult = struct {
|
|
493
|
+
const Balance = struct {
|
|
494
|
+
account_id: u128,
|
|
495
|
+
debits_pending: u128,
|
|
496
|
+
debits_posted: u128,
|
|
497
|
+
credits_pending: u128,
|
|
498
|
+
credits_posted: u128,
|
|
499
|
+
closed: ?enum { CLSD } = null,
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
event_type: ?enum { PEN, POS, VOI, EXP } = null,
|
|
503
|
+
timestamp_transfer: ?u128 = null,
|
|
504
|
+
amount: u128,
|
|
505
|
+
transfer_pending_id: ?u128 = null,
|
|
506
|
+
dr_account: Balance,
|
|
507
|
+
cr_account: Balance,
|
|
508
|
+
|
|
509
|
+
fn match(
|
|
510
|
+
self: *const TestGetChangeEventsResult,
|
|
511
|
+
accounts: *std.AutoHashMap(u128, Account),
|
|
512
|
+
transfers: *std.AutoHashMap(u128, Transfer),
|
|
513
|
+
event: *const ChangeEvent,
|
|
514
|
+
) bool {
|
|
515
|
+
if (self.timestamp_transfer) |id| {
|
|
516
|
+
const transfer = transfers.get(id).?;
|
|
517
|
+
if (event.type == .two_phase_expired) return false;
|
|
518
|
+
if (event.timestamp != transfer.timestamp) return false;
|
|
519
|
+
if (!match_transfer(event, &transfer)) return false;
|
|
520
|
+
}
|
|
521
|
+
if (self.event_type) |event_type| {
|
|
522
|
+
const expected: ChangeEventType = switch (event_type) {
|
|
523
|
+
.PEN => .two_phase_pending,
|
|
524
|
+
.POS => .two_phase_posted,
|
|
525
|
+
.VOI => .two_phase_voided,
|
|
526
|
+
.EXP => .two_phase_expired,
|
|
527
|
+
};
|
|
528
|
+
if (event.type != expected) return false;
|
|
529
|
+
} else {
|
|
530
|
+
if (event.type != .single_phase) return false;
|
|
531
|
+
}
|
|
532
|
+
if (event.transfer_amount != self.amount) return false;
|
|
533
|
+
if (self.transfer_pending_id) |transfer_pending_id| {
|
|
534
|
+
switch (event.type) {
|
|
535
|
+
.two_phase_pending, .single_phase => return false,
|
|
536
|
+
.two_phase_posted, .two_phase_voided => {
|
|
537
|
+
if (event.transfer_pending_id != transfer_pending_id) return false;
|
|
538
|
+
},
|
|
539
|
+
.two_phase_expired => {
|
|
540
|
+
const transfer = transfers.get(transfer_pending_id).?;
|
|
541
|
+
if (transfer.timeout == 0) return false;
|
|
542
|
+
if (event.timestamp <
|
|
543
|
+
transfer.timestamp + transfer.timeout_ns()) return false;
|
|
544
|
+
if (!match_transfer(event, &transfer)) return false;
|
|
545
|
+
},
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
const dr_account = accounts.get(self.dr_account.account_id).?;
|
|
550
|
+
if (dr_account.ledger != event.ledger) return false;
|
|
551
|
+
if (self.dr_account.account_id != event.debit_account_id) return false;
|
|
552
|
+
if (dr_account.timestamp != event.debit_account_timestamp) return false;
|
|
553
|
+
if (self.dr_account.debits_pending != event.debit_account_debits_pending) return false;
|
|
554
|
+
if (self.dr_account.debits_posted != event.debit_account_debits_posted) return false;
|
|
555
|
+
if (self.dr_account.credits_pending != event.debit_account_credits_pending) return false;
|
|
556
|
+
if (self.dr_account.credits_posted != event.debit_account_credits_posted) return false;
|
|
557
|
+
if ((self.dr_account.closed == .CLSD) != event.debit_account_flags.closed) return false;
|
|
558
|
+
|
|
559
|
+
const cr_account = accounts.get(self.cr_account.account_id).?;
|
|
560
|
+
if (cr_account.ledger != event.ledger) return false;
|
|
561
|
+
if (self.cr_account.account_id != event.credit_account_id) return false;
|
|
562
|
+
if (cr_account.timestamp != event.credit_account_timestamp) return false;
|
|
563
|
+
if (self.cr_account.debits_pending != event.credit_account_debits_pending) return false;
|
|
564
|
+
if (self.cr_account.debits_posted != event.credit_account_debits_posted) return false;
|
|
565
|
+
if (self.cr_account.credits_pending != event.credit_account_credits_pending) return false;
|
|
566
|
+
if (self.cr_account.credits_posted != event.credit_account_credits_posted) return false;
|
|
567
|
+
if ((self.cr_account.closed == .CLSD) != event.credit_account_flags.closed) return false;
|
|
568
|
+
|
|
569
|
+
return true;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
fn match_transfer(event: *const ChangeEvent, transfer: *const tb.Transfer) bool {
|
|
573
|
+
if (event.transfer_timestamp != transfer.timestamp) return false;
|
|
574
|
+
if (event.transfer_id != transfer.id) return false;
|
|
575
|
+
if (event.transfer_amount != transfer.amount and
|
|
576
|
+
// The in-memory model keeps the `AMOUNT_MAX`.
|
|
577
|
+
transfer.amount != std.math.maxInt(u128)) return false;
|
|
578
|
+
if (event.transfer_pending_id != transfer.pending_id) return false;
|
|
579
|
+
if (event.transfer_user_data_128 != transfer.user_data_128) return false;
|
|
580
|
+
if (event.transfer_user_data_64 != transfer.user_data_64) return false;
|
|
581
|
+
if (event.transfer_user_data_32 != transfer.user_data_32) return false;
|
|
582
|
+
if (event.transfer_code != transfer.code) return false;
|
|
583
|
+
if (event.ledger != transfer.ledger) return false;
|
|
584
|
+
if (event.ledger != transfer.ledger) return false;
|
|
585
|
+
if (@as(u16, @bitCast(transfer.flags)) !=
|
|
586
|
+
@as(u16, @bitCast(event.transfer_flags))) return false;
|
|
587
|
+
return true;
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
// Operations that share the same input.
|
|
592
|
+
const TestGetAccountBalances = TestAccountFilter;
|
|
593
|
+
const TestGetAccountTransfers = TestAccountFilter;
|
|
594
|
+
const TestQueryAccounts = TestQueryFilter;
|
|
595
|
+
const TestQueryTransfers = TestQueryFilter;
|
|
596
|
+
|
|
597
|
+
fn check(test_table: []const u8) !void {
|
|
598
|
+
const parse_table = @import("testing/table.zig").parse;
|
|
599
|
+
const test_actions = parse_table(TestAction, test_table);
|
|
600
|
+
|
|
601
|
+
// Runs the same test for each variation of supported operations,
|
|
602
|
+
// simulating different client versions.
|
|
603
|
+
for (TestContext.Operation.versions) |*version_map| {
|
|
604
|
+
try check_version(
|
|
605
|
+
test_actions.const_slice(),
|
|
606
|
+
version_map,
|
|
607
|
+
);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
fn check_version(
|
|
612
|
+
test_actions: []const TestAction,
|
|
613
|
+
version_map: *const TestContext.Operation.VersionMap,
|
|
614
|
+
) !void {
|
|
615
|
+
const allocator = std.testing.allocator;
|
|
616
|
+
|
|
617
|
+
var context: TestContext = undefined;
|
|
618
|
+
try context.init(allocator);
|
|
619
|
+
defer context.deinit(allocator);
|
|
620
|
+
|
|
621
|
+
var accounts = std.AutoHashMap(u128, Account).init(allocator);
|
|
622
|
+
defer accounts.deinit();
|
|
623
|
+
|
|
624
|
+
var transfers = std.AutoHashMap(u128, Transfer).init(allocator);
|
|
625
|
+
defer transfers.deinit();
|
|
626
|
+
|
|
627
|
+
var request = std.ArrayListAligned(u8, 16).init(allocator);
|
|
628
|
+
defer request.deinit();
|
|
629
|
+
|
|
630
|
+
try request.ensureTotalCapacity(constants.message_body_size_max);
|
|
631
|
+
|
|
632
|
+
var reply = std.ArrayListAligned(u8, 16).init(allocator);
|
|
633
|
+
defer reply.deinit();
|
|
634
|
+
|
|
635
|
+
var operation: ?TestContext.Operation = null;
|
|
636
|
+
for (test_actions) |test_action| {
|
|
637
|
+
switch (test_action) {
|
|
638
|
+
.setup => |b| {
|
|
639
|
+
assert(operation == null);
|
|
640
|
+
|
|
641
|
+
const account = context.get_account_from_cache(b.account).?;
|
|
642
|
+
var account_new = account;
|
|
643
|
+
|
|
644
|
+
account_new.debits_pending = b.debits_pending;
|
|
645
|
+
account_new.debits_posted = b.debits_posted;
|
|
646
|
+
account_new.credits_pending = b.credits_pending;
|
|
647
|
+
account_new.credits_posted = b.credits_posted;
|
|
648
|
+
assert(!account_new.debits_exceed_credits(0));
|
|
649
|
+
assert(!account_new.credits_exceed_debits(0));
|
|
650
|
+
|
|
651
|
+
if (!stdx.equal_bytes(Account, &account_new, &account)) {
|
|
652
|
+
context.state_machine.forest.grooves.accounts.update(.{
|
|
653
|
+
.old = &account,
|
|
654
|
+
.new = &account_new,
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
},
|
|
658
|
+
.tick => |ticks| {
|
|
659
|
+
assert(ticks.value != 0);
|
|
660
|
+
|
|
661
|
+
const interval_ns: u64 = @abs(ticks.value) *
|
|
662
|
+
@as(u64, switch (ticks.unit) {
|
|
663
|
+
.nanoseconds => 1,
|
|
664
|
+
.seconds => std.time.ns_per_s,
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
// The `parse` logic already computes `maxInt - value` when a unsigned int is
|
|
668
|
+
// represented as a negative number. However, we need to use a signed int and
|
|
669
|
+
// perform our own calculation to account for the unit.
|
|
670
|
+
context.state_machine.prepare_timestamp += if (ticks.value > 0)
|
|
671
|
+
interval_ns
|
|
672
|
+
else
|
|
673
|
+
TimestampRange.timestamp_max - interval_ns;
|
|
674
|
+
|
|
675
|
+
// Pulse is executed when the cluster is idle.
|
|
676
|
+
context.pulse();
|
|
677
|
+
},
|
|
678
|
+
.account => |a| {
|
|
679
|
+
assert(operation == null or operation.? == .create_accounts);
|
|
680
|
+
operation = .create_accounts;
|
|
681
|
+
|
|
682
|
+
var event = a.event();
|
|
683
|
+
try request.appendSlice(std.mem.asBytes(&event));
|
|
684
|
+
if (a.result == .ok) {
|
|
685
|
+
if (a.timestamp == 0) {
|
|
686
|
+
event.timestamp = context.state_machine.prepare_timestamp + 1 +
|
|
687
|
+
@divExact(request.items.len, @sizeOf(Account));
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
try accounts.put(a.id, event);
|
|
691
|
+
} else {
|
|
692
|
+
const result = CreateAccountsResult{
|
|
693
|
+
.index = @intCast(@divExact(request.items.len, @sizeOf(Account)) - 1),
|
|
694
|
+
.result = a.result,
|
|
695
|
+
};
|
|
696
|
+
try reply.appendSlice(std.mem.asBytes(&result));
|
|
697
|
+
}
|
|
698
|
+
},
|
|
699
|
+
.transfer => |t| {
|
|
700
|
+
assert(operation == null or operation.? == .create_transfers);
|
|
701
|
+
operation = .create_transfers;
|
|
702
|
+
|
|
703
|
+
var event = t.event();
|
|
704
|
+
try request.appendSlice(std.mem.asBytes(&event));
|
|
705
|
+
if (t.result == .ok) {
|
|
706
|
+
if (t.timestamp == 0) {
|
|
707
|
+
event.timestamp = context.state_machine.prepare_timestamp + 1 +
|
|
708
|
+
@divExact(request.items.len, @sizeOf(Transfer));
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
if (event.pending_id != 0) {
|
|
712
|
+
// Fill in default values.
|
|
713
|
+
const t_pending = transfers.get(event.pending_id).?;
|
|
714
|
+
inline for (.{
|
|
715
|
+
"debit_account_id",
|
|
716
|
+
"credit_account_id",
|
|
717
|
+
"ledger",
|
|
718
|
+
"code",
|
|
719
|
+
"user_data_128",
|
|
720
|
+
"user_data_64",
|
|
721
|
+
"user_data_32",
|
|
722
|
+
}) |field| {
|
|
723
|
+
if (@field(event, field) == 0) {
|
|
724
|
+
@field(event, field) = @field(t_pending, field);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
if (event.flags.void_pending_transfer) {
|
|
729
|
+
if (event.amount == 0) event.amount = t_pending.amount;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
try transfers.put(t.id, event);
|
|
733
|
+
} else {
|
|
734
|
+
const result = CreateTransfersResult{
|
|
735
|
+
.index = @intCast(@divExact(request.items.len, @sizeOf(Transfer)) - 1),
|
|
736
|
+
.result = t.result,
|
|
737
|
+
};
|
|
738
|
+
try reply.appendSlice(std.mem.asBytes(&result));
|
|
739
|
+
}
|
|
740
|
+
},
|
|
741
|
+
.lookup_account => |a| {
|
|
742
|
+
assert(operation == null or operation.? == .lookup_accounts);
|
|
743
|
+
operation = .lookup_accounts;
|
|
744
|
+
|
|
745
|
+
try request.appendSlice(std.mem.asBytes(&a.id));
|
|
746
|
+
if (a.data) |data| {
|
|
747
|
+
var account = accounts.get(a.id).?;
|
|
748
|
+
account.debits_pending = data.debits_pending;
|
|
749
|
+
account.debits_posted = data.debits_posted;
|
|
750
|
+
account.credits_pending = data.credits_pending;
|
|
751
|
+
account.credits_posted = data.credits_posted;
|
|
752
|
+
account.flags.closed = data.flag_closed != null;
|
|
753
|
+
try reply.appendSlice(std.mem.asBytes(&account));
|
|
754
|
+
}
|
|
755
|
+
},
|
|
756
|
+
.lookup_transfer => |t| {
|
|
757
|
+
assert(operation == null or operation.? == .lookup_transfers);
|
|
758
|
+
operation = .lookup_transfers;
|
|
759
|
+
|
|
760
|
+
try request.appendSlice(std.mem.asBytes(&t.id));
|
|
761
|
+
switch (t.data) {
|
|
762
|
+
.exists => |exists| {
|
|
763
|
+
if (exists) {
|
|
764
|
+
var transfer = transfers.get(t.id).?;
|
|
765
|
+
try reply.appendSlice(std.mem.asBytes(&transfer));
|
|
766
|
+
}
|
|
767
|
+
},
|
|
768
|
+
.amount => |amount| {
|
|
769
|
+
var transfer = transfers.get(t.id).?;
|
|
770
|
+
transfer.amount = amount;
|
|
771
|
+
try reply.appendSlice(std.mem.asBytes(&transfer));
|
|
772
|
+
},
|
|
773
|
+
.timestamp => |timestamp| {
|
|
774
|
+
var transfer = transfers.get(t.id).?;
|
|
775
|
+
transfer.timestamp = timestamp;
|
|
776
|
+
try reply.appendSlice(std.mem.asBytes(&transfer));
|
|
777
|
+
},
|
|
778
|
+
}
|
|
779
|
+
},
|
|
780
|
+
.get_account_balances => |f| {
|
|
781
|
+
assert(operation == null or operation.? == .get_account_balances);
|
|
782
|
+
operation = .get_account_balances;
|
|
783
|
+
|
|
784
|
+
const timestamp_min =
|
|
785
|
+
if (f.timestamp_min_transfer_id) |id| transfers.get(id).?.timestamp else 0;
|
|
786
|
+
const timestamp_max =
|
|
787
|
+
if (f.timestamp_max_transfer_id) |id| transfers.get(id).?.timestamp else 0;
|
|
788
|
+
|
|
789
|
+
const event = AccountFilter{
|
|
790
|
+
.account_id = f.account_id,
|
|
791
|
+
.user_data_128 = f.user_data_128 orelse 0,
|
|
792
|
+
.user_data_64 = f.user_data_64 orelse 0,
|
|
793
|
+
.user_data_32 = f.user_data_32 orelse 0,
|
|
794
|
+
.code = f.code orelse 0,
|
|
795
|
+
.timestamp_min = timestamp_min,
|
|
796
|
+
.timestamp_max = timestamp_max,
|
|
797
|
+
.limit = f.limit,
|
|
798
|
+
.flags = .{
|
|
799
|
+
.debits = f.flags_debits != null,
|
|
800
|
+
.credits = f.flags_credits != null,
|
|
801
|
+
.reversed = f.flags_reversed != null,
|
|
802
|
+
},
|
|
803
|
+
};
|
|
804
|
+
try request.appendSlice(std.mem.asBytes(&event));
|
|
805
|
+
},
|
|
806
|
+
.get_account_balances_result => |r| {
|
|
807
|
+
assert(operation.? == .get_account_balances);
|
|
808
|
+
|
|
809
|
+
const balance = AccountBalance{
|
|
810
|
+
.debits_pending = r.debits_pending,
|
|
811
|
+
.debits_posted = r.debits_posted,
|
|
812
|
+
.credits_pending = r.credits_pending,
|
|
813
|
+
.credits_posted = r.credits_posted,
|
|
814
|
+
.timestamp = transfers.get(r.transfer_id).?.timestamp,
|
|
815
|
+
};
|
|
816
|
+
try reply.appendSlice(std.mem.asBytes(&balance));
|
|
817
|
+
},
|
|
818
|
+
.get_account_transfers => |f| {
|
|
819
|
+
assert(operation == null or operation.? == .get_account_transfers);
|
|
820
|
+
operation = .get_account_transfers;
|
|
821
|
+
|
|
822
|
+
const timestamp_min =
|
|
823
|
+
if (f.timestamp_min_transfer_id) |id| transfers.get(id).?.timestamp else 0;
|
|
824
|
+
const timestamp_max =
|
|
825
|
+
if (f.timestamp_max_transfer_id) |id| transfers.get(id).?.timestamp else 0;
|
|
826
|
+
|
|
827
|
+
const event = AccountFilter{
|
|
828
|
+
.account_id = f.account_id,
|
|
829
|
+
.user_data_128 = f.user_data_128 orelse 0,
|
|
830
|
+
.user_data_64 = f.user_data_64 orelse 0,
|
|
831
|
+
.user_data_32 = f.user_data_32 orelse 0,
|
|
832
|
+
.code = f.code orelse 0,
|
|
833
|
+
.timestamp_min = timestamp_min,
|
|
834
|
+
.timestamp_max = timestamp_max,
|
|
835
|
+
.limit = f.limit,
|
|
836
|
+
.flags = .{
|
|
837
|
+
.debits = f.flags_debits != null,
|
|
838
|
+
.credits = f.flags_credits != null,
|
|
839
|
+
.reversed = f.flags_reversed != null,
|
|
840
|
+
},
|
|
841
|
+
};
|
|
842
|
+
try request.appendSlice(std.mem.asBytes(&event));
|
|
843
|
+
},
|
|
844
|
+
.get_account_transfers_result => |id| {
|
|
845
|
+
assert(operation.? == .get_account_transfers);
|
|
846
|
+
try reply.appendSlice(std.mem.asBytes(&transfers.get(id).?));
|
|
847
|
+
},
|
|
848
|
+
.query_accounts => |f| {
|
|
849
|
+
assert(operation == null or operation.? == .query_accounts);
|
|
850
|
+
operation = .query_accounts;
|
|
851
|
+
|
|
852
|
+
const timestamp_min = if (f.timestamp_min_transfer_id) |id|
|
|
853
|
+
accounts.get(id).?.timestamp
|
|
854
|
+
else
|
|
855
|
+
0;
|
|
856
|
+
const timestamp_max = if (f.timestamp_max_transfer_id) |id|
|
|
857
|
+
accounts.get(id).?.timestamp
|
|
858
|
+
else
|
|
859
|
+
0;
|
|
860
|
+
|
|
861
|
+
const event = QueryFilter{
|
|
862
|
+
.user_data_128 = f.user_data_128,
|
|
863
|
+
.user_data_64 = f.user_data_64,
|
|
864
|
+
.user_data_32 = f.user_data_32,
|
|
865
|
+
.ledger = f.ledger,
|
|
866
|
+
.code = f.code,
|
|
867
|
+
.timestamp_min = timestamp_min,
|
|
868
|
+
.timestamp_max = timestamp_max,
|
|
869
|
+
.limit = f.limit,
|
|
870
|
+
.flags = .{
|
|
871
|
+
.reversed = f.flags_reversed != null,
|
|
872
|
+
},
|
|
873
|
+
};
|
|
874
|
+
try request.appendSlice(std.mem.asBytes(&event));
|
|
875
|
+
},
|
|
876
|
+
.query_accounts_result => |a| {
|
|
877
|
+
assert(operation.? == .query_accounts);
|
|
878
|
+
var account = accounts.get(a.id).?;
|
|
879
|
+
if (a.data) |data| {
|
|
880
|
+
account.debits_pending = data.debits_pending;
|
|
881
|
+
account.debits_posted = data.debits_posted;
|
|
882
|
+
account.credits_pending = data.credits_pending;
|
|
883
|
+
account.credits_posted = data.credits_posted;
|
|
884
|
+
account.flags.closed = data.flag_closed != null;
|
|
885
|
+
}
|
|
886
|
+
try reply.appendSlice(std.mem.asBytes(&account));
|
|
887
|
+
},
|
|
888
|
+
.query_transfers => |f| {
|
|
889
|
+
assert(operation == null or operation.? == .query_transfers);
|
|
890
|
+
operation = .query_transfers;
|
|
891
|
+
|
|
892
|
+
const timestamp_min = if (f.timestamp_min_transfer_id) |id|
|
|
893
|
+
transfers.get(id).?.timestamp
|
|
894
|
+
else
|
|
895
|
+
0;
|
|
896
|
+
const timestamp_max = if (f.timestamp_max_transfer_id) |id|
|
|
897
|
+
transfers.get(id).?.timestamp
|
|
898
|
+
else
|
|
899
|
+
0;
|
|
900
|
+
|
|
901
|
+
const event = QueryFilter{
|
|
902
|
+
.user_data_128 = f.user_data_128,
|
|
903
|
+
.user_data_64 = f.user_data_64,
|
|
904
|
+
.user_data_32 = f.user_data_32,
|
|
905
|
+
.ledger = f.ledger,
|
|
906
|
+
.code = f.code,
|
|
907
|
+
.timestamp_min = timestamp_min,
|
|
908
|
+
.timestamp_max = timestamp_max,
|
|
909
|
+
.limit = f.limit,
|
|
910
|
+
.flags = .{
|
|
911
|
+
.reversed = f.flags_reversed != null,
|
|
912
|
+
},
|
|
913
|
+
};
|
|
914
|
+
try request.appendSlice(std.mem.asBytes(&event));
|
|
915
|
+
},
|
|
916
|
+
.query_transfers_result => |id| {
|
|
917
|
+
assert(operation.? == .query_transfers);
|
|
918
|
+
try reply.appendSlice(std.mem.asBytes(&transfers.get(id).?));
|
|
919
|
+
},
|
|
920
|
+
.get_change_events => |f| {
|
|
921
|
+
assert(operation == null or operation.? == .get_change_events);
|
|
922
|
+
operation = .get_change_events;
|
|
923
|
+
const timestamp_min = if (f.timestamp_min_transfer_id) |id|
|
|
924
|
+
transfers.get(id).?.timestamp
|
|
925
|
+
else
|
|
926
|
+
0;
|
|
927
|
+
const timestamp_max = if (f.timestamp_max_transfer_id) |id|
|
|
928
|
+
transfers.get(id).?.timestamp
|
|
929
|
+
else
|
|
930
|
+
0;
|
|
931
|
+
|
|
932
|
+
const event = ChangeEventsFilter{
|
|
933
|
+
.timestamp_min = timestamp_min,
|
|
934
|
+
.timestamp_max = timestamp_max,
|
|
935
|
+
.limit = f.limit,
|
|
936
|
+
};
|
|
937
|
+
try request.appendSlice(std.mem.asBytes(&event));
|
|
938
|
+
},
|
|
939
|
+
.get_change_events_result => |*t| {
|
|
940
|
+
assert(operation.? == .get_change_events);
|
|
941
|
+
try reply.appendSlice(std.mem.asBytes(t));
|
|
942
|
+
},
|
|
943
|
+
.commit => |commit_operation| {
|
|
944
|
+
assert(operation == null or operation.? == commit_operation);
|
|
945
|
+
assert(!context.busy);
|
|
946
|
+
|
|
947
|
+
const reply_actual_buffer = try allocator.alignedAlloc(
|
|
948
|
+
u8,
|
|
949
|
+
16,
|
|
950
|
+
constants.message_body_size_max,
|
|
951
|
+
);
|
|
952
|
+
defer allocator.free(reply_actual_buffer);
|
|
953
|
+
|
|
954
|
+
const payload_size: u32 = @intCast(request.items.len);
|
|
955
|
+
request.expandToCapacity();
|
|
956
|
+
|
|
957
|
+
const operation_actual = version_map.get(commit_operation);
|
|
958
|
+
const reply_actual = context.submit(
|
|
959
|
+
operation_actual,
|
|
960
|
+
request.items,
|
|
961
|
+
payload_size,
|
|
962
|
+
reply_actual_buffer[0..constants.message_body_size_max],
|
|
963
|
+
);
|
|
964
|
+
|
|
965
|
+
switch (operation_actual) {
|
|
966
|
+
inline else => |operation_actual_comptime| {
|
|
967
|
+
const Result = operation_actual_comptime.ResultType();
|
|
968
|
+
try testing.expectEqualSlices(
|
|
969
|
+
Result,
|
|
970
|
+
stdx.bytes_as_slice(.exact, Result, reply.items),
|
|
971
|
+
stdx.bytes_as_slice(.exact, Result, reply_actual),
|
|
972
|
+
);
|
|
973
|
+
},
|
|
974
|
+
.get_change_events => {
|
|
975
|
+
const results_actual = stdx.bytes_as_slice(
|
|
976
|
+
.exact,
|
|
977
|
+
ChangeEvent,
|
|
978
|
+
reply_actual,
|
|
979
|
+
);
|
|
980
|
+
const results_expected = stdx.bytes_as_slice(
|
|
981
|
+
.exact,
|
|
982
|
+
TestGetChangeEventsResult,
|
|
983
|
+
reply.items,
|
|
984
|
+
);
|
|
985
|
+
try testing.expectEqual(results_actual.len, results_expected.len);
|
|
986
|
+
for (results_actual, results_expected) |*actual, *expected| {
|
|
987
|
+
try testing.expect(expected.match(&accounts, &transfers, actual));
|
|
988
|
+
}
|
|
989
|
+
},
|
|
990
|
+
.pulse => unreachable,
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
request.clearRetainingCapacity();
|
|
994
|
+
reply.clearRetainingCapacity();
|
|
995
|
+
operation = null;
|
|
996
|
+
},
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
assert(operation == null);
|
|
1001
|
+
assert(request.items.len == 0);
|
|
1002
|
+
assert(reply.items.len == 0);
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
test "create_accounts" {
|
|
1006
|
+
try check(
|
|
1007
|
+
\\ account A1 0 0 0 0 U2 U2 U2 _ L3 C4 _ _ _ _ _ _ _ _ ok
|
|
1008
|
+
\\ account A0 1 1 1 1 _ _ _ 1 L0 C0 _ D<C C<D _ _ _ 1 1 timestamp_must_be_zero
|
|
1009
|
+
\\ account A0 1 1 1 1 _ _ _ 1 L0 C0 _ D<C C<D _ _ _ 1 _ reserved_field
|
|
1010
|
+
\\ account A0 1 1 1 1 _ _ _ _ L0 C0 _ D<C C<D _ _ _ 1 _ reserved_flag
|
|
1011
|
+
\\ account A0 1 1 1 1 _ _ _ _ L0 C0 _ D<C C<D _ _ _ _ _ id_must_not_be_zero
|
|
1012
|
+
\\ account -0 1 1 1 1 _ _ _ _ L0 C0 _ D<C C<D _ _ _ _ _ id_must_not_be_int_max
|
|
1013
|
+
\\ account A1 0 0 0 0 U1 U1 U1 _ L9 C9 _ D<C _ _ _ _ _ _ exists_with_different_flags
|
|
1014
|
+
\\ account A1 0 0 0 0 U1 U1 U1 _ L9 C9 _ _ C<D _ _ _ _ _ exists_with_different_flags
|
|
1015
|
+
\\ account A1 0 0 0 0 U1 U1 U1 _ L9 C9 _ _ _ _ _ _ _ _ exists_with_different_user_data_128
|
|
1016
|
+
\\ account A1 0 0 0 0 U2 U1 U1 _ L9 C9 _ _ _ _ _ _ _ _ exists_with_different_user_data_64
|
|
1017
|
+
\\ account A1 0 0 0 0 U2 U2 U1 _ L9 C9 _ _ _ _ _ _ _ _ exists_with_different_user_data_32
|
|
1018
|
+
\\ account A1 0 0 0 0 U2 U2 U2 _ L9 C9 _ _ _ _ _ _ _ _ exists_with_different_ledger
|
|
1019
|
+
\\ account A1 0 0 0 0 U2 U2 U2 _ L3 C9 _ _ _ _ _ _ _ _ exists_with_different_code
|
|
1020
|
+
\\ account A1 0 0 0 0 U2 U2 U2 _ L3 C4 _ _ _ _ _ _ _ _ exists
|
|
1021
|
+
\\ account A2 1 1 1 1 U1 U1 U1 _ L0 C0 _ D<C C<D _ _ _ _ _ flags_are_mutually_exclusive
|
|
1022
|
+
\\ account A2 1 1 1 1 U1 U1 U1 _ L9 C9 _ D<C _ _ _ _ _ _ debits_pending_must_be_zero
|
|
1023
|
+
\\ account A2 0 1 1 1 U1 U1 U1 _ L9 C9 _ D<C _ _ _ _ _ _ debits_posted_must_be_zero
|
|
1024
|
+
\\ account A2 0 0 1 1 U1 U1 U1 _ L9 C9 _ D<C _ _ _ _ _ _ credits_pending_must_be_zero
|
|
1025
|
+
\\ account A2 0 0 0 1 U1 U1 U1 _ L9 C9 _ D<C _ _ _ _ _ _ credits_posted_must_be_zero
|
|
1026
|
+
\\ account A2 0 0 0 0 U1 U1 U1 _ L0 C0 _ D<C _ _ _ _ _ _ ledger_must_not_be_zero
|
|
1027
|
+
\\ account A2 0 0 0 0 U1 U1 U1 _ L9 C0 _ D<C _ _ _ _ _ _ code_must_not_be_zero
|
|
1028
|
+
\\ commit create_accounts
|
|
1029
|
+
\\
|
|
1030
|
+
\\ lookup_account -0 _
|
|
1031
|
+
\\ lookup_account A0 _
|
|
1032
|
+
\\ lookup_account A1 0 0 0 0 _
|
|
1033
|
+
\\ lookup_account A2 _
|
|
1034
|
+
\\ commit lookup_accounts
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
test "create_accounts: empty" {
|
|
1039
|
+
try check(
|
|
1040
|
+
\\ commit create_transfers
|
|
1041
|
+
);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
test "linked accounts" {
|
|
1045
|
+
try check(
|
|
1046
|
+
\\ account A7 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok // An individual event (successful):
|
|
1047
|
+
|
|
1048
|
+
// A chain of 4 events (the last event in the chain closes the chain with linked=false):
|
|
1049
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ linked_event_failed // Commit/rollback.
|
|
1050
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ linked_event_failed // Commit/rollback.
|
|
1051
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ exists // Fail with .exists.
|
|
1052
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ linked_event_failed // Fail without committing.
|
|
1053
|
+
|
|
1054
|
+
// An individual event (successful):
|
|
1055
|
+
// This does not see any effect from the failed chain above.
|
|
1056
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1057
|
+
|
|
1058
|
+
// A chain of 2 events (the first event fails the chain):
|
|
1059
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C2 LNK _ _ _ _ _ _ _ exists_with_different_flags
|
|
1060
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ linked_event_failed
|
|
1061
|
+
|
|
1062
|
+
// An individual event (successful):
|
|
1063
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1064
|
+
|
|
1065
|
+
// A chain of 2 events (the last event fails the chain):
|
|
1066
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ linked_event_failed
|
|
1067
|
+
\\ account A1 0 0 0 0 _ _ _ _ L2 C1 _ _ _ _ _ _ _ _ exists_with_different_ledger
|
|
1068
|
+
|
|
1069
|
+
// A chain of 2 events (successful):
|
|
1070
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ ok
|
|
1071
|
+
\\ account A4 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1072
|
+
\\ commit create_accounts
|
|
1073
|
+
\\
|
|
1074
|
+
\\ lookup_account A7 0 0 0 0 _
|
|
1075
|
+
\\ lookup_account A1 0 0 0 0 _
|
|
1076
|
+
\\ lookup_account A2 0 0 0 0 _
|
|
1077
|
+
\\ lookup_account A3 0 0 0 0 _
|
|
1078
|
+
\\ lookup_account A4 0 0 0 0 _
|
|
1079
|
+
\\ commit lookup_accounts
|
|
1080
|
+
);
|
|
1081
|
+
|
|
1082
|
+
try check(
|
|
1083
|
+
\\ account A7 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok // An individual event (successful):
|
|
1084
|
+
|
|
1085
|
+
// A chain of 4 events:
|
|
1086
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ linked_event_failed // Commit/rollback.
|
|
1087
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ linked_event_failed // Commit/rollback.
|
|
1088
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ exists // Fail with .exists.
|
|
1089
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ linked_event_failed // Fail without committing.
|
|
1090
|
+
\\ commit create_accounts
|
|
1091
|
+
\\
|
|
1092
|
+
\\ lookup_account A7 0 0 0 0 _
|
|
1093
|
+
\\ lookup_account A1 _
|
|
1094
|
+
\\ lookup_account A2 _
|
|
1095
|
+
\\ lookup_account A3 _
|
|
1096
|
+
\\ commit lookup_accounts
|
|
1097
|
+
);
|
|
1098
|
+
|
|
1099
|
+
// TODO How can we test that events were in fact rolled back in LIFO order?
|
|
1100
|
+
// All our rollback handlers appear to be commutative.
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
test "linked_event_chain_open" {
|
|
1104
|
+
try check(
|
|
1105
|
+
// A chain of 3 events (the last event in the chain closes the chain with linked=false):
|
|
1106
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ ok
|
|
1107
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ ok
|
|
1108
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1109
|
+
|
|
1110
|
+
// An open chain of 2 events:
|
|
1111
|
+
\\ account A4 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ linked_event_failed
|
|
1112
|
+
\\ account A5 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ linked_event_chain_open
|
|
1113
|
+
\\ commit create_accounts
|
|
1114
|
+
\\
|
|
1115
|
+
\\ lookup_account A1 0 0 0 0 _
|
|
1116
|
+
\\ lookup_account A2 0 0 0 0 _
|
|
1117
|
+
\\ lookup_account A3 0 0 0 0 _
|
|
1118
|
+
\\ lookup_account A4 _
|
|
1119
|
+
\\ lookup_account A5 _
|
|
1120
|
+
\\ commit lookup_accounts
|
|
1121
|
+
);
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
test "linked_event_chain_open for an already failed batch" {
|
|
1125
|
+
try check(
|
|
1126
|
+
// An individual event (successful):
|
|
1127
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1128
|
+
|
|
1129
|
+
// An open chain of 3 events (the second one fails):
|
|
1130
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ linked_event_failed
|
|
1131
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ exists_with_different_flags
|
|
1132
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ linked_event_chain_open
|
|
1133
|
+
\\ commit create_accounts
|
|
1134
|
+
\\
|
|
1135
|
+
\\ lookup_account A1 0 0 0 0 _
|
|
1136
|
+
\\ lookup_account A2 _
|
|
1137
|
+
\\ lookup_account A3 _
|
|
1138
|
+
\\ commit lookup_accounts
|
|
1139
|
+
);
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
test "linked_event_chain_open for a batch of 1" {
|
|
1143
|
+
try check(
|
|
1144
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ linked_event_chain_open
|
|
1145
|
+
\\ commit create_accounts
|
|
1146
|
+
\\
|
|
1147
|
+
\\ lookup_account A1 _
|
|
1148
|
+
\\ commit lookup_accounts
|
|
1149
|
+
);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
// The goal is to ensure that:
|
|
1153
|
+
// 1. all CreateTransferResult enums are covered, with
|
|
1154
|
+
// 2. enums tested in the order that they are defined, for easier auditing of coverage, and that
|
|
1155
|
+
// 3. state machine logic cannot be reordered in any way, breaking determinism.
|
|
1156
|
+
test "create_transfers/lookup_transfers" {
|
|
1157
|
+
try check(
|
|
1158
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1159
|
+
\\ account A2 0 0 0 0 _ _ _ _ L2 C2 _ _ _ _ _ _ _ _ ok
|
|
1160
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1161
|
+
\\ account A4 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1162
|
+
\\ account A5 0 0 0 0 _ _ _ _ L1 C1 _ _ C<D _ _ _ _ _ ok
|
|
1163
|
+
\\ commit create_accounts
|
|
1164
|
+
|
|
1165
|
+
// Set up initial balances.
|
|
1166
|
+
\\ setup A1 100 200 0 0
|
|
1167
|
+
\\ setup A2 0 0 0 0
|
|
1168
|
+
\\ setup A3 0 0 110 210
|
|
1169
|
+
\\ setup A4 20 -700 0 -500
|
|
1170
|
+
\\ setup A5 0 -1000 10 -1100
|
|
1171
|
+
|
|
1172
|
+
// Bump the state machine time to `maxInt - 3s` for testing timeout overflow.
|
|
1173
|
+
\\ tick -3 seconds
|
|
1174
|
+
|
|
1175
|
+
// Test errors by descending precedence.
|
|
1176
|
+
\\ transfer T0 A0 A0 9 T1 _ _ _ _ L0 C0 _ PEN _ _ _ _ _ _ _ P1 1 timestamp_must_be_zero
|
|
1177
|
+
\\ transfer T0 A0 A0 9 T1 _ _ _ _ L0 C0 _ PEN _ _ _ _ _ _ _ P1 _ reserved_flag
|
|
1178
|
+
\\ transfer T0 A0 A0 9 T1 _ _ _ _ L0 C0 _ PEN _ _ _ _ _ _ _ _ _ id_must_not_be_zero
|
|
1179
|
+
\\ transfer -0 A0 A0 9 T1 _ _ _ _ L0 C0 _ PEN _ _ _ _ _ _ _ _ _ id_must_not_be_int_max
|
|
1180
|
+
\\ transfer T1 A0 A0 9 T1 _ _ _ _ L0 C0 _ PEN _ _ _ _ _ _ _ _ _ debit_account_id_must_not_be_zero
|
|
1181
|
+
\\ transfer T1 -0 A0 9 T1 _ _ _ _ L0 C0 _ PEN _ _ _ _ _ _ _ _ _ debit_account_id_must_not_be_int_max
|
|
1182
|
+
\\ transfer T1 A8 A0 9 T1 _ _ _ _ L0 C0 _ PEN _ _ _ _ _ _ _ _ _ credit_account_id_must_not_be_zero
|
|
1183
|
+
\\ transfer T1 A8 -0 9 T1 _ _ _ _ L0 C0 _ PEN _ _ _ _ _ _ _ _ _ credit_account_id_must_not_be_int_max
|
|
1184
|
+
\\ transfer T1 A8 A8 9 T1 _ _ _ _ L0 C0 _ PEN _ _ _ _ _ _ _ _ _ accounts_must_be_different
|
|
1185
|
+
\\ transfer T1 A8 A9 9 T1 _ _ _ _ L0 C0 _ PEN _ _ _ _ _ _ _ _ _ pending_id_must_be_zero
|
|
1186
|
+
\\ transfer T1 A8 A9 9 _ _ _ _ 1 L0 C0 _ _ _ _ _ _ _ _ _ _ _ timeout_reserved_for_pending_transfer
|
|
1187
|
+
\\ transfer T1 A8 A9 9 _ _ _ _ _ L0 C0 _ _ _ _ _ _ _ CDR _ _ _ closing_transfer_must_be_pending
|
|
1188
|
+
\\ transfer T1 A8 A9 9 _ _ _ _ _ L0 C0 _ _ _ _ _ _ _ _ CCR _ _ closing_transfer_must_be_pending
|
|
1189
|
+
\\ transfer T1 A8 A9 9 _ _ _ _ _ L0 C0 _ PEN _ _ _ _ _ _ _ _ _ ledger_must_not_be_zero
|
|
1190
|
+
\\ transfer T1 A8 A9 9 _ _ _ _ _ L9 C0 _ PEN _ _ _ _ _ _ _ _ _ code_must_not_be_zero
|
|
1191
|
+
// `debit_account_not_found` is a transient error, T1 cannot be reused:
|
|
1192
|
+
\\ transfer T1 A8 A9 9 _ _ _ _ _ L9 C1 _ PEN _ _ _ _ _ _ _ _ _ debit_account_not_found
|
|
1193
|
+
\\ transfer T1 A1 A3 123 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ id_already_failed
|
|
1194
|
+
// `credit_account_not_found` is a transient error, T2 cannot be reused:
|
|
1195
|
+
\\ transfer T2 A1 A9 9 _ _ _ _ _ L9 C1 _ PEN _ _ _ _ _ _ _ _ _ credit_account_not_found
|
|
1196
|
+
\\ transfer T2 A1 A3 123 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ id_already_failed
|
|
1197
|
+
\\ commit create_transfers
|
|
1198
|
+
\\
|
|
1199
|
+
\\ transfer T3 A1 A2 1 _ _ _ _ _ L9 C1 _ PEN _ _ _ _ _ _ _ _ _ accounts_must_have_the_same_ledger
|
|
1200
|
+
\\ transfer T3 A1 A3 1 _ _ _ _ _ L9 C1 _ PEN _ _ _ _ _ _ _ _ _ transfer_must_have_the_same_ledger_as_accounts
|
|
1201
|
+
\\ transfer T3 A1 A3 -99 _ _ _ _ _ L1 C1 _ PEN _ _ _ _ _ _ _ _ _ overflows_debits_pending // amount = max - A1.debits_pending + 1
|
|
1202
|
+
\\ transfer T3 A1 A3 -109 _ _ _ _ _ L1 C1 _ PEN _ _ _ _ _ _ _ _ _ overflows_credits_pending // amount = max - A3.credits_pending + 1
|
|
1203
|
+
\\ transfer T3 A1 A3 -199 _ _ _ _ _ L1 C1 _ PEN _ _ _ _ _ _ _ _ _ overflows_debits_posted // amount = max - A1.debits_posted + 1
|
|
1204
|
+
\\ transfer T3 A1 A3 -209 _ _ _ _ _ L1 C1 _ PEN _ _ _ _ _ _ _ _ _ overflows_credits_posted // amount = max - A3.credits_posted + 1
|
|
1205
|
+
\\ transfer T3 A1 A3 -299 _ _ _ _ _ L1 C1 _ PEN _ _ _ _ _ _ _ _ _ overflows_debits // amount = max - A1.debits_pending - A1.debits_posted + 1
|
|
1206
|
+
\\ transfer T3 A1 A3 -319 _ _ _ _ _ L1 C1 _ PEN _ _ _ _ _ _ _ _ _ overflows_credits // amount = max - A3.credits_pending - A3.credits_posted + 1
|
|
1207
|
+
\\ transfer T3 A4 A5 199 _ _ _ _ 999 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ overflows_timeout
|
|
1208
|
+
// `exceeds_credits` is a transient error, T3 cannot be reused:
|
|
1209
|
+
\\ transfer T3 A4 A5 199 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ exceeds_credits // amount = A4.credits_posted - A4.debits_pending - A4.debits_posted + 1
|
|
1210
|
+
\\ transfer T3 A1 A3 123 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ id_already_failed
|
|
1211
|
+
// `exceeds_debits` is a transient error, T4 cannot be reused:
|
|
1212
|
+
\\ transfer T4 A4 A5 91 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ exceeds_debits // amount = A5.debits_posted - A5.credits_pending - A5.credits_posted + 1
|
|
1213
|
+
\\ transfer T4 A1 A3 123 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ id_already_failed
|
|
1214
|
+
\\
|
|
1215
|
+
\\ transfer T5 A1 A3 123 _ _ _ _ 1 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
1216
|
+
\\ commit create_transfers
|
|
1217
|
+
|
|
1218
|
+
// Ensure that idempotence is checked first:
|
|
1219
|
+
\\ transfer T5 A1 A3 123 _ _ _ _ 1 L2 C1 _ PEN _ _ _ _ _ _ _ _ _ exists_with_different_ledger
|
|
1220
|
+
\\ transfer T5 A1 A3 -0 _ U1 U1 U1 _ L1 C2 _ _ _ _ _ _ _ _ _ _ _ exists_with_different_flags
|
|
1221
|
+
\\ transfer T5 A3 A1 -0 _ U1 U1 U1 1 L1 C2 _ PEN _ _ _ _ _ _ _ _ _ exists_with_different_debit_account_id
|
|
1222
|
+
\\ transfer T5 A1 A4 -0 _ U1 U1 U1 1 L1 C2 _ PEN _ _ _ _ _ _ _ _ _ exists_with_different_credit_account_id
|
|
1223
|
+
\\ transfer T5 A1 A3 -0 _ U1 U1 U1 1 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ exists_with_different_amount
|
|
1224
|
+
\\ transfer T5 A1 A3 123 _ U1 U1 U1 1 L1 C2 _ PEN _ _ _ _ _ _ _ _ _ exists_with_different_user_data_128
|
|
1225
|
+
\\ transfer T5 A1 A3 123 _ _ U1 U1 1 L1 C2 _ PEN _ _ _ _ _ _ _ _ _ exists_with_different_user_data_64
|
|
1226
|
+
\\ transfer T5 A1 A3 123 _ _ _ U1 1 L1 C2 _ PEN _ _ _ _ _ _ _ _ _ exists_with_different_user_data_32
|
|
1227
|
+
\\ transfer T5 A1 A3 123 _ _ _ _ 2 L1 C2 _ PEN _ _ _ _ _ _ _ _ _ exists_with_different_timeout
|
|
1228
|
+
\\ transfer T5 A1 A3 123 _ _ _ _ 1 L1 C2 _ PEN _ _ _ _ _ _ _ _ _ exists_with_different_code
|
|
1229
|
+
\\ transfer T5 A1 A3 123 _ _ _ _ 1 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ exists
|
|
1230
|
+
\\
|
|
1231
|
+
\\ transfer T6 A3 A1 7 _ _ _ _ _ L1 C2 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
1232
|
+
\\ transfer T7 A1 A3 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
1233
|
+
\\ transfer T8 A1 A3 0 _ _ _ _ _ L1 C2 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
1234
|
+
\\ commit create_transfers
|
|
1235
|
+
\\
|
|
1236
|
+
\\ lookup_account A1 223 203 0 7 _
|
|
1237
|
+
\\ lookup_account A3 0 7 233 213 _
|
|
1238
|
+
\\ commit lookup_accounts
|
|
1239
|
+
\\
|
|
1240
|
+
\\ lookup_transfer T5 exists true
|
|
1241
|
+
\\ lookup_transfer T6 exists true
|
|
1242
|
+
\\ lookup_transfer T7 exists true
|
|
1243
|
+
\\ lookup_transfer T8 exists true
|
|
1244
|
+
\\ lookup_transfer -0 exists false
|
|
1245
|
+
\\ commit lookup_transfers
|
|
1246
|
+
);
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
test "create/lookup 2-phase transfers" {
|
|
1250
|
+
try check(
|
|
1251
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1252
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1253
|
+
\\ commit create_accounts
|
|
1254
|
+
|
|
1255
|
+
// First phase.
|
|
1256
|
+
\\ transfer T1 A1 A2 15 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok // Not pending!
|
|
1257
|
+
\\ transfer T2 A1 A2 15 _ _ _ _ 1000 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
1258
|
+
\\ transfer T3 A1 A2 15 _ _ _ _ 50 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
1259
|
+
\\ transfer T4 A1 A2 15 _ _ _ _ 1 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
1260
|
+
\\ transfer T5 A1 A2 7 _ U9 U9 U9 50 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
1261
|
+
\\ transfer T6 A1 A2 1 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
1262
|
+
\\ transfer T7 A1 A2 1 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
1263
|
+
\\ commit create_transfers
|
|
1264
|
+
|
|
1265
|
+
// Check balances before resolving.
|
|
1266
|
+
\\ lookup_account A1 54 15 0 0 _
|
|
1267
|
+
\\ lookup_account A2 0 0 54 15 _
|
|
1268
|
+
\\ commit lookup_accounts
|
|
1269
|
+
|
|
1270
|
+
// Bump the state machine time in +1s for testing the timeout expiration.
|
|
1271
|
+
\\ tick 1 seconds
|
|
1272
|
+
|
|
1273
|
+
// Second phase.
|
|
1274
|
+
\\ transfer T101 A1 A2 13 T2 U1 U1 U1 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ ok
|
|
1275
|
+
\\ transfer T0 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ PEN POS VOI _ _ _ _ _ _ 1 timestamp_must_be_zero
|
|
1276
|
+
\\ transfer T0 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ PEN POS VOI _ _ _ _ _ _ _ id_must_not_be_zero
|
|
1277
|
+
\\ transfer -0 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ PEN POS VOI _ _ _ _ _ _ _ id_must_not_be_int_max
|
|
1278
|
+
\\ transfer T101 A1 A2 15 T3 U2 U2 U2 _ L1 C1 _ _ _ VOI _ _ _ _ _ _ _ exists_with_different_flags
|
|
1279
|
+
\\ transfer T101 A1 A2 14 T2 U1 U1 U1 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_amount
|
|
1280
|
+
\\ transfer T101 A1 A2 _ T2 U1 U1 U1 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_amount
|
|
1281
|
+
\\ transfer T101 A1 A2 13 T3 U2 U2 U2 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_pending_id
|
|
1282
|
+
\\ transfer T101 A1 A2 13 T2 U2 U2 U2 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_user_data_128
|
|
1283
|
+
\\ transfer T101 A1 A2 13 T2 U1 U2 U2 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_user_data_64
|
|
1284
|
+
\\ transfer T101 A1 A2 13 T2 U1 U1 U2 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_user_data_32
|
|
1285
|
+
\\ transfer T101 A1 A2 13 T2 U1 U1 U1 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists
|
|
1286
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ PEN POS VOI _ _ _ _ _ _ _ flags_are_mutually_exclusive
|
|
1287
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ PEN POS VOI BDR _ _ _ _ _ _ flags_are_mutually_exclusive
|
|
1288
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ PEN POS VOI BDR BCR _ _ _ _ _ flags_are_mutually_exclusive
|
|
1289
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ PEN POS VOI _ BCR _ _ _ _ _ flags_are_mutually_exclusive
|
|
1290
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ PEN _ VOI _ _ _ _ _ _ _ flags_are_mutually_exclusive
|
|
1291
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ _ _ VOI BDR _ _ _ _ _ _ flags_are_mutually_exclusive
|
|
1292
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ _ _ VOI BDR BCR _ _ _ _ _ flags_are_mutually_exclusive
|
|
1293
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ _ _ VOI _ BCR _ _ _ _ _ flags_are_mutually_exclusive
|
|
1294
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ _ POS _ BDR _ _ _ _ _ _ flags_are_mutually_exclusive
|
|
1295
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ _ POS _ BDR BCR _ _ _ _ _ flags_are_mutually_exclusive
|
|
1296
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ _ POS _ _ BCR _ _ _ _ _ flags_are_mutually_exclusive
|
|
1297
|
+
\\ transfer T102 A8 A9 16 T0 U2 U2 U2 50 L6 C7 _ _ _ VOI _ _ _ _ _ _ _ pending_id_must_not_be_zero
|
|
1298
|
+
\\ transfer T102 A8 A9 16 -0 U2 U2 U2 50 L6 C7 _ _ _ VOI _ _ _ _ _ _ _ pending_id_must_not_be_int_max
|
|
1299
|
+
\\ transfer T102 A8 A9 16 102 U2 U2 U2 50 L6 C7 _ _ _ VOI _ _ _ _ _ _ _ pending_id_must_be_different
|
|
1300
|
+
\\ transfer T102 A8 A9 16 103 U2 U2 U2 50 L6 C7 _ _ _ VOI _ _ _ _ _ _ _ timeout_reserved_for_pending_transfer
|
|
1301
|
+
\\ commit create_transfers
|
|
1302
|
+
|
|
1303
|
+
// `pending_transfer_not_found` is a transient error, T102 cannot be reused:
|
|
1304
|
+
\\ transfer T102 A8 A9 16 103 U2 U2 U2 _ L6 C7 _ _ _ VOI _ _ _ _ _ _ _ pending_transfer_not_found
|
|
1305
|
+
\\ transfer T102 A1 A2 13 _ U1 U1 U1 _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ id_already_failed
|
|
1306
|
+
\\
|
|
1307
|
+
\\ transfer T103 A8 A9 16 T1 U2 U2 U2 _ L6 C7 _ _ _ VOI _ _ _ _ _ _ _ pending_transfer_not_pending
|
|
1308
|
+
\\ transfer T103 A8 A9 16 T3 U2 U2 U2 _ L6 C7 _ _ _ VOI _ _ _ _ _ _ _ pending_transfer_has_different_debit_account_id
|
|
1309
|
+
\\ transfer T103 A1 A9 16 T3 U2 U2 U2 _ L6 C7 _ _ _ VOI _ _ _ _ _ _ _ pending_transfer_has_different_credit_account_id
|
|
1310
|
+
\\ transfer T103 A1 A2 16 T3 U2 U2 U2 _ L6 C7 _ _ _ VOI _ _ _ _ _ _ _ pending_transfer_has_different_ledger
|
|
1311
|
+
\\ transfer T103 A1 A2 16 T3 U2 U2 U2 _ L1 C7 _ _ _ VOI _ _ _ _ _ _ _ pending_transfer_has_different_code
|
|
1312
|
+
\\ transfer T103 A1 A2 16 T3 U2 U2 U2 _ L1 C1 _ _ _ VOI _ _ _ _ _ _ _ exceeds_pending_transfer_amount
|
|
1313
|
+
\\ transfer T103 A1 A2 14 T3 U2 U2 U2 _ L1 C1 _ _ _ VOI _ _ _ _ _ _ _ pending_transfer_has_different_amount
|
|
1314
|
+
\\ transfer T103 A1 A2 13 T2 U1 U1 U1 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ pending_transfer_already_posted
|
|
1315
|
+
\\ transfer T103 A1 A2 15 T3 U1 U1 U1 _ L1 C1 _ _ _ VOI _ _ _ _ _ _ _ ok
|
|
1316
|
+
\\ transfer T104 A1 A2 13 T3 U1 U1 U1 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ pending_transfer_already_voided
|
|
1317
|
+
\\ transfer T104 A1 A2 15 T4 U1 U1 U1 _ L1 C1 _ _ _ VOI _ _ _ _ _ _ _ pending_transfer_expired
|
|
1318
|
+
\\ commit create_transfers
|
|
1319
|
+
|
|
1320
|
+
// Transfers posted/voided with optional fields must not raise `exists_with_different_*`.
|
|
1321
|
+
// But transfers posted with posted.amount≠pending.amount may return
|
|
1322
|
+
// exists_with_different_amount.
|
|
1323
|
+
\\ transfer T101 A0 A0 14 T2 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_amount // t.amount > e.amount
|
|
1324
|
+
\\ transfer T101 A0 A0 14 T2 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_amount
|
|
1325
|
+
\\ transfer T101 A0 A0 12 T2 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_amount // t.amount < e.amount
|
|
1326
|
+
\\
|
|
1327
|
+
\\ transfer T105 A0 A0 8 T5 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ exceeds_pending_transfer_amount // t.amount > p.amount
|
|
1328
|
+
\\ transfer T105 A0 A0 -0 T5 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ ok
|
|
1329
|
+
\\ transfer T105 A0 A0 7 T5 U0 U0 U0 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists
|
|
1330
|
+
\\ transfer T105 A0 A0 7 T5 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ exists // ledger/code = 0
|
|
1331
|
+
\\ transfer T105 A0 A0 -0 T5 U0 U0 U0 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists // amount = max
|
|
1332
|
+
\\ transfer T105 A0 A0 8 T5 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_amount // t.amount > p.amount
|
|
1333
|
+
\\ transfer T105 A0 A0 6 T5 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_amount // t.amount < e.amount
|
|
1334
|
+
\\ transfer T105 A0 A0 0 T5 U0 U0 U0 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_amount
|
|
1335
|
+
\\
|
|
1336
|
+
\\ transfer T106 A0 A0 -1 T6 U0 U0 U0 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exceeds_pending_transfer_amount
|
|
1337
|
+
\\ transfer T106 A0 A0 -0 T6 U0 U0 U0 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ ok
|
|
1338
|
+
\\ transfer T106 A0 A0 -0 T6 U0 U0 U0 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists
|
|
1339
|
+
\\ transfer T106 A0 A0 1 T6 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ exists
|
|
1340
|
+
\\ transfer T106 A0 A0 2 T6 U0 U0 U0 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_amount // t.amount > p.amount
|
|
1341
|
+
\\ transfer T106 A0 A0 0 T6 U0 U0 U0 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_amount // t.amount < p.amount
|
|
1342
|
+
\\
|
|
1343
|
+
\\ transfer T107 A0 A0 0 T7 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ ok
|
|
1344
|
+
\\ transfer T107 A0 A0 0 T7 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ exists
|
|
1345
|
+
\\ transfer T107 A0 A0 1 T7 U0 U0 U0 _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ exists_with_different_amount // t.amount > e.amount
|
|
1346
|
+
\\ commit create_transfers
|
|
1347
|
+
|
|
1348
|
+
// Check balances after resolving.
|
|
1349
|
+
\\ lookup_account A1 0 36 0 0 _
|
|
1350
|
+
\\ lookup_account A2 0 0 0 36 _
|
|
1351
|
+
\\ commit lookup_accounts
|
|
1352
|
+
|
|
1353
|
+
// The posted transfer amounts are set to the actual amount posted (which may be less than
|
|
1354
|
+
// the "client" set as the amount).
|
|
1355
|
+
\\ lookup_transfer T101 amount 13
|
|
1356
|
+
\\ lookup_transfer T105 amount 7
|
|
1357
|
+
\\ lookup_transfer T106 amount 1
|
|
1358
|
+
\\ lookup_transfer T107 amount 0
|
|
1359
|
+
\\ commit lookup_transfers
|
|
1360
|
+
);
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
test "create/lookup 2-phase transfers (amount=maxInt)" {
|
|
1364
|
+
try check(
|
|
1365
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1366
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1367
|
+
\\ commit create_accounts
|
|
1368
|
+
|
|
1369
|
+
// Posting maxInt(u128) is a pun – it is interpreted as "send full pending amount", which in
|
|
1370
|
+
// this case is exactly maxInt(u127).
|
|
1371
|
+
\\ transfer T1 A1 A2 -0 _ _ _ _ _ L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
1372
|
+
\\ transfer T2 A1 A2 -0 T1 _ _ _ _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ ok
|
|
1373
|
+
\\ transfer T2 A1 A2 -0 T1 _ _ _ _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ exists
|
|
1374
|
+
\\ commit create_transfers
|
|
1375
|
+
|
|
1376
|
+
// Check balances after resolving.
|
|
1377
|
+
\\ lookup_account A1 0 -0 0 0 _
|
|
1378
|
+
\\ lookup_account A2 0 0 0 -0 _
|
|
1379
|
+
\\ commit lookup_accounts
|
|
1380
|
+
\\
|
|
1381
|
+
\\ lookup_transfer T1 amount -0
|
|
1382
|
+
\\ lookup_transfer T2 amount -0
|
|
1383
|
+
\\ commit lookup_transfers
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
test "create/lookup expired transfers" {
|
|
1388
|
+
try check(
|
|
1389
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1390
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1391
|
+
\\ commit create_accounts
|
|
1392
|
+
|
|
1393
|
+
// First phase.
|
|
1394
|
+
\\ transfer T1 A1 A2 10 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok // Timeout zero will never expire.
|
|
1395
|
+
\\ transfer T2 A1 A2 11 _ _ _ _ 1 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
1396
|
+
\\ transfer T3 A1 A2 12 _ _ _ _ 2 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
1397
|
+
\\ transfer T4 A1 A2 13 _ _ _ _ 3 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
1398
|
+
\\ commit create_transfers
|
|
1399
|
+
|
|
1400
|
+
// Check balances before expiration.
|
|
1401
|
+
\\ lookup_account A1 46 0 0 0 _
|
|
1402
|
+
\\ lookup_account A2 0 0 46 0 _
|
|
1403
|
+
\\ commit lookup_accounts
|
|
1404
|
+
|
|
1405
|
+
// Check balances after 1s.
|
|
1406
|
+
\\ tick 1 seconds
|
|
1407
|
+
\\ lookup_account A1 35 0 0 0 _
|
|
1408
|
+
\\ lookup_account A2 0 0 35 0 _
|
|
1409
|
+
\\ commit lookup_accounts
|
|
1410
|
+
|
|
1411
|
+
// Check balances after 1s.
|
|
1412
|
+
\\ tick 1 seconds
|
|
1413
|
+
\\ lookup_account A1 23 0 0 0 _
|
|
1414
|
+
\\ lookup_account A2 0 0 23 0 _
|
|
1415
|
+
\\ commit lookup_accounts
|
|
1416
|
+
|
|
1417
|
+
// Check balances after 1s.
|
|
1418
|
+
\\ tick 1 seconds
|
|
1419
|
+
\\ lookup_account A1 10 0 0 0 _
|
|
1420
|
+
\\ lookup_account A2 0 0 10 0 _
|
|
1421
|
+
\\ commit lookup_accounts
|
|
1422
|
+
|
|
1423
|
+
// Second phase.
|
|
1424
|
+
\\ transfer T101 A1 A2 10 T1 U1 U1 U1 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ ok
|
|
1425
|
+
\\ transfer T102 A1 A2 11 T2 U1 U1 U1 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ pending_transfer_expired
|
|
1426
|
+
\\ transfer T103 A1 A2 12 T3 U1 U1 U1 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ pending_transfer_expired
|
|
1427
|
+
\\ transfer T104 A1 A2 13 T4 U1 U1 U1 _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ pending_transfer_expired
|
|
1428
|
+
\\ commit create_transfers
|
|
1429
|
+
|
|
1430
|
+
// Check final balances.
|
|
1431
|
+
\\ lookup_account A1 0 10 0 0 _
|
|
1432
|
+
\\ lookup_account A2 0 0 0 10 _
|
|
1433
|
+
\\ commit lookup_accounts
|
|
1434
|
+
|
|
1435
|
+
// Check transfers.
|
|
1436
|
+
\\ lookup_transfer T101 exists true
|
|
1437
|
+
\\ lookup_transfer T102 exists false
|
|
1438
|
+
\\ lookup_transfer T103 exists false
|
|
1439
|
+
\\ lookup_transfer T104 exists false
|
|
1440
|
+
\\ commit lookup_transfers
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
test "create_transfers: empty" {
|
|
1445
|
+
try check(
|
|
1446
|
+
\\ commit create_transfers
|
|
1447
|
+
);
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
test "create_transfers/lookup_transfers: failed transfer does not exist" {
|
|
1451
|
+
try check(
|
|
1452
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1453
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1454
|
+
\\ commit create_accounts
|
|
1455
|
+
\\
|
|
1456
|
+
\\ transfer T1 A1 A2 15 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
1457
|
+
\\ transfer T2 A1 A2 15 _ _ _ _ _ L0 C1 _ _ _ _ _ _ _ _ _ _ _ ledger_must_not_be_zero
|
|
1458
|
+
\\ commit create_transfers
|
|
1459
|
+
\\
|
|
1460
|
+
\\ lookup_account A1 0 15 0 0 _
|
|
1461
|
+
\\ lookup_account A2 0 0 0 15 _
|
|
1462
|
+
\\ commit lookup_accounts
|
|
1463
|
+
\\
|
|
1464
|
+
\\ lookup_transfer T1 exists true
|
|
1465
|
+
\\ lookup_transfer T2 exists false
|
|
1466
|
+
\\ commit lookup_transfers
|
|
1467
|
+
);
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
test "create_transfers: failed linked-chains are undone" {
|
|
1471
|
+
try check(
|
|
1472
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1473
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1474
|
+
\\ commit create_accounts
|
|
1475
|
+
\\
|
|
1476
|
+
\\ transfer T1 A1 A2 15 _ _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ _ _ _ linked_event_failed
|
|
1477
|
+
\\ transfer T2 A1 A2 15 _ _ _ _ _ L0 C1 _ _ _ _ _ _ _ _ _ _ _ ledger_must_not_be_zero
|
|
1478
|
+
\\ commit create_transfers
|
|
1479
|
+
\\
|
|
1480
|
+
\\ transfer T3 A1 A2 15 _ _ _ _ 1 L1 C1 LNK PEN _ _ _ _ _ _ _ _ _ linked_event_failed
|
|
1481
|
+
\\ transfer T4 A1 A2 15 _ _ _ _ _ L0 C1 _ _ _ _ _ _ _ _ _ _ _ ledger_must_not_be_zero
|
|
1482
|
+
\\ commit create_transfers
|
|
1483
|
+
\\
|
|
1484
|
+
\\ lookup_account A1 0 0 0 0 _
|
|
1485
|
+
\\ lookup_account A2 0 0 0 0 _
|
|
1486
|
+
\\ commit lookup_accounts
|
|
1487
|
+
\\
|
|
1488
|
+
\\ lookup_transfer T1 exists false
|
|
1489
|
+
\\ lookup_transfer T2 exists false
|
|
1490
|
+
\\ lookup_transfer T3 exists false
|
|
1491
|
+
\\ lookup_transfer T4 exists false
|
|
1492
|
+
\\ commit lookup_transfers
|
|
1493
|
+
);
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
test "create_transfers: failed linked-chains are undone within a commit" {
|
|
1497
|
+
try check(
|
|
1498
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1499
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1500
|
+
\\ commit create_accounts
|
|
1501
|
+
\\
|
|
1502
|
+
\\ setup A1 0 0 0 20
|
|
1503
|
+
\\
|
|
1504
|
+
\\ transfer T1 A1 A2 15 _ _ _ _ _ L1 C1 LNK _ _ _ _ _ _ _ _ _ _ linked_event_failed
|
|
1505
|
+
\\ transfer T2 A1 A2 5 _ _ _ _ _ L0 C1 _ _ _ _ _ _ _ _ _ _ _ ledger_must_not_be_zero
|
|
1506
|
+
\\ transfer T3 A1 A2 15 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
1507
|
+
\\ commit create_transfers
|
|
1508
|
+
\\
|
|
1509
|
+
\\ lookup_account A1 0 15 0 20 _
|
|
1510
|
+
\\ lookup_account A2 0 0 0 15 _
|
|
1511
|
+
\\ commit lookup_accounts
|
|
1512
|
+
\\
|
|
1513
|
+
\\ lookup_transfer T1 exists false
|
|
1514
|
+
\\ lookup_transfer T2 exists false
|
|
1515
|
+
\\ lookup_transfer T3 exists true
|
|
1516
|
+
\\ commit lookup_transfers
|
|
1517
|
+
);
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
test "create_transfers: balancing_debit | balancing_credit (*_must_not_exceed_*)" {
|
|
1521
|
+
try check(
|
|
1522
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1523
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ C<D _ _ _ _ _ ok
|
|
1524
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1525
|
+
\\ commit create_accounts
|
|
1526
|
+
\\
|
|
1527
|
+
\\ setup A1 1 0 0 10
|
|
1528
|
+
\\ setup A2 0 10 2 0
|
|
1529
|
+
\\
|
|
1530
|
+
\\ transfer T1 A1 A3 3 _ _ _ _ _ L2 C1 _ _ _ _ BDR _ _ _ _ _ _ transfer_must_have_the_same_ledger_as_accounts
|
|
1531
|
+
\\ transfer T1 A3 A2 3 _ _ _ _ _ L2 C1 _ _ _ _ _ BCR _ _ _ _ _ transfer_must_have_the_same_ledger_as_accounts
|
|
1532
|
+
\\ transfer T1 A1 A3 3 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ ok
|
|
1533
|
+
\\ transfer T2 A1 A3 13 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ ok
|
|
1534
|
+
\\ transfer T3 A3 A2 3 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ ok
|
|
1535
|
+
\\ transfer T4 A3 A2 13 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ ok
|
|
1536
|
+
\\ transfer T5 A1 A3 1 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ ok // Amount reduced to 0.
|
|
1537
|
+
\\ transfer T6 A1 A3 1 _ _ _ _ _ L1 C1 _ _ _ _ BDR BCR _ _ _ _ _ ok // ↑
|
|
1538
|
+
\\ transfer T7 A3 A2 1 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ ok // ↑
|
|
1539
|
+
\\ transfer T8 A1 A2 1 _ _ _ _ _ L1 C1 _ _ _ _ BDR BCR _ _ _ _ _ ok // ↑
|
|
1540
|
+
\\ transfer T1 A1 A3 2 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ exists_with_different_amount // Less than the transfer amount.
|
|
1541
|
+
\\ transfer T1 A1 A3 0 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ exists_with_different_amount // ↑
|
|
1542
|
+
\\ transfer T1 A1 A3 3 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ exists // Greater-than-or-equal-to the transfer amount.
|
|
1543
|
+
\\ transfer T1 A1 A3 4 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ exists // ↑
|
|
1544
|
+
\\ transfer T2 A1 A3 6 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ exists // Equal to the transfer amount.
|
|
1545
|
+
\\ transfer T2 A1 A3 0 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ exists_with_different_amount // Less than the transfer amount.
|
|
1546
|
+
\\ transfer T3 A3 A2 2 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ exists_with_different_amount // Less than the transfer amount.
|
|
1547
|
+
\\ transfer T3 A3 A2 0 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ exists_with_different_amount // ↑
|
|
1548
|
+
\\ transfer T3 A3 A2 3 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ exists
|
|
1549
|
+
\\ transfer T3 A3 A2 4 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ exists
|
|
1550
|
+
\\ transfer T4 A3 A2 5 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ exists // Greater-than-or-equal-to the transfer amount.
|
|
1551
|
+
\\ transfer T4 A3 A2 6 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ exists // ↑
|
|
1552
|
+
\\ transfer T4 A3 A2 0 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ exists_with_different_amount // Less than the transfer amount.
|
|
1553
|
+
\\ commit create_transfers
|
|
1554
|
+
\\
|
|
1555
|
+
\\ lookup_account A1 1 9 0 10 _
|
|
1556
|
+
\\ lookup_account A2 0 10 2 8 _
|
|
1557
|
+
\\ lookup_account A3 0 8 0 9 _
|
|
1558
|
+
\\ commit lookup_accounts
|
|
1559
|
+
\\
|
|
1560
|
+
\\ lookup_transfer T1 amount 3
|
|
1561
|
+
\\ lookup_transfer T2 amount 6
|
|
1562
|
+
\\ lookup_transfer T3 amount 3
|
|
1563
|
+
\\ lookup_transfer T4 amount 5
|
|
1564
|
+
\\ lookup_transfer T5 amount 0
|
|
1565
|
+
\\ lookup_transfer T6 amount 0
|
|
1566
|
+
\\ lookup_transfer T7 amount 0
|
|
1567
|
+
\\ lookup_transfer T8 amount 0
|
|
1568
|
+
\\ commit lookup_transfers
|
|
1569
|
+
);
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
test "create_transfers: balancing_debit | balancing_credit (*_must_not_exceed_*, exceeds_*)" {
|
|
1573
|
+
try check(
|
|
1574
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1575
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1576
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ C<D _ _ _ _ _ ok
|
|
1577
|
+
\\ account A4 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1578
|
+
\\ commit create_accounts
|
|
1579
|
+
\\
|
|
1580
|
+
\\ setup A1 0 0 0 4
|
|
1581
|
+
\\ setup A2 0 5 0 0
|
|
1582
|
+
\\ setup A3 0 4 0 0
|
|
1583
|
+
\\ setup A4 0 0 0 5
|
|
1584
|
+
\\
|
|
1585
|
+
\\ transfer T1 A1 A2 10 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ exceeds_credits
|
|
1586
|
+
\\ transfer T2 A1 A2 10 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ ok
|
|
1587
|
+
\\ transfer T3 A4 A3 10 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ exceeds_debits
|
|
1588
|
+
\\ transfer T4 A4 A3 10 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ ok
|
|
1589
|
+
\\ commit create_transfers
|
|
1590
|
+
\\
|
|
1591
|
+
\\ lookup_account A1 0 4 0 4 _
|
|
1592
|
+
\\ lookup_account A2 0 5 0 4 _
|
|
1593
|
+
\\ lookup_account A3 0 4 0 4 _
|
|
1594
|
+
\\ lookup_account A4 0 4 0 5 _
|
|
1595
|
+
\\ commit lookup_accounts
|
|
1596
|
+
\\
|
|
1597
|
+
\\ lookup_transfer T1 exists false
|
|
1598
|
+
\\ lookup_transfer T2 amount 4
|
|
1599
|
+
\\ lookup_transfer T3 exists false
|
|
1600
|
+
\\ lookup_transfer T4 amount 4
|
|
1601
|
+
\\ commit lookup_transfers
|
|
1602
|
+
);
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
test "create_transfers: balancing_debit | balancing_credit (¬*_must_not_exceed_*)" {
|
|
1606
|
+
try check(
|
|
1607
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1608
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1609
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1610
|
+
\\ commit create_accounts
|
|
1611
|
+
\\
|
|
1612
|
+
\\ setup A1 1 0 0 10
|
|
1613
|
+
\\ setup A2 0 10 2 0
|
|
1614
|
+
\\
|
|
1615
|
+
\\ transfer T1 A3 A1 99 _ _ _ _ _ L1 C1 _ _ _ _ BDR BCR _ _ _ _ _ ok // Amount reduced to 0.
|
|
1616
|
+
\\ transfer T2 A3 A1 99 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ ok // ↑
|
|
1617
|
+
\\ transfer T3 A2 A3 99 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ ok // ↑
|
|
1618
|
+
\\ transfer T4 A1 A3 99 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ ok
|
|
1619
|
+
\\ transfer T5 A1 A3 99 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ ok // Amount reduced to 0.
|
|
1620
|
+
\\ transfer T6 A3 A2 99 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ ok
|
|
1621
|
+
\\ transfer T7 A3 A2 99 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ ok // Amount reduced to 0.
|
|
1622
|
+
\\ commit create_transfers
|
|
1623
|
+
\\
|
|
1624
|
+
\\ lookup_account A1 1 9 0 10 _
|
|
1625
|
+
\\ lookup_account A2 0 10 2 8 _
|
|
1626
|
+
\\ lookup_account A3 0 8 0 9 _
|
|
1627
|
+
\\ commit lookup_accounts
|
|
1628
|
+
\\
|
|
1629
|
+
\\ lookup_transfer T1 amount 0
|
|
1630
|
+
\\ lookup_transfer T2 amount 0
|
|
1631
|
+
\\ lookup_transfer T3 amount 0
|
|
1632
|
+
\\ lookup_transfer T4 amount 9
|
|
1633
|
+
\\ lookup_transfer T5 amount 0
|
|
1634
|
+
\\ lookup_transfer T6 amount 8
|
|
1635
|
+
\\ lookup_transfer T7 amount 0
|
|
1636
|
+
\\ commit lookup_transfers
|
|
1637
|
+
);
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
test "create_transfers: balancing_debit | balancing_credit (amount=0)" {
|
|
1641
|
+
try check(
|
|
1642
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1643
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ C<D _ _ _ _ _ ok
|
|
1644
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ C<D _ _ _ _ _ ok
|
|
1645
|
+
\\ account A4 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1646
|
+
\\ commit create_accounts
|
|
1647
|
+
\\
|
|
1648
|
+
\\ setup A1 1 0 0 10
|
|
1649
|
+
\\ setup A2 0 10 2 0
|
|
1650
|
+
\\ setup A3 0 10 2 0
|
|
1651
|
+
\\
|
|
1652
|
+
// Test amount=0 transfers:
|
|
1653
|
+
\\ transfer T1 A1 A4 0 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ ok
|
|
1654
|
+
\\ transfer T2 A4 A2 0 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ ok
|
|
1655
|
+
\\ transfer T3 A1 A4 0 _ _ _ _ _ L1 C1 _ _ _ _ BDR BCR _ _ _ _ _ ok
|
|
1656
|
+
\\ transfer T4 A4 A3 0 _ _ _ _ _ L1 C1 _ PEN _ _ _ BCR _ _ _ _ _ ok
|
|
1657
|
+
// The respective balancing flag reduces nonzero amounts to zero even though A4 lacks
|
|
1658
|
+
// must_not_exceed (since its net balance is zero):
|
|
1659
|
+
\\ transfer T5 A4 A1 1 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ ok
|
|
1660
|
+
\\ transfer T6 A2 A4 1 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ ok
|
|
1661
|
+
\\ commit create_transfers
|
|
1662
|
+
\\
|
|
1663
|
+
// None of the accounts' balances have changed -- none of the transfers moved any money.
|
|
1664
|
+
\\ lookup_account A1 1 0 0 10 _
|
|
1665
|
+
\\ lookup_account A2 0 10 2 0 _
|
|
1666
|
+
\\ lookup_account A3 0 10 2 0 _
|
|
1667
|
+
\\ lookup_account A4 0 0 0 0 _
|
|
1668
|
+
\\ commit lookup_accounts
|
|
1669
|
+
\\
|
|
1670
|
+
\\ lookup_transfer T1 amount 0
|
|
1671
|
+
\\ lookup_transfer T2 amount 0
|
|
1672
|
+
\\ lookup_transfer T3 amount 0
|
|
1673
|
+
\\ lookup_transfer T4 amount 0
|
|
1674
|
+
\\ lookup_transfer T5 amount 0
|
|
1675
|
+
\\ lookup_transfer T6 amount 0
|
|
1676
|
+
\\ commit lookup_transfers
|
|
1677
|
+
);
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
test "create_transfers: balancing_debit | balancing_credit (amount=maxInt, balance≈maxInt)" {
|
|
1681
|
+
try check(
|
|
1682
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1683
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1684
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ C<D _ _ _ _ _ ok
|
|
1685
|
+
\\ account A4 0 0 0 0 _ _ _ _ L1 C1 _ _ C<D _ _ _ _ _ ok
|
|
1686
|
+
\\ commit create_accounts
|
|
1687
|
+
\\
|
|
1688
|
+
\\ setup A1 0 0 0 -1
|
|
1689
|
+
\\ setup A4 0 -1 0 0
|
|
1690
|
+
\\
|
|
1691
|
+
\\ transfer T1 A1 A2 -0 _ _ _ _ _ L1 C1 _ _ _ _ BDR _ _ _ _ _ _ ok
|
|
1692
|
+
\\ transfer T2 A3 A4 -0 _ _ _ _ _ L1 C1 _ _ _ _ _ BCR _ _ _ _ _ ok
|
|
1693
|
+
\\ commit create_transfers
|
|
1694
|
+
\\
|
|
1695
|
+
\\ lookup_account A1 0 -1 0 -1 _
|
|
1696
|
+
\\ lookup_account A2 0 0 0 -1 _
|
|
1697
|
+
\\ lookup_account A3 0 -1 0 0 _
|
|
1698
|
+
\\ lookup_account A4 0 -1 0 -1 _
|
|
1699
|
+
\\ commit lookup_accounts
|
|
1700
|
+
\\
|
|
1701
|
+
\\ lookup_transfer T1 amount -1
|
|
1702
|
+
\\ lookup_transfer T2 amount -1
|
|
1703
|
+
\\ commit lookup_transfers
|
|
1704
|
+
);
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
test "create_transfers: balancing_debit & balancing_credit" {
|
|
1708
|
+
try check(
|
|
1709
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1710
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ C<D _ _ _ _ _ ok
|
|
1711
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1712
|
+
\\ commit create_accounts
|
|
1713
|
+
\\
|
|
1714
|
+
\\ setup A1 0 0 0 20
|
|
1715
|
+
\\ setup A2 0 10 0 0
|
|
1716
|
+
\\ setup A3 0 99 0 0
|
|
1717
|
+
\\
|
|
1718
|
+
\\ transfer T1 A1 A2 1 _ _ _ _ _ L1 C1 _ _ _ _ BDR BCR _ _ _ _ _ ok
|
|
1719
|
+
\\ transfer T2 A1 A2 12 _ _ _ _ _ L1 C1 _ _ _ _ BDR BCR _ _ _ _ _ ok
|
|
1720
|
+
\\ transfer T3 A1 A2 1 _ _ _ _ _ L1 C1 _ _ _ _ BDR BCR _ _ _ _ _ ok // Amount reduced to 0.
|
|
1721
|
+
\\ transfer T4 A1 A3 12 _ _ _ _ _ L1 C1 _ _ _ _ BDR BCR _ _ _ _ _ ok
|
|
1722
|
+
\\ transfer T5 A1 A3 1 _ _ _ _ _ L1 C1 _ _ _ _ BDR BCR _ _ _ _ _ ok // Amount reduced to 0.
|
|
1723
|
+
\\ commit create_transfers
|
|
1724
|
+
\\
|
|
1725
|
+
\\ lookup_account A1 0 20 0 20 _
|
|
1726
|
+
\\ lookup_account A2 0 10 0 10 _
|
|
1727
|
+
\\ lookup_account A3 0 99 0 10 _
|
|
1728
|
+
\\ commit lookup_accounts
|
|
1729
|
+
\\
|
|
1730
|
+
\\ lookup_transfer T1 amount 1
|
|
1731
|
+
\\ lookup_transfer T2 amount 9
|
|
1732
|
+
\\ lookup_transfer T3 amount 0
|
|
1733
|
+
\\ lookup_transfer T4 amount 10
|
|
1734
|
+
\\ lookup_transfer T5 amount 0
|
|
1735
|
+
\\ commit lookup_transfers
|
|
1736
|
+
);
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
test "create_transfers: balancing_debit/balancing_credit + pending" {
|
|
1740
|
+
try check(
|
|
1741
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1742
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ C<D _ _ _ _ _ ok
|
|
1743
|
+
\\ commit create_accounts
|
|
1744
|
+
\\
|
|
1745
|
+
\\ setup A1 0 0 0 10
|
|
1746
|
+
\\ setup A2 0 10 0 0
|
|
1747
|
+
\\
|
|
1748
|
+
\\ transfer T1 A1 A2 3 _ _ _ _ _ L1 C1 _ PEN _ _ BDR _ _ _ _ _ _ ok
|
|
1749
|
+
\\ transfer T2 A1 A2 13 _ _ _ _ _ L1 C1 _ PEN _ _ BDR _ _ _ _ _ _ ok
|
|
1750
|
+
\\ transfer T3 A1 A2 1 _ _ _ _ _ L1 C1 _ PEN _ _ BDR _ _ _ _ _ _ ok // Amount reduced to 0.
|
|
1751
|
+
\\ commit create_transfers
|
|
1752
|
+
\\
|
|
1753
|
+
\\ lookup_account A1 10 0 0 10 _
|
|
1754
|
+
\\ lookup_account A2 0 10 10 0 _
|
|
1755
|
+
\\ commit lookup_accounts
|
|
1756
|
+
\\
|
|
1757
|
+
\\ transfer T4 A1 A2 3 T1 _ _ _ _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ ok
|
|
1758
|
+
\\ transfer T5 A1 A2 5 T2 _ _ _ _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ ok
|
|
1759
|
+
\\ commit create_transfers
|
|
1760
|
+
\\
|
|
1761
|
+
\\ lookup_transfer T1 amount 3
|
|
1762
|
+
\\ lookup_transfer T2 amount 7
|
|
1763
|
+
\\ lookup_transfer T3 amount 0
|
|
1764
|
+
\\ lookup_transfer T4 amount 3
|
|
1765
|
+
\\ lookup_transfer T5 amount 5
|
|
1766
|
+
\\ commit lookup_transfers
|
|
1767
|
+
);
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
test "create_transfers: multiple debits, single credit, balancing debits" {
|
|
1771
|
+
// See `recipes/multi-debit-credit-transfers.md`.
|
|
1772
|
+
// Source accounts: A1, A2, A3
|
|
1773
|
+
// Control account: A4
|
|
1774
|
+
// Limit account: A5
|
|
1775
|
+
// Destination account: A6
|
|
1776
|
+
|
|
1777
|
+
// Sufficient funds:
|
|
1778
|
+
try check(
|
|
1779
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1780
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1781
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1782
|
+
\\ account A4 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1783
|
+
\\ account A5 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1784
|
+
\\ account A6 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1785
|
+
\\ commit create_accounts
|
|
1786
|
+
\\
|
|
1787
|
+
\\ setup A1 0 0 0 40
|
|
1788
|
+
\\ setup A2 0 0 0 40
|
|
1789
|
+
\\ setup A3 0 0 0 21
|
|
1790
|
+
\\
|
|
1791
|
+
\\ transfer T1 A4 A5 100 _ _ _ _ 0 L1 C1 LNK _ _ _ _ _ _ _ _ _ _ ok
|
|
1792
|
+
\\ transfer T2 A1 A4 100 _ _ _ _ 0 L1 C1 LNK _ _ _ BDR BCR _ _ _ _ _ ok
|
|
1793
|
+
\\ transfer T3 A2 A4 100 _ _ _ _ 0 L1 C1 LNK _ _ _ BDR BCR _ _ _ _ _ ok
|
|
1794
|
+
\\ transfer T4 A3 A4 100 _ _ _ _ 0 L1 C1 LNK _ _ _ BDR BCR _ _ _ _ _ ok
|
|
1795
|
+
\\ transfer T5 A4 A6 100 _ _ _ _ 0 L1 C1 LNK _ _ _ _ _ _ _ _ _ _ ok
|
|
1796
|
+
\\ transfer T6 A5 A4 -0 _ _ _ _ 0 L1 C1 _ _ _ _ _ BCR _ _ _ _ _ ok
|
|
1797
|
+
\\ commit create_transfers
|
|
1798
|
+
\\
|
|
1799
|
+
\\ lookup_account A1 0 40 0 40 _
|
|
1800
|
+
\\ lookup_account A2 0 40 0 40 _
|
|
1801
|
+
\\ lookup_account A3 0 20 0 21 _
|
|
1802
|
+
\\ lookup_account A4 0 200 0 200 _
|
|
1803
|
+
\\ lookup_account A5 0 100 0 100 _
|
|
1804
|
+
\\ lookup_account A6 0 0 0 100 _
|
|
1805
|
+
\\ commit lookup_accounts
|
|
1806
|
+
);
|
|
1807
|
+
|
|
1808
|
+
// Insufficient funds.
|
|
1809
|
+
try check(
|
|
1810
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1811
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1812
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1813
|
+
\\ account A4 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1814
|
+
\\ account A5 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1815
|
+
\\ account A6 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1816
|
+
\\ commit create_accounts
|
|
1817
|
+
\\
|
|
1818
|
+
\\ setup A1 0 0 0 40
|
|
1819
|
+
\\ setup A2 0 0 0 40
|
|
1820
|
+
\\ setup A3 0 0 0 19
|
|
1821
|
+
\\
|
|
1822
|
+
\\ transfer T1 A4 A5 100 _ _ _ _ 0 L1 C1 LNK _ _ _ _ _ _ _ _ _ _ linked_event_failed
|
|
1823
|
+
\\ transfer T2 A1 A4 100 _ _ _ _ 0 L1 C1 LNK _ _ _ BDR BCR _ _ _ _ _ linked_event_failed
|
|
1824
|
+
\\ transfer T3 A2 A4 100 _ _ _ _ 0 L1 C1 LNK _ _ _ BDR BCR _ _ _ _ _ linked_event_failed
|
|
1825
|
+
\\ transfer T4 A3 A4 100 _ _ _ _ 0 L1 C1 LNK _ _ _ BDR BCR _ _ _ _ _ linked_event_failed
|
|
1826
|
+
\\ transfer T5 A4 A6 100 _ _ _ _ 0 L1 C1 LNK _ _ _ _ _ _ _ _ _ _ linked_event_failed
|
|
1827
|
+
\\ transfer T6 A5 A4 -0 _ _ _ _ 0 L1 C1 _ _ _ _ _ BCR _ _ _ _ _ exceeds_credits
|
|
1828
|
+
\\ commit create_transfers
|
|
1829
|
+
);
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
test "create_transfers: per-transfer balance invariant" {
|
|
1833
|
+
// Temporarily enforce `credits_must_not_exceed_debits` on account `A2`.
|
|
1834
|
+
try check(
|
|
1835
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1836
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1837
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ C<D _ _ _ _ _ ok
|
|
1838
|
+
\\ commit create_accounts
|
|
1839
|
+
\\
|
|
1840
|
+
\\ setup A2 0 40 0 0
|
|
1841
|
+
\\
|
|
1842
|
+
\\ transfer T1 A1 A2 41 _ _ _ _ 0 L1 C1 LNK _ _ _ _ _ _ _ _ _ _ linked_event_failed
|
|
1843
|
+
\\ transfer T2 A2 A3 1 _ _ _ _ 0 L1 C1 LNK PEN _ _ BDR _ _ _ _ _ _ exceeds_debits
|
|
1844
|
+
\\ transfer T3 A2 A3 0 T2 _ _ _ 0 L1 C1 _ _ _ VOI _ _ _ _ _ _ _ linked_event_failed
|
|
1845
|
+
\\ commit create_transfers
|
|
1846
|
+
\\
|
|
1847
|
+
// Ids failed in a linked chain can be reused, but
|
|
1848
|
+
// `exceeds_debits` is a transient error, T2 cannot be reused:
|
|
1849
|
+
\\ transfer T1 A1 A2 0 _ _ _ _ 0 L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
1850
|
+
\\ transfer T2 A2 A3 0 _ _ _ _ 0 L1 C1 _ _ _ _ _ _ _ _ _ _ _ id_already_failed
|
|
1851
|
+
\\ transfer T3 A2 A3 0 _ _ _ _ 0 L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
1852
|
+
\\ commit create_transfers
|
|
1853
|
+
\\
|
|
1854
|
+
\\ transfer T4 A1 A2 40 _ _ _ _ 0 L1 C1 LNK _ _ _ _ _ _ _ _ _ _ ok
|
|
1855
|
+
\\ transfer T5 A2 A3 1 _ _ _ _ 0 L1 C1 LNK PEN _ _ BDR _ _ _ _ _ _ ok
|
|
1856
|
+
\\ transfer T6 A2 A3 0 T5 _ _ _ 0 L1 C1 _ _ _ VOI _ _ _ _ _ _ _ ok
|
|
1857
|
+
\\ commit create_transfers
|
|
1858
|
+
\\
|
|
1859
|
+
\\ lookup_account A1 0 40 0 0 _
|
|
1860
|
+
\\ lookup_account A2 0 40 0 40 _
|
|
1861
|
+
\\ lookup_account A3 0 0 0 0 _
|
|
1862
|
+
\\ commit lookup_accounts
|
|
1863
|
+
);
|
|
1864
|
+
|
|
1865
|
+
// Temporarily enforce `debits_must_not_exceed_credits` on account `A1`.
|
|
1866
|
+
try check(
|
|
1867
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1868
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
1869
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ D<C _ _ _ _ _ _ ok
|
|
1870
|
+
\\ commit create_accounts
|
|
1871
|
+
\\
|
|
1872
|
+
\\ setup A1 0 0 0 40
|
|
1873
|
+
\\
|
|
1874
|
+
\\ transfer T1 A1 A2 41 _ _ _ _ 0 L1 C1 LNK _ _ _ _ _ _ _ _ _ _ linked_event_failed
|
|
1875
|
+
\\ transfer T2 A3 A1 1 _ _ _ _ 0 L1 C1 LNK PEN _ _ _ BCR _ _ _ _ _ exceeds_credits
|
|
1876
|
+
\\ transfer T3 A3 A1 0 T2 _ _ _ 0 L1 C1 _ _ _ VOI _ _ _ _ _ _ _ linked_event_failed
|
|
1877
|
+
\\ commit create_transfers
|
|
1878
|
+
\\
|
|
1879
|
+
// Ids failed in a linked chain can be reused, but
|
|
1880
|
+
// `exceeds_credits` is a transient error, T2 cannot be reused:
|
|
1881
|
+
\\ transfer T1 A1 A2 0 _ _ _ _ 0 L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
1882
|
+
\\ transfer T2 A3 A1 0 _ _ _ _ 0 L1 C1 _ _ _ _ _ _ _ _ _ _ _ id_already_failed
|
|
1883
|
+
\\ transfer T3 A3 A1 0 _ _ _ _ 0 L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
1884
|
+
\\ commit create_transfers
|
|
1885
|
+
\\
|
|
1886
|
+
\\ transfer T4 A1 A2 40 _ _ _ _ 0 L1 C1 LNK _ _ _ _ _ _ _ _ _ _ ok
|
|
1887
|
+
\\ transfer T5 A3 A1 1 _ _ _ _ 0 L1 C1 LNK PEN _ _ _ BCR _ _ _ _ _ ok
|
|
1888
|
+
\\ transfer T6 A3 A1 0 T5 _ _ _ 0 L1 C1 _ _ _ VOI _ _ _ _ _ _ _ ok
|
|
1889
|
+
\\ commit create_transfers
|
|
1890
|
+
\\
|
|
1891
|
+
\\ lookup_account A1 0 40 0 40 _
|
|
1892
|
+
\\ lookup_account A2 0 0 0 40 _
|
|
1893
|
+
\\ lookup_account A3 0 0 0 0 _
|
|
1894
|
+
\\ commit lookup_accounts
|
|
1895
|
+
);
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
test "imported events: imported batch" {
|
|
1899
|
+
try check(
|
|
1900
|
+
\\ tick 10 nanoseconds
|
|
1901
|
+
// The first event determines if the batch is either imported or not.
|
|
1902
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 1 ok
|
|
1903
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ 0 imported_event_expected
|
|
1904
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 2 ok
|
|
1905
|
+
\\ commit create_accounts
|
|
1906
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ 0 ok
|
|
1907
|
+
\\ account A4 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 3 imported_event_not_expected
|
|
1908
|
+
\\ commit create_accounts
|
|
1909
|
+
\\
|
|
1910
|
+
\\ transfer T1 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 10 ok
|
|
1911
|
+
\\ transfer T2 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ _ _ _ _ 0 imported_event_expected
|
|
1912
|
+
\\ commit create_transfers
|
|
1913
|
+
\\ transfer T3 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ _ _ _ _ 0 ok
|
|
1914
|
+
\\ transfer T4 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 0 imported_event_not_expected
|
|
1915
|
+
\\ commit create_transfers
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
test "imported events: timestamp" {
|
|
1920
|
+
try check(
|
|
1921
|
+
\\ tick 10 nanoseconds
|
|
1922
|
+
\\
|
|
1923
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 0 imported_event_timestamp_out_of_range
|
|
1924
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ -1 imported_event_timestamp_out_of_range
|
|
1925
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 99 imported_event_timestamp_must_not_advance
|
|
1926
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 2 ok
|
|
1927
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 1 imported_event_timestamp_must_not_regress
|
|
1928
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 3 ok
|
|
1929
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 9 ok
|
|
1930
|
+
\\ commit create_accounts
|
|
1931
|
+
\\
|
|
1932
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 99 imported_event_timestamp_must_not_advance
|
|
1933
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 1 exists
|
|
1934
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 3 exists
|
|
1935
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 4 exists
|
|
1936
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 9 exists
|
|
1937
|
+
\\ commit create_accounts
|
|
1938
|
+
\\
|
|
1939
|
+
\\ transfer T1 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 0 imported_event_timestamp_out_of_range
|
|
1940
|
+
\\ transfer T1 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ -1 imported_event_timestamp_out_of_range
|
|
1941
|
+
\\ transfer T1 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 99 imported_event_timestamp_must_not_advance
|
|
1942
|
+
\\ transfer T1 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 2 imported_event_timestamp_must_not_regress // The same timestamp as the dr account.
|
|
1943
|
+
\\ transfer T1 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 3 imported_event_timestamp_must_not_regress // The same timestamp as the cr account.
|
|
1944
|
+
\\ transfer T1 A3 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 4 imported_event_timestamp_must_postdate_debit_account
|
|
1945
|
+
\\ transfer T1 A1 A3 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 4 imported_event_timestamp_must_postdate_credit_account
|
|
1946
|
+
\\ transfer T1 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 4 ok
|
|
1947
|
+
\\ transfer T2 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 3 imported_event_timestamp_must_not_regress
|
|
1948
|
+
\\ transfer T2 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 5 ok
|
|
1949
|
+
\\ commit create_transfers
|
|
1950
|
+
\\
|
|
1951
|
+
\\ transfer T2 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 99 imported_event_timestamp_must_not_advance
|
|
1952
|
+
\\ transfer T2 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 4 exists // T2 `exists` regardless different timestamps.
|
|
1953
|
+
\\ transfer T2 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 5 exists
|
|
1954
|
+
\\ transfer T2 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 6 exists
|
|
1955
|
+
\\ commit create_transfers
|
|
1956
|
+
\\
|
|
1957
|
+
\\ transfer T3 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 10 ok
|
|
1958
|
+
\\ commit create_transfers
|
|
1959
|
+
\\
|
|
1960
|
+
\\ account A4 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 10 imported_event_timestamp_must_not_regress // The same timestamp as a transfer.
|
|
1961
|
+
\\ commit create_accounts
|
|
1962
|
+
);
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
test "imported events: pending transfers" {
|
|
1966
|
+
try check(
|
|
1967
|
+
\\ tick 10 nanoseconds
|
|
1968
|
+
\\
|
|
1969
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 1 ok
|
|
1970
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 2 ok
|
|
1971
|
+
\\ commit create_accounts
|
|
1972
|
+
\\
|
|
1973
|
+
\\ transfer T1 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 3 ok
|
|
1974
|
+
\\ transfer T2 A1 A2 4 _ _ _ _ 1 L1 C2 _ PEN _ _ _ _ IMP _ _ _ 4 imported_event_timeout_must_be_zero
|
|
1975
|
+
\\ transfer T2 A1 A2 4 _ _ _ _ 0 L1 C2 _ PEN _ _ _ _ IMP _ _ _ 4 ok
|
|
1976
|
+
\\ commit create_transfers
|
|
1977
|
+
\\
|
|
1978
|
+
\\ lookup_account A1 4 3 0 0 _
|
|
1979
|
+
\\ lookup_account A2 0 0 4 3 _
|
|
1980
|
+
\\ commit lookup_accounts
|
|
1981
|
+
\\
|
|
1982
|
+
\\ transfer T3 A1 A2 4 T2 _ _ _ _ L1 C2 _ _ POS _ _ _ IMP _ _ _ 5 ok
|
|
1983
|
+
\\ commit create_transfers
|
|
1984
|
+
\\
|
|
1985
|
+
\\ lookup_account A1 0 7 0 0 _
|
|
1986
|
+
\\ lookup_account A2 0 0 0 7 _
|
|
1987
|
+
\\ commit lookup_accounts
|
|
1988
|
+
\\
|
|
1989
|
+
\\ lookup_transfer T1 timestamp 3
|
|
1990
|
+
\\ lookup_transfer T2 timestamp 4
|
|
1991
|
+
\\ lookup_transfer T3 timestamp 5
|
|
1992
|
+
\\ commit lookup_transfers
|
|
1993
|
+
);
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
test "imported events: linked chain" {
|
|
1997
|
+
try check(
|
|
1998
|
+
\\ tick 10 nanoseconds
|
|
1999
|
+
\\
|
|
2000
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ IMP _ _ 1 linked_event_failed
|
|
2001
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ IMP _ _ 2 linked_event_failed
|
|
2002
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 0 imported_event_timestamp_out_of_range
|
|
2003
|
+
\\ commit create_accounts
|
|
2004
|
+
\\
|
|
2005
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ IMP _ _ 1 ok
|
|
2006
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 LNK _ _ _ IMP _ _ 2 ok
|
|
2007
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ IMP _ _ 3 ok
|
|
2008
|
+
\\ commit create_accounts
|
|
2009
|
+
\\
|
|
2010
|
+
\\ transfer T1 A1 A2 3 _ _ _ _ _ L1 C2 LNK _ _ _ _ _ IMP _ _ _ 4 linked_event_failed
|
|
2011
|
+
\\ transfer T2 A1 A2 3 _ _ _ _ _ L1 C2 LNK _ _ _ _ _ IMP _ _ _ 5 linked_event_failed
|
|
2012
|
+
\\ transfer T3 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 0 imported_event_timestamp_out_of_range
|
|
2013
|
+
\\ commit create_transfers
|
|
2014
|
+
\\
|
|
2015
|
+
\\ transfer T1 A1 A2 3 _ _ _ _ _ L1 C2 LNK _ _ _ _ _ IMP _ _ _ 4 ok
|
|
2016
|
+
\\ transfer T2 A1 A2 3 _ _ _ _ _ L1 C2 LNK _ _ _ _ _ IMP _ _ _ 5 ok
|
|
2017
|
+
\\ transfer T3 A1 A2 3 _ _ _ _ _ L1 C2 _ _ _ _ _ _ IMP _ _ _ 6 ok
|
|
2018
|
+
\\ commit create_transfers
|
|
2019
|
+
\\
|
|
2020
|
+
\\ lookup_account A1 0 9 0 0 _
|
|
2021
|
+
\\ lookup_account A2 0 0 0 9 _
|
|
2022
|
+
\\ lookup_account A3 0 0 0 0 _
|
|
2023
|
+
\\ commit lookup_accounts
|
|
2024
|
+
\\
|
|
2025
|
+
\\ lookup_transfer T1 timestamp 4
|
|
2026
|
+
\\ lookup_transfer T2 timestamp 5
|
|
2027
|
+
\\ lookup_transfer T3 timestamp 6
|
|
2028
|
+
\\ commit lookup_transfers
|
|
2029
|
+
);
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
test "create_accounts: closed accounts" {
|
|
2033
|
+
try check(
|
|
2034
|
+
// Accounts can be created already closed.
|
|
2035
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ CLSD _ _ ok
|
|
2036
|
+
\\ commit create_accounts
|
|
2037
|
+
\\
|
|
2038
|
+
\\ lookup_account A1 0 0 0 0 CLSD
|
|
2039
|
+
\\ commit lookup_accounts
|
|
2040
|
+
);
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
test "create_transfers: closing accounts" {
|
|
2044
|
+
try check(
|
|
2045
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2046
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2047
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2048
|
+
\\ commit create_accounts
|
|
2049
|
+
\\
|
|
2050
|
+
// Closing the debit account.
|
|
2051
|
+
\\ transfer T1 A1 A2 15 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2052
|
+
\\ transfer T2 A1 A2 0 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ CDR _ _ _ closing_transfer_must_be_pending
|
|
2053
|
+
\\ transfer T2 A1 A2 0 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ CDR _ _ _ ok
|
|
2054
|
+
\\ transfer T2 A1 A2 0 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ CDR _ _ _ exists
|
|
2055
|
+
// `debit_account_already_closed` is a transient error, T3 cannot be reused:
|
|
2056
|
+
\\ transfer T3 A1 A2 5 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ debit_account_already_closed
|
|
2057
|
+
\\ transfer T3 A1 A2 5 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ id_already_failed
|
|
2058
|
+
// `credit_account_already_closed` is a transient error, T4 cannot be reused:
|
|
2059
|
+
\\ transfer T4 A2 A1 5 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ credit_account_already_closed
|
|
2060
|
+
\\ transfer T4 A1 A2 5 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ id_already_failed
|
|
2061
|
+
\\ commit create_transfers
|
|
2062
|
+
\\
|
|
2063
|
+
\\ lookup_account A1 0 15 0 0 CLSD
|
|
2064
|
+
\\ lookup_account A2 0 0 0 15 _
|
|
2065
|
+
\\ commit lookup_accounts
|
|
2066
|
+
// `debit_account_already_closed` is a transient error, T5 cannot be reused:
|
|
2067
|
+
\\ transfer T5 A1 A2 0 T2 _ _ _ _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ debit_account_already_closed
|
|
2068
|
+
\\ transfer T5 A1 A2 0 T2 _ _ _ _ L1 C1 _ _ _ VOI _ _ _ _ _ _ _ id_already_failed
|
|
2069
|
+
\\
|
|
2070
|
+
\\ transfer T6 A1 A2 0 T2 _ _ _ _ L1 C1 _ _ _ VOI _ _ _ _ _ _ _ ok // Re-opening the account.
|
|
2071
|
+
\\ transfer T6 A1 A2 0 T2 _ _ _ _ L1 C1 _ _ _ VOI _ _ _ _ _ _ _ exists
|
|
2072
|
+
\\ transfer T7 A1 A2 5 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2073
|
+
\\ commit create_transfers
|
|
2074
|
+
\\
|
|
2075
|
+
\\ lookup_account A1 0 20 0 0 _
|
|
2076
|
+
\\ lookup_account A2 0 0 0 20 _
|
|
2077
|
+
\\ commit lookup_accounts
|
|
2078
|
+
\\
|
|
2079
|
+
// Closing the credit account with a timeout.
|
|
2080
|
+
// Pending transfer can be voided, but not posted in a closed account.
|
|
2081
|
+
\\ transfer T8 A1 A2 10 _ _ _ _ 1 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
2082
|
+
\\ transfer T9 A1 A2 10 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
2083
|
+
\\ transfer T10 A1 A2 0 _ _ _ _ 2 L1 C1 _ PEN _ _ _ _ _ _ CCR _ _ ok
|
|
2084
|
+
\\ transfer T10 A1 A2 0 _ _ _ _ 2 L1 C1 _ PEN _ _ _ _ _ _ CCR _ _ exists
|
|
2085
|
+
// `credit_account_already_closed` is a transient error, T11 cannot be reused:
|
|
2086
|
+
\\ transfer T11 A1 A2 10 T9 _ _ _ _ L1 C1 _ _ POS _ _ _ _ _ _ _ _ credit_account_already_closed
|
|
2087
|
+
\\ transfer T11 A1 A2 10 T9 _ _ _ _ L1 C1 _ _ _ VOI _ _ _ _ _ _ _ id_already_failed
|
|
2088
|
+
\\
|
|
2089
|
+
\\ transfer T12 A1 A2 10 T9 _ _ _ _ L1 C1 _ _ _ VOI _ _ _ _ _ _ _ ok
|
|
2090
|
+
\\ transfer T12 A1 A2 10 T9 _ _ _ _ L1 C1 _ _ _ VOI _ _ _ _ _ _ _ exists
|
|
2091
|
+
\\ commit create_transfers
|
|
2092
|
+
\\
|
|
2093
|
+
\\ lookup_account A1 10 20 0 0 _
|
|
2094
|
+
\\ lookup_account A2 0 0 10 20 CLSD
|
|
2095
|
+
\\ commit lookup_accounts
|
|
2096
|
+
\\
|
|
2097
|
+
// Pending balance can expire for closed accounts.
|
|
2098
|
+
\\ tick 1 seconds
|
|
2099
|
+
\\ lookup_account A1 0 20 0 0 _
|
|
2100
|
+
\\ lookup_account A2 0 0 0 20 CLSD
|
|
2101
|
+
\\ commit lookup_accounts
|
|
2102
|
+
\\
|
|
2103
|
+
// Pending closing accounts can expire after the timeout.
|
|
2104
|
+
\\ tick 1 seconds
|
|
2105
|
+
\\ lookup_account A1 0 20 0 0 _
|
|
2106
|
+
\\ lookup_account A2 0 0 0 20 _
|
|
2107
|
+
\\ commit lookup_accounts
|
|
2108
|
+
\\
|
|
2109
|
+
// Closing both accounts.
|
|
2110
|
+
\\ transfer T13 A1 A2 0 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ CDR CCR _ _ closing_transfer_must_be_pending
|
|
2111
|
+
\\ transfer T13 A1 A2 0 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ CDR CCR _ _ ok
|
|
2112
|
+
\\ transfer T13 A1 A2 0 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ CDR CCR _ _ exists
|
|
2113
|
+
// `debit_account_already_closed` is a transient error, T14 cannot be reused:
|
|
2114
|
+
\\ transfer T14 A1 A3 5 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ debit_account_already_closed
|
|
2115
|
+
\\ transfer T14 A1 A3 5 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ id_already_failed
|
|
2116
|
+
// `credit_account_already_closed` is a transient error, T15 cannot be reused:
|
|
2117
|
+
\\ transfer T15 A3 A2 5 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ credit_account_already_closed
|
|
2118
|
+
\\ transfer T15 A3 A2 5 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ id_already_failed
|
|
2119
|
+
\\ commit create_transfers
|
|
2120
|
+
\\
|
|
2121
|
+
\\ lookup_account A1 0 20 0 0 CLSD
|
|
2122
|
+
\\ lookup_account A2 0 0 0 20 CLSD
|
|
2123
|
+
\\ commit lookup_accounts
|
|
2124
|
+
\\
|
|
2125
|
+
// Cannot close an already closed account.
|
|
2126
|
+
// `debit_account_already_closed` is a transient error, T16 cannot be reused:
|
|
2127
|
+
\\ transfer T16 A1 A3 0 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ CDR _ _ _ debit_account_already_closed
|
|
2128
|
+
\\ transfer T16 A1 A3 0 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ CDR _ _ _ id_already_failed
|
|
2129
|
+
// `credit_account_already_closed` is a transient error, T17 cannot be reused:
|
|
2130
|
+
\\ transfer T17 A3 A2 0 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ _ CCR _ _ credit_account_already_closed
|
|
2131
|
+
\\ transfer T17 A3 A2 0 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ _ CCR _ _ id_already_failed
|
|
2132
|
+
\\ commit create_transfers
|
|
2133
|
+
);
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
test "get_account_transfers: single-phase" {
|
|
2137
|
+
try check(
|
|
2138
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2139
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2140
|
+
\\ commit create_accounts
|
|
2141
|
+
\\
|
|
2142
|
+
\\ transfer T1 A1 A2 10 _ U1000 U10 U1 _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2143
|
+
\\ transfer T2 A2 A1 11 _ U1001 U10 U2 _ L1 C2 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2144
|
+
\\ transfer T3 A1 A2 12 _ U1000 U20 U2 _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2145
|
+
\\ transfer T4 A2 A1 13 _ U1001 U20 U1 _ L1 C2 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2146
|
+
\\ commit create_transfers
|
|
2147
|
+
\\
|
|
2148
|
+
// Debits + credits, chronological.
|
|
2149
|
+
\\ get_account_transfers A1 _ _ _ _ _ _ 10 DR CR _
|
|
2150
|
+
\\ get_account_transfers_result T1
|
|
2151
|
+
\\ get_account_transfers_result T2
|
|
2152
|
+
\\ get_account_transfers_result T3
|
|
2153
|
+
\\ get_account_transfers_result T4
|
|
2154
|
+
\\ commit get_account_transfers
|
|
2155
|
+
\\
|
|
2156
|
+
// Debits + credits, limit=2.
|
|
2157
|
+
\\ get_account_transfers A1 _ _ _ _ _ _ 2 DR CR _
|
|
2158
|
+
\\ get_account_transfers_result T1
|
|
2159
|
+
\\ get_account_transfers_result T2
|
|
2160
|
+
\\ commit get_account_transfers
|
|
2161
|
+
\\
|
|
2162
|
+
// Debits + credits, timestamp_min>0.
|
|
2163
|
+
\\ get_account_transfers A1 _ _ _ _ T3 _ 10 DR CR _
|
|
2164
|
+
\\ get_account_transfers_result T3
|
|
2165
|
+
\\ get_account_transfers_result T4
|
|
2166
|
+
\\ commit get_account_transfers
|
|
2167
|
+
\\
|
|
2168
|
+
// Debits + credits, timestamp_max>0.
|
|
2169
|
+
\\ get_account_transfers A1 _ _ _ _ _ T2 10 DR CR _
|
|
2170
|
+
\\ get_account_transfers_result T1
|
|
2171
|
+
\\ get_account_transfers_result T2
|
|
2172
|
+
\\ commit get_account_transfers
|
|
2173
|
+
\\
|
|
2174
|
+
// Debits + credits, 0 < timestamp_min ≤ timestamp_max.
|
|
2175
|
+
\\ get_account_transfers A1 _ _ _ _ T2 T3 10 DR CR _
|
|
2176
|
+
\\ get_account_transfers_result T2
|
|
2177
|
+
\\ get_account_transfers_result T3
|
|
2178
|
+
\\ commit get_account_transfers
|
|
2179
|
+
\\
|
|
2180
|
+
// Debits + credits, reverse-chronological.
|
|
2181
|
+
\\ get_account_transfers A1 _ _ _ _ _ _ 10 DR CR REV
|
|
2182
|
+
\\ get_account_transfers_result T4
|
|
2183
|
+
\\ get_account_transfers_result T3
|
|
2184
|
+
\\ get_account_transfers_result T2
|
|
2185
|
+
\\ get_account_transfers_result T1
|
|
2186
|
+
\\ commit get_account_transfers
|
|
2187
|
+
\\
|
|
2188
|
+
// Debits only.
|
|
2189
|
+
\\ get_account_transfers A1 _ _ _ _ _ _ 10 DR _ _
|
|
2190
|
+
\\ get_account_transfers_result T1
|
|
2191
|
+
\\ get_account_transfers_result T3
|
|
2192
|
+
\\ commit get_account_transfers
|
|
2193
|
+
\\
|
|
2194
|
+
// Credits only.
|
|
2195
|
+
\\ get_account_transfers A1 _ _ _ _ _ _ 10 _ CR _
|
|
2196
|
+
\\ get_account_transfers_result T2
|
|
2197
|
+
\\ get_account_transfers_result T4
|
|
2198
|
+
\\ commit get_account_transfers
|
|
2199
|
+
\\
|
|
2200
|
+
// Debits + credits + user_data_128, chronological.
|
|
2201
|
+
\\ get_account_transfers A1 U1001 _ _ _ _ _ 10 DR CR _
|
|
2202
|
+
\\ get_account_transfers_result T2
|
|
2203
|
+
\\ get_account_transfers_result T4
|
|
2204
|
+
\\ commit get_account_transfers
|
|
2205
|
+
\\
|
|
2206
|
+
// Debits + credits + user_data_64, chronological.
|
|
2207
|
+
\\ get_account_transfers A1 _ U10 _ _ _ _ 10 DR CR _
|
|
2208
|
+
\\ get_account_transfers_result T1
|
|
2209
|
+
\\ get_account_transfers_result T2
|
|
2210
|
+
\\ commit get_account_transfers
|
|
2211
|
+
\\
|
|
2212
|
+
// Debits + credits + user_data_32, chronological.
|
|
2213
|
+
\\ get_account_transfers A1 _ _ U1 _ _ _ 10 DR CR _
|
|
2214
|
+
\\ get_account_transfers_result T1
|
|
2215
|
+
\\ get_account_transfers_result T4
|
|
2216
|
+
\\ commit get_account_transfers
|
|
2217
|
+
\\
|
|
2218
|
+
// Debits + credits + code, chronological.
|
|
2219
|
+
\\ get_account_transfers A1 _ _ _ C1 _ _ 10 DR CR _
|
|
2220
|
+
\\ get_account_transfers_result T1
|
|
2221
|
+
\\ get_account_transfers_result T3
|
|
2222
|
+
\\ commit get_account_transfers
|
|
2223
|
+
\\
|
|
2224
|
+
// Debits + credits + all filters, 0 < timestamp_min ≤ timestamp_max, chronological.
|
|
2225
|
+
\\ get_account_transfers A1 U1000 U10 U1 C1 T1 T3 10 DR CR _
|
|
2226
|
+
\\ get_account_transfers_result T1
|
|
2227
|
+
\\ commit get_account_transfers
|
|
2228
|
+
\\
|
|
2229
|
+
// Debits only + all filters, 0 < timestamp_min ≤ timestamp_max, chronological.
|
|
2230
|
+
\\ get_account_transfers A1 U1000 U10 U1 C1 T1 T3 10 DR _ _
|
|
2231
|
+
\\ get_account_transfers_result T1
|
|
2232
|
+
\\ commit get_account_transfers
|
|
2233
|
+
\\
|
|
2234
|
+
// Credits only + all filters, 0 < timestamp_min ≤ timestamp_max, chronological.
|
|
2235
|
+
\\ get_account_transfers A2 U1000 U10 U1 C1 T1 T3 10 _ CR _
|
|
2236
|
+
\\ get_account_transfers_result T1
|
|
2237
|
+
\\ commit get_account_transfers
|
|
2238
|
+
\\
|
|
2239
|
+
// Not found.
|
|
2240
|
+
\\ get_account_transfers A1 U1000 U20 U2 C2 _ _ 10 DR CR _
|
|
2241
|
+
\\ commit get_account_transfers
|
|
2242
|
+
);
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
test "get_account_transfers: two-phase" {
|
|
2246
|
+
try check(
|
|
2247
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ HIST _ _ _ _ ok
|
|
2248
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ HIST _ _ _ _ ok
|
|
2249
|
+
\\ commit create_accounts
|
|
2250
|
+
\\
|
|
2251
|
+
\\ transfer T1 A1 A2 2 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
2252
|
+
\\ transfer T2 A1 A2 1 T1 _ _ _ 0 L1 C1 _ _ POS _ _ _ _ _ _ _ _ ok
|
|
2253
|
+
\\ commit create_transfers
|
|
2254
|
+
\\
|
|
2255
|
+
\\ get_account_transfers A1 _ _ _ _ _ _ 10 DR CR _
|
|
2256
|
+
\\ get_account_transfers_result T1
|
|
2257
|
+
\\ get_account_transfers_result T2
|
|
2258
|
+
\\ commit get_account_transfers
|
|
2259
|
+
);
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
test "get_account_transfers: invalid filter" {
|
|
2263
|
+
try check(
|
|
2264
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2265
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2266
|
+
\\ commit create_accounts
|
|
2267
|
+
\\
|
|
2268
|
+
\\ transfer T1 A1 A2 2 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
2269
|
+
\\ transfer T2 A1 A2 1 T1 _ _ _ 0 L1 C1 _ _ POS _ _ _ _ _ _ _ _ ok
|
|
2270
|
+
\\ commit create_transfers
|
|
2271
|
+
\\
|
|
2272
|
+
// Invalid account.
|
|
2273
|
+
\\ get_account_transfers A3 _ _ _ _ _ _ 10 DR CR _
|
|
2274
|
+
\\ commit get_account_transfers // Empty result.
|
|
2275
|
+
\\
|
|
2276
|
+
// Invalid filter flags.
|
|
2277
|
+
\\ get_account_transfers A1 _ _ _ _ _ _ 10 _ _ _
|
|
2278
|
+
\\ commit get_account_transfers // Empty result.
|
|
2279
|
+
\\
|
|
2280
|
+
// Invalid timestamp_min > timestamp_max.
|
|
2281
|
+
\\ get_account_transfers A1 _ _ _ _ T2 T1 10 DR CR _
|
|
2282
|
+
\\ commit get_account_transfers // Empty result.
|
|
2283
|
+
\\
|
|
2284
|
+
// Invalid limit.
|
|
2285
|
+
\\ get_account_transfers A1 _ _ _ _ _ _ 0 DR CR _
|
|
2286
|
+
\\ commit get_account_transfers // Empty result.
|
|
2287
|
+
\\
|
|
2288
|
+
// Success.
|
|
2289
|
+
\\ get_account_transfers A1 _ _ _ C1 _ _ 10 DR CR _
|
|
2290
|
+
\\ get_account_transfers_result T1
|
|
2291
|
+
\\ get_account_transfers_result T2
|
|
2292
|
+
\\ commit get_account_transfers
|
|
2293
|
+
);
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
test "get_account_balances: single-phase" {
|
|
2297
|
+
try check(
|
|
2298
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ HIST _ _ _ _ ok
|
|
2299
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ HIST _ _ _ _ ok
|
|
2300
|
+
\\ commit create_accounts
|
|
2301
|
+
\\
|
|
2302
|
+
\\ transfer T1 A1 A2 10 _ U1000 U10 U1 _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2303
|
+
\\ transfer T2 A2 A1 11 _ U1001 U10 U2 _ L1 C2 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2304
|
+
\\ transfer T3 A1 A2 12 _ U1000 U20 U2 _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2305
|
+
\\ transfer T4 A2 A1 13 _ U1001 U20 U1 _ L1 C2 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2306
|
+
\\ commit create_transfers
|
|
2307
|
+
\\
|
|
2308
|
+
// Debits + credits, chronological.
|
|
2309
|
+
\\ get_account_balances A1 _ _ _ _ _ _ 10 DR CR _
|
|
2310
|
+
\\ get_account_balances_result T1 0 10 0 0
|
|
2311
|
+
\\ get_account_balances_result T2 0 10 0 11
|
|
2312
|
+
\\ get_account_balances_result T3 0 22 0 11
|
|
2313
|
+
\\ get_account_balances_result T4 0 22 0 24
|
|
2314
|
+
\\ commit get_account_balances
|
|
2315
|
+
\\
|
|
2316
|
+
// Debits + credits, limit=2.
|
|
2317
|
+
\\ get_account_balances A1 _ _ _ _ _ _ 2 DR CR _
|
|
2318
|
+
\\ get_account_balances_result T1 0 10 0 0
|
|
2319
|
+
\\ get_account_balances_result T2 0 10 0 11
|
|
2320
|
+
\\ commit get_account_balances
|
|
2321
|
+
\\
|
|
2322
|
+
// Debits + credits, timestamp_min>0.
|
|
2323
|
+
\\ get_account_balances A1 _ _ _ _ T3 _ 10 DR CR _
|
|
2324
|
+
\\ get_account_balances_result T3 0 22 0 11
|
|
2325
|
+
\\ get_account_balances_result T4 0 22 0 24
|
|
2326
|
+
\\ commit get_account_balances
|
|
2327
|
+
\\
|
|
2328
|
+
// Debits + credits, timestamp_max>0.
|
|
2329
|
+
\\ get_account_balances A1 _ _ _ _ _ T2 10 DR CR _
|
|
2330
|
+
\\ get_account_balances_result T1 0 10 0 0
|
|
2331
|
+
\\ get_account_balances_result T2 0 10 0 11
|
|
2332
|
+
\\ commit get_account_balances
|
|
2333
|
+
\\
|
|
2334
|
+
// Debits + credits, 0 < timestamp_min ≤ timestamp_max.
|
|
2335
|
+
\\ get_account_balances A1 _ _ _ _ T2 T3 10 DR CR _
|
|
2336
|
+
\\ get_account_balances_result T2 0 10 0 11
|
|
2337
|
+
\\ get_account_balances_result T3 0 22 0 11
|
|
2338
|
+
\\ commit get_account_balances
|
|
2339
|
+
\\
|
|
2340
|
+
// Debits + credits, reverse-chronological.
|
|
2341
|
+
\\ get_account_balances A1 _ _ _ _ _ _ 10 DR CR REV
|
|
2342
|
+
\\ get_account_balances_result T4 0 22 0 24
|
|
2343
|
+
\\ get_account_balances_result T3 0 22 0 11
|
|
2344
|
+
\\ get_account_balances_result T2 0 10 0 11
|
|
2345
|
+
\\ get_account_balances_result T1 0 10 0 0
|
|
2346
|
+
\\ commit get_account_balances
|
|
2347
|
+
\\
|
|
2348
|
+
// Debits only.
|
|
2349
|
+
\\ get_account_balances A1 _ _ _ _ _ _ 10 DR _ _
|
|
2350
|
+
\\ get_account_balances_result T1 0 10 0 0
|
|
2351
|
+
\\ get_account_balances_result T3 0 22 0 11
|
|
2352
|
+
\\ commit get_account_balances
|
|
2353
|
+
\\
|
|
2354
|
+
// Credits only.
|
|
2355
|
+
\\ get_account_balances A1 _ _ _ _ _ _ 10 _ CR _
|
|
2356
|
+
\\ get_account_balances_result T2 0 10 0 11
|
|
2357
|
+
\\ get_account_balances_result T4 0 22 0 24
|
|
2358
|
+
\\ commit get_account_balances
|
|
2359
|
+
\\
|
|
2360
|
+
// Debits + credits + user_data_128, chronological.
|
|
2361
|
+
\\ get_account_balances A1 U1001 _ _ _ _ _ 10 DR CR _
|
|
2362
|
+
\\ get_account_balances_result T2 0 10 0 11
|
|
2363
|
+
\\ get_account_balances_result T4 0 22 0 24
|
|
2364
|
+
\\ commit get_account_balances
|
|
2365
|
+
\\
|
|
2366
|
+
// Debits + credits + user_data_64, chronological.
|
|
2367
|
+
\\ get_account_balances A1 _ U10 _ _ _ _ 10 DR CR _
|
|
2368
|
+
\\ get_account_balances_result T1 0 10 0 0
|
|
2369
|
+
\\ get_account_balances_result T2 0 10 0 11
|
|
2370
|
+
\\ commit get_account_balances
|
|
2371
|
+
\\
|
|
2372
|
+
// Debits + credits + user_data_32, chronological.
|
|
2373
|
+
\\ get_account_balances A1 _ _ U1 _ _ _ 10 DR CR _
|
|
2374
|
+
\\ get_account_balances_result T1 0 10 0 0
|
|
2375
|
+
\\ get_account_balances_result T4 0 22 0 24
|
|
2376
|
+
\\ commit get_account_balances
|
|
2377
|
+
\\
|
|
2378
|
+
// Debits + credits + code, chronological.
|
|
2379
|
+
\\ get_account_balances A1 _ _ _ C1 _ _ 10 DR CR _
|
|
2380
|
+
\\ get_account_balances_result T1 0 10 0 0
|
|
2381
|
+
\\ get_account_balances_result T3 0 22 0 11
|
|
2382
|
+
\\ commit get_account_balances
|
|
2383
|
+
\\
|
|
2384
|
+
// Debits + credits + all filters, 0 < timestamp_min ≤ timestamp_max, chronological.
|
|
2385
|
+
\\ get_account_balances A1 U1000 U10 U1 C1 T1 T3 10 DR CR _
|
|
2386
|
+
\\ get_account_balances_result T1 0 10 0 0
|
|
2387
|
+
\\ commit get_account_balances
|
|
2388
|
+
\\
|
|
2389
|
+
// Debits only + all filters, 0 < timestamp_min ≤ timestamp_max, chronological.
|
|
2390
|
+
\\ get_account_balances A1 U1000 U10 U1 C1 T1 T3 10 DR _ _
|
|
2391
|
+
\\ get_account_balances_result T1 0 10 0 0
|
|
2392
|
+
\\ commit get_account_balances
|
|
2393
|
+
\\
|
|
2394
|
+
// Credits only + all filters, 0 < timestamp_min ≤ timestamp_max, chronological.
|
|
2395
|
+
\\ get_account_balances A2 U1000 U10 U1 C1 T1 T3 10 _ CR _
|
|
2396
|
+
\\ get_account_balances_result T1 0 0 0 10
|
|
2397
|
+
\\ commit get_account_balances
|
|
2398
|
+
\\
|
|
2399
|
+
// Not found.
|
|
2400
|
+
\\ get_account_balances A1 U1000 U20 U2 C2 _ _ 10 DR CR _
|
|
2401
|
+
\\ commit get_account_balances
|
|
2402
|
+
);
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2405
|
+
test "get_account_balances: two-phase" {
|
|
2406
|
+
try check(
|
|
2407
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ HIST _ _ _ _ ok
|
|
2408
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ HIST _ _ _ _ ok
|
|
2409
|
+
\\ commit create_accounts
|
|
2410
|
+
\\
|
|
2411
|
+
\\ transfer T1 A1 A2 1 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok
|
|
2412
|
+
\\ transfer T2 A1 A2 1 T1 _ _ _ 0 L1 C1 _ _ POS _ _ _ _ _ _ _ _ ok
|
|
2413
|
+
\\ commit create_transfers
|
|
2414
|
+
\\
|
|
2415
|
+
\\ get_account_balances A1 _ _ _ _ _ _ 10 DR CR _
|
|
2416
|
+
\\ get_account_balances_result T1 1 0 0 0
|
|
2417
|
+
\\ get_account_balances_result T2 0 1 0 0
|
|
2418
|
+
\\ commit get_account_balances
|
|
2419
|
+
);
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
test "get_account_balances: invalid filter" {
|
|
2423
|
+
try check(
|
|
2424
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ HIST _ _ _ _ ok
|
|
2425
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2426
|
+
\\ commit create_accounts
|
|
2427
|
+
\\
|
|
2428
|
+
\\ transfer T1 A1 A2 2 _ _ _ _ 0 L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2429
|
+
\\ transfer T2 A1 A2 1 _ _ _ _ 0 L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2430
|
+
\\ commit create_transfers
|
|
2431
|
+
\\
|
|
2432
|
+
// Invalid account.
|
|
2433
|
+
\\ get_account_balances A3 _ _ _ _ _ _ 10 DR CR _
|
|
2434
|
+
\\ commit get_account_balances // Empty result.
|
|
2435
|
+
\\
|
|
2436
|
+
// Account without flags.history.
|
|
2437
|
+
\\ get_account_balances A2 _ _ _ _ _ _ 10 DR CR _
|
|
2438
|
+
\\ commit get_account_balances // Empty result.
|
|
2439
|
+
\\
|
|
2440
|
+
// Invalid filter flags.
|
|
2441
|
+
\\ get_account_balances A1 _ _ _ _ _ _ 10 _ _ _
|
|
2442
|
+
\\ commit get_account_balances // Empty result.
|
|
2443
|
+
\\
|
|
2444
|
+
// Invalid timestamp_min > timestamp_max.
|
|
2445
|
+
\\ get_account_balances A1 _ _ _ _ T2 T1 10 DR CR _
|
|
2446
|
+
\\ commit get_account_balances // Empty result.
|
|
2447
|
+
\\
|
|
2448
|
+
// Invalid limit.
|
|
2449
|
+
\\ get_account_balances A1 _ _ _ _ _ _ 0 DR CR _
|
|
2450
|
+
\\ commit get_account_balances // Empty result.
|
|
2451
|
+
\\
|
|
2452
|
+
// Success.
|
|
2453
|
+
\\ get_account_balances A1 _ _ _ C1 _ _ 10 DR CR _
|
|
2454
|
+
\\ get_account_balances_result T1 0 2 0 0
|
|
2455
|
+
\\ get_account_balances_result T2 0 3 0 0
|
|
2456
|
+
\\ commit get_account_balances
|
|
2457
|
+
);
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
test "query_accounts" {
|
|
2461
|
+
try check(
|
|
2462
|
+
\\ account A1 0 0 0 0 U1000 U10 U1 _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2463
|
+
\\ account A2 0 0 0 0 U1000 U11 U2 _ L2 C2 _ _ _ _ _ _ _ _ ok
|
|
2464
|
+
\\ account A3 0 0 0 0 U1000 U10 U3 _ L3 C3 _ _ _ _ _ _ _ _ ok
|
|
2465
|
+
\\ account A4 0 0 0 0 U1000 U11 U4 _ L4 C4 _ _ _ _ _ _ _ _ ok
|
|
2466
|
+
\\ account A5 0 0 0 0 U2000 U10 U1 _ L3 C5 _ _ _ _ _ _ _ _ ok
|
|
2467
|
+
\\ account A6 0 0 0 0 U2000 U11 U2 _ L2 C6 _ _ _ _ _ _ _ _ ok
|
|
2468
|
+
\\ account A7 0 0 0 0 U2000 U10 U3 _ L1 C7 _ _ _ _ _ _ _ _ ok
|
|
2469
|
+
\\ account A8 0 0 0 0 U1000 U10 U1 _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2470
|
+
\\ commit create_accounts
|
|
2471
|
+
|
|
2472
|
+
// WHERE user_data_128=1000:
|
|
2473
|
+
\\ query_accounts U1000 U0 U0 L0 C0 _ _ L-0 _
|
|
2474
|
+
\\ query_accounts_result A1 _
|
|
2475
|
+
\\ query_accounts_result A2 _
|
|
2476
|
+
\\ query_accounts_result A3 _
|
|
2477
|
+
\\ query_accounts_result A4 _
|
|
2478
|
+
\\ query_accounts_result A8 _
|
|
2479
|
+
\\ commit query_accounts
|
|
2480
|
+
|
|
2481
|
+
// WHERE user_data_128=1000 ORDER BY DESC:
|
|
2482
|
+
\\ query_accounts U1000 U0 U0 L0 C0 _ _ L-0 REV
|
|
2483
|
+
\\ query_accounts_result A8 _
|
|
2484
|
+
\\ query_accounts_result A4 _
|
|
2485
|
+
\\ query_accounts_result A3 _
|
|
2486
|
+
\\ query_accounts_result A2 _
|
|
2487
|
+
\\ query_accounts_result A1 _
|
|
2488
|
+
\\ commit query_accounts
|
|
2489
|
+
|
|
2490
|
+
// WHERE user_data_64=10 AND user_data_32=3
|
|
2491
|
+
\\ query_accounts U0 U10 U3 L0 C0 _ _ L-0 _
|
|
2492
|
+
\\ query_accounts_result A3 _
|
|
2493
|
+
\\ query_accounts_result A7 _
|
|
2494
|
+
\\ commit query_accounts
|
|
2495
|
+
|
|
2496
|
+
// WHERE user_data_64=10 AND user_data_32=3 ORDER BY DESC:
|
|
2497
|
+
\\ query_accounts U0 U10 U3 L0 C0 _ _ L-0 REV
|
|
2498
|
+
\\ query_accounts_result A7 _
|
|
2499
|
+
\\ query_accounts_result A3 _
|
|
2500
|
+
\\ commit query_accounts
|
|
2501
|
+
|
|
2502
|
+
// WHERE user_data_64=11 AND user_data_32=2 AND code=2:
|
|
2503
|
+
\\ query_accounts U0 U11 U2 L2 C0 _ _ L-0 _
|
|
2504
|
+
\\ query_accounts_result A2 _
|
|
2505
|
+
\\ query_accounts_result A6 _
|
|
2506
|
+
\\ commit query_accounts
|
|
2507
|
+
|
|
2508
|
+
// WHERE user_data_64=11 AND user_data_32=2 AND code=2 ORDER BY DESC:
|
|
2509
|
+
\\ query_accounts U0 U11 U2 L2 C0 _ _ L-0 REV
|
|
2510
|
+
\\ query_accounts_result A6 _
|
|
2511
|
+
\\ query_accounts_result A2 _
|
|
2512
|
+
\\ commit query_accounts
|
|
2513
|
+
|
|
2514
|
+
// WHERE user_data_128=1000 AND user_data_64=10
|
|
2515
|
+
// AND user_data_32=1 AND ledger=1 AND code=1:
|
|
2516
|
+
\\ query_accounts U1000 U10 U1 L1 C1 _ _ L-0 _
|
|
2517
|
+
\\ query_accounts_result A1 _
|
|
2518
|
+
\\ query_accounts_result A8 _
|
|
2519
|
+
\\ commit query_accounts
|
|
2520
|
+
|
|
2521
|
+
// WHERE user_data_128=1000 AND user_data_64=10
|
|
2522
|
+
// AND user_data_32=1 AND ledger=1 AND code=1 ORDER BY DESC:
|
|
2523
|
+
\\ query_accounts U1000 U10 U1 L1 C1 _ _ L-0 REV
|
|
2524
|
+
\\ query_accounts_result A8 _
|
|
2525
|
+
\\ query_accounts_result A1 _
|
|
2526
|
+
\\ commit query_accounts
|
|
2527
|
+
|
|
2528
|
+
// WHERE user_data_128=1000 AND timestamp >= A3.timestamp:
|
|
2529
|
+
\\ query_accounts U1000 U0 U0 L0 C0 A3 _ L-0 _
|
|
2530
|
+
\\ query_accounts_result A3 _
|
|
2531
|
+
\\ query_accounts_result A4 _
|
|
2532
|
+
\\ query_accounts_result A8 _
|
|
2533
|
+
\\ commit query_accounts
|
|
2534
|
+
|
|
2535
|
+
// WHERE user_data_128=1000 AND timestamp <= A3.timestamp:
|
|
2536
|
+
\\ query_accounts U1000 U0 U0 L0 C0 _ A3 L-0 _
|
|
2537
|
+
\\ query_accounts_result A1 _
|
|
2538
|
+
\\ query_accounts_result A2 _
|
|
2539
|
+
\\ query_accounts_result A3 _
|
|
2540
|
+
\\ commit query_accounts
|
|
2541
|
+
|
|
2542
|
+
// WHERE user_data_128=1000 AND timestamp BETWEEN A2.timestamp AND A4.timestamp:
|
|
2543
|
+
\\ query_accounts U1000 U0 U0 L0 C0 A2 A4 L-0 _
|
|
2544
|
+
\\ query_accounts_result A2 _
|
|
2545
|
+
\\ query_accounts_result A3 _
|
|
2546
|
+
\\ query_accounts_result A4 _
|
|
2547
|
+
\\ commit query_accounts
|
|
2548
|
+
|
|
2549
|
+
// SELECT * :
|
|
2550
|
+
\\ query_accounts U0 U0 U0 L0 C0 _ _ L-0 _
|
|
2551
|
+
\\ query_accounts_result A1 _
|
|
2552
|
+
\\ query_accounts_result A2 _
|
|
2553
|
+
\\ query_accounts_result A3 _
|
|
2554
|
+
\\ query_accounts_result A4 _
|
|
2555
|
+
\\ query_accounts_result A5 _
|
|
2556
|
+
\\ query_accounts_result A6 _
|
|
2557
|
+
\\ query_accounts_result A7 _
|
|
2558
|
+
\\ query_accounts_result A8 _
|
|
2559
|
+
\\ commit query_accounts
|
|
2560
|
+
|
|
2561
|
+
// SELECT * ORDER BY DESC:
|
|
2562
|
+
\\ query_accounts U0 U0 U0 L0 C0 _ _ L-0 REV
|
|
2563
|
+
\\ query_accounts_result A8 _
|
|
2564
|
+
\\ query_accounts_result A7 _
|
|
2565
|
+
\\ query_accounts_result A6 _
|
|
2566
|
+
\\ query_accounts_result A5 _
|
|
2567
|
+
\\ query_accounts_result A4 _
|
|
2568
|
+
\\ query_accounts_result A3 _
|
|
2569
|
+
\\ query_accounts_result A2 _
|
|
2570
|
+
\\ query_accounts_result A1 _
|
|
2571
|
+
\\ commit query_accounts
|
|
2572
|
+
|
|
2573
|
+
// SELECT * WHERE timestamp >= A2.timestamp LIMIT 3:
|
|
2574
|
+
\\ query_accounts U0 U0 U0 L0 C0 A2 _ L3 _
|
|
2575
|
+
\\ query_accounts_result A2 _
|
|
2576
|
+
\\ query_accounts_result A3 _
|
|
2577
|
+
\\ query_accounts_result A4 _
|
|
2578
|
+
\\ commit query_accounts
|
|
2579
|
+
|
|
2580
|
+
// SELECT * LIMIT 1:
|
|
2581
|
+
\\ query_accounts U0 U0 U0 L0 C0 _ _ L1 _
|
|
2582
|
+
\\ query_accounts_result A1 _
|
|
2583
|
+
\\ commit query_accounts
|
|
2584
|
+
|
|
2585
|
+
// SELECT * ORDER BY DESC LIMIT 1:
|
|
2586
|
+
\\ query_accounts U0 U0 U0 L0 C0 _ _ L1 REV
|
|
2587
|
+
\\ query_accounts_result A8 _
|
|
2588
|
+
\\ commit query_accounts
|
|
2589
|
+
|
|
2590
|
+
// NOT FOUND:
|
|
2591
|
+
|
|
2592
|
+
// SELECT * LIMIT 0:
|
|
2593
|
+
\\ query_accounts U0 U0 U0 L0 C0 _ _ L0 _
|
|
2594
|
+
\\ commit query_accounts
|
|
2595
|
+
|
|
2596
|
+
// WHERE user_data_128=3000
|
|
2597
|
+
\\ query_accounts U3000 U0 U0 L0 C0 _ _ L-0 _
|
|
2598
|
+
\\ commit query_accounts
|
|
2599
|
+
|
|
2600
|
+
// WHERE user_data_128=1000 AND code=5
|
|
2601
|
+
\\ query_accounts U1000 U0 U0 L0 C5 _ _ L-0 _
|
|
2602
|
+
\\ commit query_accounts
|
|
2603
|
+
|
|
2604
|
+
// WHERE user_data_128=1000 AND user_data_64=10
|
|
2605
|
+
// AND user_data_32=1 AND ledger=1 AND code=2:
|
|
2606
|
+
\\ query_accounts U1000 U10 U1 L1 C2 _ _ L-0 _
|
|
2607
|
+
\\ commit query_accounts
|
|
2608
|
+
|
|
2609
|
+
// WHERE user_data_128=1000 AND timestamp BETWEEN A5.timestamp AND A7.timestamp:
|
|
2610
|
+
\\ query_accounts U1000 U0 U0 L0 C0 A5 A7 L-0 _
|
|
2611
|
+
\\ commit query_accounts
|
|
2612
|
+
);
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
test "query_transfers" {
|
|
2616
|
+
try check(
|
|
2617
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2618
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2619
|
+
\\ account A3 0 0 0 0 _ _ _ _ L2 C1 _ _ _ _ _ _ _ _ ok
|
|
2620
|
+
\\ account A4 0 0 0 0 _ _ _ _ L2 C1 _ _ _ _ _ _ _ _ ok
|
|
2621
|
+
\\ commit create_accounts
|
|
2622
|
+
|
|
2623
|
+
// Creating transfers:
|
|
2624
|
+
\\ transfer T1 A1 A2 0 _ U1000 U10 U1 _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2625
|
+
\\ transfer T2 A3 A4 11 _ U1000 U11 U2 _ L2 C2 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2626
|
+
\\ transfer T3 A2 A1 12 _ U1000 U10 U3 _ L1 C3 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2627
|
+
\\ transfer T4 A4 A3 13 _ U1000 U11 U4 _ L2 C4 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2628
|
+
\\ transfer T5 A2 A1 14 _ U2000 U10 U1 _ L1 C5 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2629
|
+
\\ transfer T6 A4 A3 15 _ U2000 U11 U2 _ L2 C6 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2630
|
+
\\ transfer T7 A1 A2 16 _ U2000 U10 U3 _ L1 C7 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2631
|
+
\\ transfer T8 A2 A1 17 _ U1000 U10 U1 _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok
|
|
2632
|
+
\\ commit create_transfers
|
|
2633
|
+
|
|
2634
|
+
// WHERE user_data_128=1000:
|
|
2635
|
+
\\ query_transfers U1000 U0 U0 L0 C0 _ _ L-0 _
|
|
2636
|
+
\\ query_transfers_result T1
|
|
2637
|
+
\\ query_transfers_result T2
|
|
2638
|
+
\\ query_transfers_result T3
|
|
2639
|
+
\\ query_transfers_result T4
|
|
2640
|
+
\\ query_transfers_result T8
|
|
2641
|
+
\\ commit query_transfers
|
|
2642
|
+
|
|
2643
|
+
// WHERE user_data_128=1000 ORDER BY DESC:
|
|
2644
|
+
\\ query_transfers U1000 U0 U0 L0 C0 _ _ L-0 REV
|
|
2645
|
+
\\ query_transfers_result T8
|
|
2646
|
+
\\ query_transfers_result T4
|
|
2647
|
+
\\ query_transfers_result T3
|
|
2648
|
+
\\ query_transfers_result T2
|
|
2649
|
+
\\ query_transfers_result T1
|
|
2650
|
+
\\ commit query_transfers
|
|
2651
|
+
|
|
2652
|
+
// WHERE user_data_64=10 AND user_data_32=3
|
|
2653
|
+
\\ query_transfers U0 U10 U3 L0 C0 _ _ L-0 _
|
|
2654
|
+
\\ query_transfers_result T3
|
|
2655
|
+
\\ query_transfers_result T7
|
|
2656
|
+
\\ commit query_transfers
|
|
2657
|
+
|
|
2658
|
+
// WHERE user_data_64=10 AND user_data_32=3 ORDER BY DESC:
|
|
2659
|
+
\\ query_transfers U0 U10 U3 L0 C0 _ _ L-0 REV
|
|
2660
|
+
\\ query_transfers_result T7
|
|
2661
|
+
\\ query_transfers_result T3
|
|
2662
|
+
\\ commit query_transfers
|
|
2663
|
+
|
|
2664
|
+
// WHERE user_data_64=11 AND user_data_32=2 AND code=2:
|
|
2665
|
+
\\ query_transfers U0 U11 U2 L2 C0 _ _ L-0 _
|
|
2666
|
+
\\ query_transfers_result T2
|
|
2667
|
+
\\ query_transfers_result T6
|
|
2668
|
+
\\ commit query_transfers
|
|
2669
|
+
|
|
2670
|
+
// WHERE user_data_64=11 AND user_data_32=2 AND code=2 ORDER BY DESC:
|
|
2671
|
+
\\ query_transfers U0 U11 U2 L2 C0 _ _ L-0 REV
|
|
2672
|
+
\\ query_transfers_result T6
|
|
2673
|
+
\\ query_transfers_result T2
|
|
2674
|
+
\\ commit query_transfers
|
|
2675
|
+
|
|
2676
|
+
// WHERE user_data_128=1000 AND user_data_64=10
|
|
2677
|
+
// AND user_data_32=1 AND ledger=1 AND code=1:
|
|
2678
|
+
\\ query_transfers U1000 U10 U1 L1 C1 _ _ L-0 _
|
|
2679
|
+
\\ query_transfers_result T1
|
|
2680
|
+
\\ query_transfers_result T8
|
|
2681
|
+
\\ commit query_transfers
|
|
2682
|
+
|
|
2683
|
+
// WHERE user_data_128=1000 AND user_data_64=10
|
|
2684
|
+
// AND user_data_32=1 AND ledger=1 AND code=1 ORDER BY DESC:
|
|
2685
|
+
\\ query_transfers U1000 U10 U1 L1 C1 _ _ L-0 REV
|
|
2686
|
+
\\ query_transfers_result T8
|
|
2687
|
+
\\ query_transfers_result T1
|
|
2688
|
+
\\ commit query_transfers
|
|
2689
|
+
|
|
2690
|
+
// WHERE user_data_128=1000 AND timestamp >= T3.timestamp:
|
|
2691
|
+
\\ query_transfers U1000 U0 U0 L0 C0 A3 _ L-0 _
|
|
2692
|
+
\\ query_transfers_result T3
|
|
2693
|
+
\\ query_transfers_result T4
|
|
2694
|
+
\\ query_transfers_result T8
|
|
2695
|
+
\\ commit query_transfers
|
|
2696
|
+
|
|
2697
|
+
// WHERE user_data_128=1000 AND timestamp <= T3.timestamp:
|
|
2698
|
+
\\ query_transfers U1000 U0 U0 L0 C0 _ A3 L-0 _
|
|
2699
|
+
\\ query_transfers_result T1
|
|
2700
|
+
\\ query_transfers_result T2
|
|
2701
|
+
\\ query_transfers_result T3
|
|
2702
|
+
\\ commit query_transfers
|
|
2703
|
+
|
|
2704
|
+
// WHERE user_data_128=1000 AND timestamp BETWEEN T2.timestamp AND T4.timestamp:
|
|
2705
|
+
\\ query_transfers U1000 U0 U0 L0 C0 A2 A4 L-0 _
|
|
2706
|
+
\\ query_transfers_result T2
|
|
2707
|
+
\\ query_transfers_result T3
|
|
2708
|
+
\\ query_transfers_result T4
|
|
2709
|
+
\\ commit query_transfers
|
|
2710
|
+
|
|
2711
|
+
// SELECT * :
|
|
2712
|
+
\\ query_transfers U0 U0 U0 L0 C0 _ _ L-0 _
|
|
2713
|
+
\\ query_transfers_result T1
|
|
2714
|
+
\\ query_transfers_result T2
|
|
2715
|
+
\\ query_transfers_result T3
|
|
2716
|
+
\\ query_transfers_result T4
|
|
2717
|
+
\\ query_transfers_result T5
|
|
2718
|
+
\\ query_transfers_result T6
|
|
2719
|
+
\\ query_transfers_result T7
|
|
2720
|
+
\\ query_transfers_result T8
|
|
2721
|
+
\\ commit query_transfers
|
|
2722
|
+
|
|
2723
|
+
// SELECT * ORDER BY DESC:
|
|
2724
|
+
\\ query_transfers U0 U0 U0 L0 C0 _ _ L-0 REV
|
|
2725
|
+
\\ query_transfers_result T8
|
|
2726
|
+
\\ query_transfers_result T7
|
|
2727
|
+
\\ query_transfers_result T6
|
|
2728
|
+
\\ query_transfers_result T5
|
|
2729
|
+
\\ query_transfers_result T4
|
|
2730
|
+
\\ query_transfers_result T3
|
|
2731
|
+
\\ query_transfers_result T2
|
|
2732
|
+
\\ query_transfers_result T1
|
|
2733
|
+
\\ commit query_transfers
|
|
2734
|
+
|
|
2735
|
+
// SELECT * WHERE timestamp >= A2.timestamp LIMIT 3:
|
|
2736
|
+
\\ query_transfers U0 U0 U0 L0 C0 A2 _ L3 _
|
|
2737
|
+
\\ query_transfers_result T2
|
|
2738
|
+
\\ query_transfers_result T3
|
|
2739
|
+
\\ query_transfers_result T4
|
|
2740
|
+
\\ commit query_transfers
|
|
2741
|
+
|
|
2742
|
+
// SELECT * LIMIT 1:
|
|
2743
|
+
\\ query_transfers U0 U0 U0 L0 C0 _ _ L1 _
|
|
2744
|
+
\\ query_transfers_result T1
|
|
2745
|
+
\\ commit query_transfers
|
|
2746
|
+
|
|
2747
|
+
// SELECT * ORDER BY DESC LIMIT 1:
|
|
2748
|
+
\\ query_transfers U0 U0 U0 L0 C0 _ _ L1 REV
|
|
2749
|
+
\\ query_transfers_result T8
|
|
2750
|
+
\\ commit query_transfers
|
|
2751
|
+
|
|
2752
|
+
// NOT FOUND:
|
|
2753
|
+
|
|
2754
|
+
// SELECT * LIMIT 0:
|
|
2755
|
+
\\ query_transfers U0 U0 U0 L0 C0 _ _ L0 _
|
|
2756
|
+
\\ commit query_transfers
|
|
2757
|
+
|
|
2758
|
+
// WHERE user_data_128=3000
|
|
2759
|
+
\\ query_transfers U3000 U0 U0 L0 C0 _ _ L-0 _
|
|
2760
|
+
\\ commit query_transfers
|
|
2761
|
+
|
|
2762
|
+
// WHERE user_data_128=1000 AND code=5
|
|
2763
|
+
\\ query_transfers U1000 U0 U0 L0 C5 _ _ L-0 _
|
|
2764
|
+
\\ commit query_transfers
|
|
2765
|
+
|
|
2766
|
+
// WHERE user_data_128=1000 AND user_data_64=10
|
|
2767
|
+
// AND user_data_32=1 AND ledger=1 AND code=2:
|
|
2768
|
+
\\ query_transfers U1000 U10 U1 L1 C2 _ _ L-0 _
|
|
2769
|
+
\\ commit query_transfers
|
|
2770
|
+
|
|
2771
|
+
// WHERE user_data_128=1000 AND timestamp BETWEEN T5.timestamp AND T7.timestamp:
|
|
2772
|
+
\\ query_transfers U1000 U0 U0 L0 C0 A5 A7 L-0 _
|
|
2773
|
+
\\ commit query_transfers
|
|
2774
|
+
);
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
test "get_change_events" {
|
|
2778
|
+
try check(
|
|
2779
|
+
\\ account A1 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2780
|
+
\\ account A2 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2781
|
+
\\ account A3 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2782
|
+
\\ account A4 0 0 0 0 _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ ok
|
|
2783
|
+
\\ commit create_accounts
|
|
2784
|
+
|
|
2785
|
+
// First phase.
|
|
2786
|
+
\\ transfer T1 A1 A2 10 _ _ _ _ _ L1 C1 _ _ _ _ _ _ _ _ _ _ _ ok // Not pending.
|
|
2787
|
+
\\ transfer T2 A1 A2 11 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok // Timeout zero will never expire.
|
|
2788
|
+
\\ transfer T3 A1 A2 12 _ _ _ _ 1 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok // Will expire.
|
|
2789
|
+
\\ transfer T4 A1 A2 13 _ _ _ _ 2 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok // Will be posted.
|
|
2790
|
+
\\ transfer T5 A1 A2 14 _ _ _ _ 2 L1 C1 _ PEN _ _ _ _ _ _ _ _ _ ok // Will be voided.
|
|
2791
|
+
// Closes the debit and credit accounts.
|
|
2792
|
+
\\ transfer T6 A3 A1 0 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ CDR _ _ _ ok
|
|
2793
|
+
\\ transfer T7 A1 A4 0 _ _ _ _ 0 L1 C1 _ PEN _ _ _ _ _ _ CCR _ _ ok
|
|
2794
|
+
\\ commit create_transfers
|
|
2795
|
+
|
|
2796
|
+
// Bump the state machine time in +1s for testing the timeout expiration.
|
|
2797
|
+
\\ tick 1 seconds
|
|
2798
|
+
|
|
2799
|
+
// Second phase.
|
|
2800
|
+
\\ transfer T14 A0 A0 -0 T4 _ _ _ _ L0 C0 _ _ POS _ _ _ _ _ _ _ _ ok // Posts T4.
|
|
2801
|
+
\\ transfer T15 A0 A0 0 T5 _ _ _ _ L0 C0 _ _ _ VOI _ _ _ _ _ _ _ ok // Voids T5.
|
|
2802
|
+
// Reopens the debit and credit accounts.
|
|
2803
|
+
\\ transfer T16 A0 A0 0 T6 _ _ _ _ L0 C0 _ _ _ VOI _ _ _ _ _ _ _ ok
|
|
2804
|
+
\\ transfer T17 A0 A0 0 T7 _ _ _ _ L0 C0 _ _ _ VOI _ _ _ _ _ _ _ ok
|
|
2805
|
+
\\ commit create_transfers
|
|
2806
|
+
|
|
2807
|
+
// Check the events.
|
|
2808
|
+
\\ get_change_events _ T6 5
|
|
2809
|
+
\\ get_change_events_result _ T1 10 _ D1 0 10 0 0 _ C2 0 0 0 10 _
|
|
2810
|
+
\\ get_change_events_result PEN T2 11 _ D1 11 10 0 0 _ C2 0 0 11 10 _
|
|
2811
|
+
\\ get_change_events_result PEN T3 12 _ D1 23 10 0 0 _ C2 0 0 23 10 _
|
|
2812
|
+
\\ get_change_events_result PEN T4 13 _ D1 36 10 0 0 _ C2 0 0 36 10 _
|
|
2813
|
+
\\ get_change_events_result PEN T5 14 _ D1 50 10 0 0 _ C2 0 0 50 10 _
|
|
2814
|
+
\\ commit get_change_events
|
|
2815
|
+
\\
|
|
2816
|
+
\\ get_change_events T6 _ -0
|
|
2817
|
+
\\ get_change_events_result PEN T6 0 _ D3 0 0 0 0 CLSD A1 50 10 0 0 _
|
|
2818
|
+
\\ get_change_events_result PEN T7 0 _ D1 50 10 0 0 _ C4 0 0 0 0 CLSD
|
|
2819
|
+
\\ get_change_events_result EXP _ 12 T3 D1 38 10 0 0 _ C2 0 0 38 10 _
|
|
2820
|
+
\\ get_change_events_result POS T14 13 T4 D1 25 23 0 0 _ C2 0 0 25 23 _
|
|
2821
|
+
\\ get_change_events_result VOI T15 14 T5 D1 11 23 0 0 _ C2 0 0 11 23 _
|
|
2822
|
+
\\ get_change_events_result VOI T16 0 T6 D3 0 0 0 0 _ C1 11 23 0 0 _
|
|
2823
|
+
\\ get_change_events_result VOI T17 0 T7 D1 11 23 0 0 _ C4 0 0 0 0 _
|
|
2824
|
+
\\ commit get_change_events
|
|
2825
|
+
);
|
|
2826
|
+
}
|
|
2827
|
+
|
|
2828
|
+
// Sanity test to check the maximum batch size.
|
|
2829
|
+
// For a comprehensive test of all operations, see the `input_valid` test.
|
|
2830
|
+
test "StateMachine: batch_elements_max" {
|
|
2831
|
+
const Operation = vsr.tigerbeetle.Operation;
|
|
2832
|
+
|
|
2833
|
+
const events_max: u32 = @divExact(
|
|
2834
|
+
constants.message_body_size_max,
|
|
2835
|
+
@max(@sizeOf(Account), @sizeOf(Transfer)),
|
|
2836
|
+
);
|
|
2837
|
+
|
|
2838
|
+
// No multi-batch encode.
|
|
2839
|
+
try testing.expectEqual(events_max, Operation.deprecated_create_accounts_unbatched.event_max(
|
|
2840
|
+
constants.message_body_size_max,
|
|
2841
|
+
));
|
|
2842
|
+
try testing.expectEqual(events_max, Operation.deprecated_lookup_accounts_unbatched.event_max(
|
|
2843
|
+
constants.message_body_size_max,
|
|
2844
|
+
));
|
|
2845
|
+
try testing.expectEqual(events_max, Operation.deprecated_create_transfers_unbatched.event_max(
|
|
2846
|
+
constants.message_body_size_max,
|
|
2847
|
+
));
|
|
2848
|
+
try testing.expectEqual(events_max, Operation.deprecated_lookup_transfers_unbatched.event_max(
|
|
2849
|
+
constants.message_body_size_max,
|
|
2850
|
+
));
|
|
2851
|
+
|
|
2852
|
+
// Multi-batch encoded (the size corresponding to one element is occupied by the trailer).
|
|
2853
|
+
try testing.expectEqual(events_max - 1, Operation.create_accounts.event_max(
|
|
2854
|
+
constants.message_body_size_max,
|
|
2855
|
+
));
|
|
2856
|
+
try testing.expectEqual(events_max - 1, Operation.create_transfers.event_max(
|
|
2857
|
+
constants.message_body_size_max,
|
|
2858
|
+
));
|
|
2859
|
+
try testing.expectEqual(events_max - 1, Operation.lookup_accounts.event_max(
|
|
2860
|
+
constants.message_body_size_max,
|
|
2861
|
+
));
|
|
2862
|
+
try testing.expectEqual(events_max - 1, Operation.lookup_transfers.event_max(
|
|
2863
|
+
constants.message_body_size_max,
|
|
2864
|
+
));
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2867
|
+
// Tests the input validation logic for both multi-batch encoded messages and
|
|
2868
|
+
// the former single-batch format.
|
|
2869
|
+
test "StateMachine: input_valid" {
|
|
2870
|
+
const allocator = std.testing.allocator;
|
|
2871
|
+
const input = try allocator.alignedAlloc(u8, 16, 2 * constants.message_body_size_max);
|
|
2872
|
+
defer allocator.free(input);
|
|
2873
|
+
|
|
2874
|
+
const build_input = struct {
|
|
2875
|
+
fn build_input(buffer: []align(16) u8, options: struct {
|
|
2876
|
+
operation: TestContext.StateMachine.Operation,
|
|
2877
|
+
event_count: u32,
|
|
2878
|
+
}) []align(16) const u8 {
|
|
2879
|
+
const event_size = options.operation.event_size();
|
|
2880
|
+
const payload_size: u32 = options.event_count * event_size;
|
|
2881
|
+
if (options.operation.is_multi_batch()) {
|
|
2882
|
+
var body_encoder = vsr.multi_batch.MultiBatchEncoder.init(buffer, .{
|
|
2883
|
+
.element_size = event_size,
|
|
2884
|
+
});
|
|
2885
|
+
assert(payload_size <= body_encoder.writable().?.len);
|
|
2886
|
+
body_encoder.add(payload_size);
|
|
2887
|
+
const bytes_written = body_encoder.finish();
|
|
2888
|
+
assert(bytes_written > 0);
|
|
2889
|
+
return buffer[0..bytes_written];
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2892
|
+
return buffer[0..payload_size];
|
|
2893
|
+
}
|
|
2894
|
+
}.build_input;
|
|
2895
|
+
|
|
2896
|
+
var context: TestContext = undefined;
|
|
2897
|
+
try context.init(std.testing.allocator);
|
|
2898
|
+
defer context.deinit(std.testing.allocator);
|
|
2899
|
+
|
|
2900
|
+
const operations = std.enums.values(TestContext.StateMachine.Operation);
|
|
2901
|
+
for (operations) |operation| {
|
|
2902
|
+
if (operation == .pulse) continue;
|
|
2903
|
+
const event_size = operation.event_size();
|
|
2904
|
+
maybe(event_size == 0);
|
|
2905
|
+
|
|
2906
|
+
const event_min: u32, const event_max: u32 = limits: {
|
|
2907
|
+
if (event_size == 0) {
|
|
2908
|
+
break :limits .{ 0, 0 };
|
|
2909
|
+
}
|
|
2910
|
+
if (!operation.is_batchable()) {
|
|
2911
|
+
break :limits .{ 1, 1 };
|
|
2912
|
+
}
|
|
2913
|
+
break :limits .{
|
|
2914
|
+
0,
|
|
2915
|
+
operation.event_max(context.state_machine.batch_size_limit),
|
|
2916
|
+
};
|
|
2917
|
+
};
|
|
2918
|
+
assert(event_min <= event_max);
|
|
2919
|
+
|
|
2920
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
2921
|
+
operation,
|
|
2922
|
+
build_input(input, .{
|
|
2923
|
+
.event_count = 0,
|
|
2924
|
+
.operation = operation,
|
|
2925
|
+
}),
|
|
2926
|
+
) == (event_min == 0));
|
|
2927
|
+
if (event_size == 0) {
|
|
2928
|
+
assert(event_min == 0);
|
|
2929
|
+
assert(event_max == 0);
|
|
2930
|
+
continue;
|
|
2931
|
+
}
|
|
2932
|
+
|
|
2933
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
2934
|
+
operation,
|
|
2935
|
+
build_input(input, .{
|
|
2936
|
+
.event_count = 1,
|
|
2937
|
+
.operation = operation,
|
|
2938
|
+
}),
|
|
2939
|
+
));
|
|
2940
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
2941
|
+
operation,
|
|
2942
|
+
build_input(input, .{
|
|
2943
|
+
.event_count = event_max,
|
|
2944
|
+
.operation = operation,
|
|
2945
|
+
}),
|
|
2946
|
+
));
|
|
2947
|
+
const too_much_data = build_input(input, .{
|
|
2948
|
+
.event_count = event_max + 1,
|
|
2949
|
+
.operation = operation,
|
|
2950
|
+
});
|
|
2951
|
+
if (too_much_data.len < constants.message_body_size_max) {
|
|
2952
|
+
try std.testing.expect(!context.state_machine.input_valid(
|
|
2953
|
+
operation,
|
|
2954
|
+
too_much_data,
|
|
2955
|
+
));
|
|
2956
|
+
} else {
|
|
2957
|
+
// Don't test input larger than the message body limit, since input_valid()
|
|
2958
|
+
// would panic on an assert.
|
|
2959
|
+
}
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
|
|
2963
|
+
// Tests multi-batched query filters.
|
|
2964
|
+
// Multi-batch filters are valid as long as the sum of `filter.limit` stays within the maximum
|
|
2965
|
+
// number of results that can fit in the reply message.
|
|
2966
|
+
test "StateMachine: query multi-batch input_valid" {
|
|
2967
|
+
const allocator = std.testing.allocator;
|
|
2968
|
+
const input = try allocator.alignedAlloc(u8, 16, 2 * constants.message_body_size_max);
|
|
2969
|
+
defer allocator.free(input);
|
|
2970
|
+
|
|
2971
|
+
var context: TestContext = undefined;
|
|
2972
|
+
try context.init(std.testing.allocator);
|
|
2973
|
+
defer context.deinit(std.testing.allocator);
|
|
2974
|
+
|
|
2975
|
+
const build_input = struct {
|
|
2976
|
+
fn build_input(
|
|
2977
|
+
operation: TestContext.StateMachine.Operation,
|
|
2978
|
+
limits: []const u32,
|
|
2979
|
+
buffer: []align(16) u8,
|
|
2980
|
+
) []align(16) const u8 {
|
|
2981
|
+
switch (operation) {
|
|
2982
|
+
.get_account_transfers,
|
|
2983
|
+
.get_account_balances,
|
|
2984
|
+
=> {
|
|
2985
|
+
var body_encoder = vsr.multi_batch.MultiBatchEncoder.init(buffer, .{
|
|
2986
|
+
.element_size = @sizeOf(AccountFilter),
|
|
2987
|
+
});
|
|
2988
|
+
if (limits.len == 0) body_encoder.add(0) else for (limits) |limit| {
|
|
2989
|
+
const batch: []u8 = body_encoder.writable().?;
|
|
2990
|
+
const filter: *AccountFilter = @alignCast(std.mem.bytesAsValue(
|
|
2991
|
+
AccountFilter,
|
|
2992
|
+
batch[0..@sizeOf(AccountFilter)],
|
|
2993
|
+
));
|
|
2994
|
+
filter.* = .{
|
|
2995
|
+
.account_id = 0,
|
|
2996
|
+
.user_data_128 = 0,
|
|
2997
|
+
.user_data_64 = 0,
|
|
2998
|
+
.user_data_32 = 0,
|
|
2999
|
+
.code = 0,
|
|
3000
|
+
.timestamp_min = 0,
|
|
3001
|
+
.timestamp_max = 0,
|
|
3002
|
+
.limit = limit,
|
|
3003
|
+
.flags = .{
|
|
3004
|
+
.debits = false,
|
|
3005
|
+
.credits = false,
|
|
3006
|
+
.reversed = false,
|
|
3007
|
+
},
|
|
3008
|
+
};
|
|
3009
|
+
body_encoder.add(@sizeOf(AccountFilter));
|
|
3010
|
+
}
|
|
3011
|
+
return buffer[0..body_encoder.finish()];
|
|
3012
|
+
},
|
|
3013
|
+
.query_accounts,
|
|
3014
|
+
.query_transfers,
|
|
3015
|
+
=> {
|
|
3016
|
+
var body_encoder = vsr.multi_batch.MultiBatchEncoder.init(buffer, .{
|
|
3017
|
+
.element_size = @sizeOf(QueryFilter),
|
|
3018
|
+
});
|
|
3019
|
+
if (limits.len == 0) body_encoder.add(0) else for (limits) |limit| {
|
|
3020
|
+
const batch: []u8 = body_encoder.writable().?;
|
|
3021
|
+
const filter: *QueryFilter = @alignCast(std.mem.bytesAsValue(
|
|
3022
|
+
QueryFilter,
|
|
3023
|
+
batch[0..@sizeOf(QueryFilter)],
|
|
3024
|
+
));
|
|
3025
|
+
filter.* = .{
|
|
3026
|
+
.user_data_128 = 0,
|
|
3027
|
+
.user_data_64 = 0,
|
|
3028
|
+
.user_data_32 = 0,
|
|
3029
|
+
.code = 0,
|
|
3030
|
+
.ledger = 0,
|
|
3031
|
+
.timestamp_min = 0,
|
|
3032
|
+
.timestamp_max = 0,
|
|
3033
|
+
.limit = limit,
|
|
3034
|
+
.flags = .{
|
|
3035
|
+
.reversed = false,
|
|
3036
|
+
},
|
|
3037
|
+
};
|
|
3038
|
+
body_encoder.add(@sizeOf(QueryFilter));
|
|
3039
|
+
}
|
|
3040
|
+
return buffer[0..body_encoder.finish()];
|
|
3041
|
+
},
|
|
3042
|
+
else => unreachable,
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
}.build_input;
|
|
3046
|
+
|
|
3047
|
+
const operations = &[_]TestContext.StateMachine.Operation{
|
|
3048
|
+
.get_account_transfers,
|
|
3049
|
+
.get_account_balances,
|
|
3050
|
+
.query_accounts,
|
|
3051
|
+
.query_transfers,
|
|
3052
|
+
};
|
|
3053
|
+
|
|
3054
|
+
for (operations) |operation| {
|
|
3055
|
+
const batch_max = operation.result_max(context.state_machine.batch_size_limit);
|
|
3056
|
+
|
|
3057
|
+
// Valid inputs:
|
|
3058
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
3059
|
+
operation,
|
|
3060
|
+
build_input(operation, &.{0}, input),
|
|
3061
|
+
));
|
|
3062
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
3063
|
+
operation,
|
|
3064
|
+
build_input(operation, &.{ 0, 0 }, input),
|
|
3065
|
+
));
|
|
3066
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
3067
|
+
operation,
|
|
3068
|
+
build_input(operation, &.{1}, input),
|
|
3069
|
+
));
|
|
3070
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
3071
|
+
operation,
|
|
3072
|
+
build_input(operation, &.{ 1, 1, 1 }, input),
|
|
3073
|
+
));
|
|
3074
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
3075
|
+
operation,
|
|
3076
|
+
build_input(operation, &.{batch_max}, input),
|
|
3077
|
+
));
|
|
3078
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
3079
|
+
operation,
|
|
3080
|
+
build_input(operation, &.{ 0, batch_max }, input),
|
|
3081
|
+
));
|
|
3082
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
3083
|
+
operation,
|
|
3084
|
+
build_input(operation, &.{ 0, 1, batch_max - 1 }, input),
|
|
3085
|
+
));
|
|
3086
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
3087
|
+
operation,
|
|
3088
|
+
build_input(operation, &.{ 1, 1, batch_max - 2 }, input),
|
|
3089
|
+
));
|
|
3090
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
3091
|
+
operation,
|
|
3092
|
+
build_input(operation, &.{
|
|
3093
|
+
@divFloor(batch_max, 2),
|
|
3094
|
+
stdx.div_ceil(batch_max, 2),
|
|
3095
|
+
}, input),
|
|
3096
|
+
));
|
|
3097
|
+
try std.testing.expect(context.state_machine.input_valid(
|
|
3098
|
+
operation,
|
|
3099
|
+
build_input(operation, &.{std.math.maxInt(u32)}, input),
|
|
3100
|
+
));
|
|
3101
|
+
|
|
3102
|
+
// Invalid inputs:
|
|
3103
|
+
try std.testing.expect(!context.state_machine.input_valid(
|
|
3104
|
+
operation,
|
|
3105
|
+
build_input(operation, &.{}, input),
|
|
3106
|
+
));
|
|
3107
|
+
try std.testing.expect(!context.state_machine.input_valid(
|
|
3108
|
+
operation,
|
|
3109
|
+
build_input(operation, &.{ 1, batch_max }, input),
|
|
3110
|
+
));
|
|
3111
|
+
try std.testing.expect(!context.state_machine.input_valid(
|
|
3112
|
+
operation,
|
|
3113
|
+
build_input(operation, &.{ 1, std.math.maxInt(u32) }, input),
|
|
3114
|
+
));
|
|
3115
|
+
try std.testing.expect(!context.state_machine.input_valid(
|
|
3116
|
+
operation,
|
|
3117
|
+
build_input(operation, &.{ batch_max, batch_max }, input),
|
|
3118
|
+
));
|
|
3119
|
+
try std.testing.expect(!context.state_machine.input_valid(
|
|
3120
|
+
operation,
|
|
3121
|
+
build_input(operation, &.{
|
|
3122
|
+
@divFloor(batch_max, 2),
|
|
3123
|
+
stdx.div_ceil(batch_max, 2),
|
|
3124
|
+
1,
|
|
3125
|
+
}, input),
|
|
3126
|
+
));
|
|
3127
|
+
}
|
|
3128
|
+
}
|