Skip to content

Commit 8e64a7b

Browse files
Merge pull request #79 from dls-controls/issue-37
Allow NELM and length as aliases for waveform length Also adding tests for various issues, and resolving test race conditions
2 parents 53f107d + 0115f40 commit 8e64a7b

File tree

4 files changed

+315
-102
lines changed

4 files changed

+315
-102
lines changed

softioc/builder.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,19 @@ def Action(name, **fields):
134134
}
135135

136136

137+
def _get_length(fields, default = None):
138+
'''Helper function for getting 'length' or 'NELM' from arguments'''
139+
140+
if 'length' in fields:
141+
assert 'NELM' not in fields, 'Cannot specify NELM and length together'
142+
return fields.pop('length')
143+
elif 'NELM' in fields:
144+
return fields.pop('NELM')
145+
else:
146+
assert default is not None, 'Must specify waveform length'
147+
return default
148+
149+
137150
def _waveform(value, fields):
138151
'''Helper routine for waveform construction. If a value is given it is
139152
interpreted as an initial value and used to configure length and datatype
@@ -165,7 +178,7 @@ def _waveform(value, fields):
165178
# If a value is specified it should be the *only* non keyword argument.
166179
value, = value
167180
initial_value = device._require_waveform(value, datatype)
168-
length = fields.pop('length', len(initial_value))
181+
length = _get_length(fields, len(initial_value))
169182

170183
# Special case for [u]int64: if the initial value comes in as 64 bit
171184
# integers we cannot represent that, so recast it as [u]int32
@@ -176,7 +189,7 @@ def _waveform(value, fields):
176189
initial_value = numpy.require(initial_value, numpy.uint32)
177190
else:
178191
initial_value = numpy.array([], dtype = datatype)
179-
length = fields.pop('length')
192+
length = _get_length(fields)
180193
datatype = initial_value.dtype
181194

182195
assert length > 0, 'Array cannot be of zero length'

tests/conftest.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,20 @@
1515
sys.platform.startswith("win"), reason="Cothread doesn't work on windows"
1616
)
1717

18+
# Default length used to initialise Waveform and longString records.
19+
# Length picked to match string record length, so we can re-use test strings.
20+
WAVEFORM_LENGTH = 40
21+
22+
# Default timeout for many operations across testing
23+
TIMEOUT = 10 # Seconds
24+
25+
def create_random_prefix():
26+
"""Create 12-character random string, for generating unique Device Names"""
27+
return "".join(random.choice(string.ascii_uppercase) for _ in range(12))
28+
1829
class SubprocessIOC:
1930
def __init__(self, ioc_py):
20-
self.pv_prefix = "".join(
21-
random.choice(string.ascii_uppercase) for _ in range(12)
22-
)
31+
self.pv_prefix = create_random_prefix()
2332
sim_ioc = os.path.join(os.path.dirname(__file__), ioc_py)
2433
cmd = [sys.executable, sim_ioc, self.pv_prefix]
2534
self.proc = subprocess.Popen(
@@ -76,9 +85,9 @@ def _clear_records():
7685
# https://github.com/dls-controls/pythonSoftIOC/issues/56
7786
RecordLookup._RecordDirectory.clear()
7887

79-
@pytest.fixture
88+
@pytest.fixture(autouse=True)
8089
def clear_records():
81-
"""Fixture to delete all records before and after a test."""
90+
"""Deletes all records before and after every test"""
8291
_clear_records()
8392
yield
8493
_clear_records()
@@ -93,3 +102,21 @@ def enable_code_coverage():
93102
pass
94103
else:
95104
cleanup_on_sigterm()
105+
106+
def select_and_recv(conn, expected_char = None):
107+
"""Wait for the given Connection to have data to receive, and return it.
108+
If a character is provided check its correct before returning it.
109+
This function imports Cothread, and so must NOT be called before any
110+
multiprocessing sub-processes are spawned."""
111+
from cothread import select
112+
rrdy, _, _ = select([conn], [], [], TIMEOUT)
113+
if rrdy:
114+
val = conn.recv()
115+
else:
116+
pytest.fail("Did not receive expected char before TIMEOUT expired")
117+
118+
if expected_char:
119+
assert val == expected_char, \
120+
"Expected character did not match"
121+
122+
return val

0 commit comments

Comments
 (0)