Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,46 @@ class TestExamplePerClassSetup(ExampleTestCaseBase):
client.execute_command("SET K V")
```

For more examples, refer to the `tests` directory of this package.
**Testing Cluster Mode Enabled (CME)**

To test against a Valkey cluster, inherit `ClusterTestCase` instead of `ValkeyTestCase`. Call `setup_cluster(num_shards, num_replicas_per_shard)` to bootstrap a cluster: it starts all nodes, assigns slots, attaches replicas, waits until the cluster state is `ok`, and returns a client that follows `MOVED`/`ASK` redirections. The cluster is torn down automatically after each test.

```
from valkey_test_case import ClusterTestCase, ClusterInfo

class TestExampleCluster(ClusterTestCase):
def test_cluster_read_write(self):
self.server_path = "/path_to_your_valkey_server_binary"

# 3 primaries, each with 1 replica (6 nodes total)
client = self.setup_cluster(num_shards=3, num_replicas_per_shard=1)

client.set("key", "value")
assert client.get("key") == b"value"

# self.nodes holds every ClusterNodeHandle for direct inspection
for node in self.nodes:
assert ClusterInfo(node.client.cluster("INFO")).is_cluster_ok()
```

To apply startup arguments (modules, configs) to every node, set `self.args` inside the test before calling `setup_cluster`.

To test slot migration, use `migrate_slot(source, target, slot)` to move a slot and its keys from one node to another, then `wait_for_slot_owner(slot, target)` to wait until every node agrees on the new owner. `get_slot_owner(slot)` returns the node that currently owns a slot.

```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: does it need to import any fn here like your above example?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the ClusterTestCase and key_slot imports to the example to match the CME one above

class TestExampleMigration(ClusterTestCase):
def test_migrate(self):
self.server_path = "/path_to_your_valkey_server_binary"
self.setup_cluster(num_shards=2, num_replicas_per_shard=0)

slot = key_slot(b"key")
source = self.get_slot_owner(slot)
target = next(n for n in self.nodes if n.nodeid != source.nodeid)
source.client.set("key", "value")

self.migrate_slot(source, target, slot)
self.wait_for_slot_owner(slot, target)
assert target.client.get("key") == b"value"
```

Pass `dbs=(0, 1, ...)` to `migrate_slot` to move keys across multiple databases; migrating any database other than 0 requires the cluster to be started with `cluster-databases > 1`.
Loading