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
31 changes: 31 additions & 0 deletions .github/workflows/run-unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Run Unit Tests

on:
push:
branches:
- main
- master
pull_request:
workflow_dispatch:

jobs:
test:
runs-on: ubuntu-latest
steps:

- name: Clone Repo
uses: actions/checkout@v4

- name: Setup Build Environment
uses: ./.github/actions/setup-build-environment

- name: Run Unit Tests
run: pio test -e native -vv

- name: Upload Test Results
# Upload test results even if the test step failed.
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: .pio/build/native/
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ Here are some general principals you should try to adhere to:
* No dynamic memory allocation, except during setup/begin functions.
* Use the same brace and indenting style that's in the core source modules. (A .clang-format is prob going to be added soon, but please do NOT retroactively re-format existing code. This just creates unnecessary diffs that make finding problems harder)

### Running unit tests

To run unit tests, run the following command:

```bash
pio test --environment native --verbose
```

## Road-Map / To-Do

There are a number of fairly major features in the pipeline, with no particular time-frames attached yet. In very rough chronological order:
Expand Down
14 changes: 14 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,17 @@ lib_deps =
adafruit/Adafruit MLX90614 Library @ ^2.1.5
adafruit/Adafruit_VL53L0X @ ^1.2.4
stevemarple/MicroNMEA @ ^2.0.6

; ----------------- TESTING ---------------------

[env:native]
platform = native
build_flags = -std=c++14
-I src
-I test/mocks
test_build_src = yes
build_src_filter =
-<*>
+<../src/Utils.cpp>
lib_deps =
google/googletest @ ^1.15.2
13 changes: 13 additions & 0 deletions test/mocks/AES.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <stdint.h>
#include <stddef.h>

// Mock AES128 class for testing
// Provides minimal interface to allow Utils.cpp to compile
class AES128 {
public:
void setKey(const uint8_t* key, size_t keySize) {}
void encryptBlock(uint8_t* output, const uint8_t* input) {}
void decryptBlock(uint8_t* output, const uint8_t* input) {}
};
14 changes: 14 additions & 0 deletions test/mocks/SHA256.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include <stdint.h>
#include <stddef.h>

// Mock SHA256 class for testing
// Provides minimal interface to allow Utils.cpp to compile
class SHA256 {
public:
void update(const uint8_t* data, size_t len) {}
void finalize(uint8_t* hash, size_t hashLen) {}
void resetHMAC(const uint8_t* key, size_t keyLen) {}
void finalizeHMAC(const uint8_t* key, size_t keyLen, uint8_t* hash, size_t hashLen) {}
};
10 changes: 10 additions & 0 deletions test/mocks/Stream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

// Mock Stream class for native testing
// Provides minimal interface needed by Utils.h

class Stream {
public:
virtual void print(char c) {}
virtual void print(const char* str) {}
};
57 changes: 57 additions & 0 deletions test/test_utils/test_tohex.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <gtest/gtest.h>
#include "Utils.h"

using namespace mesh;

#define HEX_BUFFER_SIZE(input) (sizeof(input) * 2 + 1)

TEST(UtilsToHex, ConvertSingleByte) {
uint8_t input[] = {0xAB};
char output[HEX_BUFFER_SIZE(input)];

Utils::toHex(output, input, sizeof(input));

EXPECT_STREQ("AB", output);
}

TEST(UtilsToHex, ConvertMultipleBytes) {
uint8_t input[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
char output[HEX_BUFFER_SIZE(input)];

Utils::toHex(output, input, sizeof(input));

EXPECT_STREQ("0123456789ABCDEF", output);
}

TEST(UtilsToHex, ConvertZeroByte) {
uint8_t input[] = {0x00};
char output[HEX_BUFFER_SIZE(input)];

Utils::toHex(output, input, sizeof(input));

EXPECT_STREQ("00", output);
}

TEST(UtilsToHex, ConvertMaxByte) {
uint8_t input[] = {0xFF};
char output[HEX_BUFFER_SIZE(input)];

Utils::toHex(output, input, sizeof(input));

EXPECT_STREQ("FF", output);
}

TEST(UtilsToHex, NullTerminatesOnEmptyInput) {
uint8_t input[] = {0xAB};
char output[] = "X"; // Pre-fill with X.

Utils::toHex(output, input, 0);

// Should just null-terminate at position 0
EXPECT_EQ('\0', output[0]);
}

int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}