Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
193 changes: 193 additions & 0 deletions data/data_downloader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@

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)


# ---------------------------------------------------------
# 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")
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("========================================")

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("Test Data Ready")
print("========================================")
print("\nYou can now run the tests with: pio test -e native-for_mac_and_windows")


if __name__ == "__main__":
main()
44 changes: 43 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
@@ -1,3 +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
Expand Down Expand Up @@ -41,4 +43,44 @@ check_flags =
check_src_filters =
+<src/**>
+<include/**>
+<hal/**>
+<hal/**>




; 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
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
Loading