Skip to content

Commit

Permalink
tests: Add integration and acceptance tests for NI-Digital and NI-Swi…
Browse files Browse the repository at this point in the history
…tch drivers session management APIs (#503)

* tests: set platform to add integration & acceptance tests for nidigital

* tests: set platform to add integration & acceptance test for niswitch

refactor: niswitch test measurement

* fix: add pins and sites for nidigital pin map

* tests: add assets to integration dir and add niswitch integration tests

refactor: niswitch integration tests

fix: get niswitch connections test

* tests: add integration tests for nidigital session APIs

tests: add integration tests for nidigital driver session APIs

* tests: add acceptance tests for niswitch driver session APIs

* tests: add acceptance tests for nidigital driver session APIs

* fix: lint errors

* fix: typo and discard unused attributes in pin map

* fix: lint errors

* refactor: nidigital measurement private api name

* fix: add underscores between when and then clauses

* fix: remove unused files

* fix: move digital pattern files to test measurement dir

* tests: pass all the pins to the test measurement

* style: import nims namespace for TypedSession

* tests: remove wait logic & standardize terminology

* fix: lint errors

* fix: more inner method to private method due to mypy error
  • Loading branch information
jayaseelan-james authored Nov 8, 2023
1 parent ed67c7e commit f8ea647
Show file tree
Hide file tree
Showing 28 changed files with 1,134 additions and 0 deletions.
121 changes: 121 additions & 0 deletions tests/acceptance/test_nidigital_measurement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import pathlib
from typing import Generator, Iterable, NamedTuple

import pytest

from ni_measurementlink_service._internal.stubs.ni.measurementlink.measurement.v2.measurement_service_pb2 import (
MeasureRequest,
)
from ni_measurementlink_service._internal.stubs.ni.measurementlink.measurement.v2.measurement_service_pb2_grpc import (
MeasurementServiceStub,
)
from ni_measurementlink_service._internal.stubs.ni.measurementlink.pin_map_context_pb2 import (
PinMapContext,
)
from ni_measurementlink_service.measurement.service import MeasurementService
from tests.assets.stubs.nidigital_measurement.types_pb2 import Configurations, Outputs
from tests.utilities import nidigital_measurement
from tests.utilities.pin_map_client import PinMapClient


def test___single_session___measure___returns_measured_values(
pin_map_id: str,
stub_v2: MeasurementServiceStub,
) -> None:
pin_map_context = PinMapContext(pin_map_id=pin_map_id, sites=[0])
configurations = Configurations(pin_names=["CS", "SCLK", "MOSI", "MISO"], multi_session=False)

outputs = _measure(stub_v2, pin_map_context, configurations)

assert outputs.passing_sites == [0]
assert outputs.failing_sites == []


def test___single_session___measure___creates_single_session(
pin_map_id: str,
stub_v2: MeasurementServiceStub,
) -> None:
pin_map_context = PinMapContext(pin_map_id=pin_map_id, sites=[0])
configurations = Configurations(pin_names=["CS", "SCLK", "MOSI", "MISO"], multi_session=False)

outputs = _measure(stub_v2, pin_map_context, configurations)

assert _get_output(outputs) == [
_MeasurementOutput(
"DigitalPattern1",
"DigitalPattern1",
"site0/CS, site0/SCLK, site0/MOSI, site0/MISO",
"site0/CS",
)
]


def test___multiple_sessions___measure___creates_multiple_sessions(
pin_map_id: str,
stub_v2: MeasurementServiceStub,
) -> None:
pin_map_context = PinMapContext(pin_map_id=pin_map_id, sites=[0, 1])
configurations = Configurations(pin_names=["CS", "SCLK", "MOSI", "MISO"], multi_session=True)

outputs = _measure(stub_v2, pin_map_context, configurations)

assert _get_output(outputs) == [
_MeasurementOutput(
"DigitalPattern1",
"DigitalPattern1",
"site0/CS, site0/SCLK, site0/MOSI, site0/MISO",
"site0/CS, site0/SCLK, site0/MOSI, site0/MISO",
),
_MeasurementOutput(
"DigitalPattern2",
"DigitalPattern2",
"site1/CS, site1/SCLK, site1/MOSI, site1/MISO",
"site1/CS, site1/SCLK, site1/MOSI, site1/MISO",
),
]


def _measure(
stub_v2: MeasurementServiceStub,
pin_map_context: PinMapContext,
configurations: Configurations,
) -> Outputs:
request = MeasureRequest(pin_map_context=pin_map_context)
request.configuration_parameters.Pack(configurations)
response_iterator = stub_v2.Measure(request)
responses = list(response_iterator)
assert len(responses) == 1
outputs = Outputs.FromString(responses[0].outputs.value)
return outputs


@pytest.fixture(scope="module")
def measurement_service() -> Generator[MeasurementService, None, None]:
"""Test fixture that creates and hosts a measurement service."""
with nidigital_measurement.measurement_service.host_service() as service:
yield service


@pytest.fixture
def pin_map_id(pin_map_client: PinMapClient, pin_map_directory: pathlib.Path) -> str:
pin_map_name = "2Digital2Group4Pin1Site.pinmap"
return pin_map_client.update_pin_map(pin_map_directory / pin_map_name)


class _MeasurementOutput(NamedTuple):
session_name: str
resource_name: str
channel_list: str
connected_channels: str


def _get_output(outputs: Outputs) -> Iterable[_MeasurementOutput]:
return [
_MeasurementOutput(session_name, resource_name, channel_list, connected_channels)
for session_name, resource_name, channel_list, connected_channels in zip(
outputs.session_names,
outputs.resource_names,
outputs.channel_lists,
outputs.connected_channels,
)
]
96 changes: 96 additions & 0 deletions tests/acceptance/test_niswitch_measurement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import pathlib
from typing import Generator, Iterable, NamedTuple

import pytest

from ni_measurementlink_service._internal.stubs.ni.measurementlink.measurement.v2.measurement_service_pb2 import (
MeasureRequest,
)
from ni_measurementlink_service._internal.stubs.ni.measurementlink.measurement.v2.measurement_service_pb2_grpc import (
MeasurementServiceStub,
)
from ni_measurementlink_service._internal.stubs.ni.measurementlink.pin_map_context_pb2 import (
PinMapContext,
)
from ni_measurementlink_service.measurement.service import MeasurementService
from tests.assets.stubs.niswitch_measurement.types_pb2 import (
Configurations,
Outputs,
)
from tests.utilities import niswitch_measurement
from tests.utilities.pin_map_client import PinMapClient

_SITE = 0


def test___single_session___measure___creates_single_session(
pin_map_context: PinMapContext,
stub_v2: MeasurementServiceStub,
) -> None:
configurations = Configurations(relay_names=["SiteRelay1"], multi_session=False)

outputs = _measure(stub_v2, pin_map_context, configurations)

assert _get_output(outputs) == [_MeasurementOutput("RelayDriver1", "RelayDriver1", "K0", "K0")]


def test___multiple_sessions___measure___creates_multiple_sessions(
pin_map_context: PinMapContext,
stub_v2: MeasurementServiceStub,
) -> None:
configurations = Configurations(relay_names=["SiteRelay1", "SiteRelay2"], multi_session=True)

outputs = _measure(stub_v2, pin_map_context, configurations)

assert _get_output(outputs) == [
_MeasurementOutput("RelayDriver1", "RelayDriver1", "K0", "K0"),
_MeasurementOutput("RelayDriver2", "RelayDriver2", "K1", "K1"),
]


def _measure(
stub_v2: MeasurementServiceStub,
pin_map_context: PinMapContext,
configurations: Configurations,
) -> Outputs:
request = MeasureRequest(pin_map_context=pin_map_context)
request.configuration_parameters.Pack(configurations)
response_iterator = stub_v2.Measure(request)
responses = list(response_iterator)
assert len(responses) == 1
outputs = Outputs.FromString(responses[0].outputs.value)
return outputs


@pytest.fixture(scope="module")
def measurement_service() -> Generator[MeasurementService, None, None]:
"""Test fixture that creates and hosts a measurement service."""
with niswitch_measurement.measurement_service.host_service() as service:
yield service


@pytest.fixture
def pin_map_context(pin_map_client: PinMapClient, pin_map_directory: pathlib.Path) -> PinMapContext:
pin_map_name = "2Switch2Relay1Site.pinmap"
pin_map_id = pin_map_client.update_pin_map(pin_map_directory / pin_map_name)

return PinMapContext(pin_map_id=pin_map_id, sites=[_SITE])


class _MeasurementOutput(NamedTuple):
session_name: str
resource_name: str
channel_list: str
connected_channels: str


def _get_output(outputs: Outputs) -> Iterable[_MeasurementOutput]:
return [
_MeasurementOutput(session_name, resource_name, channel_list, connected_channels)
for session_name, resource_name, channel_list, connected_channels in zip(
outputs.session_names,
outputs.resource_names,
outputs.channel_lists,
outputs.connected_channels,
)
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<PinMap schemaVersion="1.5" xmlns="http://www.ni.com/TestStand/SemiconductorModule/PinMap.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Instruments>
<NIDigitalPatternInstrument name="DigitalPattern1" numberOfChannels="32" group="Digital0" />
<NIDigitalPatternInstrument name="DigitalPattern2" numberOfChannels="32" group="Digital1" />
</Instruments>
<Pins>
<DUTPin name="CS" />
<DUTPin name="SCLK" />
<DUTPin name="MOSI" />
<DUTPin name="MISO" />
</Pins>
<PinGroups></PinGroups>
<Sites>
<Site siteNumber="0" />
<Site siteNumber="1" />
</Sites>
<Connections>
<Connection pin="CS" siteNumber="0" instrument="DigitalPattern1" channel="0" />
<Connection pin="SCLK" siteNumber="0" instrument="DigitalPattern1" channel="1" />
<Connection pin="MOSI" siteNumber="0" instrument="DigitalPattern1" channel="2" />
<Connection pin="MISO" siteNumber="0" instrument="DigitalPattern1" channel="3" />
<Connection pin="CS" siteNumber="1" instrument="DigitalPattern2" channel="0" />
<Connection pin="SCLK" siteNumber="1" instrument="DigitalPattern2" channel="1" />
<Connection pin="MOSI" siteNumber="1" instrument="DigitalPattern2" channel="2" />
<Connection pin="MISO" siteNumber="1" instrument="DigitalPattern2" channel="3" />
</Connections>
</PinMap>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<PinMap xmlns="http://www.ni.com/TestStand/SemiconductorModule/PinMap.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaVersion="1.4">
<Instruments>
<NIRelayDriverModule name="RelayDriver1" numberOfControlLines="64" />
<NIRelayDriverModule name="RelayDriver2" numberOfControlLines="64" />
</Instruments>
<Pins></Pins>
<PinGroups></PinGroups>
<Relays>
<SiteRelay name="SiteRelay1" />
<SiteRelay name="SiteRelay2" />
</Relays>
<RelayGroups></RelayGroups>
<Sites>
<Site siteNumber="0" />
</Sites>
<Connections>
<RelayConnection relay="SiteRelay1" siteNumber="0" relayDriverModule="RelayDriver1" controlLine="K0" />
<RelayConnection relay="SiteRelay2" siteNumber="0" relayDriverModule="RelayDriver2" controlLine="K1" />
</Connections>
</PinMap>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<PinMap schemaVersion="1.5" xmlns="http://www.ni.com/TestStand/SemiconductorModule/PinMap.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Instruments>
<NIDigitalPatternInstrument name="DigitalPattern1" numberOfChannels="32" group="Digital0" />
<NIDigitalPatternInstrument name="DigitalPattern2" numberOfChannels="32" group="Digital1" />
</Instruments>
<Pins>
<DUTPin name="CS" />
<DUTPin name="SCLK" />
<DUTPin name="MOSI" />
<DUTPin name="MISO" />
</Pins>
<PinGroups></PinGroups>
<Sites>
<Site siteNumber="0" />
<Site siteNumber="1" />
</Sites>
<Connections>
<Connection pin="CS" siteNumber="0" instrument="DigitalPattern1" channel="0" />
<Connection pin="SCLK" siteNumber="0" instrument="DigitalPattern1" channel="1" />
<Connection pin="MOSI" siteNumber="0" instrument="DigitalPattern1" channel="2" />
<Connection pin="MISO" siteNumber="0" instrument="DigitalPattern1" channel="3" />
<Connection pin="CS" siteNumber="1" instrument="DigitalPattern2" channel="0" />
<Connection pin="SCLK" siteNumber="1" instrument="DigitalPattern2" channel="1" />
<Connection pin="MOSI" siteNumber="1" instrument="DigitalPattern2" channel="2" />
<Connection pin="MISO" siteNumber="1" instrument="DigitalPattern2" channel="3" />
</Connections>
</PinMap>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<PinMap xmlns="http://www.ni.com/TestStand/SemiconductorModule/PinMap.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaVersion="1.4">
<Instruments>
<NIRelayDriverModule name="RelayDriver1" numberOfControlLines="64" />
<NIRelayDriverModule name="RelayDriver2" numberOfControlLines="64" />
</Instruments>
<Pins></Pins>
<PinGroups></PinGroups>
<Relays>
<SiteRelay name="SiteRelay1" />
<SiteRelay name="SiteRelay2" />
</Relays>
<RelayGroups></RelayGroups>
<Sites>
<Site siteNumber="0" />
</Sites>
<Connections>
<RelayConnection relay="SiteRelay1" siteNumber="0" relayDriverModule="RelayDriver1" controlLine="K0" />
<RelayConnection relay="SiteRelay2" siteNumber="0" relayDriverModule="RelayDriver2" controlLine="K1" />
</Connections>
</PinMap>
1 change: 1 addition & 0 deletions tests/assets/stubs/nidigital_measurement/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Auto generated gRPC files for nidigital test measurement."""
16 changes: 16 additions & 0 deletions tests/assets/stubs/nidigital_measurement/types.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
syntax = "proto3";
package ni.measurementlink.measurement.tests.nidigital_measurement;

message Configurations {
repeated string pin_names = 1;
bool multi_session = 2;
}

message Outputs {
repeated string session_names = 1;
repeated string resource_names = 2;
repeated string channel_lists = 3;
repeated string connected_channels = 4;
repeated int32 passing_sites = 5;
repeated int32 failing_sites = 6;
}
27 changes: 27 additions & 0 deletions tests/assets/stubs/nidigital_measurement/types_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f8ea647

Please sign in to comment.