Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>


<groupId>io.github.java-native</groupId>
<artifactId>jssc</artifactId>
<version>2.9.7-SNAPSHOT</version>
Expand Down Expand Up @@ -55,6 +56,7 @@
<dependency.log4j.version>2.22.0</dependency.log4j.version>
<dependency.logback.version>1.2.3</dependency.logback.version>
<dependency.nativelibloader.version>2.5.0</dependency.nativelibloader.version>
<dependency.mockito.version>4.11.0</dependency.mockito.version>

<!-- plugin versions a-z -->
<plugin.animalsniffer.version>1.17</plugin.animalsniffer.version>
Expand Down Expand Up @@ -100,6 +102,18 @@
<version>${dependency.junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${dependency.mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>${dependency.mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/jssc/SerialNativeInterface.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,25 @@ public class SerialNativeInterface {
*/
public static final String PROPERTY_JSSC_PARMRK = "JSSC_PARMRK";

/**
* Allow set exotic port name(s)
*
* Usage:
* <code>System.setProperty("JSSC_ALLOW_EXOTIC_NAMES", "true");</code>
*
* @since 2.9.7
*/
public static final String PROPERTY_JSSC_ALLOW_EXOTIC_NAMES = "JSSC_ALLOW_EXOTIC_NAMES";
/**
* Exotic port name(s)
*
* Usage:
* <code>System.setProperty("JSSC_EXOTIC_NAMES", "ttyU,com");</code>
*
* @since 2.9.7
*/
public static final String PROPERTY_JSSC_EXOTIC_NAMES = "JSSC_EXOTIC_NAMES";

private static int osType;
static {
String osName = System.getProperty("os.name");
Expand Down
45 changes: 41 additions & 4 deletions src/main/java/jssc/SerialPortList.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
public class SerialPortList {

private static SerialNativeInterface serialInterface;
private static final Pattern PORTNAMES_REGEXP;
private static final String PORTNAMES_PATH;
private static Pattern PORTNAMES_REGEXP;
private static String PORTNAMES_PATH;

/**
* Default constructor
Expand All @@ -47,9 +47,16 @@ private SerialPortList() {}

static {
serialInterface = new SerialNativeInterface();
initSearchParameters();
}

/**
* For unit testing purposes
*/
public static void initSearchParameters() {
switch (SerialNativeInterface.getOsType()) {
case SerialNativeInterface.OS_LINUX: {
PORTNAMES_REGEXP = Pattern.compile("(ttyS|ttyUSB|ttyACM|ttyAMA|rfcomm|ttyO|ttyM|ttyMXUSB|ttyMUE)[0-9]{1,3}");
PORTNAMES_REGEXP = Pattern.compile("(ttyS|ttyUSB|ttyACM|ttyAMA|rfcomm|ttyO|ttyM|ttyMXUSB|ttyMUE" + getExoticPortsNames() + ")[0-9]{1,3}");
PORTNAMES_PATH = "/dev/";
break;
}
Expand All @@ -59,7 +66,7 @@ private SerialPortList() {}
break;
}
case SerialNativeInterface.OS_MAC_OS_X: {
PORTNAMES_REGEXP = Pattern.compile("(tty|cu)\\..*");
PORTNAMES_REGEXP = Pattern.compile("(tty|cu" + getExoticPortsNames() + ")\\..*");
PORTNAMES_PATH = "/dev/";
break;
}
Expand All @@ -76,6 +83,36 @@ private SerialPortList() {}
}
}

/**
* For unit testing purposes
*/
public static Pattern getPortnamesRegexp() {
return PORTNAMES_REGEXP;
}

private static String getExoticPortsNames() {
String result = "";
String readExoticNamesValue = System.getProperty(SerialNativeInterface.PROPERTY_JSSC_ALLOW_EXOTIC_NAMES, "false"),
exoticPortNamesValue = System.getProperty(SerialNativeInterface.PROPERTY_JSSC_EXOTIC_NAMES, "");
boolean decodeExoticNames = false;

try {
decodeExoticNames = Boolean.parseBoolean(readExoticNamesValue) && !exoticPortNamesValue.isEmpty();
} catch (Exception e) {
e.printStackTrace();
}

if(decodeExoticNames) {
String[] portsNamesCandidate = exoticPortNamesValue.split("[^a-zA-Z]");
for(String singlePortName : portsNamesCandidate) {
if(!singlePortName.isEmpty()) {
result += "|" + singlePortName;
}
}
}
return result;
}

//since 2.1.0 -> Fully rewritten port name comparator
private static final Comparator<String> PORTNAMES_COMPARATOR = new Comparator<String>() {

Expand Down
95 changes: 95 additions & 0 deletions src/test/java/jssc/SerialPortListTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package jssc;

import jssc.junit.rules.DisplayMethodNameRule;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;


public class SerialPortListTest extends DisplayMethodNameRule {

private static final String BASIC_LINUX_PORTNAME_REGEXP = "(ttyS|ttyUSB|ttyACM|ttyAMA|rfcomm|ttyO|ttyM|ttyMXUSB|ttyMUE%s)[0-9]{1,3}";
private static final String BASIC_MAC_OS_PORTNAME_REGEXP = "(tty|cu%s)\\..*";

private void prepareEnv() {
System.clearProperty(SerialNativeInterface.PROPERTY_JSSC_ALLOW_EXOTIC_NAMES);
System.clearProperty(SerialNativeInterface.PROPERTY_JSSC_EXOTIC_NAMES);
}

@Test
public void checkSerialPortNameRegExpOnLinux() {
MockedStatic<SerialNativeInterface> serialNativeInterface = null;
prepareEnv();

try {
serialNativeInterface = Mockito.mockStatic(SerialNativeInterface.class);
serialNativeInterface.when(SerialNativeInterface::getOsType).thenReturn(SerialNativeInterface.OS_LINUX);
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_LINUX_PORTNAME_REGEXP, ""), SerialPortList.getPortnamesRegexp().pattern());

System.setProperty(SerialNativeInterface.PROPERTY_JSSC_EXOTIC_NAMES, "abc");
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_LINUX_PORTNAME_REGEXP, ""), SerialPortList.getPortnamesRegexp().pattern());

System.setProperty(SerialNativeInterface.PROPERTY_JSSC_ALLOW_EXOTIC_NAMES, "true");
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_LINUX_PORTNAME_REGEXP, "|abc"), SerialPortList.getPortnamesRegexp().pattern());

System.setProperty(SerialNativeInterface.PROPERTY_JSSC_ALLOW_EXOTIC_NAMES, "false");
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_LINUX_PORTNAME_REGEXP, ""), SerialPortList.getPortnamesRegexp().pattern());

System.setProperty(SerialNativeInterface.PROPERTY_JSSC_ALLOW_EXOTIC_NAMES, "true");
System.setProperty(SerialNativeInterface.PROPERTY_JSSC_EXOTIC_NAMES, "abc1d|bvc");
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_LINUX_PORTNAME_REGEXP, "|abc|d|bvc"), SerialPortList.getPortnamesRegexp().pattern());

