Skip to content

Commit 26edf50

Browse files
committed
fixup single-step test
This commit is an attempt to fix the test failure here: <http://buildbot2.highlab.com/buildbot/#/builders/11/builds/990/steps/13/logs/stdio> I believe the test failure is due to a race condition in the test script, not a bug in LinuxCNC. Before this commit, the test requests a step any time the machine X and Y positions are both very near an integer multiple of 5. The test failure linked above shows this in the log: Taking step from X30.00 Y30.00 line=9; Xpos=30.98; Ypos=30.00; Zpos=0.00; counter=25 line=9; Xpos=31.82; Ypos=30.00; Zpos=0.00; counter=25 line=9; Xpos=32.65; Ypos=30.00; Zpos=0.00; counter=25 line=9; Xpos=33.48; Ypos=30.00; Zpos=0.00; counter=25 line=9; Xpos=34.32; Ypos=30.00; Zpos=0.00; counter=25 task: main loop took 0.015550 seconds Taking step from X35.00 Y30.00 line=9; Xpos=35.00; Ypos=30.00; Zpos=0.00; counter=25 Taking step from X35.00 Y30.00 line=0; Xpos=35.00; Ypos=30.00; Zpos=0.00; counter=25 Taking step from X35.00 Y30.00 line=9; Xpos=35.00; Ypos=30.00; Zpos=0.00; counter=25 Taking step from X35.00 Y30.00 line=5; Xpos=34.02; Ypos=30.00; Zpos=0.00; counter=0 line=5; Xpos=33.19; Ypos=30.00; Zpos=0.00; counter=0 ... End counter incorrect: 5 != 25 Normally the test would stop at (X=35, Y=30) with counter=25, and the test would pass. I believe in this case the test script got to run a couple of extra loops while waiting for LinuxCNC (Task & Motion) to respond to the earlier single-step requests, and thus queued up a bunch of extra single-step requests, which restarted the G-code program being single-stepped. The G-code program starts out by resetting the counter, so when the test finished it saw the new counter from the (incorrect) next run of the G-code program. This commit changes the test program to avoid this race, by waiting for each step to start and complete before considering issuing another step.
1 parent 43b8dc8 commit 26edf50

1 file changed

Lines changed: 42 additions & 7 deletions

File tree

tests/single-step/test-ui.py

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def print_state():
4444
c.home(2)
4545
l.wait_for_home([1, 1, 1, 0, 0, 0, 0, 0, 0])
4646
c.mode(linuxcnc.MODE_AUTO)
47-
47+
4848

4949
#
5050
# run the .ngc test file, starting from the special line
@@ -56,28 +56,63 @@ def print_state():
5656
def mod_5_is_0(x):
5757
return abs((x+epsilon) % 5) < 2*epsilon
5858

59-
# Take first step
59+
60+
def wait_complete_step():
61+
62+
'''The normal `linuxcnc.command.wait_complete()` function does not
63+
understand single-stepping. It waits for the `state` to return to
64+
`RCS_DONE` but this does not happen when single-stepping, `state`
65+
stays at `RCS_EXEC` while waiting for the next step.
66+
67+
This function instead waits for status.task.execState to tell us
68+
that Task is no longer waiting for Motion in any way.'''
69+
70+
timeout = 5.0
71+
start = time.time()
72+
73+
# Wait for the command to be acknowledged by Task (FIXME or is it motion?).
74+
while time.time() - start < timeout:
75+
s.poll()
76+
if s.echo_serial_number >= c.serial:
77+
break
78+
time.sleep(0.1)
79+
80+
# Wait for Task to be done waiting for Motion.
81+
while time.time() - start < timeout:
82+
s.poll()
83+
if s.exec_state not in [ linuxcnc.EXEC_WAITING_FOR_MOTION, linuxcnc.EXEC_WAITING_FOR_MOTION_AND_IO, linuxcnc.EXEC_WAITING_FOR_MOTION_QUEUE ]:
84+
return
85+
time.sleep(0.1)
86+
87+
raise SystemExit('timeout in wait_complete_step()')
88+
89+
90+
# Take first three steps (these cause no motion).
91+
c.auto(linuxcnc.AUTO_STEP)
92+
c.auto(linuxcnc.AUTO_STEP)
6093
c.auto(linuxcnc.AUTO_STEP)
94+
wait_complete_step()
6195

6296
count = 0
6397
while True:
6498
s.poll()
99+
if s.interp_state == linuxcnc.INTERP_IDLE:
100+
sys.stderr.write("Finished: Detected program finish\n")
101+
break
102+
65103
(x, y) = (h["Xpos"], h["Ypos"])
66104
if mod_5_is_0(x) and mod_5_is_0(y):
67-
# Both axes on goal; make next step and let motion start
105+
# Both axes on goal; command the next step and wait for it to finish.
68106
sys.stderr.write("Taking step from X%.2f Y%.2f\n" % (x, y))
69107
c.auto(linuxcnc.AUTO_STEP)
70-
time.sleep(0.1)
108+
wait_complete_step()
71109

72110
print_state()
73111

74112
count += 1
75113
if count >= 1000: # Shouldn't happen, but prevent runaways
76114
sys.stderr.write("Finished: Exceeded max cycles\n")
77115
sys.exit(1)
78-
if s.interp_state == linuxcnc.INTERP_IDLE:
79-
sys.stderr.write("Finished: Detected program finish\n")
80-
break
81116

82117
time.sleep(0.1)
83118

0 commit comments

Comments
 (0)