-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tests were re-written into the Unity framework supported by PlatformIO. They are run inside an ESP32 QEMU simulator.
- Loading branch information
1 parent
54ded14
commit 3480ae9
Showing
10 changed files
with
495 additions
and
362 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
name: PlatformIO CI | ||
name: Build | ||
on: [push] | ||
|
||
jobs: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
||
lib_deps = | ||
davetcc/IoAbstraction@^4.0.2 | ||
tcUnicodeHelper | ||
|
||
test_testing_command = | ||
qemu-system-xtensa | ||
-nographic | ||
-machine | ||
esp32 | ||
-drive | ||
file=${platformio.build_dir}/${this.__env__}/firmware-merged.bin,if=mtd,format=raw |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
|
||
#include <Arduino.h> | ||
#include <unity.h> | ||
#include <deque> | ||
#include <Fonts/OpenSansCyrillicLatin18.h> | ||
#include <Fonts/RobotoMedium24.h> | ||
#include <tcUnicodeHelper.h> | ||
#include <IoLogging.h> | ||
|
||
class UnitTestPlotter : public TextPlotPipeline { | ||
private: | ||
std::deque<Coord> pixelsDrawn; | ||
static const size_t max_size = 32; | ||
uint32_t col = 0; | ||
Coord where = {0,0}; | ||
public: | ||
UnitTestPlotter() = default; | ||
~UnitTestPlotter() = default; | ||
|
||
void drawPixel(uint16_t x, uint16_t y, uint32_t color) override { | ||
if (pixelsDrawn.size() == max_size) { | ||
pixelsDrawn.pop_front(); | ||
} | ||
pixelsDrawn.push_back(Coord(x, y)); | ||
} | ||
|
||
void setCursor(const Coord &p) override { | ||
where = p; | ||
} | ||
|
||
Coord getCursor() override { | ||
return where; | ||
} | ||
|
||
Coord getDimensions() override { | ||
return Coord(320, 200); | ||
} | ||
|
||
void init() { | ||
pixelsDrawn.clear(); | ||
where = {0,0}; | ||
} | ||
} unitTestPlotter; | ||
|
||
UnicodeFontHandler* handler = nullptr; | ||
|
||
void setUp() { | ||
unitTestPlotter.init(); | ||
handler = new UnicodeFontHandler(&unitTestPlotter, ENCMODE_UTF8); | ||
handler->setFont(OpenSansCyrillicLatin18); | ||
handler->setDrawColor(20); | ||
} | ||
|
||
void tearDown() { | ||
delete handler; | ||
} | ||
|
||
bool checkGlyph(uint32_t code, uint32_t bmpOffset, int width, int height, int xAdvance, int xOffset, int yOffset) { | ||
GlyphWithBitmap glyphWithBitmap; | ||
if(handler->findCharInFont(code, glyphWithBitmap)) { | ||
const UnicodeFontGlyph *glyph = glyphWithBitmap.getGlyph(); | ||
bool success = true; | ||
if(bmpOffset != glyph->relativeBmpOffset) { | ||
serlogF4(SER_DEBUG, "Bmp offset out ", code, bmpOffset, glyph->relativeBmpOffset); | ||
success = false; | ||
} | ||
if(width != glyph->width || height != glyph->height) { | ||
serlogF4(SER_DEBUG, "Bmp width out ", code, width, glyph->width); | ||
serlogF3(SER_DEBUG, "Bmp height ", height, glyph->height); | ||
success = false; | ||
} | ||
if(xOffset != glyph->xOffset || yOffset != glyph->yOffset) { | ||
serlogF4(SER_DEBUG, "Bmp xoffs out ", code, xOffset, glyph->xOffset); | ||
serlogF3(SER_DEBUG, "Bmp yoffs ", yOffset, glyph->yOffset); | ||
success = false; | ||
} | ||
if(xAdvance != glyph->xAdvance) { | ||
serlogF4(SER_DEBUG, "Bmp xadv out ", code, xAdvance, glyph->xAdvance); | ||
success = false; | ||
} | ||
|
||
return success; | ||
} else { | ||
serlogF2(SER_DEBUG, "Glyph not found ", code); | ||
return false; | ||
} | ||
} | ||
|
||
void test_TextExtents() { | ||
int bl; | ||
handler->setFont(OpenSansCyrillicLatin18); | ||
Coord coord = handler->textExtents("Abc", &bl, false); | ||
TEST_ASSERT_EQUAL_INT16(31, coord.x); | ||
TEST_ASSERT_EQUAL_INT16(24, coord.y); | ||
|
||
handler->setFont(RobotoMedium24pt); | ||
coord = handler->textExtents("Abc", &bl, false); | ||
TEST_ASSERT_EQUAL_INT16(43, coord.x); | ||
TEST_ASSERT_EQUAL_INT16(28, coord.y); | ||
} | ||
|
||
void test_GetGlyphOnEachRange() { | ||
TEST_ASSERT_TRUE(checkGlyph(65, 320, 11, 13, 11, 0, -18)); | ||
TEST_ASSERT_TRUE(checkGlyph(55 + 128, 198, 2, 2, 5, 1, -12)); | ||
TEST_ASSERT_TRUE(checkGlyph(17 + 1024, 285, 8, 13, 11, 2, -18)); | ||
} | ||
|
||
void test_ReadingEveryGlyphInRange() { | ||
GlyphWithBitmap glyphWithBitmap; | ||
|
||
// test all known characters work | ||
for (int i = 32; i < 127; i++) { | ||
serlogF2(SER_DEBUG, "Test character = ", i); | ||
TEST_ASSERT_TRUE(handler->findCharInFont(i, glyphWithBitmap)); | ||
TEST_ASSERT_NOT_NULL(glyphWithBitmap.getGlyph()); | ||
TEST_ASSERT_NOT_NULL(glyphWithBitmap.getBitmapData()); | ||
} | ||
|
||
// test a few that should fail | ||
TEST_ASSERT_FALSE(handler->findCharInFont(0, glyphWithBitmap)); | ||
TEST_ASSERT_FALSE(handler->findCharInFont(5, glyphWithBitmap)); | ||
TEST_ASSERT_FALSE(handler->findCharInFont(10, glyphWithBitmap)); | ||
TEST_ASSERT_FALSE(handler->findCharInFont(0xFFFF, glyphWithBitmap)); | ||
} | ||
|
||
void test_AdafruitFont() { | ||
GlyphWithBitmap glyphWithBitmap; | ||
handler->setFont(RobotoMedium24pt); | ||
|
||
// test a few that should fail | ||
TEST_ASSERT_TRUE(checkGlyph(32, 0, 0, 0, 6, 0, -28)); | ||
TEST_ASSERT_TRUE(checkGlyph(48, 243, 12, 17, 14, 1, -23)); | ||
TEST_ASSERT_TRUE(checkGlyph(65, 611, 16, 17, 16, 0, -23)); | ||
TEST_ASSERT_TRUE(checkGlyph(126, 1990, 14, 5, 16, 1, -16)); | ||
TEST_ASSERT_FALSE(handler->findCharInFont(5, glyphWithBitmap)); | ||
TEST_ASSERT_FALSE(handler->findCharInFont(127, glyphWithBitmap)); | ||
TEST_ASSERT_FALSE(handler->findCharInFont(31, glyphWithBitmap)); | ||
} | ||
|
||
void setup() { | ||
UNITY_BEGIN(); | ||
RUN_TEST(test_TextExtents); | ||
RUN_TEST(test_GetGlyphOnEachRange); | ||
RUN_TEST(test_ReadingEveryGlyphInRange); | ||
RUN_TEST(test_AdafruitFont); | ||
UNITY_END(); | ||
} | ||
|
||
void loop() {} |
Oops, something went wrong.