Embedded testing failed with Broken pipe on Arduino

I’ve tried to run unit test in embedded mode using Arduino Micro and Leonardo boards using the Calculator example:

On both boards uploaded unit-test works (as I can see fast blinking of the led) but pio test failed with error message:

Testing…
If you don’t see any output for the first 10 secs, please reset board (press reset button)

[Errno 32] Broken pipe

What’s wrong?

Thank you in advance!

Do you see the effect of

on the board, aka a blinking builtin-LED?

Yeap, as I wrote in the starting topic I see fast blinking of the led – then it’s uploaded the test code.

So, it works, but not possible to see results of the test – after the Broken pipe error appears the test marked as ERRORED, which is not quite helpful for TDD…

I would be quite baffled by this but then the default PlatformIO implementation for the Unity I/O functions kills it maybe. Specifically I can image that Serial.end() which is called during UNITY_END(); shuts down the USB serial port completely, resulting in a broken pipe.

Try and follow Unity — PlatformIO latest documentation (or this) to give it your own implementation of this, i.e.,

  1. create test/unity_config.h and fill it with this content
  2. create test/unity_config.cpp and use the implementation quotes above, but leave unityOutputComplete() as empty function.

Thank you for the answer!

I’ve added some debugging prints in the setup() and it seems that the Broken pipe error occurred before even the test start executing:

void setup()
{
    // this delay is required, otherwise test results
    // would not be communicated to the host terminal
    delay(1000);

    UNITY_BEGIN();
    RUN_TEST(simple_test);
    UNITY_END();
}

I use the cli command to start test:
pio test --upload-port /dev/ttyACM0 --test-port /dev/ttyACM0 --environment leonardo

and I see the Broken pipe error in the terminal immediately after the upload finished, much before 1 second delay ends up and the RUN_TEST() even started…

Is another program accessing the port maybe? Something like the infamous brltty service? What’s the output of sudo dmesg | tail -n50 after the pipe breaks?

No brltty service, but dmesg shows each time I run the test 2 consecutive disconnections of the Arduino Leonardo with different idProduct:

[ 1810.138979] usb 1-2: USB disconnect, device number 10
[ 1810.488209] usb 1-2: new full-speed USB device number 11 using xhci_hcd
[ 1810.638580] usb 1-2: New USB device found, idVendor=2341, idProduct=0036, bcdDevice= 0.01
[ 1810.638588] usb 1-2: New USB device strings: Mfr=2, Product=1, SerialNumber=0
[ 1810.638591] usb 1-2: Product: Arduino Leonardo
[ 1810.638593] usb 1-2: Manufacturer: Arduino LLC
[ 1810.640662] cdc_acm 1-2:1.0: ttyACM0: USB ACM device

[ 1813.005040] usb 1-2: USB disconnect, device number 11
[ 1813.316350] usb 1-2: new full-speed USB device number 12 using xhci_hcd
[ 1813.469629] usb 1-2: New USB device found, idVendor=2341, idProduct=8036, bcdDevice= 1.00
[ 1813.469634] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 1813.469636] usb 1-2: Product: Arduino Leonardo
[ 1813.469638] usb 1-2: Manufacturer: Arduino LLC
[ 1813.471652] cdc_acm 1-2:1.0: ttyACM0: USB ACM device

Each time these two groups of messages appears and device numbers increased all the time, here they are 10 and 11, next run it would be 12, 13 etc.

In the terminal I see per each test run:

Disconnected (device reports readiness to read but returned no data (device disconnected or multiple access on port?))
Reconnecting to /dev/ttyACM0 .   Connected!
Disconnected (device reports readiness to read but returned no data (device disconnected or multiple access on port?))
Reconnecting to /dev/ttyACM0     Connected!
Disconnected (device reports readiness to read but returned no data (device disconnected or multiple access on port?))
Reconnecting to /dev/ttyACM0     Connected!
Disconnected (device reports readiness to read but returned no data (device disconnected or multiple access on port?))
Reconnecting to /dev/ttyACM0     Connected!
test/test_blink/test_main.cpp:48:simple_test:PASS
test/test_blink/test_main.cpp:49:led_on_test:PASS
test/test_blink/test_main.cpp:50:led_off_test:PASS

-----------------------
3 Tests 0 Failures 0 Ignored
OK

So, the test works but not responded to pio due to this Broken pipe.

Ah, no I remember something: Can you apply this to your project?

i.e

extra_scripts = post:extra_script.py

in the platformio.ini and a new file extra_script.py on the same level as the platformio.ini with

import time

Import("env")

if "test" in env.GetBuildType():
    env.AddPostAction("upload", lambda *_, **__: time.sleep(2))

Amazing, it fixes the problem, works now – many thanks for your help!