def test_Worker_DAQ___rate(): print_title("Worker_DAQ - INTERNAL_TIMER - DAQ rate") def DAQ_function(): # Must return True when successful, False otherwise reply = dev.fake_query_1() dprint(" " * 50 + "%.1f Hz" % qdev.obtained_DAQ_rate_Hz) return reply[-4:] == "0101" app = create_QApplication() dev = FakeDevice() qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ(DAQ_trigger=DAQ_TRIGGER.INTERNAL_TIMER, DAQ_function=DAQ_function, DAQ_interval_ms=10, critical_not_alive_count=1, debug=DEBUG) # fmt: on assert qdev.start() == True # Simulate device runtime start_time = time.perf_counter() while time.perf_counter() - start_time < 1.51: app.processEvents() time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() assert 9 <= qdev.obtained_DAQ_interval_ms <= 11 assert 99 <= qdev.obtained_DAQ_rate_Hz <= 101
def test_Worker_jobs__quit_without_start(): print_title("Worker_jobs - quit without start") app = create_QApplication() qdev = QDeviceIO(FakeDevice()) qdev.create_worker_jobs() tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit()
def test_Worker_DAQ___CONTINUOUS(start_alive=True): print_title("Worker_DAQ - CONTINUOUS" + ("" if start_alive else " - start dead")) def DAQ_function(): # Must return True when successful, False otherwise time.sleep(0.1) # Simulate blocking processing time on the device reply = dev.fake_query_1() return reply[-4:] == "0101" app = create_QApplication() dev = FakeDevice(start_alive=start_alive) qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ( DAQ_trigger=DAQ_TRIGGER.CONTINUOUS, DAQ_function=DAQ_function, critical_not_alive_count=1, debug=DEBUG, ) # fmt: on qdev.signal_DAQ_updated.connect(process_DAQ_updated) qdev.signal_DAQ_paused.connect(process_DAQ_paused) assert qdev.start() == start_alive # Immediately fire a call to test if the worker is ready for it qdev.unpause_DAQ() # Simulate device runtime start_time = time.perf_counter() QtCore.QTimer.singleShot(300, qdev.pause_DAQ) QtCore.QTimer.singleShot(600, qdev.unpause_DAQ) QtCore.QTimer.singleShot(900, qdev.pause_DAQ) QtCore.QTimer.singleShot(1200, qdev.unpause_DAQ) while time.perf_counter() - start_time < 1.6: app.processEvents() if dev.count_commands == 12: break time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() if start_alive: assert dev.count_commands >= 10 assert dev.count_replies >= 10 assert (cnt_DAQ_updated >= 9 ) # Last signal is not always received before thread is quit assert cnt_DAQ_paused == 3
def test_Worker_DAQ___lose_connection(): print_title("Worker_DAQ - INTERNAL_TIMER - lose connection") def DAQ_function(): # Must return True when successful, False otherwise if qdev.update_counter_DAQ == 10: dev.is_alive = False reply = dev.fake_query_1() return reply[-4:] == "0101" # NOTE: The global 'go' mechanism used here is a quick and dirty way to # pytest. In production, it should be implemented by an boolean external # class member. global go go = True @QtCore.pyqtSlot() def process_connection_lost(): tprint("---> received: connection_lost") global go go = False app = create_QApplication() dev = FakeDevice() # Forcefully remove members as extra test del dev.name del dev.is_alive qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ(DAQ_trigger=DAQ_TRIGGER.INTERNAL_TIMER, DAQ_function=DAQ_function, DAQ_interval_ms=20, critical_not_alive_count=3, debug=DEBUG) # fmt: on qdev.create_worker_jobs(debug=DEBUG) qdev.signal_connection_lost.connect(process_connection_lost) assert qdev.start() == True # Simulate device runtime while go: app.processEvents() time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True assert qdev.quit() == True # Twice, to check for msg 'already closed'. app.quit()
def test_Worker_jobs__jobs_function(): print_title("Worker_jobs - jobs_function") def jobs_function(func, args): if func == "special command": dev.fake_query_2() else: # Default job handling where, e.g. # func = self.dev.write # args = ("toggle LED",) func(*args) app = create_QApplication() dev = FakeDevice() qdev = QDeviceIO(dev) qdev.create_worker_jobs( jobs_function=jobs_function, debug=DEBUG, ) qdev.signal_jobs_updated.connect(process_jobs_updated) assert qdev.start() == True # Immediately fire a call to test if the worker is ready for it qdev.send(dev.fake_query_2) # fmt: off # Simulate device runtime start_time = time.perf_counter() QtCore.QTimer.singleShot(100, lambda: qdev.send("special command")) QtCore.QTimer.singleShot( 200, lambda: qdev.send(dev.fake_command_with_argument, 0)) # fmt: on while time.perf_counter() - start_time < 0.5: app.processEvents() time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() assert dev.count_commands == 3 assert dev.count_replies == 2 assert cnt_jobs_updated == 3
def test_Worker_jobs(start_alive=True): print_title("Worker_jobs" + ("" if start_alive else " - start dead")) app = create_QApplication() dev = FakeDevice(start_alive=start_alive) qdev = QDeviceIO(dev) qdev.create_worker_jobs(debug=DEBUG) qdev.signal_jobs_updated.connect(process_jobs_updated) assert qdev.start() == start_alive # Immediately fire a call to test if the worker is ready for it qdev.add_to_jobs_queue(dev.fake_query_2) # fmt: off # Simulate device runtime start_time = time.perf_counter() QtCore.QTimer.singleShot(100, qdev.process_jobs_queue) QtCore.QTimer.singleShot(200, lambda: qdev.send(dev.fake_query_2)) QtCore.QTimer.singleShot( 300, lambda: qdev.add_to_jobs_queue(dev.fake_command_with_argument, 0)) QtCore.QTimer.singleShot( 400, lambda: qdev.add_to_jobs_queue(dev.fake_command_with_argument, 0)) QtCore.QTimer.singleShot( 500, lambda: qdev.add_to_jobs_queue(dev.fake_command_with_argument, 0)) QtCore.QTimer.singleShot(600, qdev.process_jobs_queue) QtCore.QTimer.singleShot( 700, lambda: qdev.send("trigger_illegal_function_call_error")) # fmt: on while time.perf_counter() - start_time < 1: app.processEvents() time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() if start_alive: assert dev.count_commands == 5 assert dev.count_replies == 2 assert cnt_jobs_updated == 4
def test_Worker_DAQ___SINGLE_SHOT_WAKE_UP(start_alive=True): print_title("Worker_DAQ - SINGLE_SHOT_WAKE_UP" + ("" if start_alive else " - start dead")) def DAQ_function(): # Must return True when successful, False otherwise reply = dev.fake_query_1() return reply[-4:] == "0101" app = create_QApplication() dev = FakeDevice(start_alive=start_alive) qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ(DAQ_trigger=DAQ_TRIGGER.SINGLE_SHOT_WAKE_UP, DAQ_function=DAQ_function, critical_not_alive_count=1, debug=DEBUG) # fmt: on qdev.signal_DAQ_updated.connect(process_DAQ_updated) assert qdev.start() == start_alive # Immediately fire a call to test if the worker is ready for it qdev.wake_up_DAQ() # Simulate device runtime start_time = time.perf_counter() QtCore.QTimer.singleShot(300, qdev.wake_up_DAQ) QtCore.QTimer.singleShot(600, qdev.wake_up_DAQ) while time.perf_counter() - start_time < 1: app.processEvents() time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() if start_alive: assert dev.count_commands == 3 assert dev.count_replies == 3 assert cnt_DAQ_updated == 3
def test_Worker_DAQ___INTERNAL_TIMER(start_alive=True): print_title("Worker_DAQ - INTERNAL_TIMER" + ("" if start_alive else " - start dead")) def DAQ_function(): # Must return True when successful, False otherwise reply = dev.fake_query_1() return reply[-4:] == "0101" app = create_QApplication() dev = FakeDevice(start_alive=start_alive) qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ(DAQ_trigger=DAQ_TRIGGER.INTERNAL_TIMER, DAQ_function=DAQ_function, DAQ_interval_ms=100, critical_not_alive_count=10, debug=DEBUG) # fmt: on qdev.signal_DAQ_updated.connect(process_DAQ_updated) assert qdev.start() == start_alive # Simulate device runtime start_time = time.perf_counter() while time.perf_counter() - start_time < 1: app.processEvents() if dev.count_commands == 3: break time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() if start_alive: assert dev.count_commands >= 3 assert dev.count_replies >= 3 assert (cnt_DAQ_updated >= 2 ) # Last signal is not always received before thread is quit
def test_Worker_DAQ___INTERNAL_TIMER__subclassed(): print_title("Worker_DAQ - INTERNAL_TIMER - subclassed") def DAQ_function(): # Must return True when successful, False otherwise reply = dev.fake_query_1() return reply[-4:] == "0101" app = create_QApplication() dev = FakeDevice() qdev = QDeviceIO_subclassed( dev=dev, DAQ_function=DAQ_function, debug=DEBUG, ) qdev.signal_DAQ_updated.connect(process_DAQ_updated) qdev.signal_jobs_updated.connect(process_jobs_updated) qdev.start() # fmt: off # Simulate device runtime start_time = time.perf_counter() QtCore.QTimer.singleShot(300, lambda: qdev.send(dev.fake_query_2)) QtCore.QTimer.singleShot( 600, lambda: qdev.send(dev.fake_command_with_argument, 0)) # fmt: on while time.perf_counter() - start_time < 1: app.processEvents() time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() assert dev.count_commands >= 11 assert dev.count_replies >= 10 assert (cnt_DAQ_updated >= 9 ) # Last signal is not always received before thread is quit assert cnt_jobs_updated == 2
def test_Worker_DAQ___ILLEGAL_DAQ_FUNCTION(): print_title("Worker_DAQ - ILLEGAL_DAQ_FUNCTION") def DAQ_function(): # Must return True when successful, False otherwise if qdev.update_counter_DAQ == 2: 0 / 0 else: reply = dev.fake_query_1() return reply[-4:] == "0101" app = create_QApplication() dev = FakeDevice() qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ(DAQ_trigger=DAQ_TRIGGER.INTERNAL_TIMER, DAQ_function=DAQ_function, DAQ_interval_ms=100, debug=DEBUG) # fmt: on qdev.signal_DAQ_updated.connect(process_DAQ_updated) assert qdev.start() == True # Simulate device runtime start_time = time.perf_counter() while time.perf_counter() - start_time < 1: app.processEvents() if dev.count_commands == 3: break time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit()
def update_chart(self): if DEBUG: tprint("update_curve") self.history_chart_curve.update()
def test_tprint(): with mock.patch("sys.stdout", new=io.StringIO()) as fake_stdout: tprint("No color") assert fake_stdout.getvalue()[-9:] == "No color\n"
def process_connection_lost(): tprint("---> received: connection_lost") global go go = False
def process_jobs_updated(): # In production code, your GUI update routine would go here tprint("---> received: jobs_updated") global cnt_jobs_updated cnt_jobs_updated += 1
def update_chart(self): if DEBUG: tprint("update_chart") for tscurve in self.tscurves: tscurve.update()