Skip to content

Commit f8ea647

Browse files
tests: Add integration and acceptance tests for NI-Digital and NI-Switch 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
1 parent ed67c7e commit f8ea647

28 files changed

+1134
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import pathlib
2+
from typing import Generator, Iterable, NamedTuple
3+
4+
import pytest
5+
6+
from ni_measurementlink_service._internal.stubs.ni.measurementlink.measurement.v2.measurement_service_pb2 import (
7+
MeasureRequest,
8+
)
9+
from ni_measurementlink_service._internal.stubs.ni.measurementlink.measurement.v2.measurement_service_pb2_grpc import (
10+
MeasurementServiceStub,
11+
)
12+
from ni_measurementlink_service._internal.stubs.ni.measurementlink.pin_map_context_pb2 import (
13+
PinMapContext,
14+
)
15+
from ni_measurementlink_service.measurement.service import MeasurementService
16+
from tests.assets.stubs.nidigital_measurement.types_pb2 import Configurations, Outputs
17+
from tests.utilities import nidigital_measurement
18+
from tests.utilities.pin_map_client import PinMapClient
19+
20+
21+
def test___single_session___measure___returns_measured_values(
22+
pin_map_id: str,
23+
stub_v2: MeasurementServiceStub,
24+
) -> None:
25+
pin_map_context = PinMapContext(pin_map_id=pin_map_id, sites=[0])
26+
configurations = Configurations(pin_names=["CS", "SCLK", "MOSI", "MISO"], multi_session=False)
27+
28+
outputs = _measure(stub_v2, pin_map_context, configurations)
29+
30+
assert outputs.passing_sites == [0]
31+
assert outputs.failing_sites == []
32+
33+
34+
def test___single_session___measure___creates_single_session(
35+
pin_map_id: str,
36+
stub_v2: MeasurementServiceStub,
37+
) -> None:
38+
pin_map_context = PinMapContext(pin_map_id=pin_map_id, sites=[0])
39+
configurations = Configurations(pin_names=["CS", "SCLK", "MOSI", "MISO"], multi_session=False)
40+
41+
outputs = _measure(stub_v2, pin_map_context, configurations)
42+
43+
assert _get_output(outputs) == [
44+
_MeasurementOutput(
45+
"DigitalPattern1",
46+
"DigitalPattern1",
47+
"site0/CS, site0/SCLK, site0/MOSI, site0/MISO",
48+
"site0/CS",
49+
)
50+
]
51+
52+
53+
def test___multiple_sessions___measure___creates_multiple_sessions(
54+
pin_map_id: str,
55+
stub_v2: MeasurementServiceStub,
56+
) -> None:
57+
pin_map_context = PinMapContext(pin_map_id=pin_map_id, sites=[0, 1])
58+
configurations = Configurations(pin_names=["CS", "SCLK", "MOSI", "MISO"], multi_session=True)
59+
60+
outputs = _measure(stub_v2, pin_map_context, configurations)
61+
62+
assert _get_output(outputs) == [
63+
_MeasurementOutput(
64+
"DigitalPattern1",
65+
"DigitalPattern1",
66+
"site0/CS, site0/SCLK, site0/MOSI, site0/MISO",
67+
"site0/CS, site0/SCLK, site0/MOSI, site0/MISO",
68+
),
69+
_MeasurementOutput(
70+
"DigitalPattern2",
71+
"DigitalPattern2",
72+
"site1/CS, site1/SCLK, site1/MOSI, site1/MISO",
73+
"site1/CS, site1/SCLK, site1/MOSI, site1/MISO",
74+
),
75+
]
76+
77+
78+
def _measure(
79+
stub_v2: MeasurementServiceStub,
80+
pin_map_context: PinMapContext,
81+
configurations: Configurations,
82+
) -> Outputs:
83+
request = MeasureRequest(pin_map_context=pin_map_context)
84+
request.configuration_parameters.Pack(configurations)
85+
response_iterator = stub_v2.Measure(request)
86+
responses = list(response_iterator)
87+
assert len(responses) == 1
88+
outputs = Outputs.FromString(responses[0].outputs.value)
89+
return outputs
90+
91+
92+
@pytest.fixture(scope="module")
93+
def measurement_service() -> Generator[MeasurementService, None, None]:
94+
"""Test fixture that creates and hosts a measurement service."""
95+
with nidigital_measurement.measurement_service.host_service() as service:
96+
yield service
97+
98+
99+
@pytest.fixture
100+
def pin_map_id(pin_map_client: PinMapClient, pin_map_directory: pathlib.Path) -> str:
101+
pin_map_name = "2Digital2Group4Pin1Site.pinmap"
102+
return pin_map_client.update_pin_map(pin_map_directory / pin_map_name)
103+
104+
105+
class _MeasurementOutput(NamedTuple):
106+
session_name: str
107+
resource_name: str
108+
channel_list: str
109+
connected_channels: str
110+
111+
112+
def _get_output(outputs: Outputs) -> Iterable[_MeasurementOutput]:
113+
return [
114+
_MeasurementOutput(session_name, resource_name, channel_list, connected_channels)
115+
for session_name, resource_name, channel_list, connected_channels in zip(
116+
outputs.session_names,
117+
outputs.resource_names,
118+
outputs.channel_lists,
119+
outputs.connected_channels,
120+
)
121+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import pathlib
2+
from typing import Generator, Iterable, NamedTuple
3+
4+
import pytest
5+
6+
from ni_measurementlink_service._internal.stubs.ni.measurementlink.measurement.v2.measurement_service_pb2 import (
7+
MeasureRequest,
8+
)
9+
from ni_measurementlink_service._internal.stubs.ni.measurementlink.measurement.v2.measurement_service_pb2_grpc import (
10+
MeasurementServiceStub,
11+
)
12+
from ni_measurementlink_service._internal.stubs.ni.measurementlink.pin_map_context_pb2 import (
13+
PinMapContext,
14+
)
15+
from ni_measurementlink_service.measurement.service import MeasurementService
16+
from tests.assets.stubs.niswitch_measurement.types_pb2 import (
17+
Configurations,
18+
Outputs,
19+
)
20+
from tests.utilities import niswitch_measurement
21+
from tests.utilities.pin_map_client import PinMapClient
22+
23+
_SITE = 0
24+
25+
26+
def test___single_session___measure___creates_single_session(
27+
pin_map_context: PinMapContext,
28+
stub_v2: MeasurementServiceStub,
29+
) -> None:
30+
configurations = Configurations(relay_names=["SiteRelay1"], multi_session=False)
31+
32+
outputs = _measure(stub_v2, pin_map_context, configurations)
33+
34+
assert _get_output(outputs) == [_MeasurementOutput("RelayDriver1", "RelayDriver1", "K0", "K0")]
35+
36+
37+
def test___multiple_sessions___measure___creates_multiple_sessions(
38+
pin_map_context: PinMapContext,
39+
stub_v2: MeasurementServiceStub,
40+
) -> None:
41+
configurations = Configurations(relay_names=["SiteRelay1", "SiteRelay2"], multi_session=True)
42+
43+
outputs = _measure(stub_v2, pin_map_context, configurations)
44+
45+
assert _get_output(outputs) == [
46+
_MeasurementOutput("RelayDriver1", "RelayDriver1", "K0", "K0"),
47+
_MeasurementOutput("RelayDriver2", "RelayDriver2", "K1", "K1"),
48+
]
49+
50+
51+
def _measure(
52+
stub_v2: MeasurementServiceStub,
53+
pin_map_context: PinMapContext,
54+
configurations: Configurations,
55+
) -> Outputs:
56+
request = MeasureRequest(pin_map_context=pin_map_context)
57+
request.configuration_parameters.Pack(configurations)
58+
response_iterator = stub_v2.Measure(request)
59+
responses = list(response_iterator)
60+
assert len(responses) == 1
61+
outputs = Outputs.FromString(responses[0].outputs.value)
62+
return outputs
63+
64+
65+
@pytest.fixture(scope="module")
66+
def measurement_service() -> Generator[MeasurementService, None, None]:
67+
"""Test fixture that creates and hosts a measurement service."""
68+
with niswitch_measurement.measurement_service.host_service() as service:
69+
yield service
70+
71+
72+
@pytest.fixture
73+
def pin_map_context(pin_map_client: PinMapClient, pin_map_directory: pathlib.Path) -> PinMapContext:
74+
pin_map_name = "2Switch2Relay1Site.pinmap"
75+
pin_map_id = pin_map_client.update_pin_map(pin_map_directory / pin_map_name)
76+
77+
return PinMapContext(pin_map_id=pin_map_id, sites=[_SITE])
78+
79+
80+
class _MeasurementOutput(NamedTuple):
81+
session_name: str
82+
resource_name: str
83+
channel_list: str
84+
connected_channels: str
85+
86+
87+
def _get_output(outputs: Outputs) -> Iterable[_MeasurementOutput]:
88+
return [
89+
_MeasurementOutput(session_name, resource_name, channel_list, connected_channels)
90+
for session_name, resource_name, channel_list, connected_channels in zip(
91+
outputs.session_names,
92+
outputs.resource_names,
93+
outputs.channel_lists,
94+
outputs.connected_channels,
95+
)
96+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<PinMap schemaVersion="1.5" xmlns="http://www.ni.com/TestStand/SemiconductorModule/PinMap.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
3+
<Instruments>
4+
<NIDigitalPatternInstrument name="DigitalPattern1" numberOfChannels="32" group="Digital0" />
5+
<NIDigitalPatternInstrument name="DigitalPattern2" numberOfChannels="32" group="Digital1" />
6+
</Instruments>
7+
<Pins>
8+
<DUTPin name="CS" />
9+
<DUTPin name="SCLK" />
10+
<DUTPin name="MOSI" />
11+
<DUTPin name="MISO" />
12+
</Pins>
13+
<PinGroups></PinGroups>
14+
<Sites>
15+
<Site siteNumber="0" />
16+
<Site siteNumber="1" />
17+
</Sites>
18+
<Connections>
19+
<Connection pin="CS" siteNumber="0" instrument="DigitalPattern1" channel="0" />
20+
<Connection pin="SCLK" siteNumber="0" instrument="DigitalPattern1" channel="1" />
21+
<Connection pin="MOSI" siteNumber="0" instrument="DigitalPattern1" channel="2" />
22+
<Connection pin="MISO" siteNumber="0" instrument="DigitalPattern1" channel="3" />
23+
<Connection pin="CS" siteNumber="1" instrument="DigitalPattern2" channel="0" />
24+
<Connection pin="SCLK" siteNumber="1" instrument="DigitalPattern2" channel="1" />
25+
<Connection pin="MOSI" siteNumber="1" instrument="DigitalPattern2" channel="2" />
26+
<Connection pin="MISO" siteNumber="1" instrument="DigitalPattern2" channel="3" />
27+
</Connections>
28+
</PinMap>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<PinMap xmlns="http://www.ni.com/TestStand/SemiconductorModule/PinMap.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaVersion="1.4">
3+
<Instruments>
4+
<NIRelayDriverModule name="RelayDriver1" numberOfControlLines="64" />
5+
<NIRelayDriverModule name="RelayDriver2" numberOfControlLines="64" />
6+
</Instruments>
7+
<Pins></Pins>
8+
<PinGroups></PinGroups>
9+
<Relays>
10+
<SiteRelay name="SiteRelay1" />
11+
<SiteRelay name="SiteRelay2" />
12+
</Relays>
13+
<RelayGroups></RelayGroups>
14+
<Sites>
15+
<Site siteNumber="0" />
16+
</Sites>
17+
<Connections>
18+
<RelayConnection relay="SiteRelay1" siteNumber="0" relayDriverModule="RelayDriver1" controlLine="K0" />
19+
<RelayConnection relay="SiteRelay2" siteNumber="0" relayDriverModule="RelayDriver2" controlLine="K1" />
20+
</Connections>
21+
</PinMap>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<PinMap schemaVersion="1.5" xmlns="http://www.ni.com/TestStand/SemiconductorModule/PinMap.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
3+
<Instruments>
4+
<NIDigitalPatternInstrument name="DigitalPattern1" numberOfChannels="32" group="Digital0" />
5+
<NIDigitalPatternInstrument name="DigitalPattern2" numberOfChannels="32" group="Digital1" />
6+
</Instruments>
7+
<Pins>
8+
<DUTPin name="CS" />
9+
<DUTPin name="SCLK" />
10+
<DUTPin name="MOSI" />
11+
<DUTPin name="MISO" />
12+
</Pins>
13+
<PinGroups></PinGroups>
14+
<Sites>
15+
<Site siteNumber="0" />
16+
<Site siteNumber="1" />
17+
</Sites>
18+
<Connections>
19+
<Connection pin="CS" siteNumber="0" instrument="DigitalPattern1" channel="0" />
20+
<Connection pin="SCLK" siteNumber="0" instrument="DigitalPattern1" channel="1" />
21+
<Connection pin="MOSI" siteNumber="0" instrument="DigitalPattern1" channel="2" />
22+
<Connection pin="MISO" siteNumber="0" instrument="DigitalPattern1" channel="3" />
23+
<Connection pin="CS" siteNumber="1" instrument="DigitalPattern2" channel="0" />
24+
<Connection pin="SCLK" siteNumber="1" instrument="DigitalPattern2" channel="1" />
25+
<Connection pin="MOSI" siteNumber="1" instrument="DigitalPattern2" channel="2" />
26+
<Connection pin="MISO" siteNumber="1" instrument="DigitalPattern2" channel="3" />
27+
</Connections>
28+
</PinMap>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<PinMap xmlns="http://www.ni.com/TestStand/SemiconductorModule/PinMap.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaVersion="1.4">
3+
<Instruments>
4+
<NIRelayDriverModule name="RelayDriver1" numberOfControlLines="64" />
5+
<NIRelayDriverModule name="RelayDriver2" numberOfControlLines="64" />
6+
</Instruments>
7+
<Pins></Pins>
8+
<PinGroups></PinGroups>
9+
<Relays>
10+
<SiteRelay name="SiteRelay1" />
11+
<SiteRelay name="SiteRelay2" />
12+
</Relays>
13+
<RelayGroups></RelayGroups>
14+
<Sites>
15+
<Site siteNumber="0" />
16+
</Sites>
17+
<Connections>
18+
<RelayConnection relay="SiteRelay1" siteNumber="0" relayDriverModule="RelayDriver1" controlLine="K0" />
19+
<RelayConnection relay="SiteRelay2" siteNumber="0" relayDriverModule="RelayDriver2" controlLine="K1" />
20+
</Connections>
21+
</PinMap>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Auto generated gRPC files for nidigital test measurement."""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
syntax = "proto3";
2+
package ni.measurementlink.measurement.tests.nidigital_measurement;
3+
4+
message Configurations {
5+
repeated string pin_names = 1;
6+
bool multi_session = 2;
7+
}
8+
9+
message Outputs {
10+
repeated string session_names = 1;
11+
repeated string resource_names = 2;
12+
repeated string channel_lists = 3;
13+
repeated string connected_channels = 4;
14+
repeated int32 passing_sites = 5;
15+
repeated int32 failing_sites = 6;
16+
}

tests/assets/stubs/nidigital_measurement/types_pb2.py

+27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)