Skip to content

Commit

Permalink
#206 move all tests to unity and ensure they pass
Browse files Browse the repository at this point in the history
  • Loading branch information
davetcc committed Aug 25, 2024
1 parent b30610c commit 6d2f02e
Show file tree
Hide file tree
Showing 16 changed files with 626 additions and 550 deletions.
62 changes: 62 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Test
on: [push]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/cache@v4
with:
path: |
~/.cache/pip
~/.platformio/.cache
key: ${{ runner.os }}-pio
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y libsdl2-2.0-0
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Set up QEMU
id: setup-qemu
run: |
if [[ "$(uname -m)" == "x86_64" ]]; then
QEMU_URL="https://github.com/espressif/qemu/releases/download/esp-develop-8.2.0-20240122/qemu-xtensa-softmmu-esp_develop_8.2.0_20240122-x86_64-linux-gnu.tar.xz"
elif [[ "$(uname -m)" == "aarch64" ]]; then
QEMU_URL="https://github.com/espressif/qemu/releases/download/esp-develop-8.2.0-20240122/qemu-xtensa-softmmu-esp_develop_8.2.0_20240122-aarch64-linux-gnu.tar.xz"
else
echo "Unsupported architecture: $(uname -m)"
exit 1
fi
wget $QEMU_URL -O qemu.tar.xz
mkdir -p qemu
tar -xf qemu.tar.xz -C qemu --strip-components=1
sudo mv qemu /usr/local/qemu
- name: Add QEMU to PATH
run: echo "/usr/local/qemu/bin" >> $GITHUB_PATH

- name: Run unit tests
run: pio test --without-uploading --project-conf=platformio-test.ini

static-analysis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/cache@v4
with:
path: |
~/.cache/pip
~/.platformio/.cache
key: ${{ runner.os }}-pio
- uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install PlatformIO Core
run: pip install --upgrade platformio

