I've been studying to do TDD in embedded development. Until now, I've been studying mainly on applications, so I'll try to create something that looks a bit like embedded (assuming embedded Linux). Since it is a close-out departure, the policy may change on the way. You will not know until you actually do it, so please watch with warm eyes.
Feel free to give us your feedback on your opinions and requests! It's very encouraging.
Speaking of built-in, it would be L Chika! However, I want to make it easier to try, so I'll make the LED on the keyboard flicker (such as caps lock). It does not use a high-performance library, but manages by manipulating device files.
If it's too easy, it's too easy, and it's not practical, so I'll think about realizing the next function.
Since it is built-in, always consider portability to another hardware.
OS | Virtual box ubuntu 16.04 |
compiler | gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609 |
Build tool | autotools, pkg-config |
Library | libevdev-1.0 |
Test framework | googletest/googlemock@62ba5d9 |
Product code | C or C++(I am thinking) |
Preliminary research is important for everything you do. For the time being, I will investigate my environment.
To get keyboard input events on Linux, monitor the / dev / input / event 〇〇 file. Numbers are entered in the part of 〇〇, but the number of the keyboard changes in the order recognized in the environment and startup (it is possible to fix it with udev, but this time I will leave it for the time being).
Look in / proc / bus / input / devices to find the keyboard. Currently, event2 (input2) supports keyboards.
cat /proc/bus/input/devices
==Omitted on the way==
I: Bus=0011 Vendor=0001 Product=0001 Version=ab41
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
S: Sysfs=/devices/platform/i8042/serio0/input/input2
U: Uniq=
H: Handlers=sysrq kbd event2 leds
B: PROP=0
B: EV=120013
B: KEY=402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=7
==Omitted below==
For event devices like / dev / input, Linux provides an evdev (Linux Input drivers v1.0) interface. doing. The wrapper library for this evdev is libevdev. This time, we will use this libevdev.
Then check the LEDs on your keyboard. Linux provides an LED class, and when Linux recognizes the LED, it will be exported under / sys / class / leds in sysfs. The LEDs for capslock, numlock, and scrolllock are recognized. (My keyboard doesn't have LEDs on the numlock and scrolllock keys ... need to be investigated)
ls /sys/class/leds/
input2::capslock input2::numlock input2::scrolllock
Since we started from the privileged state of having both hardware (keyboard) and library (libevdev), we will write tests to understand the target library. By writing this test, you will test your library comprehension. It seems very good that what you understand remains as a test.
If this can be done on the host machine, you're lucky.
If it is 1, you can proceed while cross-building obediently. In case 2, if you know the API, let's make a mock. When the real thing comes out, you can test whether the usage written in the test is correct. Imagine making a mock if you don't understand the API. Creating a mock without knowing the implementation details also has its advantages, and the API may be reasonably abstracted.
The introduction has become long, but let's take a look at the test I wrote this time. Some code is omitted and posted. If you want to see the whole picture, click here [https://github.com/tomoyuki-nakabayashi/TDDforEmbeddedSystem).
First, get the control data of evdev from the file descriptor. If successful, 0 or more will be returned. Initially, this test failed. Now that we know we need root privileges, we'll make the test name known (add AsRoot). Now you won't be addicted to the same thing at a later date. If you suddenly take over to someone, you'll find that you can't run it without root privileges.
TEST_F(EvdevSampleTest, InputEventFileCanOpenAsRoot) {
struct libevdev *dev = nullptr;
int fd = open("/dev/input/event2", O_RDONLY|O_NONBLOCK);
int rc = libevdev_new_from_fd(fd, &dev);
EXPECT_GE(rc, 0);
}
Since the control data of evdev has been acquired, confirm that EAGAIN is returned when there is no input. This passed in one shot.
TEST_F(EvdevSampleTest, ReturnsEAGAIN) {
input_event ev {};
int actual = libevdev_next_event(evdev_, LIBEVDEV_READ_FLAG_NORMAL, &ev);
EXPECT_EQ(-EAGAIN, actual);
}
Then press Enter and it will return LIBEVDEV_READ_STATUS_SUCCESS to test that you can get the input_event you expected. After executing the test, the test will stop during the execution of this test, so if you press the Enter key, the test will pass (it is no longer a unit test, but I don't care). By the time we reach the final EXPECT_EQ, we've confirmed that the events we've acquired are as expected, but we don't care for the time being.
TEST_F(EvdevSampleTest, CaptureEnterKeyPress) {
auto expect = create_key_event(KEY_ENTER, KEY_PRESSED);
input_event actual {};
while (true) {
int rc = libevdev_next_event(evdev_, LIBEVDEV_READ_FLAG_NORMAL, &actual);
if ((rc == LIBEVDEV_READ_STATUS_SUCCESS) && actual == expect) break;
}
EXPECT_EQ(expect, actual);
}
Considering that it can be used with other input devices, it would be nice to have a general-purpose callback interface. libevdev doesn't provide a callback mechanism, so I wonder if I can create a callback mechanism from scratch.
Next: Try to develop something close to embedded with TDD ~ Problem raising ~
Recommended Posts