From 85bcec24ca19b023ed9ce741e672c8bbd9f49c0a Mon Sep 17 00:00:00 2001 From: chrisruk Date: Thu, 23 Jun 2022 11:21:59 +0100 Subject: [PATCH 1/4] Test uploading firmware --- test/firmware.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 test/firmware.py diff --git a/test/firmware.py b/test/firmware.py new file mode 100644 index 0000000..0da70a7 --- /dev/null +++ b/test/firmware.py @@ -0,0 +1,47 @@ +"""Test uploading firmware""" + +import time +import unittest +from multiprocessing import Process + +from gpiozero import DigitalOutputDevice + +RESET_GPIO_NUMBER = 4 +BOOT0_GPIO_NUMBER = 22 + + +def resethat(): + """Reset the HAT""" + reset = DigitalOutputDevice(RESET_GPIO_NUMBER) + boot0 = DigitalOutputDevice(BOOT0_GPIO_NUMBER) + boot0.off() + reset.off() + time.sleep(0.01) + reset.on() + time.sleep(0.01) + boot0.close() + reset.close() + time.sleep(0.5) + + +def reboot(): + """Reboot hat""" + from buildhat import Hat + resethat() + h = Hat(debug=True) + print(h.get()) + + +class TestFirmware(unittest.TestCase): + """Test firmware uploading functions""" + + def test_upload(self): + """Test uploading firmware""" + for _ in range(200): + p = Process(target=reboot) + p.start() + p.join() + + +if __name__ == '__main__': + unittest.main() From 0bd8fcf9901a2c97a47df4121a1c10345a4f5443 Mon Sep 17 00:00:00 2001 From: chrisruk Date: Fri, 24 Jun 2022 10:44:10 +0100 Subject: [PATCH 2/4] Catch exceptions in subprocess --- test/firmware.py | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/test/firmware.py b/test/firmware.py index 0da70a7..72723f8 100644 --- a/test/firmware.py +++ b/test/firmware.py @@ -2,7 +2,8 @@ import time import unittest -from multiprocessing import Process +from multiprocessing import Process, Queue +from queue import Empty from gpiozero import DigitalOutputDevice @@ -24,23 +25,37 @@ def resethat(): time.sleep(0.5) -def reboot(): - """Reboot hat""" - from buildhat import Hat - resethat() - h = Hat(debug=True) - print(h.get()) +def reboot(exc): + """Reboot hat and load firmware + + :param exc: Queue to pass exceptions + """ + try: + from buildhat import Hat + resethat() + h = Hat(debug=True) + print(h.get()) + except Exception as e: + exc.put(e) class TestFirmware(unittest.TestCase): """Test firmware uploading functions""" def test_upload(self): - """Test uploading firmware""" - for _ in range(200): - p = Process(target=reboot) + """Test upload firmware + + :raises exc.get: Raised if exception in subprocess + """ + for _ in range(500): + exc = Queue() + p = Process(target=reboot, args=(exc,)) p.start() p.join() + try: + raise exc.get(False) + except Empty: + pass if __name__ == '__main__': From 3d7e26224c790795e3bc0355eff5eb6808dfab08 Mon Sep 17 00:00:00 2001 From: chrisruk Date: Tue, 19 Jul 2022 16:24:52 +0100 Subject: [PATCH 3/4] Power cycle the pi for testing timed out issue --- test/powercycle/.gitignore | 1 + test/powercycle/control.yml | 29 +++++++++++++++++++ test/powercycle/restart.py | 56 +++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 test/powercycle/.gitignore create mode 100644 test/powercycle/control.yml create mode 100644 test/powercycle/restart.py diff --git a/test/powercycle/.gitignore b/test/powercycle/.gitignore new file mode 100644 index 0000000..6ff331c --- /dev/null +++ b/test/powercycle/.gitignore @@ -0,0 +1 @@ +hosts diff --git a/test/powercycle/control.yml b/test/powercycle/control.yml new file mode 100644 index 0000000..aa5248d --- /dev/null +++ b/test/powercycle/control.yml @@ -0,0 +1,29 @@ +- name: Run test + hosts: hosts + gather_facts: false + environment: + PYTHONPATH: /home/pi/Repositories/python-build-hat:/home/pi/.local/lib/python3.9/site-packages/ + tasks: + - name: Wait 300 seconds, but only start checking after 60 seconds + wait_for_connection: + delay: 60 + timeout: 300 + - name: Run experiment + command: python3 /home/pi/Repositories/python-build-hat/test/firmware.py + vars: + ansible_command_timeout: 60 # timeout set to double time firmware.py takes to run + - name: Find logs from experiment + find: + paths: /tmp + patterns: "buildhat-*.log" + register: log_files + - name: Copy + copy: + remote_src: yes + src: "{{item.path}}" + dest: "/home/pi/logs/" + loop: "{{log_files.files}}" + - name: Shutdown machine + command: systemctl poweroff + when: shutdown is defined + become: yes diff --git a/test/powercycle/restart.py b/test/powercycle/restart.py new file mode 100644 index 0000000..9b9d51b --- /dev/null +++ b/test/powercycle/restart.py @@ -0,0 +1,56 @@ +import json +import os +import time +import urllib.request + +from ansible import context +from ansible.cli import CLI +from ansible.executor.playbook_executor import PlaybookExecutor +from ansible.inventory.manager import InventoryManager +from ansible.module_utils.common.collections import ImmutableDict +from ansible.parsing.dataloader import DataLoader +from ansible.vars.manager import VariableManager + + +def runPlaybook(yml, evars): + loader = DataLoader() + context.CLIARGS = ImmutableDict(tags={}, timeout=300, listtags=False, listtasks=False, listhosts=False, syntax=False, connection='ssh', + module_path=None, forks=100, private_key_file=None, ssh_common_args=None, ssh_extra_args=None, + sftp_extra_args=None, scp_extra_args=None, become=False, become_method='sudo', become_user='root', + verbosity=True, check=False, start_at_task=None, extra_vars=[{**{"ansible_python_interpreter": "/usr/bin/python3"}, **evars}]) + inventory = InventoryManager(loader=loader, sources=('hosts',)) + variable_manager = VariableManager(loader=loader, inventory=inventory, version_info=CLI.version_info(gitinfo=False)) + pbex = PlaybookExecutor(playbooks=[yml], inventory=inventory, variable_manager=variable_manager, loader=loader, passwords={}) + results = pbex.run() + if results != 0: + raise RuntimeError("Playbook failed to run correctly") + +def switch(plug, on): + if on: + state = "On" + else: + state = "Off" + api_url = f"http://{plug}/cm?cmnd=Power%20{state}" + request = urllib.request.Request(api_url) + with urllib.request.urlopen(request) as response: + data = json.loads(response.read().decode("utf-8")) + if data['POWER'] != state.upper(): + raise Exception("Failed to set power", data['POWER']) + +if __name__ == "__main__": + + plug = os.getenv('TASMOTA') + if plug is None: + raise Exception("Need to set TASMOTA env variable") + + COUNT = 3 + for i in range(COUNT): + print(f"At {i}") + if i < COUNT - 1: + runPlaybook("control.yml", {"shutdown" : True}) + time.sleep(20) + switch(plug, False) + time.sleep(5) + switch(plug, True) + else: + runPlaybook("control.yml", {}) From 51f0140c1e4e7e90f8e83740d38042850334d92f Mon Sep 17 00:00:00 2001 From: chrisruk Date: Thu, 21 Jul 2022 10:04:09 +0100 Subject: [PATCH 4/4] Alter number of tests to run --- test/firmware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/firmware.py b/test/firmware.py index 72723f8..66a1633 100644 --- a/test/firmware.py +++ b/test/firmware.py @@ -47,7 +47,7 @@ def test_upload(self): :raises exc.get: Raised if exception in subprocess """ - for _ in range(500): + for _ in range(2): exc = Queue() p = Process(target=reboot, args=(exc,)) p.start()