Skip to content

Commit

Permalink
Bring up tests on macOS.
Browse files Browse the repository at this point in the history
Some platform issues which should be fixed in the library, but which we
can work around in tests for now.
  • Loading branch information
MrDOS committed May 28, 2020
1 parent 59a72af commit 5e4a04c
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 20 deletions.
24 changes: 21 additions & 3 deletions src/test/java/gnu/io/SerialPortControlTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public class SerialPortControlTest
{
private static final Logger log = Logger.getLogger(SerialPortControlTest.class.getName());

private static final String BUGGY_DSR_EVENTS = "DSR event propagation is buggy! DSR events are useless until this is fixed.";
private static final String BUGGY_CTS_EVENTS = "CTS event propagation is buggy! CTS events are useless until this is fixed.";

/**
* How long to wait (in milliseconds) for asynchronous events to arrive
* before failing the test.
Expand Down Expand Up @@ -118,8 +121,11 @@ void testDTRDSREvents() throws TooManyListenersException, InterruptedException
* that's the workaround employed here for now; but this really is
* papering over a hole. The DSR event being one edge late means
* it's basically impossible for any consumer to hand-roll their
* own hardware flow control. */
log.warning("DSR event propagation is buggy! DSR events are useless until this is fixed.");
* own hardware flow control.
*
* TODO: This is broken on Windows (10) and macOS (10.15). Check
* Linux behaviour. */
log.warning(SerialPortControlTest.BUGGY_DSR_EVENTS);
this.ports.a.setDTR(false);
sawEvent = latch.await(SerialPortControlTest.EVENT_TIMEOUT, TimeUnit.MILLISECONDS);
}
Expand Down Expand Up @@ -147,6 +153,18 @@ void testRTSCTSEvents() throws TooManyListenersException, InterruptedException
});
this.ports.b.notifyOnCTS(true);
this.ports.a.setRTS(true);
assertTrue(latch.await(SerialPortControlTest.EVENT_TIMEOUT, TimeUnit.MILLISECONDS));
boolean sawEvent = false;
sawEvent = latch.await(SerialPortControlTest.EVENT_TIMEOUT, TimeUnit.MILLISECONDS);
if (!sawEvent)
{
/* FIXME: Same story here as with DSR events. This works correctly
* on Windows (10), but fails on macOS (10.15).
*
* TODO: Check Linux behaviour. */
log.warning(SerialPortControlTest.BUGGY_CTS_EVENTS);
this.ports.a.setRTS(false);
sawEvent = latch.await(SerialPortControlTest.EVENT_TIMEOUT, TimeUnit.MILLISECONDS);
}
assertTrue(sawEvent);
}
}
12 changes: 9 additions & 3 deletions src/test/java/gnu/io/SerialPortExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,23 @@ public SerialPortExtension()
if (OS.WINDOWS.isCurrentOs())
{
example = new String[] { "set " + SerialPortExtension.A_PORT_ENV + "=COM1",
"set " + SerialPortExtension.B_PORT_ENV + "=COM2", "gradlew.bat test" };
"set " + SerialPortExtension.B_PORT_ENV + "=COM2", "gradlew.bat" };
}
else if (OS.MAC.isCurrentOs())
{
example = new String[] { SerialPortExtension.A_PORT_ENV + "=/dev/tty.usbserial-a "
+ SerialPortExtension.B_PORT_ENV + "=/dev/tty.usbserial-b ./gradlew" };
}
else
{
example = new String[] { SerialPortExtension.A_PORT_ENV + "=/dev/ttyUSB0 "
+ SerialPortExtension.B_PORT_ENV + "=/dev/ttyUSB1 ./gradlew test" };
+ SerialPortExtension.B_PORT_ENV + "=/dev/ttyUSB1 ./gradlew" };
}
log.severe("The serial port functionality tests require the use of two ports. These should be connected to "
+ "each other with a null modem cable. Then set the environment variables "
+ SerialPortExtension.A_PORT_ENV + " and " + SerialPortExtension.B_PORT_ENV + " to the names of "
+ "the ports, and re-run the tests. For example:\n\n\t" + String.join("\n\t", example));
+ "the ports, and re-run the tests. For example:\n\n\t" + String.join("\n\t", example) + " "
+ "cleanTest test --no-build-cache --info");

this.hasIds = false;
this.aId = null;
Expand Down
24 changes: 12 additions & 12 deletions src/test/java/gnu/io/SerialPortFlowControlTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import java.util.logging.Logger;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.extension.RegisterExtension;

