Skip to content

Commit

Permalink
tokc-hardware-ci: ported test script
Browse files Browse the repository at this point in the history
  • Loading branch information
charles37 committed Oct 28, 2024
1 parent 4a930b8 commit 67a0cdb
Show file tree
Hide file tree
Showing 25 changed files with 341 additions and 10 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/treadmill-ci-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on:
push:
branches:
- main
- dev/test_ci_branch
# Pull requests from forks will not have access to the required GitHub API
# secrets below, even if they are using an appropriate deployment environment
# and the workflow runs have been approved according to this environment's
Expand Down Expand Up @@ -45,5 +46,28 @@ jobs:
# Use the latest upstream Tock kernel / userspace components:
tock-kernel-ref: 'master'
libtock-c-ref: 'master'
tests: |
tests/ble_env_sense.py
tests/ble_advertising.py
tests/ble_passive_scanning.py
tests/c_hello.py
tests/printf_long.py
tests/c_hello_and_printf_long.py
tests/sensors.py
tests/console_recv_short.py
tests/console_recv_long.py
tests/lua_hello.py
tests/malloc_test01.py
tests/malloc_test02.py
tests/stack_size_test01.py
tests/stack_size_test02.py
tests/mpu_stack_growth.py
tests/mpu_walk_region.py
tests/adc.py
tests/adc_continuous.py
tests/ipc_logic.py
tests/gpio_interrupt.py
tests/whileone.py
tests/multi_alarm_simple_test.py
secrets: inherit
30 changes: 20 additions & 10 deletions .github/workflows/treadmill-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ on:
libtock-c-ref:
required: true
type: string
tests:
required: false
type: string
default: "tests/c_hello.py" # Default to single test for backward compatibility

jobs:
test-prepare:
Expand Down Expand Up @@ -116,7 +120,11 @@ jobs:
# identically:
HOST_TYPE: nbd-netboot
HOST_ARCH: arm64
TESTS: ${{ inputs.tests }}
run: |
# Read the list of tests and convert to JSON array
TEST_LIST=$(echo "$TESTS" | jq -R -s -c 'split("\n") | map(select(length > 0))')
# When we eventually launch tests on multiple hardware platforms in
# parallel, we need to supply different SUB_TEST_IDs here:
SUB_TEST_ID="0"
Expand All @@ -126,6 +134,7 @@ jobs:
# runner (connected to the exact board we want to run tests on).
RUNNER_ID="tml-gh-actions-runner-${GITHUB_REPOSITORY_ID}-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${SUB_TEST_ID}"
# Obtain a new just-in-time runner registration token:
RUNNER_CONFIG_JSON="$(gh api \
-H "Accept: application/vnd.github+json" \
Expand Down Expand Up @@ -162,18 +171,13 @@ jobs:
TML_JOB_ID="$(echo "$TML_JOB_ID_JSON" | jq -r .job_id)"
echo "Enqueued Treadmill job with ID $TML_JOB_ID"
# Pass the job IDs and other configuration data into the outputs of
# this step, such that we can run test-execute job instances for each
# Treadmill job we've started:
echo "tml-job-ids=[ \
\"$TML_JOB_ID\" \
]" >> "$GITHUB_OUTPUT"
echo "tml-job-ids=[ \"$TML_JOB_ID\" ]" >> "$GITHUB_OUTPUT"
echo "tml-jobs={ \"$TML_JOB_ID\": { \"runner-id\": \"$RUNNER_ID\", \"tests\": $TEST_LIST } }" >> "$GITHUB_OUTPUT"
echo "tml-jobs={ \
\"$TML_JOB_ID\": { \
\"runner-id\": \"$RUNNER_ID\", \
} \
}" >> "$GITHUB_OUTPUT"
test-execute:
needs: test-prepare
Expand Down Expand Up @@ -258,11 +262,17 @@ jobs:
pip install -r hwci/requirements.txt -c hwci/requirements-frozen.txt
- name: Run tests
env:
JSON_TEST_ARRAY: ${{ toJSON(fromJSON(needs.test-prepare.outputs.tml-jobs)[matrix.tml-job-id].tests) }}
run: |
source ./hwcienv/bin/activate
cd ./hwci
cd ./tools/hwci
export PYTHONPATH="$PWD:$PYTHONPATH"
python3 core/main.py --board boards/nrf52dk.py --test tests/c_hello.py
echo "$JSON_TEST_ARRAY" | jq -r -c '.[]' | while read TEST; do
echo "===== RUNNING TEST $TEST ====="
python3 core/main.py --board boards/nrf52dk.py --test "$TEST" || echo "===== Test failed! ====="
done
- name: Request shutdown after successful job completion
run: |
Expand Down
10 changes: 10 additions & 0 deletions hwci/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Licensed under the Apache License, Version 2.0 or the MIT License.
# SPDX-License-Identifier: Apache-2.0 OR MIT
# Copyright Tock Contributors 2024.

