Bidirectional test mode signaling over GPIO
* Implements a bidirectional synchronous handshake protocol over
dut_flaga/b GPIOs. This protocol is designed to return true (test
mode) only if the DUT is connected to a servo board which implements
the remote end.
* Includes unit tests for the test mode signaling routine, complete with
mock/fake implementation of the remote end.
Note that we still do not deploy GpioHandler in actual update
processing, which will be done later.
BUG=chromium-os:25397,chromium-os:27109,chromium-os:27672
TEST=Builds and passes unit tests (including new ones)
Change-Id: I265407ed735c3e1354e10782ac30566b16caeb20
Reviewed-on: https://gerrit.chromium.org/gerrit/23330
Reviewed-by: Gaurav Shah <gauravsh@chromium.org>
Tested-by: Gilad Arnold <garnold@chromium.org>
Commit-Ready: Gilad Arnold <garnold@chromium.org>
Reviewed-by: Gilad Arnold <garnold@chromium.org>
diff --git a/gpio_handler_unittest.cc b/gpio_handler_unittest.cc
index a133ac7..53ffb61 100644
--- a/gpio_handler_unittest.cc
+++ b/gpio_handler_unittest.cc
@@ -5,15 +5,9 @@
#include <gtest/gtest.h>
#include "update_engine/gpio_handler.h"
+#include "update_engine/gpio_mock_file_descriptor.h"
#include "update_engine/gpio_mock_udev_interface.h"
-// Some common strings used by the different cooperating mocks for this module.
-// We use preprocessor constants to allow concatenation at compile-time.
-#define MOCK_GPIO_CHIP_ID "100"
-#define MOCK_DUTFLAGA_GPIO_ID "101"
-#define MOCK_DUTFLAGB_GPIO_ID "102"
-#define MOCK_SYSFS_PREFIX "/mock/sys/class/gpio"
-
namespace chromeos_update_engine {
class StandardGpioHandlerTest : public ::testing::Test {};
@@ -23,7 +17,10 @@
// all udev resources are deallocated afterwards. The mock file descriptor is
// not to be used.
StandardGpioMockUdevInterface mock_udev;
- StandardGpioHandler gpio_hander(&mock_udev, false);
+ TestModeGpioMockFileDescriptor
+ mock_file_descriptor(base::TimeDelta::FromSeconds(1));
+ StandardGpioHandler gpio_hander(&mock_udev, &mock_file_descriptor,
+ false, false);
mock_udev.ExpectAllResourcesDeallocated();
mock_udev.ExpectDiscoverySuccess();
}
@@ -32,27 +29,230 @@
// Attempt GPIO discovery with a udev mock that returns two GPIO chip devices.
// It should fail, of course. The mock file descriptor is not to be used.
MultiChipGpioMockUdevInterface mock_udev;
- StandardGpioHandler gpio_handler(&mock_udev, false);
+ TestModeGpioMockFileDescriptor
+ mock_file_descriptor(base::TimeDelta::FromSeconds(1));
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
mock_udev.ExpectAllResourcesDeallocated();
mock_udev.ExpectDiscoveryFail();
}
+TEST(StandardGpioHandlerTest, TestModeGpioSignalingTest) {
+ // Initialize the GPIO module and test for successful completion of the test
+ // signaling protocol.
+ StandardGpioMockUdevInterface mock_udev;
+ TestModeGpioMockFileDescriptor
+ mock_file_descriptor(base::TimeDelta::FromSeconds(1));
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
+ EXPECT_TRUE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
+TEST(StandardGpioHandlerTest, DeferredInitTestModeGpioSignalingTest) {
+ // Initialize the GPIO module with deferred initialization, test for
+ // successful completion of the test signaling protocol.
+ StandardGpioMockUdevInterface mock_udev;
+ TestModeGpioMockFileDescriptor
+ mock_file_descriptor(base::TimeDelta::FromSeconds(1));
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ true, false);
+ EXPECT_TRUE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
+TEST(StandardGpioHandlerTest, TestModeGpioSignalingTwiceTest) {
+ // Initialize the GPIO module and query for test signal twice (uncached); the
+ // first query should succeed whereas the second should fail.
+ StandardGpioMockUdevInterface mock_udev;
+ TestModeGpioMockFileDescriptor
+ mock_file_descriptor(base::TimeDelta::FromSeconds(1));
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
+ EXPECT_TRUE(gpio_handler.IsTestModeSignaled());
+ EXPECT_FALSE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
+TEST(StandardGpioHandlerTest, TestModeGpioSignalingTwiceCachedTest) {
+ // Initialize the GPIO module and query for test signal twice (cached); both
+ // queries should succeed.
+ StandardGpioMockUdevInterface mock_udev;
+ TestModeGpioMockFileDescriptor
+ mock_file_descriptor(base::TimeDelta::FromSeconds(1));
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, true);
+ EXPECT_TRUE(gpio_handler.IsTestModeSignaled());
+ EXPECT_TRUE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
TEST(StandardGpioHandlerTest, NormalModeGpioSignalingTest) {
// Initialize the GPIO module, run the signaling procedure, ensure that it
// concluded that this is a normal mode run.
StandardGpioMockUdevInterface mock_udev;
- StandardGpioHandler gpio_handler(&mock_udev, false);
+ NormalModeGpioMockFileDescriptor mock_file_descriptor;
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
EXPECT_FALSE(gpio_handler.IsTestModeSignaled());
mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
+TEST(StandardGpioHandlerTest, NonPulledUpNormalModeGpioSignalingTest) {
+ // Initialize the GPIO module with a non-pulled up mock (which means the it
+ // returns a different default signal), run the signaling procedure, ensure
+ // that it concluded that this is a normal mode run.
+ StandardGpioMockUdevInterface mock_udev;
+ NonPulledUpNormalModeGpioMockFileDescriptor mock_file_descriptor;
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
+ EXPECT_FALSE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
}
TEST(StandardGpioHandlerTest, DeferredInitNormalModeGpioSignalingTest) {
// Initialize the GPIO module with deferred discovery, run the signaling
// procedure, ensure that it concluded that this is a normal mode run.
StandardGpioMockUdevInterface mock_udev;
- StandardGpioHandler gpio_handler(&mock_udev, true);
+ NormalModeGpioMockFileDescriptor mock_file_descriptor;
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ true, false);
EXPECT_FALSE(gpio_handler.IsTestModeSignaled());
mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
+TEST(StandardGpioHandlerTest, FlipInputDirErrorNormalModeGpioSignalingTest) {
+ // Test the GPIO module with a mock that simulates a GPIO sysfs race/hack,
+ // which causes the input GPIO to flip direction. Ensure that it concludes
+ // that this is a normal mode run.
+ StandardGpioMockUdevInterface mock_udev;
+ ErrorNormalModeGpioMockFileDescriptor
+ mock_file_descriptor(
+ base::TimeDelta::FromSeconds(1),
+ ErrorNormalModeGpioMockFileDescriptor::kGpioErrorFlipInputDir);
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
+ EXPECT_FALSE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
+TEST(StandardGpioHandlerTest, ReadInvalidValErrorNormalModeGpioSignalingTest) {
+ // Test the GPIO module with a mock that simulates an invalid value reading
+ // from a GPIO device. Ensure that it concludes that this is a normal mode
+ // run.
+ StandardGpioMockUdevInterface mock_udev;
+ ErrorNormalModeGpioMockFileDescriptor
+ mock_file_descriptor(
+ base::TimeDelta::FromSeconds(1),
+ ErrorNormalModeGpioMockFileDescriptor::kGpioErrorReadInvalidVal);
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
+ EXPECT_FALSE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
+TEST(StandardGpioHandlerTest, ReadInvalidDirErrorNormalModeGpioSignalingTest) {
+ // Test the GPIO module with a mock that simulates an invalid value reading
+ // from a GPIO device. Ensure that it concludes that this is a normal mode
+ // run.
+ StandardGpioMockUdevInterface mock_udev;
+ ErrorNormalModeGpioMockFileDescriptor
+ mock_file_descriptor(
+ base::TimeDelta::FromSeconds(1),
+ ErrorNormalModeGpioMockFileDescriptor::kGpioErrorReadInvalidDir);
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
+ EXPECT_FALSE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
+TEST(StandardGpioHandlerTest, FailFileOpenErrorNormalModeGpioSignalingTest) {
+ // Test the GPIO module with a mock that simulates an invalid value reading
+ // from a GPIO device. Ensure that it concludes that this is a normal mode
+ // run.
+ StandardGpioMockUdevInterface mock_udev;
+ ErrorNormalModeGpioMockFileDescriptor
+ mock_file_descriptor(
+ base::TimeDelta::FromSeconds(1),
+ ErrorNormalModeGpioMockFileDescriptor::kGpioErrorFailFileOpen);
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
+ EXPECT_FALSE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
+TEST(StandardGpioHandlerTest, FailFileReadErrorNormalModeGpioSignalingTest) {
+ // Test the GPIO module with a mock that simulates an invalid value reading
+ // from a GPIO device. Ensure that it concludes that this is a normal mode
+ // run.
+ StandardGpioMockUdevInterface mock_udev;
+ ErrorNormalModeGpioMockFileDescriptor
+ mock_file_descriptor(
+ base::TimeDelta::FromSeconds(1),
+ ErrorNormalModeGpioMockFileDescriptor::kGpioErrorFailFileRead);
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
+ EXPECT_FALSE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
+TEST(StandardGpioHandlerTest, FailFileWriteErrorNormalModeGpioSignalingTest) {
+ // Test the GPIO module with a mock that simulates an invalid value reading
+ // from a GPIO device. Ensure that it concludes that this is a normal mode
+ // run.
+ StandardGpioMockUdevInterface mock_udev;
+ ErrorNormalModeGpioMockFileDescriptor
+ mock_file_descriptor(
+ base::TimeDelta::FromSeconds(1),
+ ErrorNormalModeGpioMockFileDescriptor::kGpioErrorFailFileWrite);
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
+ EXPECT_FALSE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllGpiosRestoredToDefault();
+}
+
+TEST(StandardGpioHandlerTest, FailFileCloseErrorNormalModeGpioSignalingTest) {
+ // Test the GPIO module with a mock that simulates an invalid value reading
+ // from a GPIO device. Ensure that it concludes that this is a normal mode
+ // run.
+ StandardGpioMockUdevInterface mock_udev;
+ ErrorNormalModeGpioMockFileDescriptor
+ mock_file_descriptor(
+ base::TimeDelta::FromSeconds(1),
+ ErrorNormalModeGpioMockFileDescriptor::kGpioErrorFailFileClose);
+ StandardGpioHandler gpio_handler(&mock_udev, &mock_file_descriptor,
+ false, false);
+ EXPECT_FALSE(gpio_handler.IsTestModeSignaled());
+ mock_udev.ExpectAllResourcesDeallocated();
+ mock_file_descriptor.ExpectAllResourcesDeallocated();
+ // Don't test GPIO status restored; since closing of sysfs files fails, all
+ // bets are off.
}
} // namespace chromeos_update_engine