From 15928ecae76bc170240a39b3f2812ba9629d12f9 Mon Sep 17 00:00:00 2001 From: Georgy Moshkin <gmoshkin@picodata.io> Date: Mon, 15 May 2023 13:16:14 +0300 Subject: [PATCH] test: cleanup ddl tests --- src/storage.rs | 2 + test/int/test_ddl.py | 152 +++++++++++++++++++++++++++++++------------ 2 files changed, 112 insertions(+), 42 deletions(-) diff --git a/src/storage.rs b/src/storage.rs index 2910769fe0..4499f0b899 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -424,6 +424,8 @@ impl Clusterwide { } } + // If we're not the replication master, the rest of the data will come + // via tarantool replication. if !is_master { return Ok(()); } diff --git a/test/int/test_ddl.py b/test/int/test_ddl.py index c75890f504..176f14ea2a 100644 --- a/test/int/test_ddl.py +++ b/test/int/test_ddl.py @@ -2,15 +2,23 @@ from conftest import Cluster def test_ddl_create_space_bulky(cluster: Cluster): - # TODO: add 2 more instances, to check that another replicaset is handled - # correctly - i1, i2 = cluster.deploy(instance_count=2, init_replication_factor=2) + i1, i2, i3, i4 = cluster.deploy(instance_count=4, init_replication_factor=2) # At cluster boot schema version is 0 assert i1.call("box.space._pico_property:get", "current_schema_version")[1] == 0 assert i2.call("box.space._pico_property:get", "current_schema_version")[1] == 0 + assert i3.call("box.space._pico_property:get", "current_schema_version")[1] == 0 + assert i4.call("box.space._pico_property:get", "current_schema_version")[1] == 0 + + # And next schema version will be 1 + assert i1.next_schema_version() == 1 + assert i2.next_schema_version() == 1 + assert i3.next_schema_version() == 1 + assert i4.next_schema_version() == 1 + ############################################################################ # Propose a space creation which will fail + abort_index = i1.ddl_create_space( dict( id=666, @@ -21,39 +29,69 @@ def test_ddl_create_space_bulky(cluster: Cluster): ), ) + i1.call(".proc_sync_raft", abort_index, (3, 0)) i2.call(".proc_sync_raft", abort_index, (3, 0)) + i3.call(".proc_sync_raft", abort_index, (3, 0)) + i4.call(".proc_sync_raft", abort_index, (3, 0)) # No space was created assert i1.call("box.space._pico_space:get", 666) is None - assert i1.call("box.space._space:get", 666) is None assert i2.call("box.space._pico_space:get", 666) is None + assert i3.call("box.space._pico_space:get", 666) is None + assert i4.call("box.space._pico_space:get", 666) is None + assert i1.call("box.space._space:get", 666) is None assert i2.call("box.space._space:get", 666) is None + assert i3.call("box.space._space:get", 666) is None + assert i4.call("box.space._space:get", 666) is None # Schema version hasn't changed assert i1.call("box.space._pico_property:get", "current_schema_version")[1] == 0 assert i2.call("box.space._pico_property:get", "current_schema_version")[1] == 0 + assert i3.call("box.space._pico_property:get", "current_schema_version")[1] == 0 + assert i4.call("box.space._pico_property:get", "current_schema_version")[1] == 0 + # But next schema version did change + assert i1.next_schema_version() == 2 + assert i2.next_schema_version() == 2 + assert i3.next_schema_version() == 2 + assert i4.next_schema_version() == 2 + + ############################################################################ # Propose a space creation which will succeed + commit_index = i1.ddl_create_space( dict( id=666, name="stuff", format=[dict(name="id", type="unsigned", is_nullable=False)], - primary_key=[dict(field=0, type="unsigned")], + primary_key=[dict(field="id")], distribution=dict(kind="global"), ), ) + i1.call(".proc_sync_raft", commit_index, (3, 0)) i2.call(".proc_sync_raft", commit_index, (3, 0)) + i3.call(".proc_sync_raft", commit_index, (3, 0)) + i4.call(".proc_sync_raft", commit_index, (3, 0)) - # Schema version was updated + # This time schema version did change assert i1.call("box.space._pico_property:get", "current_schema_version")[1] == 2 assert i2.call("box.space._pico_property:get", "current_schema_version")[1] == 2 + assert i3.call("box.space._pico_property:get", "current_schema_version")[1] == 2 + assert i4.call("box.space._pico_property:get", "current_schema_version")[1] == 2 + + # And so did next schema version obviously + assert i1.next_schema_version() == 3 + assert i2.next_schema_version() == 3 + assert i3.next_schema_version() == 3 + assert i4.next_schema_version() == 3 # Space was created and is operable pico_space_def = [666, "stuff", ["global"], [["id", "unsigned", False]], 2, True] assert i1.call("box.space._pico_space:get", 666) == pico_space_def assert i2.call("box.space._pico_space:get", 666) == pico_space_def + assert i3.call("box.space._pico_space:get", 666) == pico_space_def + assert i4.call("box.space._pico_space:get", 666) == pico_space_def tt_space_def = [ 666, @@ -66,6 +104,8 @@ def test_ddl_create_space_bulky(cluster: Cluster): ] assert i1.call("box.space._space:get", 666) == tt_space_def assert i2.call("box.space._space:get", 666) == tt_space_def + assert i3.call("box.space._space:get", 666) == tt_space_def + assert i4.call("box.space._space:get", 666) == tt_space_def # Primary index was also created # TODO: maybe we want to replace these `None`s with the default values when @@ -82,6 +122,8 @@ def test_ddl_create_space_bulky(cluster: Cluster): ] assert i1.call("box.space._pico_index:get", [666, 0]) == pico_pk_def assert i2.call("box.space._pico_index:get", [666, 0]) == pico_pk_def + assert i3.call("box.space._pico_index:get", [666, 0]) == pico_pk_def + assert i4.call("box.space._pico_index:get", [666, 0]) == pico_pk_def tt_pk_def = [ 666, @@ -93,27 +135,30 @@ def test_ddl_create_space_bulky(cluster: Cluster): ] assert i1.call("box.space._index:get", [666, 0]) == tt_pk_def assert i2.call("box.space._index:get", [666, 0]) == tt_pk_def + assert i3.call("box.space._index:get", [666, 0]) == tt_pk_def + assert i4.call("box.space._index:get", [666, 0]) == tt_pk_def - # Add a new replicaset master - i3 = cluster.add_instance(wait_online=True, replicaset_id="r2") + ############################################################################ + # A new replicaset catches up after the fact successfully - # It's schema was updated automatically - assert i3.call("box.space._pico_property:get", "current_schema_version")[1] == 2 - assert i3.call("box.space._pico_space:get", 666) == pico_space_def - assert i3.call("box.space._pico_index:get", [666, 0]) == pico_pk_def - # TODO: this fails - assert i3.call("box.space._space:get", 666) == tt_space_def - assert i3.call("box.space._index:get", [666, 0]) == tt_pk_def + i5 = cluster.add_instance(wait_online=True, replicaset_id="r3") + + assert i5.call("box.space._pico_property:get", "current_schema_version")[1] == 2 + assert i5.next_schema_version() == 3 + assert i5.call("box.space._pico_space:get", 666) == pico_space_def + assert i5.call("box.space._pico_index:get", [666, 0]) == pico_pk_def + assert i5.call("box.space._space:get", 666) == tt_space_def + assert i5.call("box.space._index:get", [666, 0]) == tt_pk_def - # Add a follower to the new replicaset - i4 = cluster.add_instance(wait_online=True, replicaset_id="r2") + i6 = cluster.add_instance(wait_online=True, replicaset_id="r3") # It's schema was updated automatically as well - assert i4.call("box.space._pico_property:get", "current_schema_version")[1] == 2 - assert i4.call("box.space._pico_space:get", 666) == pico_space_def - assert i4.call("box.space._pico_index:get", [666, 0]) == pico_pk_def - assert i4.call("box.space._space:get", 666) == tt_space_def - assert i4.call("box.space._index:get", [666, 0]) == tt_pk_def + assert i6.call("box.space._pico_property:get", "current_schema_version")[1] == 2 + assert i6.next_schema_version() == 3 + assert i6.call("box.space._pico_space:get", 666) == pico_space_def + assert i6.call("box.space._pico_index:get", [666, 0]) == pico_pk_def + assert i6.call("box.space._space:get", 666) == tt_space_def + assert i6.call("box.space._index:get", [666, 0]) == tt_pk_def def test_ddl_create_sharded_space(cluster: Cluster): @@ -138,6 +183,7 @@ def test_ddl_create_sharded_space(cluster: Cluster): i1.call(".proc_sync_raft", index, (3, 0)) i2.call(".proc_sync_raft", index, (3, 0)) + ############################################################################ # Space was created and is operable pico_space_def = [ 666, @@ -173,6 +219,7 @@ def test_ddl_create_sharded_space(cluster: Cluster): assert i1.call("box.space._space:get", 666) == tt_space_def assert i2.call("box.space._space:get", 666) == tt_space_def + ############################################################################ # Primary index was also created pico_pk_def = [ 666, @@ -198,6 +245,7 @@ def test_ddl_create_sharded_space(cluster: Cluster): assert i1.call("box.space._index:get", [666, 0]) == tt_pk_def assert i2.call("box.space._index:get", [666, 0]) == tt_pk_def + ############################################################################ # This time bucket id was also created pico_bucket_id_def = [ 666, @@ -232,34 +280,32 @@ def test_ddl_create_space_partial_failure(cluster: Cluster): i3.eval("box.schema.space.create(...)", "space_name_conflict") # Propose a space creation which will fail - index = i1.ddl_create_space( - dict( - id=666, - name="space_name_conflict", - format=[dict(name="id", type="unsigned", is_nullable=False)], - primary_key=[dict(field=1, type="unsigned")], - distribution=dict(kind="global"), - ), + space_def = dict( + id=666, + name="space_name_conflict", + format=[dict(name="id", type="unsigned", is_nullable=False)], + primary_key=[dict(field="id")], + distribution=dict(kind="global"), ) + index = i1.ddl_create_space(space_def) i2.call(".proc_sync_raft", index, (3, 0)) i3.call(".proc_sync_raft", index, (3, 0)) # No space was created assert i1.call("box.space._pico_space:get", 666) is None - assert i1.call("box.space._space:get", 666) is None assert i2.call("box.space._pico_space:get", 666) is None - assert i2.call("box.space._space:get", 666) is None assert i3.call("box.space._pico_space:get", 666) is None + assert i1.call("box.space._space:get", 666) is None + assert i2.call("box.space._space:get", 666) is None assert i3.call("box.space._space:get", 666) is None - # TODO: add instance which will conflict with this ddl and make sure it - # panics + # TODO: terminate i3, commit create space and wake i3 back up def test_ddl_from_snapshot(cluster: Cluster): # Second instance is only for quorum - i1, i2 = cluster.deploy(instance_count=2) + i1, i2 = cluster.deploy(instance_count=2, init_replication_factor=2) i1.assert_raft_status("Leader") @@ -270,8 +316,8 @@ def test_ddl_from_snapshot(cluster: Cluster): id=666, name="stuff", format=[dict(name="id", type="unsigned", is_nullable=False)], - primary_key=[dict(field=1, type="unsigned")], - distribution=dict(kind="global"), + primary_key=[dict(field="id")], + distribution=dict(kind="sharded_implicitly", sharding_key=["id"]), ), ) @@ -284,7 +330,10 @@ def test_ddl_from_snapshot(cluster: Cluster): "memtx", 0, dict(), - [dict(name="id", type="unsigned", is_nullable=False)], + [ + dict(name="id", type="unsigned", is_nullable=False), + dict(name="bucket_id", type="unsigned", is_nullable=False), + ], ] assert i1.call("box.space._space:get", 666) == tt_space_def assert i2.call("box.space._space:get", 666) == tt_space_def @@ -295,17 +344,36 @@ def test_ddl_from_snapshot(cluster: Cluster): "primary_key", "tree", dict(unique=True), - [[1, "unsigned", None, None, None]], + [[0, "unsigned", None, False, None]], ] assert i1.call("box.space._index:get", [666, 0]) == tt_pk_def assert i2.call("box.space._index:get", [666, 0]) == tt_pk_def + tt_bucket_id_def = [ + 666, + 1, + "bucket_id", + "tree", + dict(unique=False), + [[1, "unsigned", None, False, None]], + ] + assert i1.call("box.space._index:get", [666, 1]) == tt_bucket_id_def + assert i2.call("box.space._index:get", [666, 1]) == tt_bucket_id_def + # Compact the log to trigger snapshot for the newcommer i1.raft_compact_log() i2.raft_compact_log() - i3 = cluster.add_instance(wait_online=True) - - # Check space was created from the snapshot data + # A replicaset master catches up from snapshot + i3 = cluster.add_instance(wait_online=True, replicaset_id="R2") assert i3.call("box.space._space:get", 666) == tt_space_def assert i3.call("box.space._index:get", [666, 0]) == tt_pk_def + assert i3.call("box.space._index:get", [666, 1]) == tt_bucket_id_def + assert i3.call("box.space._schema:get", "pico_schema_version")[1] == 1 + + # A replicaset follower catches up from snapshot + i4 = cluster.add_instance(wait_online=True, replicaset_id="R2") + assert i4.call("box.space._space:get", 666) == tt_space_def + assert i4.call("box.space._index:get", [666, 0]) == tt_pk_def + assert i4.call("box.space._index:get", [666, 1]) == tt_bucket_id_def + assert i4.call("box.space._schema:get", "pico_schema_version")[1] == 1 -- GitLab