Anvil v1.0.0 -- Arduino build tool with HAL and test scaffolding
Single-binary CLI that scaffolds testable Arduino projects, compiles, uploads, and monitors serial output. Templates embed a hardware abstraction layer, Google Mock infrastructure, and CMake-based host tests so application logic can be verified without hardware. Commands: new, doctor, setup, devices, build, upload, monitor 39 Rust tests (21 unit, 18 integration) Cross-platform: Linux and Windows
This commit is contained in:
124
templates/basic/test/test_unit.cpp.tmpl
Normal file
124
templates/basic/test/test_unit.cpp.tmpl
Normal file
@@ -0,0 +1,124 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "hal.h"
|
||||
#include "mock_hal.h"
|
||||
#include "{{PROJECT_NAME}}_app.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::AnyNumber;
|
||||
using ::testing::Return;
|
||||
using ::testing::HasSubstr;
|
||||
|
||||
// ============================================================================
|
||||
// Unit Tests -- verify exact HAL interactions
|
||||
// ============================================================================
|
||||
|
||||
class BlinkAppUnitTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
ON_CALL(mock_, millis()).WillByDefault(Return(0));
|
||||
ON_CALL(mock_, digitalRead(_)).WillByDefault(Return(HIGH));
|
||||
EXPECT_CALL(mock_, serialBegin(_)).Times(AnyNumber());
|
||||
EXPECT_CALL(mock_, serialPrintln(_)).Times(AnyNumber());
|
||||
EXPECT_CALL(mock_, millis()).Times(AnyNumber());
|
||||
}
|
||||
|
||||
::testing::NiceMock<MockHal> mock_;
|
||||
};
|
||||
|
||||
TEST_F(BlinkAppUnitTest, BeginConfiguresPins) {
|
||||
BlinkApp app(&mock_, 13, 2);
|
||||
|
||||
EXPECT_CALL(mock_, pinMode(13, OUTPUT)).Times(1);
|
||||
EXPECT_CALL(mock_, pinMode(2, INPUT_PULLUP)).Times(1);
|
||||
EXPECT_CALL(mock_, serialBegin(115200)).Times(1);
|
||||
|
||||
app.begin();
|
||||
}
|
||||
|
||||
TEST_F(BlinkAppUnitTest, StartsInSlowMode) {
|
||||
BlinkApp app(&mock_);
|
||||
app.begin();
|
||||
|
||||
EXPECT_FALSE(app.fastMode());
|
||||
EXPECT_EQ(app.interval(), BlinkApp::SLOW_INTERVAL_MS);
|
||||
}
|
||||
|
||||
TEST_F(BlinkAppUnitTest, TogglesLedAfterInterval) {
|
||||
BlinkApp app(&mock_);
|
||||
|
||||
ON_CALL(mock_, millis()).WillByDefault(Return(0));
|
||||
app.begin();
|
||||
|
||||
ON_CALL(mock_, millis()).WillByDefault(Return(500));
|
||||
EXPECT_CALL(mock_, digitalWrite(13, _)).Times(1);
|
||||
app.update();
|
||||
}
|
||||
|
||||
TEST_F(BlinkAppUnitTest, DoesNotToggleBeforeInterval) {
|
||||
BlinkApp app(&mock_);
|
||||
|
||||
ON_CALL(mock_, millis()).WillByDefault(Return(0));
|
||||
app.begin();
|
||||
|
||||
ON_CALL(mock_, millis()).WillByDefault(Return(499));
|
||||
EXPECT_CALL(mock_, digitalWrite(_, _)).Times(0);
|
||||
app.update();
|
||||
}
|
||||
|
||||
TEST_F(BlinkAppUnitTest, ButtonPressSwitchesToFastMode) {
|
||||
BlinkApp app(&mock_, 13, 2);
|
||||
|
||||
ON_CALL(mock_, millis()).WillByDefault(Return(0));
|
||||
ON_CALL(mock_, digitalRead(2)).WillByDefault(Return(HIGH));
|
||||
app.begin();
|
||||
|
||||
ON_CALL(mock_, digitalRead(2)).WillByDefault(Return(LOW));
|
||||
EXPECT_CALL(mock_, serialPrintln(HasSubstr("FAST"))).Times(1);
|
||||
app.update();
|
||||
|
||||
EXPECT_TRUE(app.fastMode());
|
||||
EXPECT_EQ(app.interval(), BlinkApp::FAST_INTERVAL_MS);
|
||||
}
|
||||
|
||||
TEST_F(BlinkAppUnitTest, SecondButtonPressReturnsToSlowMode) {
|
||||
BlinkApp app(&mock_, 13, 2);
|
||||
|
||||
ON_CALL(mock_, millis()).WillByDefault(Return(0));
|
||||
ON_CALL(mock_, digitalRead(2)).WillByDefault(Return(HIGH));
|
||||
app.begin();
|
||||
|
||||
// First press: fast mode
|
||||
ON_CALL(mock_, digitalRead(2)).WillByDefault(Return(LOW));
|
||||
app.update();
|
||||
EXPECT_TRUE(app.fastMode());
|
||||
|
||||
// Release
|
||||
ON_CALL(mock_, digitalRead(2)).WillByDefault(Return(HIGH));
|
||||
app.update();
|
||||
|
||||
// Second press: back to slow
|
||||
ON_CALL(mock_, digitalRead(2)).WillByDefault(Return(LOW));
|
||||
EXPECT_CALL(mock_, serialPrintln(HasSubstr("SLOW"))).Times(1);
|
||||
app.update();
|
||||
|
||||
EXPECT_FALSE(app.fastMode());
|
||||
}
|
||||
|
||||
TEST_F(BlinkAppUnitTest, HoldingButtonDoesNotRepeatToggle) {
|
||||
BlinkApp app(&mock_, 13, 2);
|
||||
|
||||
ON_CALL(mock_, millis()).WillByDefault(Return(0));
|
||||
ON_CALL(mock_, digitalRead(2)).WillByDefault(Return(HIGH));
|
||||
app.begin();
|
||||
|
||||
ON_CALL(mock_, digitalRead(2)).WillByDefault(Return(LOW));
|
||||
app.update();
|
||||
EXPECT_TRUE(app.fastMode());
|
||||
|
||||
// Still held -- should NOT toggle again
|
||||
app.update();
|
||||
app.update();
|
||||
EXPECT_TRUE(app.fastMode());
|
||||
}
|
||||
Reference in New Issue
Block a user