- name: Run static analysis
run: pio check
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# IoAbstraction for Arduino and mbed summary
[![PlatformIO](https://github.com/TcMenu/IoAbstraction/actions/workflows/platformio.yml/badge.svg)](https://github.com/TcMenu/IoAbstraction/actions/workflows/platformio.yml)
[![Test](https://github.com/TcMenu/IoAbstraction/actions/workflows/test.yml/badge.svg)](https://github.com/TcMenu/IoAbstraction/actions/workflows/test.yml)
[![License: Apache 2.0](https://img.shields.io/badge/license-Apache--2.0-green.svg)](https://github.com/TcMenu/IoAbstraction/blob/main/LICENSE)
[![GitHub release](https://img.shields.io/github/release/TcMenu/IoAbstraction.svg?maxAge=3600)](https://github.com/TcMenu/IoAbstraction/releases)
[![davetcc](https://img.shields.io/badge/davetcc-dev-blue.svg)](https://github.com/davetcc)
[![JSC TechMinds](https://img.shields.io/badge/JSC-TechMinds-green.svg)](https://www.jsctm.cz)

Dave Cherry / TheCodersCorner.com made this library available for you to use. It takes me significant effort to keep all my libraries current and working on a wide range of boards. Please consider making at least a one off donation via the sponsor button if you find it useful. In forks, please keep text to here intact.
TcMenu organisation made this framework available for you to use. It takes significant effort to keep all our libraries current and working on a wide range of boards. Please consider making at least a one off donation via the sponsor button if you find it useful. In forks, please keep text to here intact.

This library provides several useful extensions that make programming Arduino / mbed for non-trivial apps simpler. There are many different practical and familiar examples packaged with it in the `examples` folder. Below I cover each of the main functions briefly with a link to more detailed documentation. The API is almost identical between Arduino and mbed making it easier to port between the two.

Expand Down
43 changes: 43 additions & 0 deletions merge-bin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/python3

# Adds PlatformIO post-processing to merge all the ESP flash images into a single image.

import os

Import("env", "projenv")

board_config = env.BoardConfig()
firmware_bin = "${BUILD_DIR}/${PROGNAME}.bin"
merged_bin = os.environ.get("MERGED_BIN_PATH", "${BUILD_DIR}/${PROGNAME}-merged.bin")


def merge_bin_action(source, target, env):
flash_images = [
*env.Flatten(env.get("FLASH_EXTRA_IMAGES", [])),
"$ESP32_APP_OFFSET",
source[0].get_abspath(),
]
merge_cmd = " ".join(
[
'"$PYTHONEXE"',
'"$OBJCOPY"',
"--chip",
board_config.get("build.mcu", "esp32"),
"merge_bin",
"-o",
merged_bin,
"--flash_mode",
board_config.get("build.flash_mode", "dio"),
"--flash_freq",
"${__get_board_f_flash(__env__)}",
"--flash_size",
board_config.get("upload.flash_size", "4MB"),
"--fill-flash-size",
board_config.get("upload.flash_size", "4MB"),
*flash_images,
]
)
env.Execute(merge_cmd)


env.AddPostAction("buildprog", merge_bin_action)
17 changes: 17 additions & 0 deletions platformio-test.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[env:esp32dev]
platform = espressif32
framework = arduino
board = esp32dev
extra_scripts = post:merge-bin.py
test_build_src = true

lib_deps =
TaskManagerIO

test_testing_command =
qemu-system-xtensa
-nographic
-machine
esp32
-drive
file=${platformio.build_dir}/${this.__env__}/firmware-merged.bin,if=mtd,format=raw
160 changes: 160 additions & 0 deletions test/local_hardware_int/at24i2cTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#include <Arduino.h>
#include <IoAbstraction.h>
#include <EepromAbstractionWire.h>
#include <TaskManagerIO.h>
#include <unity.h>

/**
* NOTES:
* This is a local only test, and requires `Wire` to be properly configured and an I2C ROM attached. It will check
* the ROM operations are working correctly for At24 based EEPROMs.
*
* DO NOT USE UNLESS YOU WANT ALL CONTENTS OF THE ROM CLEARED DOWN AND RESET
*/

char memToWrite[110];
char readBuffer[110];
const uint8_t i2cAddr = 0x50;
const At24EepromType eepromType = PAGESIZE_AT24C16;//PAGESIZE_AT24C128;

const char smallerTestString[] = "Test string that exceeds page size";
const char longerTestString[] = "This is a test string that exceeds page size on larger EEPROMs with big pages";

uint8_t pageSize;
size_t eepromSize;

void testI2CEeprom() {
int loopsPerformed = 0;

I2cAt24Eeprom eeprom(i2cAddr, eepromType);
for(int i=0; i<eepromSize; i++) {
eeprom.write8(i, 0);
serlogF2(SER_DEBUG, "Loop ", i)
TEST_ASSERT_EQUAL(0, eeprom.read8(i));
TEST_ASSERT_FALSE(eeprom.hasErrorOccurred());
loopsPerformed++;
}

serdebugF2("8 Bit finished OK, loops = ", loopsPerformed);

for(int i=0; i<(eepromSize - 2); i+=2) {
eeprom.write16(i, i);
serlogF2(SER_DEBUG, "Loop ", i)
TEST_ASSERT_EQUAL((uint16_t)i, eeprom.read16(i));
TEST_ASSERT_FALSE(eeprom.hasErrorOccurred());
loopsPerformed++;
}

serdebugF2("16 Bit finished OK", loopsPerformed);

eeprom.write32(eepromSize - 10, 0xf00dbeef);
auto ret = eeprom.read32(eepromSize - 10);
TEST_ASSERT_EQUAL(ret, 0xf00dbeef);
TEST_ASSERT_FALSE(eeprom.hasErrorOccurred());

const char* dataToWrite = (pageSize < 16) ? smallerTestString : longerTestString;
size_t sizeToWrite = (pageSize < 16) ? sizeof smallerTestString : sizeof longerTestString;
auto where = eepromSize - (sizeToWrite + 20);
eeprom.writeArrayToRom(where, reinterpret_cast<const uint8_t *>(dataToWrite), sizeToWrite);
TEST_ASSERT_FALSE(eeprom.hasErrorOccurred());

uint8_t readBack[100];
eeprom.readIntoMemArray(readBack, where, sizeToWrite);
TEST_ASSERT_FALSE(eeprom.hasErrorOccurred());

serdebugF2("Array read back = ", (const char*)readBack);

TEST_ASSERT_TRUE(strncmp((const char*)readBack, dataToWrite, sizeToWrite) == 0);
serdebugF("Array test finished OK");

eeprom.read8(eepromSize * 2);
TEST_ASSERT_TRUE(eeprom.hasErrorOccurred());
serdebugF("Oversize finished OK");
}

bool romClear(EepromAbstraction& eeprom, EepromPosition pos) {
for(int i=0;i<100;i++) {
eeprom.write8(pos + i, 0xaa);

if(eeprom.read8(pos + i) != 0xaa) return false;
}
return true;
}


void testI2cArrayWrites() {
I2cAt24Eeprom eeprom(0x50, PAGESIZE_AT24C128);
TEST_ASSERT_TRUE(romClear(eeprom, 700));
serdebug("Run array tests on i2c rom");

strcpy(memToWrite, "This is a very large string to write into the rom to ensure it crosses memory boundaries in the rom");
eeprom.writeArrayToRom(710, (const uint8_t*)memToWrite, sizeof(memToWrite));

serdebug("I2C eeprom array written.");

eeprom.readIntoMemArray((uint8_t*)readBuffer, 710, sizeof(memToWrite));
TEST_ASSERT_EQUAL_STRING(memToWrite, readBuffer);
serdebug("Read into mem done");
}

void testI2cSingleWrites() {
serdebug("Run single tests on i2c rom");
I2cAt24Eeprom eeprom(0x50, PAGESIZE_AT24C128);
TEST_ASSERT_TRUE(romClear(eeprom, 700));

eeprom.write8(700, 0xFF);
TEST_ASSERT_EQUAL(0xFF, eeprom.read8(700));
eeprom.write8(700, 0xDD);
TEST_ASSERT_EQUAL(0xDD, eeprom.read8(700));

eeprom.write16(701, 0xf00d);
eeprom.write32(703, 0xbeeff00d);

yield();
serdebug("I2C reads...");

TEST_ASSERT_EQUAL((uint16_t)0xf00d, eeprom.read16(701));
TEST_ASSERT_EQUAL((uint32_t)0xbeeff00d, eeprom.read32(703));

TEST_ASSERT_FALSE(eeprom.hasErrorOccurred());
}

void badI2cEepromDoesNotLockCode() {
serdebug("I2C bad EEPROM address test start.");

I2cAt24Eeprom eepromBad(0x73, PAGESIZE_AT24C128);
eepromBad.write8(800, 123);
TEST_ASSERT_TRUE(eepromBad.hasErrorOccurred());

serdebug("I2C bad EEPROM address test end.");
}

#ifdef __AVR__
void testClockRollover();
#endif // AVR

void setup() {
Wire.begin();
Serial.begin(115200);
while (!Serial);

pageSize = at24PageFromRomSize(eepromType);
eepromSize = at24ActualSizeFromRomSize(eepromType);

UNITY_BEGIN();

RUN_TEST(testI2CEeprom);
RUN_TEST(testI2cSingleWrites);
RUN_TEST(testI2cArrayWrites);
RUN_TEST(badI2cEepromDoesNotLockCode);

#ifdef __AVR__
RUN_TEST(testClockRollover);
#endif // AVR

UNITY_END();
}

void loop() {

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@

#include <TaskManagerIO.h>
#include <testing/SimpleTest.h>

using namespace SimpleTest;
#include <unity.h>

#if defined(__AVR__)

Expand Down Expand Up @@ -39,7 +37,7 @@ int avrCount2 = 0;
//
// this test only runs on AVR - it sets the timer near to overflow and schedules some tasks
//
test(testClockRollover) {
void testClockRollover() {
avrCount1 = avrCount2 = 0;

// set the clock so that it will roll
Expand All @@ -55,7 +53,7 @@ test(testClockRollover) {
}, TIME_MICROS);

// make sure it's still to wrap.
assertTrue(millis() > 100000000UL);
TEST_ASSERT_TRUE(millis() > 100000000UL);

// now run the loop
dumpTaskTiming();
Expand All @@ -67,31 +65,19 @@ test(testClockRollover) {
dumpTaskTiming();

// the one second task should have executed exactly once.
assertEquals(avrCount1, 1);
TEST_ASSERT_EQUAL(avrCount1, 1);
assertMoreThan(1000, avrCount2);

// make sure millis has wrapped now.
assertTrue(millis() < 10000UL);
TEST_ASSERT_TRUE(millis() < 10000UL);

// and make sure the microsecond job is still going..
int avrCount2Then = avrCount2;
taskManager.yieldForMicros(10000);
assertTrue(avrCount2Then != avrCount2);
TEST_ASSERT_TRUE(avrCount2Then != avrCount2);

// reset the millisecond timer where it was before.
setMillis(oldMillis);
}

test(legacyCheckIoDevice) {
auto systemDevice = internalDigitalIo();
ioDevicePinMode(systemDevice, LED_BUILTIN, OUTPUT);
ioDevicePinMode(systemDevice, 2, INPUT);
ioDeviceDigitalWrite(systemDevice, LED_BUILTIN, HIGH);
ioDeviceSync(systemDevice);
ioDeviceDigitalRead(systemDevice, 2);
delay(250);
ioDeviceDigitalWriteS(systemDevice, LED_BUILTIN, LOW);
ioDeviceDigitalReadS(systemDevice, 2);
}

#endif // __AVR__
Loading

0 comments on commit 6d2f02e

Please sign in to comment.