Skip to content
test_unitary.py 13.2 KiB
Newer Older
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
import copy, grpc, logging, pytest
from google.protobuf.json_format import MessageToDict
from common.database.Factory import get_database, DatabaseEngineEnum
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
from common.database.api.context.topology.device.OperationalStatus import OperationalStatus
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
from common.tests.Assertions import validate_device_id, validate_empty
from device.client.DeviceClient import DeviceClient
from device.proto.context_pb2 import Device, DeviceId
from device.service.DeviceService import DeviceService
from device.Config import GRPC_SERVICE_PORT, GRPC_MAX_WORKERS, GRPC_GRACE_PERIOD

LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.DEBUG)

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
DEVICE_ID = {'device_id': {'uuid': 'DEV1'}}
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
DEVICE = {
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    'device_id': {'device_id': {'uuid': 'DEV1'}},
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    'device_type': 'ROADM',
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    'device_config': {'device_config': '<config/>'},
    'devOperationalStatus': OperationalStatus.ENABLED.value,
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    'endpointList' : [
        {
            'port_id': {
                'topoId': {
                    'contextId': {'contextUuid': {'uuid': 'admin'}},
                    'topoId': {'uuid': 'admin'}
                },
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                'dev_id': {'device_id': {'uuid': 'DEV1'}},
                'port_id': {'uuid' : 'EP2'}
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            },
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            'port_type': 'WDM'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        },
        {
            'port_id': {
                'topoId': {
                    'contextId': {'contextUuid': {'uuid': 'admin'}},
                    'topoId': {'uuid': 'admin'}
                },
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                'dev_id': {'device_id': {'uuid': 'DEV1'}},
                'port_id': {'uuid' : 'EP3'}
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            },
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            'port_type': 'WDM'
        },
        {
            'port_id': {
                'topoId': {
                    'contextId': {'contextUuid': {'uuid': 'admin'}},
                    'topoId': {'uuid': 'admin'}
                },
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                'dev_id': {'device_id': {'uuid': 'DEV1'}},
                'port_id': {'uuid' : 'EP4'}
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            },
            'port_type': 'WDM'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def device_database():
    _database = get_database(engine=DatabaseEngineEnum.INMEMORY)
    return _database

@pytest.fixture(scope='session')
def device_service(device_database):
    _service = DeviceService(
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_database, port=GRPC_SERVICE_PORT, max_workers=GRPC_MAX_WORKERS, grace_period=GRPC_GRACE_PERIOD)
    _service.start()
    yield _service
    _service.stop()

@pytest.fixture(scope='session')
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def device_client(device_service):
    _client = DeviceClient(address='127.0.0.1', port=GRPC_SERVICE_PORT)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    yield _client
    _client.close()

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device_empty_device_uuid(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with device uuid is empty
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
        copy_device['device_id']['device_id']['uuid'] = ''
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.AddDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'device.device_id.device_id.uuid() string is empty.'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device_empty_device_type(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with device type is empty
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
        copy_device['device_type'] = ''
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.AddDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'device.device_type() string is empty.'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device_wrong_device_operational_status(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with wrong device operational status
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
        copy_device['devOperationalStatus'] = OperationalStatus.KEEP_STATE.value
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.AddDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
    msg = ' '.join([
        'Device has to be created with either ENABLED/DISABLED Operational State.',
        'Use KEEP_STATE only in configure Device methods.',
    ])
    assert e.value.details() == msg

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device_endpoint_wrong_context(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with unsupported context
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
        copy_device['endpointList'][0]['port_id']['topoId']['contextId']['contextUuid']['uuid'] = 'wrong-context'
        request = Device(**copy_device)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.AddDevice(request)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
    msg = ' '.join([
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        'Unsupported Context(wrong-context) in Endpoint(#0) of Device(DEV1).',
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        'Only default Context(admin) is currently supported.',
        'Optionally, leave field empty to use default Context.',
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    ])
    assert e.value.details() == msg

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device_endpoint_wrong_topology(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with unsupported topology
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
        copy_device['endpointList'][0]['port_id']['topoId']['topoId']['uuid'] = 'wrong-topo'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.AddDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
    msg = ' '.join([
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        'Unsupported Topology(wrong-topo) in Endpoint(#0) of Device(DEV1).',
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        'Only default Topology(admin) is currently supported.',
        'Optionally, leave field empty to use default Topology.',
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    ])
    assert e.value.details() == msg

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device_endpoint_wrong_device(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with wrong endpoint device
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
        copy_device['endpointList'][0]['port_id']['dev_id']['device_id']['uuid'] = 'wrong-device'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.AddDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
    msg = ' '.join([
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        'Wrong Device(wrong-device) in Endpoint(#0).',
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        'Parent specified in message is Device(DEV1).',
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        'Optionally, leave field empty to use parent Device.',
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    ])
    assert e.value.details() == msg

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device_empty_port_uuid(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with port uuid is empty
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
        copy_device['endpointList'][0]['port_id']['port_id']['uuid'] = ''
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.AddDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'endpoint[#0].port_id.port_id.uuid() string is empty.'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device_empty_port_type(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with port type is empty
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
        copy_device['endpointList'][0]['port_type'] = ''
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.AddDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'endpoint[#0].port_type() string is empty.'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device_duplicate_port(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with uplicate port in device
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        copy_device['endpointList'][1]['port_id']['port_id']['uuid'] = 'EP2'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.AddDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.ALREADY_EXISTS
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'Duplicated Port(EP2) in Endpoint(#1) of Device(DEV1).'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should work
    validate_device_id(MessageToDict(
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            device_client.AddDevice(Device(**DEVICE)),
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            including_default_value_fields=True, preserving_proto_field_name=True,
            use_integers_for_enums=False))

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device_duplicate(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with device already exists
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.AddDevice(Device(**DEVICE))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.ALREADY_EXISTS
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'Device(DEV1) already exists in the database.'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_delete_device_empty_uuid(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with device uuid is empty
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device_id = copy.deepcopy(DEVICE_ID)
        copy_device_id['device_id']['uuid'] = ''
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.DeleteDevice(DeviceId(**copy_device_id))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'device_id.device_id.uuid() string is empty.'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_delete_device_not_found(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with device not found
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device_id = copy.deepcopy(DEVICE_ID)
        copy_device_id['device_id']['uuid'] = 'wrong-device-id'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.DeleteDevice(DeviceId(**copy_device_id))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.NOT_FOUND
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'Device(wrong-device-id) does not exist in the database.'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_delete_device(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should work
    validate_empty(MessageToDict(
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            device_client.DeleteDevice(DeviceId(**DEVICE_ID)),
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            including_default_value_fields=True, preserving_proto_field_name=True,
            use_integers_for_enums=False))

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_configure_device_empty_device_uuid(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with device uuid is empty
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
        copy_device['device_id']['device_id']['uuid'] = ''
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.ConfigureDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'device.device_id.device_id.uuid() string is empty.'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_configure_device_not_found(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with device not found
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
        copy_device['device_id']['device_id']['uuid'] = 'wrong-device-id'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.ConfigureDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.NOT_FOUND
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'Device(wrong-device-id) does not exist in the database.'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_add_device_default_endpoint_context_topology_device(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should work
    copy_device = copy.deepcopy(DEVICE)
    copy_device['endpointList'][0]['port_id']['topoId']['contextId']['contextUuid']['uuid'] = ''
    copy_device['endpointList'][0]['port_id']['topoId']['topoId']['uuid'] = ''
    copy_device['endpointList'][0]['port_id']['dev_id']['device_id']['uuid'] = ''
    validate_device_id(MessageToDict(
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            device_client.AddDevice(Device(**copy_device)),
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            including_default_value_fields=True, preserving_proto_field_name=True,
            use_integers_for_enums=False))

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_configure_device_wrong_device_type(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with device type is wrong
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
        copy_device['device_type'] = 'wrong-type'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.ConfigureDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'Device(DEV1) has Type(ROADM) in the database. Cannot be changed to Type(wrong-type).'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_configure_device_with_endpoints(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with endpoints cannot be modified
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.ConfigureDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.details() == 'Endpoints belonging to Device(DEV1) cannot be modified.'
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_configure_device_no_change(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should fail with any change detected
    with pytest.raises(grpc._channel._InactiveRpcError) as e:
        copy_device = copy.deepcopy(DEVICE)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        copy_device['device_config']['device_config'] = ''
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        copy_device['devOperationalStatus'] = OperationalStatus.KEEP_STATE.value
        copy_device['endpointList'].clear()
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        device_client.ConfigureDevice(Device(**copy_device))
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    assert e.value.code() == grpc.StatusCode.ABORTED
    msg = ' '.join([
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        'Any change has been requested for Device(DEV1).',
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        'Either specify a new configuration or a new device operational status.',
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    ])
    assert e.value.details() == msg
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
def test_configure_device(device_client : DeviceClient):
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
    # should work
    copy_device = copy.deepcopy(DEVICE)
    copy_device['device_config']['device_config'] = '<new_config/>'
    copy_device['devOperationalStatus'] = OperationalStatus.DISABLED.value
    copy_device['endpointList'].clear()
    validate_device_id(MessageToDict(
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            device_client.ConfigureDevice(Device(**copy_device)),
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            including_default_value_fields=True, preserving_proto_field_name=True,
            use_integers_for_enums=False))