From fe959ccc968284aca985fde94575aa1f7958966b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Z=C3=A1hradn=C3=ADk?= Date: Sat, 3 Aug 2024 15:47:46 +0200 Subject: [PATCH] Enable unit tests --- .github/ISSUE_TEMPLATE/bug_report.md | 26 ++ .github/ISSUE_TEMPLATE/feature_request.md | 17 + .github/workflows/build.yml | 31 ++ .github/workflows/test.yml | 62 ++++ .gitignore | 300 ++++++++++++++++++ README.md | 8 +- merge-bin.py | 43 +++ platformio-test.ini | 17 + platformio.ini | 19 ++ .../stm32ThreadedTests/stm32ThreadedTests.cpp | 0 .../CircularBufferTest.cpp | 107 +++++++ .../SimpleCollectionsTest.cpp | 267 ++++++++++++++++ tests/collectionTests/CircularBufferTest.cpp | 93 ------ .../collectionTests/SimpleCollectionsTest.cpp | 254 --------------- tests/collectionTests/collectionTests.cpp | 14 - 15 files changed, 896 insertions(+), 362 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/test.yml create mode 100644 .gitignore create mode 100644 merge-bin.py create mode 100644 platformio-test.ini create mode 100644 platformio.ini rename {tests => test}/stm32ThreadedTests/stm32ThreadedTests.cpp (100%) create mode 100644 test/test_circular_buffer/CircularBufferTest.cpp create mode 100644 test/test_simple_collection/SimpleCollectionsTest.cpp delete mode 100644 tests/collectionTests/CircularBufferTest.cpp delete mode 100644 tests/collectionTests/SimpleCollectionsTest.cpp delete mode 100644 tests/collectionTests/collectionTests.cpp diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..d82c3b2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,26 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior, if it is more than trival to set up the test for this, please include a sketch that recreates the problem. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Device and Environment** +Please include a complete breakdown of your board, attached hardware, developer environment etc. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..df81be2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..7cef404 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,31 @@ +name: Build +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + example: + - examples/bookshop/bookshop.ino + - examples/circularBuffer/circularBuffer.ino + - examples/iteration/iteration.ino + # MBED + # - examples/mbedExample + 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: Build PlatformIO examples + run: pio ci --project-conf=platformio.ini + env: + PLATFORMIO_CI_SRC: ${{ matrix.example }} \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..afce0cd --- /dev/null +++ b/.github/workflows/test.yml @@ -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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a25967 --- /dev/null +++ b/.gitignore @@ -0,0 +1,300 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +.DS_Store + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +.vscode + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Typescript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs +**/__vm/* +**/*.vcxproj* +**/*.vcxitems +vs-readme.txt + +# Arduino and platform io directories and files that should not be committed +**/.pio +.development +cmake-build-* diff --git a/README.md b/README.md index ebc7d8f..d8ed5b5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,10 @@ -# SimpleCollections for Arduino and mbed summary +# SimpleCollections +[![Build](https://github.com/TcMenu/SimpleCollections/actions/workflows/build.yml/badge.svg)](https://github.com/TcMenu/SimpleCollections/actions/workflows/build.yml) +[![Test](https://github.com/TcMenu/SimpleCollections/actions/workflows/test.yml/badge.svg)](https://github.com/TcMenu/SimpleCollections/actions/workflows/test.yml) +[![License: Apache 2.0](https://img.shields.io/badge/license-Apache--2.0-green.svg)](https://github.com/TcMenu/SimpleCollections/blob/main/LICENSE) +[![GitHub release](https://img.shields.io/github/release/TcMenu/SimpleCollections.svg?maxAge=3600)](https://github.com/TcMenu/SimpleCollections/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 make 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. diff --git a/merge-bin.py b/merge-bin.py new file mode 100644 index 0000000..a063ab9 --- /dev/null +++ b/merge-bin.py @@ -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) diff --git a/platformio-test.ini b/platformio-test.ini new file mode 100644 index 0000000..b4166b6 --- /dev/null +++ b/platformio-test.ini @@ -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 + SimpleCollections + +test_testing_command = + qemu-system-xtensa + -nographic + -machine + esp32 + -drive + file=${platformio.build_dir}/${this.__env__}/firmware-merged.bin,if=mtd,format=raw diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..3c80dd2 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,19 @@ +[env] +framework = arduino + +lib_deps = + davetcc/TaskManagerIO@^1.4.3 + davetcc/IoAbstraction@^4.0.2 + SimpleCollections + +[env:megaatmega2560] +platform = atmelavr +board = megaatmega2560 + +[env:esp32dev] +platform = espressif32 +board = esp32dev + +[env:esp01_1m] +platform = espressif8266 +board = esp01_1m diff --git a/tests/stm32ThreadedTests/stm32ThreadedTests.cpp b/test/stm32ThreadedTests/stm32ThreadedTests.cpp similarity index 100% rename from tests/stm32ThreadedTests/stm32ThreadedTests.cpp rename to test/stm32ThreadedTests/stm32ThreadedTests.cpp diff --git a/test/test_circular_buffer/CircularBufferTest.cpp b/test/test_circular_buffer/CircularBufferTest.cpp new file mode 100644 index 0000000..079f335 --- /dev/null +++ b/test/test_circular_buffer/CircularBufferTest.cpp @@ -0,0 +1,107 @@ + +#include +#include +#include +#include +#include + +void setUp() {} + +void tearDown() {} + +void putIntoBuffer(tccollection::SCCircularBuffer& buffer, const char* data) { + while(*data) { + buffer.put(*data); + data++; + } +} + +bool verifyBuffer(tccollection::SCCircularBuffer& buffer, const char* data) { + bool ret = true; + while(*data) { + if(!buffer.available()) { + serdebugF2("Not available at ", *data); + return false; + } + else { + auto act = buffer.get(); + serdebugF3("Read expected, actual: ", *data, (char)act); + if(act != *data) ret = false; + } + data++; + } + return ret; +} + +void testWritingAndThenReadingWithoutLoss() { + tccollection::SCCircularBuffer buffer(20); + + putIntoBuffer(buffer, "hello"); + TEST_ASSERT_TRUE(verifyBuffer(buffer, "hello")); + TEST_ASSERT_FALSE(buffer.available()); + + putIntoBuffer(buffer, "world"); + TEST_ASSERT_TRUE(verifyBuffer(buffer, "world")); + TEST_ASSERT_FALSE(buffer.available()); + + putIntoBuffer(buffer, "0123456789"); + TEST_ASSERT_TRUE(verifyBuffer(buffer, "0123456789")); + TEST_ASSERT_FALSE(buffer.available()); +} + +void testWritingAndThenReadingMoreThanAvailable() { + tccollection::SCCircularBuffer buffer(20); + + putIntoBuffer(buffer, "this is longer than 20 chars"); + // The buffer has wrapped, so we have lost everything before the wrapping point basically + TEST_ASSERT_TRUE(verifyBuffer(buffer, "20 chars")); + TEST_ASSERT_FALSE(buffer.available()); +} + +volatile bool testRunning = true; +tccollection::SCCircularBuffer glBuffer(200); +uint8_t counter = 0; + +void* threadProc(void*) { + while(testRunning && counter < 200) { + glBuffer.put(counter); + counter++; + vTaskDelay(1); + } + return nullptr; +} + +void testThreadedWriterAndReader() { + pthread_t myThreadPtr; + pthread_create(&myThreadPtr, nullptr, threadProc, (void*) nullptr); + + auto millisThen = millis(); + uint8_t myCount = 0; + int itemsReceived = 0; + + while (myCount < 199U && (millis() - millisThen) < 1000) { + if (glBuffer.available()) { + myCount = glBuffer.get(); + serdebugF2("Thread read ", myCount); + itemsReceived++; + } else { + vPortYield(); + } + } + + TEST_ASSERT_GREATER_THAN_UINT8(198, myCount); + TEST_ASSERT_GREATER_THAN_UINT8(190, itemsReceived); + + // Cleanup + pthread_join(myThreadPtr, nullptr); +} + +void setup() { + UNITY_BEGIN(); + RUN_TEST(testWritingAndThenReadingWithoutLoss); + RUN_TEST(testWritingAndThenReadingMoreThanAvailable); + RUN_TEST(testThreadedWriterAndReader); + UNITY_END(); +} + +void loop() {} \ No newline at end of file diff --git a/test/test_simple_collection/SimpleCollectionsTest.cpp b/test/test_simple_collection/SimpleCollectionsTest.cpp new file mode 100644 index 0000000..73c1c80 --- /dev/null +++ b/test/test_simple_collection/SimpleCollectionsTest.cpp @@ -0,0 +1,267 @@ +#include +#include +#include +#include + +void setUp() {} + +void tearDown() {} + +class TestStorage { +private: + int testItem; + int testKey; +public: + TestStorage() { + testItem = testKey = 0; + } + + TestStorage(int key, int item) { + this->testKey = key; + this->testItem = item; + } + + TestStorage(const TestStorage& other) { + this->testItem = other.testItem; + this->testKey = other.testKey; + } + + TestStorage& operator=(const TestStorage& other) { + if(this == &other) return *this; + this->testItem = other.testItem; + this->testKey = other.testKey; + return *this; + } + + int getKey() const { + return testKey; + } + + int getItem() const { + return testItem; + } +}; + +void printArray(const TestStorage* list, int size) { + char sz[120]; + strcpy(sz, "array: "); + for(int i=0;i btreeList(5, GROW_NEVER); + TEST_ASSERT_EQUAL_UINT8(0, btreeList.nearestLocation(1)); + + TEST_ASSERT_TRUE(btreeList.add(storage4)); + printArray(btreeList.items(), btreeList.count()); + + TEST_ASSERT_EQUAL_UINT8(0, btreeList.nearestLocation(1)); + TEST_ASSERT_EQUAL_UINT8(1, btreeList.nearestLocation(5)); +} + +void testAddingWithoutSortOrResize() { + BtreeList btreeList(5, GROW_NEVER); + + TEST_ASSERT_TRUE(btreeList.add(storage1)); + TEST_ASSERT_TRUE(btreeList.add(storage2)); + TEST_ASSERT_TRUE(btreeList.add(storage3)); + TEST_ASSERT_TRUE(btreeList.add(storage4)); + TEST_ASSERT_TRUE(btreeList.add(storage5)); + TEST_ASSERT_FALSE(btreeList.add(storage6)); + printArray(btreeList.items(), btreeList.count()); + + TEST_ASSERT_NOT_NULL(btreeList.getByKey(1)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(2)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(3)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(4)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(5)); + TEST_ASSERT_NULL(btreeList.getByKey(6)); + + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(1)->getItem(), 100); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(2)->getItem(), 101); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(3)->getItem(), 102); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(4)->getItem(), 103); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(5)->getItem(), 104); +} + +void testAddingWithSortNoResize() { + BtreeList btreeList(5, GROW_NEVER); + + TEST_ASSERT_TRUE(btreeList.add(storage2)); + TEST_ASSERT_TRUE(btreeList.add(storage1)); + TEST_ASSERT_TRUE(btreeList.add(storage5)); + TEST_ASSERT_TRUE(btreeList.add(storage4)); + TEST_ASSERT_TRUE(btreeList.add(storage3)); + TEST_ASSERT_FALSE(btreeList.add(storage6)); + printArray(btreeList.items(), btreeList.count()); + + TEST_ASSERT_NOT_NULL(btreeList.getByKey(1)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(2)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(3)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(4)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(5)); + TEST_ASSERT_NULL(btreeList.getByKey(6)); + + const TestStorage* allItems = btreeList.items(); + TEST_ASSERT_EQUAL_INT(allItems[0].getKey(), 1); + TEST_ASSERT_EQUAL_INT(allItems[1].getKey(), 2); + TEST_ASSERT_EQUAL_INT(allItems[2].getKey(), 3); + TEST_ASSERT_EQUAL_INT(allItems[3].getKey(), 4); + TEST_ASSERT_EQUAL_INT(allItems[4].getKey(), 5); + + TEST_ASSERT_EQUAL_INT(allItems[0].getKey(), btreeList.itemAtIndex(0)->getKey()); + TEST_ASSERT_EQUAL_INT(allItems[1].getKey(), btreeList.itemAtIndex(1)->getKey()); + + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(1)->getItem(), 100); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(2)->getItem(), 101); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(3)->getItem(), 102); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(4)->getItem(), 103); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(5)->getItem(), 104); +} + +void testAddingWithSortAndResizeBy5() { + BtreeList btreeList(5, GROW_BY_5); + + TEST_ASSERT_TRUE(btreeList.add(storage9)); + TEST_ASSERT_TRUE(btreeList.add(storage8)); + TEST_ASSERT_TRUE(btreeList.add(storage5)); + TEST_ASSERT_TRUE(btreeList.add(storage4)); + TEST_ASSERT_TRUE(btreeList.add(storage3)); + + TEST_ASSERT_EQUAL_UINT8(5, btreeList.capacity()); + TEST_ASSERT_TRUE(btreeList.add(storage6)); + TEST_ASSERT_TRUE(btreeList.add(storage7)); + TEST_ASSERT_TRUE(btreeList.add(storage2)); + TEST_ASSERT_TRUE(btreeList.add(storage1)); + TEST_ASSERT_TRUE(btreeList.add(storage10)); + TEST_ASSERT_EQUAL_UINT8(10, btreeList.capacity()); + printArray(btreeList.items(), btreeList.count()); + + TEST_ASSERT_NOT_NULL(btreeList.getByKey(1)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(2)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(3)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(4)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(5)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(6)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(7)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(8)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(9)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(10)); + + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(1)->getItem(), 100); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(2)->getItem(), 101); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(3)->getItem(), 102); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(4)->getItem(), 103); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(5)->getItem(), 104); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(6)->getItem(), 105); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(7)->getItem(), 106); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(8)->getItem(), 107); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(9)->getItem(), 108); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(10)->getItem(), 109); + + // clear the tree and ensure it clears + btreeList.clear(); + TEST_ASSERT_EQUAL_UINT8(10, btreeList.capacity()); + TEST_ASSERT_EQUAL_UINT8(0, btreeList.count()); + + // now add an item back and make sure we find it. + TEST_ASSERT_TRUE(btreeList.add(storage9)); + TEST_ASSERT_NOT_NULL(btreeList.getByKey(9)); + TEST_ASSERT_EQUAL_INT(btreeList.getByKey(9)->getItem(), 108); +} + +class NumericStorageItem { +private: + uint32_t item; + +public: + NumericStorageItem() : item(0xffffffff) {} + explicit NumericStorageItem(uint32_t value) : item(value) {} + NumericStorageItem(const NumericStorageItem& other) = default; + NumericStorageItem& operator= (const NumericStorageItem& other) = default; + uint32_t getKey() const { return item; } +}; + +void printArray(const NumericStorageItem* list, int size) { + char sz[160]; + strcpy(sz, "array: "); + for(int i=0;i myList; + + for(int i=0;i<20;i++) { + TEST_ASSERT_TRUE(myList.add(NumericStorageItem(i + 100))); + } + + // should have 20 items now + TEST_ASSERT_EQUAL_UINT8(myList.count(), bsize_t(20)); + + // remove key 102 + TEST_ASSERT_TRUE(myList.removeByKey(102)); + TEST_ASSERT_FALSE(myList.removeByKey(10002)); + + printArray(myList.items(), myList.count()); + + // should have 19 items + TEST_ASSERT_EQUAL_UINT8(myList.count(), bsize_t(19)); + + // ensure that only 102 was removed + TEST_ASSERT_NULL(myList.getByKey(102)); + TEST_ASSERT_NOT_NULL(myList.getByKey(103)); + TEST_ASSERT_NOT_NULL(myList.getByKey(101)); + + // put 102 back + myList.add(NumericStorageItem(102)); + + printArray(myList.items(), myList.count()); + + for(int i=0;i<20;i++) { + auto entry = myList.itemAtIndex(i); + TEST_ASSERT_EQUAL_UINT32(entry->getKey(), uint32_t(i + 100)); + } + + // now test removing the edge cases, IE head and tail of list + myList.removeIndex(0); + myList.removeIndex(19); + printArray(myList.items(), myList.count()); + + TEST_ASSERT_EQUAL_UINT8(myList.count(), bsize_t(18)); + TEST_ASSERT_NULL(myList.getByKey(100)); + TEST_ASSERT_NULL(myList.getByKey(119)); +} + +void setup() { + UNITY_BEGIN(); + RUN_TEST(testNearestLocationEdgeCases); + RUN_TEST(testAddingWithoutSortOrResize); + RUN_TEST(testAddingWithSortNoResize); + RUN_TEST(testAddingWithSortAndResizeBy5); + RUN_TEST(testAddingThenRemovingThenAddingItems); + UNITY_END(); +} + +void loop() {} \ No newline at end of file diff --git a/tests/collectionTests/CircularBufferTest.cpp b/tests/collectionTests/CircularBufferTest.cpp deleted file mode 100644 index 480b21c..0000000 --- a/tests/collectionTests/CircularBufferTest.cpp +++ /dev/null @@ -1,93 +0,0 @@ - -#include -#include -#include - -using namespace SimpleTest; - -void putIntoBuffer(SCCircularBuffer& buffer, const char* data) { - while(*data) { - buffer.put(*data); - data++; - } -} - -bool verifyBuffer(SCCircularBuffer& buffer, const char* data) { - bool ret = true; - while(*data) { - if(!buffer.available()) { - serdebugF2("Not available at ", *data); - return false; - } - else { - auto act = buffer.get(); - serdebugF3("Read expected, actual: ", *data, (char)act); - if(act != *data) ret = false; - } - data++; - } - return ret; -} - -test(testWritingAndThenReadingWithoutLoss) { - SCCircularBuffer buffer(20); - - putIntoBuffer(buffer, "hello"); - assertTrue(verifyBuffer(buffer, "hello")); - assertFalse(buffer.available()); - - putIntoBuffer(buffer, "world"); - assertTrue(verifyBuffer(buffer, "world")); - assertFalse(buffer.available()); - - putIntoBuffer(buffer, "0123456789"); - assertTrue(verifyBuffer(buffer, "0123456789")); - assertFalse(buffer.available()); -} - -test(testWritingAndThenReadingMoreThanAvailable) { - SCCircularBuffer buffer(20); - - putIntoBuffer(buffer, "this is longer than 20 chars"); - // the buffer has wrapped, so we have lost everything before the wrapping point basically - assertTrue(verifyBuffer(buffer, "20 chars")); - assertFalse(buffer.available()); -} - -#ifdef ESP32 -#include - -volatile bool testRunning = true; -SCCircularBuffer glBuffer(200); -uint8_t counter = 0; - -void* threadProc(void*) { - while(testRunning && counter < 200) { - glBuffer.put(counter); - counter++; - vTaskDelay(1); - } - return nullptr; -} - -test(testThreadedWriterAndReader) { - pthread_t myThreadPtr; - pthread_create(&myThreadPtr, nullptr, threadProc, (void*) nullptr); - - auto millisThen = millis(); - uint8_t myCount = 0; - int itemsReceived = 0; - while(myCount < 199U && (millis() - millisThen) < 1000) { - if (glBuffer.available()) { - myCount = glBuffer.get(); - serdebugF2("Thread read ", myCount); - itemsReceived++; - } - else vPortYield(); - } - - assertMoreThan((uint8_t)198, myCount); - assertMoreThan((uint8_t)190, itemsReceived); -} - -#endif \ No newline at end of file diff --git a/tests/collectionTests/SimpleCollectionsTest.cpp b/tests/collectionTests/SimpleCollectionsTest.cpp deleted file mode 100644 index 4456913..0000000 --- a/tests/collectionTests/SimpleCollectionsTest.cpp +++ /dev/null @@ -1,254 +0,0 @@ -#include -#include -#include - -using namespace SimpleTest; - -class TestStorage { -private: - int testItem; - int testKey; -public: - TestStorage() { - testItem = testKey = 0; - } - - TestStorage(int key, int item) { - this->testKey = key; - this->testItem = item; - } - - TestStorage(const TestStorage& other) { - this->testItem = other.testItem; - this->testKey = other.testKey; - } - - TestStorage& operator=(const TestStorage& other) { - if(this == &other) return *this; - this->testItem = other.testItem; - this->testKey = other.testKey; - return *this; - } - - int getKey() const { - return testKey; - } - - int getItem() const { - return testItem; - } -}; - -void printArray(const TestStorage* list, int size) { - char sz[120]; - strcpy(sz, "array: "); - for(int i=0;i btreeList(5, GROW_NEVER); - assertEquals((bsize_t)0, btreeList.nearestLocation(1)); - - assertTrue(btreeList.add(storage4)); - printArray(btreeList.items(), btreeList.count()); - - assertEquals((bsize_t)0, btreeList.nearestLocation(1)); - assertEquals((bsize_t)1, btreeList.nearestLocation(5)); -} - -test(testAddingWithoutSortOrResize) { - BtreeList btreeList(5, GROW_NEVER); - - assertTrue(btreeList.add(storage1)); - assertTrue(btreeList.add(storage2)); - assertTrue(btreeList.add(storage3)); - assertTrue(btreeList.add(storage4)); - assertTrue(btreeList.add(storage5)); - assertFalse(btreeList.add(storage6)); - printArray(btreeList.items(), btreeList.count()); - - assertTrue(btreeList.getByKey(1) != nullptr); - assertTrue(btreeList.getByKey(2) != nullptr); - assertTrue(btreeList.getByKey(3) != nullptr); - assertTrue(btreeList.getByKey(4) != nullptr); - assertTrue(btreeList.getByKey(5) != nullptr); - assertTrue(btreeList.getByKey(6) == nullptr); - - assertEquals(btreeList.getByKey(1)->getItem(), 100); - assertEquals(btreeList.getByKey(2)->getItem(), 101); - assertEquals(btreeList.getByKey(3)->getItem(), 102); - assertEquals(btreeList.getByKey(4)->getItem(), 103); - assertEquals(btreeList.getByKey(5)->getItem(), 104); -} - -test(testAddingWithSortNoResize) { - BtreeList btreeList(5, GROW_NEVER); - - assertTrue(btreeList.add(storage2)); - assertTrue(btreeList.add(storage1)); - assertTrue(btreeList.add(storage5)); - assertTrue(btreeList.add(storage4)); - assertTrue(btreeList.add(storage3)); - assertFalse(btreeList.add(storage6)); - printArray(btreeList.items(), btreeList.count()); - - assertTrue(btreeList.getByKey(1) != nullptr); - assertTrue(btreeList.getByKey(2) != nullptr); - assertTrue(btreeList.getByKey(3) != nullptr); - assertTrue(btreeList.getByKey(4) != nullptr); - assertTrue(btreeList.getByKey(5) != nullptr); - assertTrue(btreeList.getByKey(6) == nullptr); - - const TestStorage* allItems = btreeList.items(); - assertEquals(allItems[0].getKey(), 1); - assertEquals(allItems[1].getKey(), 2); - assertEquals(allItems[2].getKey(), 3); - assertEquals(allItems[3].getKey(), 4); - assertEquals(allItems[4].getKey(), 5); - - assertEquals(allItems[0].getKey(), btreeList.itemAtIndex(0)->getKey()); - assertEquals(allItems[1].getKey(), btreeList.itemAtIndex(1)->getKey()); - - assertEquals(btreeList.getByKey(1)->getItem(), 100); - assertEquals(btreeList.getByKey(2)->getItem(), 101); - assertEquals(btreeList.getByKey(3)->getItem(), 102); - assertEquals(btreeList.getByKey(4)->getItem(), 103); - assertEquals(btreeList.getByKey(5)->getItem(), 104); -} - -test(testAddingWithSortAndResizeBy5) { - BtreeList btreeList(5, GROW_BY_5); - - assertTrue(btreeList.add(storage9)); - assertTrue(btreeList.add(storage8)); - assertTrue(btreeList.add(storage5)); - assertTrue(btreeList.add(storage4)); - assertTrue(btreeList.add(storage3)); - - assertEquals((bsize_t)5, btreeList.capacity()); - assertTrue(btreeList.add(storage6)); - assertTrue(btreeList.add(storage7)); - assertTrue(btreeList.add(storage2)); - assertTrue(btreeList.add(storage1)); - assertTrue(btreeList.add(storage10)); - assertEquals((bsize_t)10, btreeList.capacity()); - printArray(btreeList.items(), btreeList.count()); - - assertTrue(btreeList.getByKey(1) != nullptr); - assertTrue(btreeList.getByKey(2) != nullptr); - assertTrue(btreeList.getByKey(3) != nullptr); - assertTrue(btreeList.getByKey(4) != nullptr); - assertTrue(btreeList.getByKey(5) != nullptr); - assertTrue(btreeList.getByKey(6) != nullptr); - assertTrue(btreeList.getByKey(7) != nullptr); - assertTrue(btreeList.getByKey(8) != nullptr); - assertTrue(btreeList.getByKey(9) != nullptr); - assertTrue(btreeList.getByKey(10) != nullptr); - - assertEquals(btreeList.getByKey(1)->getItem(), 100); - assertEquals(btreeList.getByKey(2)->getItem(), 101); - assertEquals(btreeList.getByKey(3)->getItem(), 102); - assertEquals(btreeList.getByKey(4)->getItem(), 103); - assertEquals(btreeList.getByKey(5)->getItem(), 104); - assertEquals(btreeList.getByKey(6)->getItem(), 105); - assertEquals(btreeList.getByKey(7)->getItem(), 106); - assertEquals(btreeList.getByKey(8)->getItem(), 107); - assertEquals(btreeList.getByKey(9)->getItem(), 108); - assertEquals(btreeList.getByKey(10)->getItem(), 109); - - // clear the tree and ensure it clears - btreeList.clear(); - assertEquals((bsize_t)10, btreeList.capacity()); - assertEquals((bsize_t)0, btreeList.count()); - - // now add an item back and make sure we find it. - assertTrue(btreeList.add(storage9)); - assertTrue(btreeList.getByKey(9) != nullptr); - assertEquals(btreeList.getByKey(9)->getItem(), 108); - -} - -class NumericStorageItem { -private: - uint32_t item; - -public: - NumericStorageItem() : item(0xffffffff) {} - explicit NumericStorageItem(uint32_t value) : item(value) {} - NumericStorageItem(const NumericStorageItem& other) = default; - NumericStorageItem& operator= (const NumericStorageItem& other) = default; - uint32_t getKey() const { return item; } -}; - -void printArray(const NumericStorageItem* list, int size) { - char sz[160]; - strcpy(sz, "array: "); - for(int i=0;i myList; - - for(int i=0;i<20;i++) { - myList.add(NumericStorageItem(i + 100)); - } - - // should have 20 items now - assertEquals(myList.count(), bsize_t(20)); - - // remove key 102 - assertTrue(myList.removeByKey(102)); - assertFalse(myList.removeByKey(10002)); - - printArray(myList.items(), myList.count()); - - // should have 19 items - assertEquals(myList.count(), bsize_t(19)); - - // ensure that only 102 was removed - assertTrue(myList.getByKey(102) == nullptr); - assertTrue(myList.getByKey(103) != nullptr); - assertTrue(myList.getByKey(101) != nullptr); - - // put 102 back - myList.add(NumericStorageItem(102)); - - printArray(myList.items(), myList.count()); - - for(int i=0;i<20;i++) { - auto entry = myList.itemAtIndex(i); - assertEquals(entry->getKey(), uint32_t(i + 100)); - } - - // now test removing the edge cases, IE head and tail of list - myList.removeIndex(0); - myList.removeIndex(19); - printArray(myList.items(), myList.count()); - - assertEquals(myList.count(), bsize_t(18)); - assertTrue(myList.getByKey(100) == nullptr); - assertTrue(myList.getByKey(119) == nullptr); -} \ No newline at end of file diff --git a/tests/collectionTests/collectionTests.cpp b/tests/collectionTests/collectionTests.cpp deleted file mode 100644 index 1ef8602..0000000 --- a/tests/collectionTests/collectionTests.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -#include -#include - -using namespace SimpleTest; - -IOLOG_MBED_PORT_IF_NEEDED(USBTX, USBRX) - -void setup() { - IOLOG_START_SERIAL - startTesting(); -} - -DEFAULT_TEST_RUNLOOP