from .console_hello_test import (
OneshotTest,
AnalyzeConsoleTest,
WaitForConsoleMessageTest,
)
from .c_hello import test as c_hello_test
30 changes: 30 additions & 0 deletions hwci/tests/adc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from utils.test_helpers import AnalyzeConsoleTest
import logging


class AdcTest(AnalyzeConsoleTest):
def __init__(self):
super().__init__(apps=["tests/adc/adc"])

def analyze(self, lines):
adc_driver_found = False
adc_readings_found = False
for line in lines:
if "ADC driver exists" in line:
adc_driver_found = True
if "ADC Reading:" in line:
adc_readings_found = True
break
if "No ADC driver!" in line:
logging.warning("No ADC driver available.")
return # Test passes if ADC is not available
if adc_driver_found and adc_readings_found:
logging.info("ADC Test passed with readings.")
elif adc_driver_found:
raise Exception("ADC Test failed: Driver found but no readings.")
else:
logging.warning("ADC Test skipped: No ADC driver.")
return # Test passes if ADC is not available


test = AdcTest()
3 changes: 3 additions & 0 deletions hwci/tests/adc_continuous.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from utils.test_helpers import WaitForConsoleMessageTest

test = WaitForConsoleMessageTest(["tests/adc/adc_continuous"], "No ADC driver!")
5 changes: 5 additions & 0 deletions hwci/tests/ble_advertising.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from utils.test_helpers import WaitForConsoleMessageTest

test = WaitForConsoleMessageTest(
["ble_advertising"], "Now advertising every 300 ms as 'TockOS'"
)
6 changes: 6 additions & 0 deletions hwci/tests/ble_env_sense.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from utils.test_helpers import WaitForConsoleMessageTest

test = WaitForConsoleMessageTest(
["services/ble-env-sense", "services/ble-env-sense/test-with-sensors"],
"BLE ERROR: Code = 16385",
)
26 changes: 26 additions & 0 deletions hwci/tests/ble_passive_scanning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from utils.test_helpers import AnalyzeConsoleTest
import logging


class BlePassiveScanningTest(AnalyzeConsoleTest):
def __init__(self):
super().__init__(apps=["ble_passive_scanning"])

def analyze(self, lines):
found_advertisements = False
for line in lines:
if "PDU Type:" in line:
found_advertisements = True
break
if found_advertisements:
logging.info("BLE Passive Scanning Test passed.")
else:
logging.warning(
"BLE Passive Scanning Test could not detect advertisements. Ensure BLE devices are nearby."
)
raise Exception(
"BLE Passive Scanning Test failed: No advertisements detected."
)


test = BlePassiveScanningTest()
28 changes: 28 additions & 0 deletions hwci/tests/c_hello_and_printf_long.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from utils.test_helpers import AnalyzeConsoleTest
import logging


class CHelloAndPrintfLongTest(AnalyzeConsoleTest):
def __init__(self):
super().__init__(apps=["c_hello", "tests/printf_long"])

def analyze(self, lines):
expected_messages = [
"Hello World!",
"Hi welcome to Tock. This test makes sure that a greater than 64 byte message can be printed.",
"And a short message.",
]
messages_found = {msg: False for msg in expected_messages}

for line in lines:
for msg in expected_messages:
if msg in line:
messages_found[msg] = True

for msg, found in messages_found.items():
if not found:
raise Exception(f"Did not find expected message: '{msg}'")
logging.info("C Hello and Printf Long Test passed.")


test = CHelloAndPrintfLongTest()
5 changes: 5 additions & 0 deletions hwci/tests/console_recv_long.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from utils.test_helpers import WaitForConsoleMessageTest

test = WaitForConsoleMessageTest(
["tests/console/console_recv_long"], "[SHORT] Error doing UART receive: -2"
)
5 changes: 5 additions & 0 deletions hwci/tests/console_recv_short.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from utils.test_helpers import WaitForConsoleMessageTest

test = WaitForConsoleMessageTest(
["tests/console/console_recv_short"], "[SHORT] Error doing UART receive: -2"
)
21 changes: 21 additions & 0 deletions hwci/tests/gpio_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from utils.test_helpers import AnalyzeConsoleTest
import logging


