From e4ab8a78b3a5b9e472380d105bbbd813c3d56519 Mon Sep 17 00:00:00 2001 From: Naoki Iwakami Date: Fri, 29 Aug 2025 05:24:49 +0000 Subject: [PATCH] Add gtest cases for ISR --- wiringPi/gtest/.gitignore | 2 + wiringPi/gtest/Makefile | 92 ++++++++++++ wiringPi/gtest/README.md | 26 ++++ wiringPi/gtest/run_isr.cpp | 31 ++++ wiringPi/gtest/test_isr_both.cpp | 51 +++++++ .../test_isr_conflict_between_processes.cpp | 68 +++++++++ wiringPi/gtest/test_isr_falling.cpp | 57 ++++++++ wiringPi/gtest/test_isr_restart.cpp | 67 +++++++++ wiringPi/gtest/test_isr_restart2.cpp | 109 ++++++++++++++ wiringPi/gtest/test_isr_rising.cpp | 80 +++++++++++ wiringPi/gtest/test_isr_rising2.cpp | 135 ++++++++++++++++++ 11 files changed, 718 insertions(+) create mode 100644 wiringPi/gtest/.gitignore create mode 100644 wiringPi/gtest/Makefile create mode 100644 wiringPi/gtest/README.md create mode 100644 wiringPi/gtest/run_isr.cpp create mode 100644 wiringPi/gtest/test_isr_both.cpp create mode 100644 wiringPi/gtest/test_isr_conflict_between_processes.cpp create mode 100644 wiringPi/gtest/test_isr_falling.cpp create mode 100644 wiringPi/gtest/test_isr_restart.cpp create mode 100644 wiringPi/gtest/test_isr_restart2.cpp create mode 100644 wiringPi/gtest/test_isr_rising.cpp create mode 100644 wiringPi/gtest/test_isr_rising2.cpp diff --git a/wiringPi/gtest/.gitignore b/wiringPi/gtest/.gitignore new file mode 100644 index 0000000..b868581 --- /dev/null +++ b/wiringPi/gtest/.gitignore @@ -0,0 +1,2 @@ +bin +googletest-main diff --git a/wiringPi/gtest/Makefile b/wiringPi/gtest/Makefile new file mode 100644 index 0000000..87e679c --- /dev/null +++ b/wiringPi/gtest/Makefile @@ -0,0 +1,92 @@ +CXX := g++ +CXXFLAGS := -std=c++17 -Wall -Wextra -Werror -g \ + -Igoogletest-main/googletest/include -Igoogletest-main/googlemock/include +LDFLAGS := -pthread +WIRING_PI_LIBS := -lwiringPi + +# Where to download googletest +GTEST_URL := https://github.com/google/googletest/archive/refs/heads/main.zip +GTEST_ZIP := googletest.zip +GTEST_DIR := googletest-main + +# Output directory +BIN_DIR := bin + +# Helper program +RUN_ISR_SRC := run_isr.cpp +RUN_ISR_BIN := $(BIN_DIR)/run_isr + +# Need BCM1 <-> BCM12 connection +TEST_SRCS := \ + test_isr_both.cpp \ + test_isr_conflict_between_processes.cpp \ + test_isr_falling.cpp \ + test_isr_restart.cpp \ + test_isr_restart2.cpp \ + test_isr_rising.cpp \ + test_isr_rising2.cpp + +# Derive test binaries (in bin/) +TEST_BINS := $(addprefix $(BIN_DIR)/, $(TEST_SRCS:.cpp=)) + +# gtest/gmock sources +GTEST_SRCS := $(GTEST_DIR)/googletest/src/gtest-all.cc +GMOCK_SRCS := $(GTEST_DIR)/googlemock/src/gmock-all.cc +GTEST_MAIN := $(GTEST_DIR)/googletest/src/gtest_main.cc +GTEST_INCLUDES := -I$(GTEST_DIR)/googletest/include -I$(GTEST_DIR)/googlemock/include + +GTEST_OBJS := $(GTEST_SRCS:.cc=.o) +GMOCK_OBJS := $(GMOCK_SRCS:.cc=.o) +GTEST_MAIN_OBJ := $(GTEST_MAIN:.cc=.o) + +# Default: build everything +all: $(GTEST_DIR) $(BIN_DIR) $(TEST_BINS) $(RUN_ISR_BIN) + +# Rule: build normal test binaries +$(filter-out $(BIN_DIR)/test_conflict_between_processes,$(TEST_BINS)): $(BIN_DIR)/%: %.cpp $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ) + $(CXX) $(CXXFLAGS) $< $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ) -o $@ $(LDFLAGS) $(WIRING_PI_LIBS) + +# Special case: test_conflict_between_processes depends on run_isr +$(BIN_DIR)/test_conflict_between_processes: test_conflict_between_processes.cpp $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ) $(RUN_ISR_BIN) + $(CXX) $(CXXFLAGS) $< $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ) -o $@ $(LDFLAGS) $(WIRING_PI_LIBS) + +# Build run_isr +$(RUN_ISR_BIN): $(RUN_ISR_SRC) | $(BIN_DIR) + $(CXX) $(CXXFLAGS) $< -o $@ $(WIRING_PI_LIBS) + +# Ensure bin directory exists +$(BIN_DIR): + mkdir -p $(BIN_DIR) + +# Download googletest if not already present +$(GTEST_DIR): + @echo "Downloading GoogleTest..." + curl -L $(GTEST_URL) -o $(GTEST_ZIP) + unzip -q $(GTEST_ZIP) + rm -f $(GTEST_ZIP) + +# Generic rules for compiling gtest/gmock sources +%.o: %.cc + $(CXX) $(CXXFLAGS) $(GTEST_INCLUDES) -I$(GTEST_DIR)/googletest -I$(GTEST_DIR)/googlemock -c $< -o $@ + +# Run all tests +test: all + @failed=0; \ + for t in $(TEST_BINS); do \ + echo "Running $$t..."; \ + ./$$t || failed=1; \ + done; \ + if [ $$failed -eq 0 ]; then \ + echo "✅ All tests passed."; \ + else \ + echo "❌ Some tests failed."; \ + exit 1; \ + fi + +clean: + rm -f $(TEST_BINS) $(RUN_ISR_BIN) + +distclean: clean + rm -rf $(GTEST_DIR) $(BIN_DIR) + +.PHONY: all clean distclean test \ No newline at end of file diff --git a/wiringPi/gtest/README.md b/wiringPi/gtest/README.md new file mode 100644 index 0000000..e4c277d --- /dev/null +++ b/wiringPi/gtest/README.md @@ -0,0 +1,26 @@ +## Quick Start + +g++ is required to build the test cases. + +Connect wPi pin 31 (BCM 1) and wPi pin 26 (BCM 12) to run ISR tests. +Also, wPi pin 28 (BCM 20) should be unconnected. + +Run `make test` or do following to run the test: + +``` +make googletest-main +make -j 4 +make test +``` + +To clean up the environment: + +``` +make clean +``` + +## Dependencies + +Googletest is downloaded during +the build for the first time. The downloaded items are in directory `googletest-main`. `make clean` keeps this directory. Run `make distclean` +to erase all built images including googletest. diff --git a/wiringPi/gtest/run_isr.cpp b/wiringPi/gtest/run_isr.cpp new file mode 100644 index 0000000..8f4a61b --- /dev/null +++ b/wiringPi/gtest/run_isr.cpp @@ -0,0 +1,31 @@ +/* + * Helper program of test_conflict_between_processes. + * + * The program configures ISR on pin 31 (BCM 1) and polls for a termination request. + */ +#include +#include +#include + +#define LISTENER_PIN 31 // BCM 1 + +static uint8_t ok_to_stop = 0; +static void noop() { + fprintf(stderr, "interrupted\n"); + ok_to_stop = 1; +} + +int main(int, char *[]) { + fprintf(stderr, "start\n"); + wiringPiSetup(); + if (wiringPiISR(LISTENER_PIN, INT_EDGE_RISING, noop)) { + fprintf(stderr, "failed to start listener\n"); + return -1; + } + fprintf(stderr, "start listening\n"); + + while (!ok_to_stop) { + delay(1000); + } + fprintf(stderr, "bye\n"); +} \ No newline at end of file diff --git a/wiringPi/gtest/test_isr_both.cpp b/wiringPi/gtest/test_isr_both.cpp new file mode 100644 index 0000000..09fb58d --- /dev/null +++ b/wiringPi/gtest/test_isr_both.cpp @@ -0,0 +1,51 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 + +/** + * Tests ISR for both edges. + */ +class ISRBoth : public ::testing::Test { + public: + static void SetUpTestSuite() { + wiringPiSetup(); + pinMode(TRIGGER_PIN, OUTPUT); + digitalWrite(TRIGGER_PIN, LOW); + wiringPiISR(LISTENER_PIN, INT_EDGE_BOTH, ISRBoth::TriggerCount); + delay(100); + } + + static uint32_t count; + static void TriggerCount() { ++count; } + + protected: + virtual void SetUp() { count = 0; } + + virtual void TearDown() { + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + } +}; + +uint32_t ISRBoth::count = 0; + +TEST_F(ISRBoth, Fundamental) { + EXPECT_EQ(count, 0u); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1u); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 2u); +} + +TEST_F(ISRBoth, ThreeTriggers) { + for (int i = 0; i < 5; ++i) { + digitalWrite(TRIGGER_PIN, (i + 1) % 2); + delay(10); + } + EXPECT_EQ(count, 5u); +} \ No newline at end of file diff --git a/wiringPi/gtest/test_isr_conflict_between_processes.cpp b/wiringPi/gtest/test_isr_conflict_between_processes.cpp new file mode 100644 index 0000000..31f954b --- /dev/null +++ b/wiringPi/gtest/test_isr_conflict_between_processes.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 +#define ANOTHER_LISTENER_PIN 28 // BCM 20 + +static void *remote_isr(void *) { + std::system("./bin/run_isr"); + return NULL; +} + +/** + * Tests ISR setup conflict between two processes. + * + * Another program 'run_isr' starts first that occupies the pin 31 for an ISR. + * This program should fail to start ISR on the same pin. + */ +class ISRConflict : public ::testing::Test { + public: + static void SetUpTestSuite() { + wiringPiSetup(); + digitalWrite(TRIGGER_PIN, LOW); + + pthread_t tid; + pthread_create(&tid, NULL, remote_isr, NULL); + delay(1000); + } + + static void TearDownTestSuite() { + delay(1000); + } + + static uint32_t count; + + static void TriggerCount() { ++count; } + static void TriggerCount2(WPIWfiStatus, void *userdata) { + ++*(uint32_t *)userdata; + } + + protected: + virtual void SetUp() { count = 0; } + + virtual void TearDown() { + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + } +}; + +uint32_t ISRConflict::count = 0; + +TEST_F(ISRConflict, TestConflictBetweenProcesses) { + // The ISRs should fail to start because run_isr is listening on the + // same port + EXPECT_EQ( + wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRConflict::TriggerCount), + -1); + EXPECT_EQ(wiringPiISR2(LISTENER_PIN, INT_EDGE_FALLING, + ISRConflict::TriggerCount2, 0, &ISRConflict::count), + -1); + + // to exit run_isr + digitalWrite(TRIGGER_PIN, HIGH); +} diff --git a/wiringPi/gtest/test_isr_falling.cpp b/wiringPi/gtest/test_isr_falling.cpp new file mode 100644 index 0000000..bfda8c0 --- /dev/null +++ b/wiringPi/gtest/test_isr_falling.cpp @@ -0,0 +1,57 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 + +/** + * Tests ISR for falling edges. + */ +class ISRFalling : public ::testing::Test { + public: + static void SetUpTestSuite() { + wiringPiSetup(); + pinMode(TRIGGER_PIN, OUTPUT); + digitalWrite(TRIGGER_PIN, HIGH); + wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRFalling::TriggerCount); + delay(100); + } + + static void TearDownTestSuite() { digitalWrite(TRIGGER_PIN, LOW); } + + static uint32_t count; + static void TriggerCount() { ++count; } + + protected: + virtual void SetUp() { count = 0; } + + virtual void TearDown() { + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + } +}; + +uint32_t ISRFalling::count = 0; + +TEST_F(ISRFalling, Fundamental) { + EXPECT_EQ(count, 0u); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 1u); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1u); +} + +TEST_F(ISRFalling, ThreeTriggers) { + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + count = 0; + for (int i = 0; i < 6; ++i) { + delay(10); + digitalWrite(TRIGGER_PIN, (i + 1) % 2); + } + delay(10); + EXPECT_EQ(count, 3u); +} \ No newline at end of file diff --git a/wiringPi/gtest/test_isr_restart.cpp b/wiringPi/gtest/test_isr_restart.cpp new file mode 100644 index 0000000..c7a5c7a --- /dev/null +++ b/wiringPi/gtest/test_isr_restart.cpp @@ -0,0 +1,67 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 +#define ANOTHER_LISTENER_PIN 28 // BCM 20 + +/** + * Tests restarting ISR. + */ +class ISRRestart : public ::testing::Test { + public: + static void SetUpTestSuite() { + wiringPiSetup(); + pinMode(TRIGGER_PIN, OUTPUT); + digitalWrite(TRIGGER_PIN, LOW); + wiringPiISR(LISTENER_PIN, INT_EDGE_RISING, ISRRestart::TriggerCount); + delay(100); + } + + static uint32_t count; + + static void TriggerCount() { ++count; } + + static void TriggerCountDown() { --count; } + + protected: + virtual void SetUp() { count = 0; } + + virtual void TearDown() { + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + } +}; + +uint32_t ISRRestart::count = 0; + +TEST_F(ISRRestart, RestartISR) { + // fundamental ISR test + EXPECT_EQ(count, 0u); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1u); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 1u); + + // stop the ISR + EXPECT_EQ(wiringPiISRStop(LISTENER_PIN), 0); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1u); + digitalWrite(TRIGGER_PIN, LOW); + + // start another ISR on the same pin + EXPECT_EQ( + wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRRestart::TriggerCountDown), + 0); + delay(100); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1u); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 0u); +} diff --git a/wiringPi/gtest/test_isr_restart2.cpp b/wiringPi/gtest/test_isr_restart2.cpp new file mode 100644 index 0000000..173d3d5 --- /dev/null +++ b/wiringPi/gtest/test_isr_restart2.cpp @@ -0,0 +1,109 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 +#define ANOTHER_LISTENER_PIN 28 // BCM 20 + +struct counters { + int32_t *primary; + int32_t *secondary; +}; + +/** + * Tests restarting ISR using function wiringPiISR2(). + */ +class ISRRestart2 : public ::testing::Test { + public: + static void SetUpTestSuite() { + wiringPiSetup(); + pinMode(TRIGGER_PIN, OUTPUT); + digitalWrite(TRIGGER_PIN, LOW); + counters_a.primary = &count; + counters_a.secondary = &count2; + counters_b.primary = &count; + counters_b.secondary = &count3; + wiringPiISR2(LISTENER_PIN, INT_EDGE_RISING, ISRRestart2::TriggerCount, 1000, + &counters_a); + delay(100); + } + + static int32_t count; + static int32_t count2; + static int32_t count3; + + static counters counters_a; + static counters counters_b; + + static void TriggerCount(WPIWfiStatus, void *userdata) { + struct counters *counters = (struct counters *)userdata; + ++*counters->primary; + ++*counters->secondary; + } + + static void TriggerCountDown(WPIWfiStatus, void *userdata) { + struct counters *counters = (struct counters *)userdata; + ++*counters->primary; + --*counters->secondary; + } + + protected: + virtual void SetUp() { + count = 0; + count2 = 0; + count3 = 0; + } + + virtual void TearDown() { + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + } +}; + +int32_t ISRRestart2::count = 0; +int32_t ISRRestart2::count2 = 0; +int32_t ISRRestart2::count3 = 0; +struct counters ISRRestart2::counters_a; +struct counters ISRRestart2::counters_b; + +TEST_F(ISRRestart2, RestartISR2) { + // fundamental ISR2 test + EXPECT_EQ(count, 0); + EXPECT_EQ(count2, 0); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1); + EXPECT_EQ(count2, 1); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 1); + EXPECT_EQ(count2, 1); + + // stop the ISR + EXPECT_EQ(wiringPiISRStop(LISTENER_PIN), 0); + delay(100); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1); + EXPECT_EQ(count2, 1); + EXPECT_EQ(count3, 0); + digitalWrite(TRIGGER_PIN, LOW); + + // start another ISR2 on the same pin + EXPECT_EQ(wiringPiISR2(LISTENER_PIN, INT_EDGE_FALLING, + ISRRestart2::TriggerCountDown, 0, &counters_b), + 0); + delay(100); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1); + EXPECT_EQ(count2, 1); + EXPECT_EQ(count3, 0); + + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 2); + EXPECT_EQ(count2, 1); + EXPECT_EQ(count3, -1); +} diff --git a/wiringPi/gtest/test_isr_rising.cpp b/wiringPi/gtest/test_isr_rising.cpp new file mode 100644 index 0000000..9a41b14 --- /dev/null +++ b/wiringPi/gtest/test_isr_rising.cpp @@ -0,0 +1,80 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 +#define ANOTHER_LISTENER_PIN 28 // BCM 20 + +/** + * Tests ISR for rising edges. + */ +class ISRRising : public ::testing::Test { + public: + static void SetUpTestSuite() { + wiringPiSetup(); + pinMode(TRIGGER_PIN, OUTPUT); + digitalWrite(TRIGGER_PIN, LOW); + wiringPiISR(LISTENER_PIN, INT_EDGE_RISING, ISRRising::TriggerCount); + delay(100); + } + + static uint32_t count; + + static void TriggerCount() { ++count; } + + static void TriggerCountDown() { --count; } + + protected: + virtual void SetUp() { count = 0; } + + virtual void TearDown() { + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + } +}; + +uint32_t ISRRising::count = 0; + +TEST_F(ISRRising, Fundamental) { + EXPECT_EQ(count, 0u); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1u); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 1u); +} + +TEST_F(ISRRising, ThreeTriggers) { + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + count = 0; + for (int i = 0; i < 6; ++i) { + delay(10); + digitalWrite(TRIGGER_PIN, i % 2); + } + delay(10); + EXPECT_EQ(count, 3u); +} + +TEST_F(ISRRising, ISRInitConflict) { + // this initialization should fail for ISR conflict + EXPECT_EQ( + wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRRising::TriggerCountDown), + -1); + // ensure the initialization above has released the mutex lock + EXPECT_EQ(wiringPiISR(ANOTHER_LISTENER_PIN, INT_EDGE_RISING, + ISRRising::TriggerCountDown), + 0); + delay(100); + + // ensure the existing ISR has not broken + EXPECT_EQ(count, 0u); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1u); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 1u); +} diff --git a/wiringPi/gtest/test_isr_rising2.cpp b/wiringPi/gtest/test_isr_rising2.cpp new file mode 100644 index 0000000..b40ea4c --- /dev/null +++ b/wiringPi/gtest/test_isr_rising2.cpp @@ -0,0 +1,135 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 +#define ANOTHER_LISTENER_PIN 28 // BCM 20 + +struct counters { + uint32_t *primary; + uint32_t *secondary; +}; + +/** + * Tests ISR for rising edges. + * Function wiringPiISR2 is used for the configuraiton. + */ +class ISRRising2 : public ::testing::Test { + public: + static void SetUpTestSuite() { + wiringPiSetup(); + pinMode(TRIGGER_PIN, OUTPUT); + digitalWrite(TRIGGER_PIN, LOW); + counters_a.primary = &count; + counters_a.secondary = &count2; + counters_b.primary = &count; + counters_b.secondary = &count3; + wiringPiISR2(LISTENER_PIN, INT_EDGE_RISING, ISRRising2::TriggerCount, 1000, + &counters_a); + delay(100); + } + + static uint32_t count; + static uint32_t count2; + static uint32_t count3; + + static counters counters_a; + static counters counters_b; + + static void TriggerCount(WPIWfiStatus, void *userdata) { + struct counters *counters = (struct counters *)userdata; + ++*counters->primary; + ++*counters->secondary; + } + + static void TriggerCountDown(WPIWfiStatus, void *userdata) { + struct counters *counters = (struct counters *)userdata; + ++*counters->primary; + --*counters->secondary; + } + + protected: + virtual void SetUp() { + count = 0; + count2 = 0; + count3 = 0; + } + + virtual void TearDown() { + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + } +}; + +uint32_t ISRRising2::count = 0; +uint32_t ISRRising2::count2 = 0; +uint32_t ISRRising2::count3 = 0; +struct counters ISRRising2::counters_a; +struct counters ISRRising2::counters_b; + +TEST_F(ISRRising2, Fundamental) { + EXPECT_EQ(count, 0u); + EXPECT_EQ(count2, 0u); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1u); + EXPECT_EQ(count2, 1u); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 1u); + EXPECT_EQ(count2, 1u); +} + +TEST_F(ISRRising2, ThreeTriggers) { + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + count = 0; + for (int i = 0; i < 6; ++i) { + delay(10); + digitalWrite(TRIGGER_PIN, i % 2); + } + delay(10); + EXPECT_EQ(count, 3u); +} + +TEST_F(ISRRising2, Debounce) { + delay(10); + for (int i = 0; i < 7; ++i) { + digitalWrite(TRIGGER_PIN, (i + 1) % 2); + } + delay(10); + EXPECT_EQ(count, 1u); +} + +TEST_F(ISRRising2, ISRInitConflict) { + // this initialization should fail for ISR conflict + EXPECT_EQ(wiringPiISR2(LISTENER_PIN, INT_EDGE_FALLING, + ISRRising2::TriggerCountDown, 0, &counters_b), + -1); + // ensure the initialization above has released the mutex lock + EXPECT_EQ(wiringPiISR2(ANOTHER_LISTENER_PIN, INT_EDGE_BOTH, + ISRRising2::TriggerCountDown, 0, &counters_b), + 0); + delay(100); + + // ensure the existing ISR has not broken + EXPECT_EQ(count, 0u); + EXPECT_EQ(count2, 0u); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1u); + EXPECT_EQ(count2, 1u); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 1u); + EXPECT_EQ(count2, 1u); + + delay(10); + count = 0; + for (int i = 0; i < 7; ++i) { + digitalWrite(TRIGGER_PIN, (i + 1) % 2); + } + delay(10); + EXPECT_EQ(count, 1u); +}