System.clearProperty(SerialNativeInterface.PROPERTY_JSSC_EXOTIC_NAMES);
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_LINUX_PORTNAME_REGEXP, ""), SerialPortList.getPortnamesRegexp().pattern());
} finally {
if(serialNativeInterface != null) {
serialNativeInterface.close();
}
}
}

@Test
public void checkSerialPortNameRegExpOnMacOS() {
MockedStatic<SerialNativeInterface> serialNativeInterface = null;
prepareEnv();

try {
serialNativeInterface = Mockito.mockStatic(SerialNativeInterface.class);
serialNativeInterface.when(SerialNativeInterface::getOsType).thenReturn(SerialNativeInterface.OS_MAC_OS_X);
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_MAC_OS_PORTNAME_REGEXP, ""), SerialPortList.getPortnamesRegexp().pattern());

System.setProperty(SerialNativeInterface.PROPERTY_JSSC_EXOTIC_NAMES, "abc");
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_MAC_OS_PORTNAME_REGEXP, ""), SerialPortList.getPortnamesRegexp().pattern());

System.setProperty(SerialNativeInterface.PROPERTY_JSSC_ALLOW_EXOTIC_NAMES, "true");
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_MAC_OS_PORTNAME_REGEXP, "|abc"), SerialPortList.getPortnamesRegexp().pattern());

System.setProperty(SerialNativeInterface.PROPERTY_JSSC_ALLOW_EXOTIC_NAMES, "false");
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_MAC_OS_PORTNAME_REGEXP, ""), SerialPortList.getPortnamesRegexp().pattern());

System.setProperty(SerialNativeInterface.PROPERTY_JSSC_ALLOW_EXOTIC_NAMES, "true");
System.setProperty(SerialNativeInterface.PROPERTY_JSSC_EXOTIC_NAMES, "abc1d|bvc");
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_MAC_OS_PORTNAME_REGEXP, "|abc|d|bvc"), SerialPortList.getPortnamesRegexp().pattern());

System.clearProperty(SerialNativeInterface.PROPERTY_JSSC_EXOTIC_NAMES);
SerialPortList.initSearchParameters();
Assert.assertEquals(String.format(BASIC_MAC_OS_PORTNAME_REGEXP, ""), SerialPortList.getPortnamesRegexp().pattern());
} finally {
if(serialNativeInterface != null) {
serialNativeInterface.close();
}
}
}
}
Loading