forked from openebs/mayastor
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(py): add pytest-bdd feature tests for pools and replicas
roughly translated from test/grpc/test_replica.js resolves CAS-961
- Loading branch information
1 parent
1a2ca89
commit 714b406
Showing
4 changed files
with
642 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
Feature: Mayastor pool management | ||
|
||
Background: | ||
Given a mayastor instance "ms0" | ||
|
||
Scenario: creating a pool using disk with invalid block size | ||
When the user attempts to create a pool specifying a disk with an invalid block size | ||
Then the pool creation should fail | ||
|
||
Scenario: creating a pool with multiple disks | ||
When the user attempts to create a pool specifying multiple disks | ||
Then the pool creation should fail | ||
|
||
Scenario: creating a pool with an AIO disk | ||
When the user creates a pool specifying a URI representing an aio disk | ||
Then the pool should be created | ||
|
||
Scenario: creating a pool with a name that already exists | ||
Given a pool "p0" | ||
When the user creates a pool with the name of an existing pool | ||
Then the pool creation should succeed | ||
|
||
Scenario: listing pools | ||
Given a pool "p0" | ||
When the user lists the current pools | ||
Then the pool should appear in the output list | ||
|
||
Scenario: destroying a pool | ||
Given a pool "p0" | ||
When the user destroys the pool | ||
Then the pool should be destroyed | ||
|
||
Scenario: destroying a pool that does not exist | ||
When the user destroys a pool that does not exist | ||
Then the pool destroy command should succeed |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
Feature: Mayastor replica management | ||
|
||
Background: | ||
Given a mayastor instance "ms0" | ||
And a pool "p0" | ||
|
||
Scenario: creating a replica | ||
When the user creates an unshared replica | ||
Then the replica is created | ||
And the share state is unshared | ||
|
||
Scenario: creating a replica shared over "iscsi" | ||
When the user attempts to create a replica shared over "iscsi" | ||
Then the create replica command should fail | ||
|
||
Scenario: creating a replica with a name that already exists | ||
Given a replica | ||
When the user creates a replica that already exists | ||
Then the create replica command should succeed | ||
|
||
Scenario: listing replicas | ||
Given a replica | ||
When the user lists the current replicas | ||
Then the replica should appear in the output list | ||
|
||
Scenario: sharing a replica over "nvmf" | ||
Given a replica that is unshared | ||
When the user shares the replica over "nvmf" | ||
Then the share state should change to "nvmf" | ||
|
||
Scenario: sharing a replica over "iscsi" | ||
Given a replica that is unshared | ||
When the user attempts to share the replica over "iscsi" | ||
Then the share replica command should fail | ||
|
||
Scenario: sharing a replica that is already shared with the same protocol | ||
Given a replica shared over "nvmf" | ||
When the user shares the replica with the same protocol | ||
Then the share replica command should succeed | ||
|
||
Scenario: sharing a replica that is already shared with a different protocol | ||
Given a replica shared over "nvmf" | ||
When the user attempts to share the replica with a different protocol | ||
Then the share replica command should fail | ||
|
||
Scenario: unsharing a replica | ||
Given a replica shared over "nvmf" | ||
When the user unshares the replica | ||
Then the share state should change to unshared | ||
|
||
Scenario: destroying a replica | ||
Given a replica | ||
When the user destroys the replica | ||
Then the replica should be destroyed | ||
|
||
Scenario: destroying a replica that does not exist | ||
When the user destroys a replica that does not exist | ||
Then the replica destroy command should succeed | ||
|
||
Scenario: listing replica stats | ||
Given a replica | ||
When the user gets replica stats | ||
Then the stats for the replica should be listed | ||
|
||
Scenario: creating a replica shared over "nvmf" | ||
When the user creates a replica shared over "nvmf" | ||
Then the replica is created | ||
And the share state is "nvmf" | ||
|
||
Scenario: listing replicas | ||
Given a replica | ||
When the user lists the current replicas | ||
Then the replica should appear in the output list | ||
|
||
Scenario: writing to a shared replica | ||
Given a replica shared over "nvmf" | ||
When the user writes to the replica | ||
Then the write operation should succeed | ||
|
||
Scenario: reading from a shared replica | ||
Given a replica shared over "nvmf" | ||
When the user reads from the replica | ||
Then the read operation should succeed | ||
|
||
Scenario: recreating a replica | ||
Given a replica | ||
When the user attempts to recreate the existing replica | ||
Then the old data should have been reset |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import pytest | ||
from pytest_bdd import given, scenario, then, when, parsers | ||
|
||
from common.command import run_cmd | ||
from common.mayastor import mayastor_mod | ||
|
||
import grpc | ||
import mayastor_pb2 as pb | ||
|
||
|
||
@scenario("features/pool.feature", "creating a pool using disk with invalid block size") | ||
def test_fail_creating_a_pool_using_disk_with_invalid_block_size(): | ||
"Creating a pool using disk with invalid block size." | ||
|
||
|
||
@scenario("features/pool.feature", "creating a pool with a name that already exists") | ||
def test_creating_a_pool_with_a_name_that_already_exists(): | ||
"Creating a pool with a name that already exists." | ||
|
||
|
||
@scenario("features/pool.feature", "creating a pool with an AIO disk") | ||
def test_creating_a_pool_with_an_aio_disk(): | ||
"Creating a pool with an AIO disk." | ||
|
||
|
||
@scenario("features/pool.feature", "creating a pool with multiple disks") | ||
def test_fail_creating_a_pool_with_multiple_disks(): | ||
"Creating a pool with multiple disks." | ||
|
||
|
||
@scenario("features/pool.feature", "destroying a pool") | ||
def test_destroying_a_pool(): | ||
"Destroying a pool." | ||
|
||
|
||
@scenario("features/pool.feature", "destroying a pool that does not exist") | ||
def test_destroying_a_pool_that_does_not_exist(): | ||
"Destroying a pool that does not exist." | ||
|
||
|
||
@scenario("features/pool.feature", "listing pools") | ||
def test_listing_pools(): | ||
"Listing pools." | ||
|
||
|
||
@pytest.fixture | ||
def image_file(): | ||
name = "/tmp/ms0-disk0.img" | ||
run_cmd(f"rm -f '{name}'", True) | ||
run_cmd(f"truncate -s 64M '{name}'", True) | ||
yield name | ||
run_cmd(f"rm -f '{name}'", True) | ||
|
||
|
||
@pytest.fixture | ||
def find_pool(get_mayastor_instance): | ||
def find(name): | ||
for pool in get_mayastor_instance.ms.ListPools(pb.Null()).pools: | ||
if pool.name == name: | ||
return pool | ||
return None | ||
|
||
yield find | ||
|
||
|
||
@pytest.fixture | ||
def replica_pools(get_mayastor_instance): | ||
pools = {} | ||
yield pools | ||
for name in pools.keys(): | ||
get_mayastor_instance.ms.DestroyPool(pb.DestroyPoolRequest(name=name)) | ||
|
||
|
||
@pytest.fixture | ||
def create_pool(get_mayastor_instance, replica_pools): | ||
def create(name, disks): | ||
pool = get_mayastor_instance.ms.CreatePool( | ||
pb.CreatePoolRequest(name=name, disks=disks) | ||
) | ||
replica_pools[name] = pool | ||
|
||
yield create | ||
|
||
|
||
@given( | ||
parsers.parse('a mayastor instance "{name}"'), | ||
target_fixture="get_mayastor_instance", | ||
) | ||
def get_mayastor_instance(mayastor_mod, name): | ||
return mayastor_mod[name] | ||
|
||
|
||
@given(parsers.parse('a pool "{name}"'), target_fixture="get_pool_name") | ||
def get_pool_name(get_mayastor_instance, create_pool, name): | ||
create_pool(name, ["malloc:///disk0?size_mb=100"]) | ||
return name | ||
|
||
|
||
@when("the user creates a pool specifying a URI representing an aio disk") | ||
def create_pool_from_aio_disk(get_mayastor_instance, create_pool, image_file): | ||
create_pool("p0", [f"aio://{image_file}"]) | ||
|
||
|
||
@when("the user attempts to create a pool specifying a disk with an invalid block size") | ||
def attempt_to_create_pool_from_disk_with_invalid_block_size( | ||
get_mayastor_instance, create_pool | ||
): | ||
with pytest.raises(grpc.RpcError) as error: | ||
create_pool("p0", "malloc:///disk0?size_mb=100&blk_size=1024") | ||
assert error.value.code() == grpc.StatusCode.INVALID_ARGUMENT | ||
|
||
|
||
@when("the user attempts to create a pool specifying multiple disks") | ||
def attempt_to_create_pool_from_multiple_disks(get_mayastor_instance, create_pool): | ||
with pytest.raises(grpc.RpcError) as error: | ||
create_pool( | ||
"p0", ["malloc:///disk0?size_mb=100", "malloc:///disk1?size_mb=100"] | ||
) | ||
assert error.value.code() == grpc.StatusCode.INVALID_ARGUMENT | ||
|
||
|
||
@when("the user creates a pool with the name of an existing pool") | ||
def create_pool_that_already_exists(get_mayastor_instance, create_pool, get_pool_name): | ||
create_pool(get_pool_name, ["malloc:///disk0?size_mb=100"]) | ||
|
||
|
||
@when("the user destroys a pool that does not exist") | ||
def destroy_pool_that_does_not_exist(get_mayastor_instance, find_pool): | ||
assert find_pool("p0") == None | ||
get_mayastor_instance.ms.DestroyPool(pb.DestroyPoolRequest(name="p0")) | ||
|
||
|
||
@when("the user destroys the pool") | ||
def destroy_pool(get_mayastor_instance, replica_pools, get_pool_name): | ||
pool = replica_pools[get_pool_name] | ||
get_mayastor_instance.ms.DestroyPool(pb.DestroyPoolRequest(name=pool.name)) | ||
del replica_pools[get_pool_name] | ||
|
||
|
||
@when("the user lists the current pools", target_fixture="list_pools") | ||
def list_pools(get_mayastor_instance): | ||
return get_mayastor_instance.ms.ListPools(pb.Null(), wait_for_ready=True).pools | ||
|
||
|
||
@then("the pool creation should fail") | ||
def pool_creation_should_fail(find_pool): | ||
assert find_pool("p0") == None | ||
|
||
|
||
@then("the pool creation should succeed") | ||
@then("the pool should be created") | ||
def pool_creation_should_succeed(find_pool): | ||
assert find_pool("p0") != None | ||
|
||
|
||
@then("the pool destroy command should succeed") | ||
@then("the pool should be destroyed") | ||
def pool_destruction_should_succeed(find_pool): | ||
assert find_pool("p0") == None | ||
|
||
|
||
@then("the pool should appear in the output list") | ||
def pool_should_appear_in_output(get_pool_name, list_pools): | ||
assert get_pool_name in [pool.name for pool in list_pools] |
Oops, something went wrong.