class GpioInterruptTest(AnalyzeConsoleTest):
def __init__(self):
super().__init__(apps=["tests/gpio/gpio_interrupt"])

def analyze(self, lines):
interrupt_detected = False
for line in lines:
if "GPIO Interrupt!" in line:
interrupt_detected = True
break
if interrupt_detected:
logging.info("GPIO Interrupt Test passed.")
else:
raise Exception("GPIO Interrupt Test failed: No interrupt detected.")


test = GpioInterruptTest()
24 changes: 24 additions & 0 deletions hwci/tests/ipc_logic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from utils.test_helpers import AnalyzeConsoleTest
import logging


class IpcLogicTest(AnalyzeConsoleTest):
def __init__(self):
super().__init__(
apps=[
"tutorials/05_ipc/led",
"tutorials/05_ipc/rng",
"tutorials/05_ipc/logic",
]
)

def analyze(self, lines):
expected_output = "Number of LEDs:"
for line in lines:
if expected_output in line:
logging.info("IPC Logic Test passed.")
return
raise Exception("IPC Logic Test failed: Expected output not found.")


test = IpcLogicTest()
3 changes: 3 additions & 0 deletions hwci/tests/lua_hello.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from utils.test_helpers import WaitForConsoleMessageTest

test = WaitForConsoleMessageTest(["lua-hello"], "Hello from Lua!")
3 changes: 3 additions & 0 deletions hwci/tests/malloc_test01.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from utils.test_helpers import WaitForConsoleMessageTest

test = WaitForConsoleMessageTest(["tests/malloc_test01"], "malloc01: success")
3 changes: 3 additions & 0 deletions hwci/tests/malloc_test02.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from utils.test_helpers import WaitForConsoleMessageTest

test = WaitForConsoleMessageTest(["tests/malloc_test02"], "malloc02: success")
16 changes: 16 additions & 0 deletions hwci/tests/mpu_stack_growth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from utils.test_helpers import AnalyzeConsoleTest


class MpuStackGrowthTest(AnalyzeConsoleTest):
def __init__(self):
super().__init__(apps=["tests/mpu/mpu_stack_growth"])

def analyze(self, lines):
for line in lines:
if "[TEST] MPU Stack Growth" in line:
# Test started successfully
return
raise Exception("MPU Stack Growth test did not start")


test = MpuStackGrowthTest()
16 changes: 16 additions & 0 deletions hwci/tests/mpu_walk_region.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from utils.test_helpers import AnalyzeConsoleTest


class MpuWalkRegionTest(AnalyzeConsoleTest):
def __init__(self):
super().__init__(apps=["tests/mpu/mpu_walk_region"])

def analyze(self, lines):
for line in lines:
if "[TEST] MPU Walk Regions" in line:
# Test started successfully
return
raise Exception("MPU Walk Region test did not start")


test = MpuWalkRegionTest()
41 changes: 41 additions & 0 deletions hwci/tests/multi_alarm_simple_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from utils.test_helpers import AnalyzeConsoleTest
import logging


class MultiAlarmSimpleTest(AnalyzeConsoleTest):
def __init__(self):
super().__init__(apps=["tests/multi_alarm_simple_test"])

def analyze(self, lines):
# Initialize counts for each alarm
alarm_counts = {1: 0, 2: 0}

for line in lines:
tokens = line.strip().split()
if len(tokens) >= 3:
try:
alarm_index = int(tokens[0])
# Optional: parse timestamps if needed
# now = int(tokens[1])
# expiration = int(tokens[2])

# Record counts
if alarm_index in [1, 2]:
alarm_counts[alarm_index] += 1
except ValueError:
continue # Skip lines that don't parse correctly

logging.info(f"Alarm counts: {alarm_counts}")
count1 = alarm_counts.get(1, 0)
count2 = alarm_counts.get(2, 0)
if count1 < 2 or count2 < 1:
raise Exception("MultiAlarmSimpleTest failed: Not enough alarms fired")
if count1 < 2 * count2:
raise Exception(
"MultiAlarmSimpleTest failed: Alarm 1 did not fire at least twice as often as Alarm 2"
)

logging.info("MultiAlarmSimpleTest passed")


test = MultiAlarmSimpleTest()
Empty file added hwci/tests/multi_alarm_test.py
Empty file.
6 changes: 6 additions & 0 deletions hwci/tests/printf_long.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from utils.test_helpers import WaitForConsoleMessageTest

test = WaitForConsoleMessageTest(
["tests/printf_long"],
"Hi welcome to Tock. This test makes sure that a greater than 64 byte message can be printed.",
)
Loading

0 comments on commit 67a0cdb

Please sign in to comment.