From 1e75f914673b3559f757a39cab0d22084586bc42 Mon Sep 17 00:00:00 2001 From: kai-morich Date: Mon, 12 Oct 2020 21:14:06 +0200 Subject: [PATCH] slightly more coverage, local coverage report, dependency update --- build.gradle | 2 +- usbSerialExamples/build.gradle | 6 +- usbSerialForAndroid/build.gradle | 4 +- usbSerialForAndroid/coverage.gradle | 19 ++++++ .../hoho/android/usbserial/CrossoverTest.java | 6 +- .../hoho/android/usbserial/DeviceTest.java | 61 +++++++++++++------ .../android/usbserial/util/TelnetWrapper.java | 61 ++++++++----------- .../android/usbserial/util/UsbWrapper.java | 4 +- 8 files changed, 100 insertions(+), 63 deletions(-) diff --git a/build.gradle b/build.gradle index c45cc71..20788bb 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'com.android.tools.build:gradle:4.0.2' } } diff --git a/usbSerialExamples/build.gradle b/usbSerialExamples/build.gradle index dc22a37..5d6d887 100644 --- a/usbSerialExamples/build.gradle +++ b/usbSerialExamples/build.gradle @@ -11,7 +11,7 @@ android { defaultConfig { minSdkVersion 17 - targetSdkVersion 28 + targetSdkVersion 29 vectorDrawables.useSupportLibrary = true testInstrumentationRunner "android.test.InstrumentationTestRunner" @@ -27,6 +27,6 @@ android { dependencies { implementation project(':usbSerialForAndroid') - implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'com.google.android.material:material:1.1.0' + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.2.1' } diff --git a/usbSerialForAndroid/build.gradle b/usbSerialForAndroid/build.gradle index 12e5fc0..0cdf329 100644 --- a/usbSerialForAndroid/build.gradle +++ b/usbSerialForAndroid/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { minSdkVersion 17 - targetSdkVersion 28 + targetSdkVersion 29 consumerProguardFiles 'proguard-rules.pro' testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -26,7 +26,7 @@ dependencies { androidTestImplementation 'com.android.support:support-annotations:28.0.0' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'commons-net:commons-net:3.6' - androidTestImplementation 'org.apache.commons:commons-lang3:3.8.1' // starting with 3.9 requires min-api 26 + androidTestImplementation 'org.apache.commons:commons-lang3:3.11' } //apply from: 'publishToMavenLocal.gradle' diff --git a/usbSerialForAndroid/coverage.gradle b/usbSerialForAndroid/coverage.gradle index 2d08c63..c77ed22 100644 --- a/usbSerialForAndroid/coverage.gradle +++ b/usbSerialForAndroid/coverage.gradle @@ -1,3 +1,4 @@ +// see https://github.com/mik3y/usb-serial-for-android/wiki/Device-Tests-&-Coverage-Report for instructions apply plugin: 'jacoco' android { @@ -43,9 +44,27 @@ android { } } } + // create report even if tests fail project.gradle.taskGraph.whenReady { -> project.tasks.findAll { it.name =~ /connected.+AndroidTest/ }.each { it.ignoreFailures = true } } + +task jacocoTestReport(type: JacocoReport /*, dependsOn: ['testDebugUnitTest', 'createAnyDeviceDebugCoverageReport']*/) { + reports { + xml.enabled = false + html.enabled = true + } + + def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*'] + def debugTree = fileTree(dir: "$project.buildDir/intermediates/javac/debug", excludes: fileFilter) + def mainSrc = "$project.projectDir/src/main/java" + + sourceDirectories.from files([mainSrc]) + classDirectories.from files([debugTree]) + executionData.from fileTree(dir: project.buildDir, includes: [ + 'jacoco/testDebugUnitTest.exec', 'outputs/code_coverage/*AndroidTest/connected/*.ec' + ]) +} diff --git a/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/CrossoverTest.java b/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/CrossoverTest.java index fed2551..89e2018 100644 --- a/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/CrossoverTest.java +++ b/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/CrossoverTest.java @@ -62,12 +62,12 @@ public class CrossoverTest { if (availableDrivers.size() == 0) { fail("no USB device found"); } else if (availableDrivers.size() == 1) { - assertEquals(2, availableDrivers.get(0).getPorts().size()); + assertEquals("expected device with 2 ports.", 2, availableDrivers.get(0).getPorts().size()); usb1 = new UsbWrapper(context, availableDrivers.get(0), 0); usb2 = new UsbWrapper(context, availableDrivers.get(0), 1); } else { - assertEquals(1, availableDrivers.get(0).getPorts().size()); - assertEquals(1, availableDrivers.get(1).getPorts().size()); + assertEquals("expected 2 devices with 1 port.", 1, availableDrivers.get(0).getPorts().size()); + assertEquals("expected 2 devices with 1 port.", 1, availableDrivers.get(1).getPorts().size()); usb1 = new UsbWrapper(context, availableDrivers.get(0), 0); usb2 = new UsbWrapper(context, availableDrivers.get(1), 0); } diff --git a/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/DeviceTest.java b/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/DeviceTest.java index 33d1c50..92868c2 100644 --- a/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/DeviceTest.java +++ b/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/DeviceTest.java @@ -364,7 +364,7 @@ public class DeviceTest { try { usb.setParameters(183, 8, 1, UsbSerialPort.PARITY_NONE); fail("baud rate to low expected"); - } catch (IOException ignored) { + } catch (UnsupportedOperationException ignored) { } usb.setParameters(184, 8, 1, UsbSerialPort.PARITY_NONE); usb.setParameters( 960000, 8, 1, UsbSerialPort.PARITY_NONE); @@ -380,7 +380,7 @@ public class DeviceTest { try { usb.setParameters((int)(2000000/1.04), 8, 1, UsbSerialPort.PARITY_NONE); fail("baud rate error expected"); - } catch (IOException ignored) { + } catch (UnsupportedOperationException ignored) { } usb.setParameters((int)(2000000/1.03), 8, 1, UsbSerialPort.PARITY_NONE); usb.setParameters(2000000, 8, 1, UsbSerialPort.PARITY_NONE); @@ -388,14 +388,14 @@ public class DeviceTest { try { usb.setParameters((int)(2000000*1.04), 8, 1, UsbSerialPort.PARITY_NONE); fail("baud rate error expected"); - } catch (IOException ignored) { + } catch (UnsupportedOperationException ignored) { } usb.setParameters(2000000, 8, 1, UsbSerialPort.PARITY_NONE); usb.setParameters(3000000, 8, 1, UsbSerialPort.PARITY_NONE); try { usb.setParameters(4000000, 8, 1, UsbSerialPort.PARITY_NONE); fail("baud rate to high expected"); - } catch (IOException ignored) { + } catch (UnsupportedOperationException ignored) { } } @@ -922,7 +922,7 @@ public class DeviceTest { if (usb.serialDriver instanceof Cp21xxSerialDriver && usb.serialDriver.getPorts().size() == 1) Assert.assertNotEquals(0, data.length); // can be shorter or full length else if (usb.serialDriver instanceof ProlificSerialDriver) - Assert.assertTrue("expected > 0 and < 16 byte, got " + data.length, data.length > 0 && data.length < 16); + Assert.assertTrue("sporadic issue! expected > 0 and < 16 byte, got " + data.length, data.length > 0 && data.length < 16); else // ftdi, ch340, cp2105 Assert.assertEquals(0, data.length); telnet.write("2ccc".getBytes()); @@ -998,7 +998,7 @@ public class DeviceTest { public void readSpeed() throws Exception { // see logcat for performance results // - // CDC arduino_leonardo_bridge.ini has transfer speed ~ 100 byte/sec + // CDC arduino_leonardo_bridge.ino has transfer speed ~ 100 byte/sec // all other devices are near physical limit with ~ 10-12k/sec // // readBufferOverflow provokes read errors, but they can also happen here where the data is actually read fast enough. @@ -1068,7 +1068,7 @@ public class DeviceTest { public void writeSpeed() throws Exception { // see logcat for performance results // - // CDC arduino_leonardo_bridge.ini has transfer speed ~ 100 byte/sec + // CDC arduino_leonardo_bridge.ino has transfer speed ~ 100 byte/sec // all other devices can get near physical limit: // longlines=true:, speed is near physical limit at 11.5k // longlines=false: speed is 3-4k for all devices, as more USB packets are required @@ -1194,8 +1194,6 @@ public class DeviceTest { usb.ioManager = new SerialInputOutputManager(usb.serialPort, usb); assertEquals(usb, usb.ioManager.getListener()); - usb.ioManager.setThreadPriority(Process.THREAD_PRIORITY_AUDIO); - assertEquals(0, usb.ioManager.getReadTimeout()); usb.ioManager.setReadTimeout(10); assertEquals(10, usb.ioManager.getReadTimeout()); @@ -1210,10 +1208,22 @@ public class DeviceTest { usb.ioManager.setWriteBufferSize(13); assertEquals(13, usb.ioManager.getWriteBufferSize()); - usb.open(); // creates new IoManager + usb.ioManager.setReadBufferSize(usb.ioManager.getReadBufferSize()); + usb.ioManager.setWriteBufferSize(usb.ioManager.getWriteBufferSize()); + usb.ioManager.setReadTimeout(usb.ioManager.getReadTimeout()); + usb.ioManager.setWriteTimeout(usb.ioManager.getWriteTimeout()); + + usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_IOMANAGER_START)); // creates new IoManager usb.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); telnet.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); + usb.ioManager.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); + usb.startIoManager(); usb.waitForIoManagerStarted(); + try { + usb.ioManager.run(); + fail("already running error expected"); + } catch (IllegalStateException ignored) { + } try { usb.ioManager.setThreadPriority(Process.THREAD_PRIORITY_LOWEST); fail("setThreadPriority IllegalStateException expected"); @@ -1384,7 +1394,7 @@ public class DeviceTest { // date loss with high transfer rate and short read timeout !!! diffLen = readSpeedInt(5, -1, shortTimeout); - assertNotEquals(0, diffLen); + assertNotEquals("sporadic issue!", 0, diffLen); // data loss observed with read timeout up to 200 msec, e.g. // difference at 181 len 64 @@ -1791,9 +1801,15 @@ public class DeviceTest { } catch (UnsupportedOperationException ignored) { } if(purged) { + usb.serialPort.purgeHwBuffers(false, false); try { - usb.serialPort.purgeHwBuffers(true, true); - fail("purgeHwBuffers error expected"); + usb.serialPort.purgeHwBuffers(true, false); + fail("purgeHwBuffers(write) error expected"); + } catch (IOException ignored) { + } + try { + usb.serialPort.purgeHwBuffers(false, true); + fail("purgeHwBuffers(read) error expected"); } catch (IOException ignored) { } } @@ -1845,10 +1861,10 @@ public class DeviceTest { } catch (IOException ignored) { } try { - usb.ioManager.run(); - fail("already running error expected"); - } catch (IllegalStateException ignored) { - } + byte[] buffer = new byte[0]; + usb.serialPort.read(buffer, UsbWrapper.USB_READ_WAIT); + fail("read buffer to small expected"); + } catch(IllegalArgumentException ignored) {} } @Test @@ -1876,5 +1892,16 @@ public class DeviceTest { ftdiSerialPort.setLatencyTimer(lt); assertEquals("latency 1", 99, Math.max(t2-t1, 99)); // looks strange, but shows actual value assertEquals("latency 100", 99, Math.min(t3-t2, 99)); + + usb.deviceConnection.close(); + try { + ftdiSerialPort.getLatencyTimer(); + fail("getLatencyTimer error expected"); + } catch (IOException ignored) {} + usb.deviceConnection.close(); + try { + ftdiSerialPort.setLatencyTimer(1); + fail("setLatencyTimer error expected"); + } catch (IOException ignored) {} } } diff --git a/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/util/TelnetWrapper.java b/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/util/TelnetWrapper.java index 78922fc..b1d44b3 100644 --- a/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/util/TelnetWrapper.java +++ b/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/util/TelnetWrapper.java @@ -9,6 +9,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; +import java.util.ArrayList; import static org.junit.Assert.assertEquals; @@ -31,7 +32,7 @@ public class TelnetWrapper { private TelnetClient telnetClient; private InputStream readStream; private OutputStream writeStream; - private Integer[] comPortOptionCounter = {0}; + private ArrayList commandResponse = new ArrayList<>(); public int writeDelay = 0; public TelnetWrapper(String host, int port) { @@ -47,7 +48,9 @@ public class TelnetWrapper { telnetClient.addOptionHandler(new TelnetOptionHandler(RFC2217_COM_PORT_OPTION, false, false, false, false) { @Override public int[] answerSubnegotiation(int[] suboptionData, int suboptionLength) { - comPortOptionCounter[0] += 1; + int[] data = new int[suboptionLength]; + System.arraycopy(suboptionData, 0, data, 0, suboptionLength); + commandResponse.add(data); return super.answerSubnegotiation(suboptionData, suboptionLength); } }); @@ -59,18 +62,25 @@ public class TelnetWrapper { readStream = telnetClient.getInputStream(); } + private int[] doCommand(String name, byte[] command) throws IOException, InterruptedException { + commandResponse.clear(); + telnetClient.sendCommand((byte) TelnetCommand.SB); + writeStream.write(command); + telnetClient.sendCommand((byte)TelnetCommand.SE); + + for(int i=0; i 0) break; + Thread.sleep(1); + } + assertEquals("RFC2217 " + name+ " w/o response.", 1, commandResponse.size()); + //Log.d(TAG, name + " -> " + Arrays.toString(commandResponse.get(0))); + return commandResponse.get(0); + } + public void setUp() throws Exception { setUpFixtureInt(); telnetClient.sendAYT(1000); // not correctly handled by rfc2217_server.py, but WARNING output "ignoring Telnet command: '\xf6'" is a nice separator between tests - comPortOptionCounter[0] = 0; - telnetClient.sendCommand((byte)TelnetCommand.SB); - writeStream.write(new byte[] {RFC2217_COM_PORT_OPTION, RFC2217_PURGE_DATA, 3}); - telnetClient.sendCommand((byte)TelnetCommand.SE); - for(int i=0; i>24), (byte)(baudRate>>16), (byte)(baudRate>>8), (byte)baudRate}); - telnetClient.sendCommand((byte)TelnetCommand.SE); - - telnetClient.sendCommand((byte)TelnetCommand.SB); - writeStream.write(new byte[] {RFC2217_COM_PORT_OPTION, RFC2217_SET_DATASIZE, (byte)dataBits}); - telnetClient.sendCommand((byte)TelnetCommand.SE); - - telnetClient.sendCommand((byte)TelnetCommand.SB); - writeStream.write(new byte[] {RFC2217_COM_PORT_OPTION, RFC2217_SET_STOPSIZE, (byte)stopBits}); - telnetClient.sendCommand((byte)TelnetCommand.SE); - - telnetClient.sendCommand((byte)TelnetCommand.SB); - writeStream.write(new byte[] {RFC2217_COM_PORT_OPTION, RFC2217_SET_PARITY, (byte)(parity+1)}); - telnetClient.sendCommand((byte)TelnetCommand.SE); - - // windows does not like nonstandard baudrates. rfc2217_server.py terminates w/o response - for(int i=0; i>24), (byte)(baudRate>>16), (byte)(baudRate>>8), (byte)baudRate}); + doCommand("set-datasize", new byte[] {RFC2217_COM_PORT_OPTION, RFC2217_SET_DATASIZE, (byte)dataBits}); + doCommand("set-stopsize", new byte[] {RFC2217_COM_PORT_OPTION, RFC2217_SET_STOPSIZE, (byte)stopBits}); + doCommand("set-parity", new byte[] {RFC2217_COM_PORT_OPTION, RFC2217_SET_PARITY, (byte)(parity+1)}); } + } diff --git a/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/util/UsbWrapper.java b/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/util/UsbWrapper.java index dcc5d64..b428c2d 100644 --- a/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/util/UsbWrapper.java +++ b/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/util/UsbWrapper.java @@ -33,8 +33,8 @@ import static org.junit.Assert.fail; public class UsbWrapper implements SerialInputOutputManager.Listener { - private final static int USB_READ_WAIT = 500; - private final static int USB_WRITE_WAIT = 500; + public final static int USB_READ_WAIT = 500; + public final static int USB_WRITE_WAIT = 500; private static final String TAG = UsbWrapper.class.getSimpleName(); public enum OpenCloseFlags { NO_IOMANAGER_THREAD, NO_IOMANAGER_START, NO_CONTROL_LINE_INIT, NO_DEVICE_CONNECTION };