/**
Expand Down Expand Up @@ -68,12 +70,12 @@ public class SerialPortFlowControlTest
* accurately. To test port behaviour upon filling it, we'll try to send
* this much data, and hope that we hit the limit.
*/
private static final int INPUT_BUFFER_MAX = 1024 * 1000;
private static final int INPUT_BUFFER_MAX = 128 * 1024;
/**
* Write in chunks of this size when attempting to hit the input buffer
* limit so that we can return early after hitting it.
*/
private static final int INPUT_BUFFER_CHUNK = 1024 * 4;
private static final int INPUT_BUFFER_CHUNK = 4 * 1024;

@RegisterExtension
SerialPortExtension ports = new SerialPortExtension();
Expand All @@ -99,16 +101,11 @@ public class SerialPortFlowControlTest
@Test
void testHardwareFlowControlWrite() throws UnsupportedCommOperationException, InterruptedException, IOException
{
/* Enabling hardware flow control on port A should automatically set
* the RTS control line. */
assertFalse(this.ports.b.isCTS());
this.ports.a.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT);
assertTrue(this.ports.b.isCTS());
/* On Windows, RTS is off by default when opening the port. On other
* platforms, it's on. We'll explicitly turn it off for consistency. */
this.ports.b.setRTS(false);

/* Note that RTS is being asserted implicitly by the driver due to the
* flow control mode. The explicit RTS control flag does _not_ reflect
* this state. */
assertFalse(this.ports.a.isRTS());
this.ports.a.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT);

this.ports.b.enableReceiveTimeout(SerialPortFlowControlTest.TIMEOUT);

Expand Down Expand Up @@ -232,6 +229,9 @@ void testSoftwareFlowControlWrite() throws UnsupportedCommOperationException, IO
* leaving it disabled on the other. The generation of flow control
* characters by first port can then be verified by reading from the second
* port.
* <p>
* FIXME: On macOS (tested 10.15), I never received the XOFF even after
* passing multiple megabytes of data.
*
* @throws UnsupportedCommOperationException if the flow control mode is
* unsupported by the driver
Expand All @@ -240,6 +240,7 @@ void testSoftwareFlowControlWrite() throws UnsupportedCommOperationException, IO
* of the ports
*/
@Test
@DisabledOnOs(OS.MAC)
void testSoftwareFlowControlRead() throws UnsupportedCommOperationException, IOException
{
this.ports.a.setSerialPortParams(
Expand Down Expand Up @@ -271,7 +272,6 @@ void testSoftwareFlowControlRead() throws UnsupportedCommOperationException, IOE
out.write(buffer);
}

assertEquals(1, in.available(), SerialPortFlowControlTest.ERRONEOUS_CTS);
assertEquals(1, in.available(), SerialPortFlowControlTest.MISSING_XOFF);
log.info(String.format(SerialPortFlowControlTest.FILLED_INPUT_BUFFER, written));
}
Expand Down
31 changes: 29 additions & 2 deletions src/test/java/gnu/io/SerialPortReadWriteTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.extension.RegisterExtension;

/**
Expand Down Expand Up @@ -76,14 +77,29 @@ class SerialPortReadWriteTest

/** The baud rates at which to test reading/writing. */
private static final int[] BAUDS = new int[] {
50, 75, 110, 134,
150, 200, 300, 600,
1_200, 2_400, 4_800, 9_600,
19_200, 38_400, 57_600, 115_200
};

/**
* Low-speed baud rates.
* <p>
* FIXME: Defined on all supported platforms, but not actually functional
* on macOS.
*/
private static final int[] LOW_SPEED_BAUDS = new int[] {
50, 75, 110, 134
};

/**
* Whether the high-speed baud rates should also be tested.
* <p>
* Even when supported by the driver and hardware, you may encounter errors
* at high baud rates due to anomalies in the physical connection.
* High-speed baud rates work best over short connections and communication
* may fail through no fault of the software – due to dodgy cabling, or
* connectors, or interference.
*
* @see SerialPortReadWriteTest#HIGH_SPEED_BAUDS
*/
Expand Down Expand Up @@ -146,7 +162,18 @@ Stream<DynamicTest> testAllReadWriteBytes()
*/
private IntStream getTestBauds()
{
IntStream bauds = Arrays.stream(SerialPortReadWriteTest.BAUDS);
IntStream bauds;
if (OS.MAC.isCurrentOs())
{
bauds = IntStream.empty();
}
else
{
bauds = Arrays.stream(LOW_SPEED_BAUDS);
}
bauds = IntStream.concat(
bauds,
Arrays.stream(SerialPortReadWriteTest.BAUDS));
if (SerialPortReadWriteTest.INCLUDE_HIGH_SPEED_BAUDS)
{
bauds = IntStream.concat(
Expand Down

0 comments on commit 5e4a04c

Please sign in to comment.