From 9abd07bb0535d67ad807800aba854f11aaf61395 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Tue, 31 Dec 2024 16:06:38 -0600 Subject: [PATCH 01/11] Set ch341 MAD Address via sprintf formatting (#5713) --- src/platform/portduino/PortduinoGlue.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index b020f5991..b042510f5 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -232,9 +231,9 @@ void portduinoSetup() dmac[3] = hash[3]; dmac[4] = hash[4]; dmac[5] = hash[5]; - std::stringstream mactmp; - mactmp << std::hex << +dmac[0] << +dmac[1] << +dmac[2] << +dmac[3] << +dmac[4] << +dmac[5]; - settingsStrings[mac_address] = mactmp.str(); + char macBuf[13] = {0}; + sprintf(macBuf, "%02X%02X%02X%02X%02X%02X", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]); + settingsStrings[mac_address] = macBuf; } } @@ -244,7 +243,7 @@ void portduinoSetup() std::cout << "Please set a MAC Address in config.yaml using either MACAddress or MACAddressSource." << std::endl; exit(EXIT_FAILURE); } - std::cout << "MAC Address: " << std::hex << +dmac[0] << +dmac[1] << +dmac[2] << +dmac[3] << +dmac[4] << +dmac[5] << std::endl; + printf("MAC ADDRESS: %02X:%02X:%02X:%02X:%02X:%02X\n", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]); // Rather important to set this, if not running simulated. randomSeed(time(NULL)); From c2c06ed0adb3f779d88ab6f812a380d848c72c75 Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Wed, 1 Jan 2025 16:40:14 -0800 Subject: [PATCH 02/11] Move DecodedServiceEnvelope into its own file (#5715) --- src/mqtt/MQTT.cpp | 19 +------------------ src/mqtt/ServiceEnvelope.cpp | 23 +++++++++++++++++++++++ src/mqtt/ServiceEnvelope.h | 13 +++++++++++++ 3 files changed, 37 insertions(+), 18 deletions(-) create mode 100644 src/mqtt/ServiceEnvelope.cpp create mode 100644 src/mqtt/ServiceEnvelope.h diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 4260ae201..5141af560 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -2,6 +2,7 @@ #include "MeshService.h" #include "NodeDB.h" #include "PowerFSM.h" +#include "ServiceEnvelope.h" #include "configuration.h" #include "main.h" #include "mesh/Channels.h" @@ -25,7 +26,6 @@ #endif #include #include -#include #include #include @@ -47,23 +47,6 @@ static uint8_t bytes[meshtastic_MqttClientProxyMessage_size + 30]; // 12 for cha static bool isMqttServerAddressPrivate = false; -// meshtastic_ServiceEnvelope that automatically releases dynamically allocated memory when it goes out of scope. -struct DecodedServiceEnvelope : public meshtastic_ServiceEnvelope { - DecodedServiceEnvelope() = delete; - DecodedServiceEnvelope(const uint8_t *payload, size_t length) - : meshtastic_ServiceEnvelope(meshtastic_ServiceEnvelope_init_default), - validDecode(pb_decode_from_bytes(payload, length, &meshtastic_ServiceEnvelope_msg, this)) - { - } - ~DecodedServiceEnvelope() - { - if (validDecode) - pb_release(&meshtastic_ServiceEnvelope_msg, this); - } - // Clients must check that this is true before using. - const bool validDecode; -}; - inline void onReceiveProto(char *topic, byte *payload, size_t length) { const DecodedServiceEnvelope e(payload, length); diff --git a/src/mqtt/ServiceEnvelope.cpp b/src/mqtt/ServiceEnvelope.cpp new file mode 100644 index 000000000..ee55f22f6 --- /dev/null +++ b/src/mqtt/ServiceEnvelope.cpp @@ -0,0 +1,23 @@ +#include "ServiceEnvelope.h" +#include "mesh-pb-constants.h" +#include + +DecodedServiceEnvelope::DecodedServiceEnvelope(const uint8_t *payload, size_t length) + : meshtastic_ServiceEnvelope(meshtastic_ServiceEnvelope_init_default), + validDecode(pb_decode_from_bytes(payload, length, &meshtastic_ServiceEnvelope_msg, this)) +{ +} + +DecodedServiceEnvelope::DecodedServiceEnvelope(DecodedServiceEnvelope &&other) + : meshtastic_ServiceEnvelope(meshtastic_ServiceEnvelope_init_zero), validDecode(other.validDecode) +{ + std::swap(packet, other.packet); + std::swap(channel_id, other.channel_id); + std::swap(gateway_id, other.gateway_id); +} + +DecodedServiceEnvelope::~DecodedServiceEnvelope() +{ + if (validDecode) + pb_release(&meshtastic_ServiceEnvelope_msg, this); +} \ No newline at end of file diff --git a/src/mqtt/ServiceEnvelope.h b/src/mqtt/ServiceEnvelope.h new file mode 100644 index 000000000..6ab0695db --- /dev/null +++ b/src/mqtt/ServiceEnvelope.h @@ -0,0 +1,13 @@ +#pragma once + +#include "mesh/generated/meshtastic/mqtt.pb.h" + +// meshtastic_ServiceEnvelope that automatically releases dynamically allocated memory when it goes out of scope. +struct DecodedServiceEnvelope : public meshtastic_ServiceEnvelope { + DecodedServiceEnvelope(const uint8_t *payload, size_t length); + DecodedServiceEnvelope(DecodedServiceEnvelope &) = delete; + DecodedServiceEnvelope(DecodedServiceEnvelope &&); + ~DecodedServiceEnvelope(); + // Clients must check that this is true before using. + const bool validDecode; +}; \ No newline at end of file From 9f32995d7fcf96384dc01b5b953772327a600e97 Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Wed, 1 Jan 2025 17:25:01 -0800 Subject: [PATCH 03/11] Implement MeshModule destructor (#5714) --- src/mesh/MeshModule.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mesh/MeshModule.cpp b/src/mesh/MeshModule.cpp index 9de54ade5..2f2863fa5 100644 --- a/src/mesh/MeshModule.cpp +++ b/src/mesh/MeshModule.cpp @@ -4,6 +4,7 @@ #include "NodeDB.h" #include "configuration.h" #include "modules/RoutingModule.h" +#include #include std::vector *MeshModule::modules; @@ -29,7 +30,9 @@ void MeshModule::setup() {} MeshModule::~MeshModule() { - assert(0); // FIXME - remove from list of modules once someone needs this feature + auto it = std::find(modules->begin(), modules->end(), this); + assert(it != modules->end()); + modules->erase(it); } meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex, From 183f68ba0005e9bfeb4423681693b225d28a5f6d Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Wed, 1 Jan 2025 17:26:12 -0800 Subject: [PATCH 04/11] Run tests as part of the main CI (#5712) * Create an shared action to install native dependecies * Create a workflow for running native tests * Artifact names contain version * Add test-native to main_matrix.yml * No permission are required for test_native.yml * Add permissions for dorny/test-reporter * No permissions when running tests * s/Generate Reports/Generate Test Reports/ --- .github/actions/setup-native/action.yml | 14 +++ .github/workflows/build_native.yml | 20 +--- .github/workflows/main_matrix.yml | 3 + .github/workflows/test_native.yml | 153 ++++++++++++++++++++++++ .github/workflows/tests.yml | 75 +----------- 5 files changed, 175 insertions(+), 90 deletions(-) create mode 100644 .github/actions/setup-native/action.yml create mode 100644 .github/workflows/test_native.yml diff --git a/.github/actions/setup-native/action.yml b/.github/actions/setup-native/action.yml new file mode 100644 index 000000000..36c95d943 --- /dev/null +++ b/.github/actions/setup-native/action.yml @@ -0,0 +1,14 @@ +name: Setup native build +description: Install libraries needed for building the Native/Portduino build + +runs: + using: composite + steps: + - name: Setup base + id: base + uses: ./.github/actions/setup-base + + - name: Install libs needed for native build + shell: bash + run: | + sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev diff --git a/.github/workflows/build_native.yml b/.github/workflows/build_native.yml index 74bc074aa..11ba09ad7 100644 --- a/.github/workflows/build_native.yml +++ b/.github/workflows/build_native.yml @@ -10,12 +10,6 @@ jobs: build-native: runs-on: ubuntu-latest steps: - - name: Install libs needed for native build - shell: bash - run: | - sudo apt-get update --fix-missing - sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev - - name: Checkout code uses: actions/checkout@v4 with: @@ -23,17 +17,9 @@ jobs: ref: ${{github.event.pull_request.head.ref}} repository: ${{github.event.pull_request.head.repo.full_name}} - - name: Upgrade python tools - shell: bash - run: | - python -m pip install --upgrade pip - pip install -U platformio adafruit-nrfutil - pip install -U meshtastic --pre - - - name: Upgrade platformio - shell: bash - run: | - pio upgrade + - name: Setup native build + id: base + uses: ./.github/actions/setup-native - name: Build Native run: bin/build-native.sh diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index 0109bef1a..a437411b5 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -137,6 +137,9 @@ jobs: package-native: uses: ./.github/workflows/package_amd64.yml + test-native: + uses: ./.github/workflows/test_native.yml + build-docker: if: ${{ github.event_name == 'workflow_dispatch' }} uses: ./.github/workflows/build_docker.yml diff --git a/.github/workflows/test_native.yml b/.github/workflows/test_native.yml new file mode 100644 index 000000000..8fe4e1c03 --- /dev/null +++ b/.github/workflows/test_native.yml @@ -0,0 +1,153 @@ +name: Run Tests on Native platform + +on: + workflow_call: + workflow_dispatch: + +permissions: {} + +env: + LCOV_CAPTURE_FLAGS: --quiet --capture --include "${PWD}/src/*" --exclude '*/src/mesh/generated/*' --directory .pio/build/coverage/src --base-directory "${PWD}" + +jobs: + simulator-tests: + name: Native Simulator Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup native build + id: base + uses: ./.github/actions/setup-native + + - name: Install simulator dependencies + run: pip install -U dotmap + + # We now run integration test before other build steps (to quickly see runtime failures) + - name: Build for native/coverage + run: platformio run -e coverage + + - name: Capture initial coverage information + shell: bash + run: | + sudo apt-get install -y lcov + lcov ${{ env.LCOV_CAPTURE_FLAGS }} --initial --output-file coverage_base.info + + - name: Integration test + run: | + .pio/build/coverage/program & + PID=$! + timeout 20 bash -c "until ls -al /proc/$PID/fd | grep socket; do sleep 1; done" + echo "Simulator started, launching python test..." + python3 -c 'from meshtastic.test import testSimulator; testSimulator()' + wait + + - name: Capture coverage information + if: always() # run this step even if previous step failed + run: lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name integration --output-file coverage_integration.info + + - name: Get release version string + if: always() # run this step even if previous step failed + run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT + id: version + + - name: Save coverage information + uses: actions/upload-artifact@v4 + if: always() # run this step even if previous step failed + with: + name: lcov-coverage-info-native-simulator-test-${{ steps.version.outputs.version }}.zip + overwrite: true + path: ./coverage_*.info + + platformio-tests: + name: Native PlatformIO Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup native build + id: base + uses: ./.github/actions/setup-native + + - name: Get release version string + run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT + id: version + + - name: PlatformIO Tests + run: platformio test -e coverage --junit-output-path testreport.xml + + - name: Save test results + if: always() # run this step even if previous step failed + uses: actions/upload-artifact@v4 + with: + name: platformio-test-report-${{ steps.version.outputs.version }}.zip + overwrite: true + path: ./testreport.xml + + - name: Capture coverage information + if: always() # run this step even if previous step failed + run: | + sudo apt-get install -y lcov + lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name tests --output-file coverage_tests.info + + - name: Save coverage information + uses: actions/upload-artifact@v4 + if: always() # run this step even if previous step failed + with: + name: lcov-coverage-info-native-platformio-tests-${{ steps.version.outputs.version }}.zip + overwrite: true + path: ./coverage_*.info + + generate-reports: + name: Generate Test Reports + runs-on: ubuntu-latest + permissions: # Needed for dorny/test-reporter. + contents: read + actions: read + checks: write + needs: + - simulator-tests + - platformio-tests + if: always() + steps: + - uses: actions/checkout@v4 + + - name: Get release version string + run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT + id: version + + - name: Download test artifacts + uses: actions/download-artifact@v4 + with: + name: platformio-test-report-${{ steps.version.outputs.version }}.zip + merge-multiple: true + + - name: Test Report + uses: dorny/test-reporter@v1.9.1 + with: + name: PlatformIO Tests + path: testreport.xml + reporter: java-junit + + - name: Download coverage artifacts + uses: actions/download-artifact@v4 + with: + pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.version }}.zip + path: code-coverage-report + merge-multiple: true + + - name: Generate Code Coverage Report + run: | + sudo apt-get install -y lcov + lcov --quiet --add-tracefile code-coverage-report/coverage_base.info --add-tracefile code-coverage-report/coverage_integration.info --add-tracefile code-coverage-report/coverage_tests.info --output-file code-coverage-report/coverage_src.info + genhtml --quiet --legend --prefix "${PWD}" code-coverage-report/coverage_src.info --output-directory code-coverage-report + + - name: Save Code Coverage Report + uses: actions/upload-artifact@v4 + with: + name: code-coverage-report-${{ steps.version.outputs.version }}.zip + path: code-coverage-report diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ae9f82543..c9489db1a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -6,79 +6,8 @@ on: workflow_dispatch: {} jobs: - test-simulator: - runs-on: ubuntu-latest - env: - LCOV_CAPTURE_FLAGS: --quiet --capture --include "${PWD}/src/*" --exclude '*/src/mesh/generated/*' --directory .pio/build/coverage/src --base-directory "${PWD}" - steps: - - name: Install libs needed for native build - shell: bash - run: | - sudo apt-get update --fix-missing - sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev - sudo apt-get install -y lcov - - - name: Checkout code - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Upgrade python tools - shell: bash - run: | - python -m pip install --upgrade pip - pip install -U platformio adafruit-nrfutil dotmap - pip install -U meshtastic --pre - - - name: Upgrade platformio - shell: bash - run: | - pio upgrade - - - name: Build Native - run: bin/build-native.sh - - # We now run integration test before other build steps (to quickly see runtime failures) - - name: Build for native/coverage - run: | - platformio run -e coverage - lcov ${{ env.LCOV_CAPTURE_FLAGS }} --initial --output-file coverage_base.info - - - name: Integration test - run: | - .pio/build/coverage/program & - PID=$! - timeout 20 bash -c "until ls -al /proc/$PID/fd | grep socket; do sleep 1; done" - echo "Simulator started, launching python test..." - python3 -c 'from meshtastic.test import testSimulator; testSimulator()' - wait - lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name integration --output-file coverage_integration.info - - - name: PlatformIO Tests - run: | - platformio test -e coverage --junit-output-path testreport.xml - lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name tests --output-file coverage_tests.info - - - name: Test Report - uses: dorny/test-reporter@v1.9.1 - if: success() || failure() # run this step even if previous step failed - with: - name: PlatformIO Tests - path: testreport.xml - reporter: java-junit - - - name: Generate Code Coverage Report - run: | - lcov --quiet --add-tracefile coverage_base.info --add-tracefile coverage_integration.info --add-tracefile coverage_tests.info --output-file coverage_src.info - mkdir code-coverage-report - genhtml --quiet --legend --prefix "${PWD}" coverage_src.info --output-directory code-coverage-report - mv coverage_*.info code-coverage-report - - - name: Save Code Coverage Report - uses: actions/upload-artifact@v4 - with: - name: code-coverage-report - path: code-coverage-report + native-tests: + uses: ./.github/workflows/test_native.yml hardware-tests: runs-on: test-runner From 88d8ab53c8fba2830a71c9c0131b990d0f0f4e64 Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Wed, 1 Jan 2025 19:37:11 -0800 Subject: [PATCH 05/11] Disable coverage generation (#5719) * Disable coverage generation * Comment a bit more of the report generation --- .github/workflows/test_native.yml | 54 +++++++++++++++---------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/test_native.yml b/.github/workflows/test_native.yml index 8fe4e1c03..9de3b34a6 100644 --- a/.github/workflows/test_native.yml +++ b/.github/workflows/test_native.yml @@ -120,34 +120,34 @@ jobs: run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT id: version - - name: Download test artifacts - uses: actions/download-artifact@v4 - with: - name: platformio-test-report-${{ steps.version.outputs.version }}.zip - merge-multiple: true + # - name: Download test artifacts + # uses: actions/download-artifact@v4 + # with: + # name: platformio-test-report-${{ steps.version.outputs.version }}.zip + # merge-multiple: true - - name: Test Report - uses: dorny/test-reporter@v1.9.1 - with: - name: PlatformIO Tests - path: testreport.xml - reporter: java-junit + # - name: Test Report + # uses: dorny/test-reporter@v1.9.1 + # with: + # name: PlatformIO Tests + # path: testreport.xml + # reporter: java-junit - - name: Download coverage artifacts - uses: actions/download-artifact@v4 - with: - pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.version }}.zip - path: code-coverage-report - merge-multiple: true + # - name: Download coverage artifacts + # uses: actions/download-artifact@v4 + # with: + # pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.version }}.zip + # path: code-coverage-report + # merge-multiple: true - - name: Generate Code Coverage Report - run: | - sudo apt-get install -y lcov - lcov --quiet --add-tracefile code-coverage-report/coverage_base.info --add-tracefile code-coverage-report/coverage_integration.info --add-tracefile code-coverage-report/coverage_tests.info --output-file code-coverage-report/coverage_src.info - genhtml --quiet --legend --prefix "${PWD}" code-coverage-report/coverage_src.info --output-directory code-coverage-report + # - name: Generate Code Coverage Report + # run: | + # sudo apt-get install -y lcov + # lcov --quiet --add-tracefile code-coverage-report/coverage_base.info --add-tracefile code-coverage-report/coverage_integration.info --add-tracefile code-coverage-report/coverage_tests.info --output-file code-coverage-report/coverage_src.info + # genhtml --quiet --legend --prefix "${PWD}" code-coverage-report/coverage_src.info --output-directory code-coverage-report - - name: Save Code Coverage Report - uses: actions/upload-artifact@v4 - with: - name: code-coverage-report-${{ steps.version.outputs.version }}.zip - path: code-coverage-report + # - name: Save Code Coverage Report + # uses: actions/upload-artifact@v4 + # with: + # name: code-coverage-report-${{ steps.version.outputs.version }}.zip + # path: code-coverage-report From 7a1c32b89aa348871ff2e97ebf7a618f8274309e Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Wed, 1 Jan 2025 20:41:13 -0800 Subject: [PATCH 06/11] test_native.yaml checks out code for the PR. (#5720) --- .github/workflows/test_native.yml | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test_native.yml b/.github/workflows/test_native.yml index 9de3b34a6..1cc1f7c40 100644 --- a/.github/workflows/test_native.yml +++ b/.github/workflows/test_native.yml @@ -16,6 +16,8 @@ jobs: steps: - uses: actions/checkout@v4 with: + ref: ${{github.event.pull_request.head.ref}} + repository: ${{github.event.pull_request.head.repo.full_name}} submodules: recursive - name: Setup native build @@ -67,6 +69,8 @@ jobs: steps: - uses: actions/checkout@v4 with: + ref: ${{github.event.pull_request.head.ref}} + repository: ${{github.event.pull_request.head.repo.full_name}} submodules: recursive - name: Setup native build @@ -115,23 +119,26 @@ jobs: if: always() steps: - uses: actions/checkout@v4 + with: + ref: ${{github.event.pull_request.head.ref}} + repository: ${{github.event.pull_request.head.repo.full_name}} - name: Get release version string run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT id: version - # - name: Download test artifacts - # uses: actions/download-artifact@v4 - # with: - # name: platformio-test-report-${{ steps.version.outputs.version }}.zip - # merge-multiple: true + - name: Download test artifacts + uses: actions/download-artifact@v4 + with: + name: platformio-test-report-${{ steps.version.outputs.version }}.zip + merge-multiple: true - # - name: Test Report - # uses: dorny/test-reporter@v1.9.1 - # with: - # name: PlatformIO Tests - # path: testreport.xml - # reporter: java-junit + - name: Test Report + uses: dorny/test-reporter@v1.9.1 + with: + name: PlatformIO Tests + path: testreport.xml + reporter: java-junit # - name: Download coverage artifacts # uses: actions/download-artifact@v4 From 93e2bc7058ba0d0b7b3936590b5c185bc418fba9 Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Wed, 1 Jan 2025 22:53:07 -0800 Subject: [PATCH 07/11] Use relative paths in coverage info files (#5721) --- .github/workflows/test_native.yml | 38 +++++++++++++++++-------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/.github/workflows/test_native.yml b/.github/workflows/test_native.yml index 1cc1f7c40..8c1527279 100644 --- a/.github/workflows/test_native.yml +++ b/.github/workflows/test_native.yml @@ -36,6 +36,7 @@ jobs: run: | sudo apt-get install -y lcov lcov ${{ env.LCOV_CAPTURE_FLAGS }} --initial --output-file coverage_base.info + sed -i -e "s#${PWD}#.#" coverage_base.info # Make paths relative. - name: Integration test run: | @@ -48,7 +49,9 @@ jobs: - name: Capture coverage information if: always() # run this step even if previous step failed - run: lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name integration --output-file coverage_integration.info + run: | + lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name integration --output-file coverage_integration.info + sed -i -e "s#${PWD}#.#" coverage_integration.info # Make paths relative. - name: Get release version string if: always() # run this step even if previous step failed @@ -97,6 +100,7 @@ jobs: run: | sudo apt-get install -y lcov lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name tests --output-file coverage_tests.info + sed -i -e "s#${PWD}#.#" coverage_tests.info # Make paths relative. - name: Save coverage information uses: actions/upload-artifact@v4 @@ -140,21 +144,21 @@ jobs: path: testreport.xml reporter: java-junit - # - name: Download coverage artifacts - # uses: actions/download-artifact@v4 - # with: - # pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.version }}.zip - # path: code-coverage-report - # merge-multiple: true + - name: Download coverage artifacts + uses: actions/download-artifact@v4 + with: + pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.version }}.zip + path: code-coverage-report + merge-multiple: true - # - name: Generate Code Coverage Report - # run: | - # sudo apt-get install -y lcov - # lcov --quiet --add-tracefile code-coverage-report/coverage_base.info --add-tracefile code-coverage-report/coverage_integration.info --add-tracefile code-coverage-report/coverage_tests.info --output-file code-coverage-report/coverage_src.info - # genhtml --quiet --legend --prefix "${PWD}" code-coverage-report/coverage_src.info --output-directory code-coverage-report + - name: Generate Code Coverage Report + run: | + sudo apt-get install -y lcov + lcov --quiet --add-tracefile code-coverage-report/coverage_base.info --add-tracefile code-coverage-report/coverage_integration.info --add-tracefile code-coverage-report/coverage_tests.info --output-file code-coverage-report/coverage_src.info + genhtml --quiet --legend --prefix "${PWD}" code-coverage-report/coverage_src.info --output-directory code-coverage-report - # - name: Save Code Coverage Report - # uses: actions/upload-artifact@v4 - # with: - # name: code-coverage-report-${{ steps.version.outputs.version }}.zip - # path: code-coverage-report + - name: Save Code Coverage Report + uses: actions/upload-artifact@v4 + with: + name: code-coverage-report-${{ steps.version.outputs.version }}.zip + path: code-coverage-report From 9f7cbf1b4fe61979c5e98f9affb1d801af7147c8 Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Thu, 2 Jan 2025 03:32:39 -0800 Subject: [PATCH 08/11] MQTT unit test can inject WiFiClient (#5716) --- src/mqtt/MQTT.cpp | 12 +++++++----- src/mqtt/MQTT.h | 40 +++++++++++++++++++++++----------------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 5141af560..46fb607b5 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -282,7 +282,9 @@ void mqttInit() } #if HAS_NETWORKING -MQTT::MQTT() : concurrency::OSThread("mqtt"), pubSub(mqttClient), mqttQueue(MAX_MQTT_QUEUE) +MQTT::MQTT() : MQTT(std::unique_ptr(new MQTTClient())) {} +MQTT::MQTT(std::unique_ptr _mqttClient) + : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE), mqttClient(std::move(_mqttClient)), pubSub(*mqttClient) #else MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE) #endif @@ -420,13 +422,13 @@ void MQTT::reconnect() } } else { LOG_INFO("Use non-TLS-encrypted session"); - pubSub.setClient(mqttClient); + pubSub.setClient(*mqttClient); } #else - pubSub.setClient(mqttClient); + pubSub.setClient(*mqttClient); #endif #elif HAS_NETWORKING - pubSub.setClient(mqttClient); + pubSub.setClient(*mqttClient); #endif std::pair hostAndPort = parseHostAndPort(serverAddr, serverPort); @@ -444,7 +446,7 @@ void MQTT::reconnect() enabled = true; // Start running background process again runASAP = true; reconnectCount = 0; - isMqttServerAddressPrivate = isPrivateIpAddress(mqttClient.remoteIP()); + isMqttServerAddressPrivate = isPrivateIpAddress(mqttClient->remoteIP()); publishNodeInfo(); sendSubscriptions(); diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h index cb1fffcc9..cf52ad877 100644 --- a/src/mqtt/MQTT.h +++ b/src/mqtt/MQTT.h @@ -22,6 +22,7 @@ #if HAS_NETWORKING #include +#include #endif #define MAX_MQTT_QUEUE 16 @@ -32,24 +33,7 @@ */ class MQTT : private concurrency::OSThread { - // supposedly the current version is busted: - // http://www.iotsharing.com/2017/08/how-to-use-esp32-mqtts-with-mqtts-mosquitto-broker-tls-ssl.html -#if HAS_WIFI - WiFiClient mqttClient; -#if !defined(ARCH_PORTDUINO) -#if (defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR < 3) || defined(RPI_PICO) - WiFiClientSecure wifiSecureClient; -#endif -#endif -#endif -#if HAS_ETHERNET - EthernetClient mqttClient; -#endif - public: -#if HAS_NETWORKING - PubSubClient pubSub; -#endif MQTT(); /** @@ -93,7 +77,29 @@ class MQTT : private concurrency::OSThread virtual int32_t runOnce() override; +#ifndef PIO_UNIT_TESTING private: +#endif + // supposedly the current version is busted: + // http://www.iotsharing.com/2017/08/how-to-use-esp32-mqtts-with-mqtts-mosquitto-broker-tls-ssl.html +#if HAS_WIFI + using MQTTClient = WiFiClient; +#if !defined(ARCH_PORTDUINO) +#if (defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR < 3) || defined(RPI_PICO) + WiFiClientSecure wifiSecureClient; +#endif +#endif +#endif +#if HAS_ETHERNET + using MQTTClient = EthernetClient; +#endif + +#if HAS_NETWORKING + std::unique_ptr mqttClient; + PubSubClient pubSub; + explicit MQTT(std::unique_ptr mqttClient); +#endif + std::string cryptTopic = "/2/e/"; // msh/2/e/CHANNELID/NODEID std::string jsonTopic = "/2/json/"; // msh/2/json/CHANNELID/NODEID std::string mapTopic = "/2/map/"; // For protobuf-encoded MapReport messages From 9bda080e3d0be0f025f88d36bb4a9aa605954fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Thu, 2 Jan 2025 16:05:12 +0100 Subject: [PATCH 09/11] evaluate GPS_THREAD_INTERVAL after variant file (#5722) --- src/configuration.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/configuration.h b/src/configuration.h index 994f1e72e..2c77b55e3 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -178,13 +178,6 @@ along with this program. If not, see . #define TCA9535_ADDR 0x20 #define TCA9555_ADDR 0x26 -// ----------------------------------------------------------------------------- -// GPS -// ----------------------------------------------------------------------------- -#ifndef GPS_THREAD_INTERVAL -#define GPS_THREAD_INTERVAL 200 -#endif - // ----------------------------------------------------------------------------- // Touchscreen // ----------------------------------------------------------------------------- @@ -206,6 +199,10 @@ along with this program. If not, see . #define VEXT_ON_VALUE LOW #endif +// ----------------------------------------------------------------------------- +// GPS +// ----------------------------------------------------------------------------- + #ifndef GPS_BAUDRATE #define GPS_BAUDRATE 9600 #define GPS_BAUDRATE_FIXED 0 @@ -213,6 +210,10 @@ along with this program. If not, see . #define GPS_BAUDRATE_FIXED 1 #endif +#ifndef GPS_THREAD_INTERVAL +#define GPS_THREAD_INTERVAL 200 +#endif + /* Step #2: follow with defines common to the architecture; also enable HAS_ option not specifically disabled by variant.h */ #include "architecture.h" From b41efc17ba60a0f4b93cf85fe0c1b08070aeb67e Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Thu, 2 Jan 2025 08:32:38 -0800 Subject: [PATCH 10/11] Disable BUILD_EPOCH for unit tests (#5723) --- .github/workflows/test_native.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test_native.yml b/.github/workflows/test_native.yml index 8c1527279..d016635ef 100644 --- a/.github/workflows/test_native.yml +++ b/.github/workflows/test_native.yml @@ -84,6 +84,11 @@ jobs: run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT id: version + # Disable (comment-out) BUILD_EPOCH. It causes a full rebuild between tests and resets the + # coverage information each time. + - name: Disable BUILD_EPOCH + run: sed -i 's/-DBUILD_EPOCH=$UNIX_TIME/#-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini + - name: PlatformIO Tests run: platformio test -e coverage --junit-output-path testreport.xml From 9d710041c43af266dc0e32703e39775bb1f4929e Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Fri, 3 Jan 2025 09:01:10 +0800 Subject: [PATCH 11/11] Add MESHTASTIC_EXCLUDE_SOCKETAPI (#5729) MESHTASTIC_EXCLUDE_SOCKETAPI disables the API Server when set. Co-authored-by: mverch67 Co-authored-by: GUVWAF --- src/mesh/eth/ethClient.cpp | 3 ++- src/mesh/wifi/WiFiAPClient.cpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mesh/eth/ethClient.cpp b/src/mesh/eth/ethClient.cpp index 08ecb7ce8..24c4f0db1 100644 --- a/src/mesh/eth/ethClient.cpp +++ b/src/mesh/eth/ethClient.cpp @@ -66,8 +66,9 @@ static int32_t reconnectETH() syslog.enable(); } - // initWebServer(); +#if !MESHTASTIC_EXCLUDE_SOCKETAPI initApiServer(); +#endif ethStartupComplete = true; } diff --git a/src/mesh/wifi/WiFiAPClient.cpp b/src/mesh/wifi/WiFiAPClient.cpp index 38aa2e2a2..2f8138921 100644 --- a/src/mesh/wifi/WiFiAPClient.cpp +++ b/src/mesh/wifi/WiFiAPClient.cpp @@ -106,7 +106,9 @@ static void onNetworkConnected() #if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WEBSERVER initWebServer(); #endif +#if !MESHTASTIC_EXCLUDE_SOCKETAPI initApiServer(); +#endif APStartupComplete = true; }