diff --git a/.gitignore b/.gitignore index 9f19284..0a973f3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ .vscode/ipch report.xml output +__pycache__ +.pytest_cache diff --git a/testlib/Makefile b/testlib/Makefile new file mode 100644 index 0000000..581cf96 --- /dev/null +++ b/testlib/Makefile @@ -0,0 +1,9 @@ +.PHONY: install test + +default: install test + +install: + pip3 install -r requirements.txt + +test: + ESP_PORT=/dev/ttyUSB0 pytest tests -v diff --git a/testlib/__init__.py b/testlib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/testlib/aprs_con.py b/testlib/aprs_con.py new file mode 100644 index 0000000..b7d839d --- /dev/null +++ b/testlib/aprs_con.py @@ -0,0 +1,83 @@ +import pytest +import socket + + +class AprsIs: + def __init__(self, callsign, passwd="-1", host="localhost", port=10152) -> None: + self.callsign = callsign + self.passwd = passwd + self.server = (host, port) + self.socket = None + self.buffer = "" + + def connect(self): + if self.socket: + return False + + self.socket = socket.create_connection(self.server) + peer = self.socket.getpeername() + print(f"Connected to {str(peer)}") + self.socket.setblocking(1) + self.socket.settimeout(1) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) + banner = list(self._get_line()) + print(f"Banner: {banner[0].rstrip()}") + + self.send_line( + f"user {self.callsign} pass {self.passwd} vers testlib 0.1\r\n") + + login = list(self._get_line()) + # self.socket.setblocking(0) + print(f"login line: {login[0]}") + _, _, _, status, _ = login[0].split(' ', 4) + if status == "verified": + return True + self.close() + return False + + # self._send_login() + + def close(self): + if not self.socket: + self.socket.close() + self.socket = None + + def send_line(self, line): + if self.socket: + self.socket.sendall(bytearray(f"{line}\r\n", encoding='utf8')) + + def get_line(self): + line = self._get_line() + if line.startswith("#"): + return None + yield line + + def _get_line(self): + if self.socket: + try: + buf = self.socket.recv(4096) + self.buffer = self.buffer + buf.decode('latin-1') + except: + pass + while "\r\n" in self.buffer: + line, self.buffer = self.buffer.split("\r\n", 1) + yield line + return None + + +@pytest.fixture +def APRSIS(): + aprs = AprsIs("OE5BPA-1", passwd="22948", + host="localhost", port=10152) + aprs.connect() + return aprs + + +aprs = AprsIs("OE5BPA-1", passwd="22948", + # host="localhost", port=10152) + host="rotate.aprs.net", port=10152) +aprs.connect() +while True: + line = list(aprs._get_line()) + if len(line) > 0: + print(line) diff --git a/testlib/common.py b/testlib/common.py new file mode 100644 index 0000000..dc8bc96 --- /dev/null +++ b/testlib/common.py @@ -0,0 +1,5 @@ +import subprocess + + +def runProcess(cmd): + subprocess.run(cmd, shell=True).check_returncode() diff --git a/testlib/esp_dut.py b/testlib/esp_dut.py new file mode 100644 index 0000000..8e3070b --- /dev/null +++ b/testlib/esp_dut.py @@ -0,0 +1,63 @@ +import os +import pytest +import serial +from testlib.common import runProcess + + +class EspFlash: + def __init__(self, port): + self.pio_package_path = "$HOME/.platformio/packages" + self.port = port + + def runESPTool(self, cmd): + runProcess( + f"/usr/bin/python3 {self.pio_package_path}/tool-esptoolpy/esptool.py --chip esp32 --port {self.port} {cmd}") + + def erase(self): + self.runESPTool("erase_flash") + + def write(self, addr, bin_file): + self.runESPTool( + f"--baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_size detect {addr} {bin_file}") + + def verify(self, addr, bin_file): + self.runESPTool( + f"--baud 460800 --before default_reset --after hard_reset verify_flash --flash_mode dio --flash_size detect {addr} {bin_file}") + + def make_spiffs(self, fs_path, fs_bin): + self.runESPTool( + f"{self.pio_package_path}/tool-mkspiffs/mkspiffs_espressif32_arduino -c {fs_path} -p 256 -b 4096 -s 1507328 {fs_bin}") + + +class EspDut: + def __init__(self, port): + self.port = port + self.serial = None + self.flash = EspFlash(self.port) + + def writeFlash(self, bin_dir, fs_path=None): + self.flash.erase() + if fs_path: + fs_bin = "spiffs.bin" + self.flash.make_spiffs(fs_path, fs_bin) + self.flash.write("2686976", fs_bin) + self.flash.write("0x1000", f"{bin_dir}/bootloader_dio_40m.bin") + self.flash.write("0x8000", f"{bin_dir}/partitions.bin") + self.flash.write("0xe000", f"{bin_dir}/boot_app0.bin") + self.flash.write("0x10000", f"{bin_dir}/firmware.bin") + + def openPort(self): + self.serial = serial.Serial(self.port, 115200, timeout=0) + + def getLine(self): + return self.serial.readline() + + def closePort(self): + if self.serial: + self.serial.close() + self.serial = None + + +@pytest.fixture +def ESP(): + return EspDut(os.environ["ESP_PORT"]) diff --git a/testlib/requirements.txt b/testlib/requirements.txt new file mode 100644 index 0000000..99e909e --- /dev/null +++ b/testlib/requirements.txt @@ -0,0 +1,3 @@ +pytest +pyserial +aprs diff --git a/testlib/testbinary/boot_app0.bin b/testlib/testbinary/boot_app0.bin new file mode 100644 index 0000000..13562ca Binary files /dev/null and b/testlib/testbinary/boot_app0.bin differ diff --git a/testlib/testbinary/bootloader_dio_40m.bin b/testlib/testbinary/bootloader_dio_40m.bin new file mode 100644 index 0000000..ac05788 Binary files /dev/null and b/testlib/testbinary/bootloader_dio_40m.bin differ diff --git a/testlib/testbinary/firmware.bin b/testlib/testbinary/firmware.bin new file mode 100644 index 0000000..021d5e7 Binary files /dev/null and b/testlib/testbinary/firmware.bin differ diff --git a/testlib/testbinary/partitions.bin b/testlib/testbinary/partitions.bin new file mode 100644 index 0000000..0e52b4c Binary files /dev/null and b/testlib/testbinary/partitions.bin differ diff --git a/testlib/tests/__init__.py b/testlib/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/testlib/tests/test_aprs.py b/testlib/tests/test_aprs.py new file mode 100644 index 0000000..9d244b9 --- /dev/null +++ b/testlib/tests/test_aprs.py @@ -0,0 +1,5 @@ +from testlib.aprs_con import APRSIS + + +def test_aprs_login(APRSIS): + pass diff --git a/testlib/tests/test_basic.py b/testlib/tests/test_basic.py new file mode 100644 index 0000000..8a3259a --- /dev/null +++ b/testlib/tests/test_basic.py @@ -0,0 +1,16 @@ +from testlib.esp_dut import ESP + + +def test_basic_port(ESP): + ESP.openPort() + ESP.closePort() + + +def test_flash(ESP): + bin_dir = "testbinary" + ESP.writeFlash(bin_dir) + ESP.flash.verify("0x1000", f"{bin_dir}/bootloader_dio_40m.bin") + ESP.flash.verify("0x8000", f"{bin_dir}/partitions.bin") + ESP.flash.verify("0xe000", f"{bin_dir}/boot_app0.bin") + ESP.flash.verify("0x10000", f"{bin_dir}/firmware.bin") + ESP.flash.erase()