From ea8f27f5fc13a4349c47eec439f426d8e3a75d71 Mon Sep 17 00:00:00 2001 From: Logan Rundle <154925928+LoganRundle-1@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:20:49 -0400 Subject: [PATCH 1/3] added new test env for pio that works on mac and windows. Also added a script to downlaod the data for the test. --- data/data_downloader.py | 152 ++++++++++++++++++++++++++++++++++++++++ platformio.ini | 37 +++++++++- 2 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 data/data_downloader.py diff --git a/data/data_downloader.py b/data/data_downloader.py new file mode 100644 index 0000000..4739185 --- /dev/null +++ b/data/data_downloader.py @@ -0,0 +1,152 @@ + +import json +import shutil +import subprocess +import sys +import urllib.request +from pathlib import Path + + +# --------------------------------------------------------- +# Configuration +# --------------------------------------------------------- + +REPO_API = ( + "https://api.github.com/repos/" + "CURocketEngineering/Rocket-Test-Data/releases/tags/v1.0.0" +) + +DATA_DIR = Path("data") + +BAD_FILENAME = "AA.Data.Collection.-.Second.Launch.Trimmed.csv" +GOOD_FILENAME = "AA Data Collection - Second Launch Trimmed.csv" + + +# --------------------------------------------------------- +# Helpers +# --------------------------------------------------------- + +def run_command(command): + """Run a command and stop if it fails.""" + print(f"\n> {' '.join(command)}") + result = subprocess.run(command) + + if result.returncode != 0: + print(f"\nCommand failed with exit code {result.returncode}") + sys.exit(result.returncode) + + +# --------------------------------------------------------- +# Download Rocket Test Data +# --------------------------------------------------------- + +def download_test_data(): + print("\n========================================") + print("Downloading Rocket Test Data v1.0.0") + print("========================================") + + DATA_DIR.mkdir(parents=True, exist_ok=True) + + request = urllib.request.Request( + REPO_API, + headers={ + "Accept": "application/vnd.github+json", + "User-Agent": "Avionics-Test-Runner", + }, + ) + + try: + with urllib.request.urlopen(request) as response: + release = json.load(response) + except Exception as e: + print(f"Failed to get GitHub release information: {e}") + sys.exit(1) + + assets = release.get("assets", []) + + if not assets: + print("No release assets found.") + sys.exit(1) + + for asset in assets: + filename = asset["name"] + download_url = asset["browser_download_url"] + + output_path = DATA_DIR / filename + + print(f"\nDownloading:") + print(f" {download_url}") + print(f" -> {output_path}") + + try: + download_request = urllib.request.Request( + download_url, + headers={ + "User-Agent": "Avionics-Test-Runner", + }, + ) + + with urllib.request.urlopen(download_request) as response: + with open(output_path, "wb") as output: + shutil.copyfileobj(response, output) + + except Exception as e: + print(f"Failed to download {filename}: {e}") + sys.exit(1) + + +# --------------------------------------------------------- +# Fix Filename +# --------------------------------------------------------- + +def fix_filename(): + print("\n========================================") + print("Fixing Test Data Filename") + print("========================================") + + old_path = DATA_DIR / BAD_FILENAME + new_path = DATA_DIR / GOOD_FILENAME + + if not old_path.exists(): + # It may already have been renamed. + if new_path.exists(): + print(f"Already fixed:") + print(f" {new_path}") + return + + print(f"Could not find:") + print(f" {old_path}") + sys.exit(1) + + if new_path.exists(): + print(f"Removing existing:") + print(f" {new_path}") + new_path.unlink() + + print(f"Moving:") + print(f" {old_path}") + print(f" -> {new_path}") + + old_path.rename(new_path) + + + + +# --------------------------------------------------------- +# Main +# --------------------------------------------------------- + +def main(): + print("========================================") + print("CURE Avionics Native Test Runner") + print("========================================") + + download_test_data() + fix_filename() + print("========================================") + print("Data Downloaded and Renamed") + print("========================================") + + +if __name__ == "__main__": + main() diff --git a/platformio.ini b/platformio.ini index 7215bae..750f6a6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -41,4 +41,39 @@ check_flags = check_src_filters = + + - + \ No newline at end of file + + + +[env:native-for_mac_and_windows] +platform = native +test_framework = unity +test_build_src = yes + +build_flags = + -std=c++17 + + ; Warnings + -Wall + -Wextra + -Wpedantic + -Wshadow + + -Wconversion + -Wsign-conversion + -Wformat=2 + -Wundef + -Wnull-dereference + -Wdouble-promotion + + ; Better analysis/debuggability + -O1 + -g3 + -fno-omit-frame-pointer + + ; Runtime checks + -fno-sanitize-recover=all + -D_GLIBCXX_ASSERTIONS + + ; Project includes + -DUNITY_INCLUDE_DETAILS + -Ihal + -Itest \ No newline at end of file From c398402879a60dc88c822aba17a2c9b3b00c9337 Mon Sep 17 00:00:00 2001 From: Logan Rundle <154925928+LoganRundle-1@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:39:15 -0400 Subject: [PATCH 2/3] added comments stating which pio env is used for what. Updated data download script to check if they already exist. --- data/data_downloader.py | 43 +++++++++++++++++++++++++++++++++++++++-- platformio.ini | 3 +++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/data/data_downloader.py b/data/data_downloader.py index 4739185..0e29deb 100644 --- a/data/data_downloader.py +++ b/data/data_downloader.py @@ -36,13 +36,37 @@ def run_command(command): sys.exit(result.returncode) +# --------------------------------------------------------- +# check if the data already exists +#--------------------------------------------------------- + +def check_data_exists(): + """Check if the test data has already been downloaded.""" + good_path = DATA_DIR / GOOD_FILENAME + bad_path = DATA_DIR / BAD_FILENAME + + if good_path.exists(): + print("\nTest data already exists:") + print(f" {good_path}") + return True + + if bad_path.exists(): + print("\nTest data already exists but needs filename fixing:") + print(f" {bad_path}") + return True + + print("\nTest data not found. Downloading...") + return False + + + # --------------------------------------------------------- # Download Rocket Test Data # --------------------------------------------------------- def download_test_data(): print("\n========================================") - print("Downloading Rocket Test Data v1.0.0") + print("Downloading Rocket Test Data") print("========================================") DATA_DIR.mkdir(parents=True, exist_ok=True) @@ -141,10 +165,25 @@ def main(): print("CURE Avionics Native Test Runner") print("========================================") + if check_data_exists(): + print("========================================") + print("Test Data Already Exists") + print("========================================") + print("\nWould you like to download the test data again? (y/n)") + answer = input() + if answer.lower() == "y": + print("\n") + + else: + print("\nexiting") + return + download_test_data() + fix_filename() + print("========================================") - print("Data Downloaded and Renamed") + print("Test Data Ready") print("========================================") diff --git a/platformio.ini b/platformio.ini index 750f6a6..dff2eba 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,3 +1,4 @@ +; PlatformIO Project Configuration to run on linux or on github actions [env:native] platform = native test_framework = unity @@ -43,6 +44,8 @@ check_src_filters = + + + +; PlatformIO Project Configuration to run on mac and windows [env:native-for_mac_and_windows] platform = native test_framework = unity From d64ad15f7a1a181a0646ff440132bd8b59c7c8b3 Mon Sep 17 00:00:00 2001 From: Logan Rundle <154925928+LoganRundle-1@users.noreply.github.com> Date: Mon, 14 Sep 2026 14:28:31 -0400 Subject: [PATCH 3/3] updated the read me to show the new pio config --- README.md | 4 ++-- data/data_downloader.py | 2 ++ platformio.ini | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index af914a0..75e979c 100644 --- a/README.md +++ b/README.md @@ -95,9 +95,9 @@ The following systems integrate Avionics as a submodule: Unit tests are part of this repository under `test/`, and can run on a laptop/desktop without embedded hardware. 1. Install PlatformIO Core (`pip install -U platformio`) or the PlatformIO IDE extension. -2. Place test CSV files in `data/` (or let CI download them). +2. Place test CSV files in `data/` (or either let CI download them or use the `data_downloader.py` script in the data folder). 3. Run tests from the repo root: - - `pio test -e native` + - `pio test -e native-for_mac_and_windows` or `pio test -e native` ## Hardware Abstraction Note: diff --git a/data/data_downloader.py b/data/data_downloader.py index 0e29deb..181e1b7 100644 --- a/data/data_downloader.py +++ b/data/data_downloader.py @@ -11,6 +11,7 @@ # Configuration # --------------------------------------------------------- + REPO_API = ( "https://api.github.com/repos/" "CURocketEngineering/Rocket-Test-Data/releases/tags/v1.0.0" @@ -185,6 +186,7 @@ def main(): print("========================================") print("Test Data Ready") print("========================================") + print("\nYou can now run the tests with: pio test -e native-for_mac_and_windows") if __name__ == "__main__": diff --git a/platformio.ini b/platformio.ini index dff2eba..922c013 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,4 +1,5 @@ ; PlatformIO Project Configuration to run on linux or on github actions +; This is the default configuration and does more checks [env:native] platform = native test_framework = unity @@ -45,7 +46,10 @@ check_src_filters = + + + ; PlatformIO Project Configuration to run on mac and windows +; This configuration is for testing on personal devices and does all the main tests [env:native-for_mac_and_windows] platform = native test_framework = unity