This is an automated email from the ASF dual-hosted git repository.
chrisdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/develop by this push:
new aaeb887e3e fix: Refactored the handling of PCAP on windows differently
as it was multiple modules affected.
aaeb887e3e is described below
commit aaeb887e3ea685532e5f10c9d1a43875a97b1147
Author: Christofer Dutz <[email protected]>
AuthorDate: Fri Jun 12 17:58:56 2026 +0200
fix: Refactored the handling of PCAP on windows differently as it was
multiple modules affected.
---
plc4j/transports/pcap-replay/pom.xml | 7 ++
.../transport/pcapreplay/PcapFilePlayerTest.java | 23 ++----
.../PcapReplayTransportInstanceTest.java | 26 +++----
.../pcapreplay/PcapReplayTransportTest.java | 21 ++----
plc4j/transports/raw-socket/pom.xml | 7 ++
.../java/transport/rawsocket/PcapTestSupport.java | 84 ----------------------
.../rawsocket/RawSocketTransportInstanceTest.java | 13 ++--
.../rawsocket/RawSocketTransportTest.java | 32 ++++++---
.../rawsocket/SharedRawSocketManagerTest.java | 13 +++-
.../java/utils/testutils/RequirePcapCondition.java | 30 ++++++--
10 files changed, 98 insertions(+), 158 deletions(-)
diff --git a/plc4j/transports/pcap-replay/pom.xml
b/plc4j/transports/pcap-replay/pom.xml
index 537fa3a984..5ec8982f8b 100644
--- a/plc4j/transports/pcap-replay/pom.xml
+++ b/plc4j/transports/pcap-replay/pom.xml
@@ -74,6 +74,13 @@
</dependency>
<!-- Test Dependencies -->
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-utils-test-utils</artifactId>
+ <version>0.14.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
diff --git
a/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapFilePlayerTest.java
b/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapFilePlayerTest.java
index c4397eed63..7dbbfc239d 100644
---
a/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapFilePlayerTest.java
+++
b/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapFilePlayerTest.java
@@ -18,6 +18,7 @@
*/
package org.apache.plc4x.java.transport.pcapreplay;
+import org.apache.plc4x.java.utils.testutils.RequirePcap;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@@ -26,14 +27,17 @@ import org.pcap4j.packet.factory.PacketFactories;
import org.pcap4j.packet.namednumber.DataLinkType;
import org.pcap4j.util.MacAddress;
-import java.io.File;
import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests for PcapFilePlayer.
+ * <p>
+ * Every test here drives real pcap playback, so the whole class is skipped
when the pcap
+ * native library can't be loaded (e.g. on Windows CI without Npcap installed).
*/
+@RequirePcap
class PcapFilePlayerTest {
private PcapFilePlayer player;
@@ -50,23 +54,6 @@ class PcapFilePlayerTest {
@BeforeEach
void setUp() {
- try {
- // For some reason it doesn't work if we pass this in from the
outside.
- //if (os == "mac") {
- // On my Intel Mac I found the libs in:
"/usr/local/Cellar/libpcap/1.10.1/lib"
- // On my M1 Mac I found the libs in:
"/opt/homebrew/Cellar/libpcap/1.10.1/lib"
- if (new File("/usr/local/Cellar/libpcap/1.10.1/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/usr/local/Cellar/libpcap/1.10.1/lib");
- } else if (new
File("/usr/local/Cellar/libpcap/1.10.5/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/usr/local/Cellar/libpcap/1.10.5/lib");
- } else if (new File("/opt/homebrew/opt/libpcap/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/opt/homebrew/opt/libpcap/lib");
- }
- //}
- } catch (Error e) {
- e.printStackTrace();
- }
-
localMac = MacAddress.getByName("00:11:22:33:44:55");
remoteMac = MacAddress.getByName("AA:BB:CC:DD:EE:FF");
}
diff --git
a/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapReplayTransportInstanceTest.java
b/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapReplayTransportInstanceTest.java
index b3310f01bb..dda491fae3 100644
---
a/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapReplayTransportInstanceTest.java
+++
b/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapReplayTransportInstanceTest.java
@@ -21,12 +21,12 @@ package org.apache.plc4x.java.transport.pcapreplay;
import org.apache.plc4x.java.spi.transports.api.exceptions.TransportException;
import
org.apache.plc4x.java.transport.pcapreplay.config.PcapReplayTransportConfiguration;
import org.apache.plc4x.java.utils.auditlog.api.AuditLog;
+import org.apache.plc4x.java.utils.testutils.RequirePcap;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pcap4j.util.MacAddress;
-import java.io.File;
import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.*;
@@ -45,23 +45,6 @@ class PcapReplayTransportInstanceTest {
@BeforeEach
void setUp() throws TransportException {
- try {
- // For some reason it doesn't work if we pass this in from the
outside.
- //if (os == "mac") {
- // On my Intel Mac I found the libs in:
"/usr/local/Cellar/libpcap/1.10.1/lib"
- // On my M1 Mac I found the libs in:
"/opt/homebrew/Cellar/libpcap/1.10.1/lib"
- if (new File("/usr/local/Cellar/libpcap/1.10.1/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/usr/local/Cellar/libpcap/1.10.1/lib");
- } else if (new
File("/usr/local/Cellar/libpcap/1.10.5/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/usr/local/Cellar/libpcap/1.10.5/lib");
- } else if (new File("/opt/homebrew/opt/libpcap/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/opt/homebrew/opt/libpcap/lib");
- }
- //}
- } catch (Error e) {
- e.printStackTrace();
- }
-
// Create a mock player
mockPlayer = mock(PcapFilePlayer.class);
when(mockPlayer.isPlaying()).thenReturn(true);
@@ -423,6 +406,7 @@ class PcapReplayTransportInstanceTest {
}
@Test
+ @RequirePcap
void testRead_withActualPcapPlayback() throws Exception {
// Create a real player instance that uses test.pcap
config.mockPlayer = null; // Use real player
@@ -448,6 +432,7 @@ class PcapReplayTransportInstanceTest {
}
@Test
+ @RequirePcap
void testPeekReadableBytes_withActualData() throws Exception {
config.mockPlayer = null;
config.pcapFile = "/test.pcap";
@@ -469,6 +454,7 @@ class PcapReplayTransportInstanceTest {
}
@Test
+ @RequirePcap
void testGetNumBytesAvailable_withRealPlayer() throws Exception {
config.mockPlayer = null;
config.pcapFile = "/test.pcap";
@@ -485,6 +471,7 @@ class PcapReplayTransportInstanceTest {
}
@Test
+ @RequirePcap
void testStartStopReplay_withRealPlayer() throws Exception {
config.mockPlayer = null;
config.pcapFile = "/test.pcap";
@@ -507,6 +494,7 @@ class PcapReplayTransportInstanceTest {
}
@Test
+ @RequirePcap
void testGetPacketsReplayed_withRealPlayer() throws Exception {
config.mockPlayer = null;
config.pcapFile = "/test.pcap";
@@ -546,6 +534,7 @@ class PcapReplayTransportInstanceTest {
}
@Test
+ @RequirePcap
void testMultipleReadsInSequence() throws Exception {
config.mockPlayer = null;
config.pcapFile = "/test.pcap";
@@ -569,6 +558,7 @@ class PcapReplayTransportInstanceTest {
}
@Test
+ @RequirePcap
void testRead_afterStoppingReplay() throws Exception {
config.mockPlayer = null;
config.pcapFile = "/test.pcap";
diff --git
a/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapReplayTransportTest.java
b/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapReplayTransportTest.java
index 84e85eb90c..11438a1354 100644
---
a/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapReplayTransportTest.java
+++
b/plc4j/transports/pcap-replay/src/test/java/org/apache/plc4x/java/transport/pcapreplay/PcapReplayTransportTest.java
@@ -22,6 +22,7 @@ import
org.apache.plc4x.java.spi.transports.api.TransportInstance;
import org.apache.plc4x.java.spi.transports.api.exceptions.TransportException;
import
org.apache.plc4x.java.transport.pcapreplay.config.PcapReplayTransportConfiguration;
import org.apache.plc4x.java.utils.auditlog.api.AuditLog;
+import org.apache.plc4x.java.utils.testutils.RequirePcap;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@@ -49,23 +50,6 @@ class PcapReplayTransportTest {
@BeforeEach
void setUp() throws IOException {
- try {
- // For some reason it doesn't work if we pass this in from the
outside.
- //if (os == "mac") {
- // On my Intel Mac I found the libs in:
"/usr/local/Cellar/libpcap/1.10.1/lib"
- // On my M1 Mac I found the libs in:
"/opt/homebrew/Cellar/libpcap/1.10.1/lib"
- if (new File("/usr/local/Cellar/libpcap/1.10.1/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/usr/local/Cellar/libpcap/1.10.1/lib");
- } else if (new
File("/usr/local/Cellar/libpcap/1.10.5/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/usr/local/Cellar/libpcap/1.10.5/lib");
- } else if (new File("/opt/homebrew/opt/libpcap/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/opt/homebrew/opt/libpcap/lib");
- }
- //}
- } catch (Error e) {
- e.printStackTrace();
- }
-
transport = new PcapReplayTransport();
// Create a minimal test PCAP file
@@ -145,6 +129,7 @@ class PcapReplayTransportTest {
}
@Test
+ @RequirePcap
void testCreateTransportInstance_withValidPcap() throws Exception {
PcapReplayTransportConfiguration config = new
PcapReplayTransportConfiguration();
config.pcapFile = "/test.pcap";
@@ -166,6 +151,7 @@ class PcapReplayTransportTest {
}
@Test
+ @RequirePcap
void testCreateTransportInstance_withLoop() throws Exception {
PcapReplayTransportConfiguration config = new
PcapReplayTransportConfiguration();
config.pcapFile = "/test.pcap";
@@ -187,6 +173,7 @@ class PcapReplayTransportTest {
}
@Test
+ @RequirePcap
void testCreateTransportInstance_onlyIncoming() throws Exception {
PcapReplayTransportConfiguration config = new
PcapReplayTransportConfiguration();
config.pcapFile = "/test.pcap";
diff --git a/plc4j/transports/raw-socket/pom.xml
b/plc4j/transports/raw-socket/pom.xml
index 924355f1dd..0f315cd4fd 100644
--- a/plc4j/transports/raw-socket/pom.xml
+++ b/plc4j/transports/raw-socket/pom.xml
@@ -70,6 +70,13 @@
</dependency>
<!-- Test Dependencies -->
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-utils-test-utils</artifactId>
+ <version>0.14.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
diff --git
a/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/PcapTestSupport.java
b/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/PcapTestSupport.java
deleted file mode 100644
index ca7a8987bd..0000000000
---
a/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/PcapTestSupport.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.transport.rawsocket;
-
-import org.pcap4j.core.PcapNetworkInterface;
-import org.pcap4j.core.Pcaps;
-
-import java.io.File;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assumptions.assumeTrue;
-
-/**
- * Helper for the pcap-based tests.
- * <p>
- * The pcap4j native library (libpcap on *nix/macOS, wpcap.dll on Windows) is
not
- * available on all CI nodes - notably Windows runners without WinPcap/Npcap
installed.
- * When the native library can't be loaded, pcap4j fails by throwing {@link
Error}s
- * (e.g. {@link NoClassDefFoundError} / {@link UnsatisfiedLinkError} /
- * {@link ExceptionInInitializerError}) rather than checked exceptions, so a
plain
- * {@code catch (Exception ...)} doesn't skip the affected tests and the build
fails.
- * These helpers translate any {@link Throwable} into a JUnit assumption so
the tests
- * are skipped instead.
- */
-final class PcapTestSupport {
-
- private PcapTestSupport() {
- }
-
- /**
- * Points JNA at a libpcap installation in the well-known Homebrew
locations on macOS.
- * On other platforms this is a no-op and the default library resolution
is used.
- */
- static void configureNativeLibraryPath() {
- // For some reason it doesn't work if we pass this in from the outside.
- // On an Intel Mac the libs are in:
"/usr/local/Cellar/libpcap/<version>/lib"
- // On an M1 Mac the libs are in: "/opt/homebrew/opt/libpcap/lib"
- if (new File("/usr/local/Cellar/libpcap/1.10.1/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/usr/local/Cellar/libpcap/1.10.1/lib");
- } else if (new File("/usr/local/Cellar/libpcap/1.10.5/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/usr/local/Cellar/libpcap/1.10.5/lib");
- } else if (new File("/opt/homebrew/opt/libpcap/lib").exists()) {
- System.getProperties().setProperty("jna.library.path",
"/opt/homebrew/opt/libpcap/lib");
- }
- }
-
- /**
- * Returns the available pcap network interfaces, or aborts the current
test (via a
- * JUnit assumption) if pcap is unavailable - either because the native
library could
- * not be loaded or because no interfaces were found.
- *
- * @return the (non-empty) list of network interfaces
- */
- static List<PcapNetworkInterface> findAllDevsOrSkip() {
- configureNativeLibraryPath();
- List<PcapNetworkInterface> devs;
- try {
- devs = Pcaps.findAllDevs();
- } catch (Throwable t) {
- // Native library missing/unloadable (NoClassDefFoundError,
UnsatisfiedLinkError, ...)
- // or pcap permission issues - skip rather than fail.
- assumeTrue(false, "pcap native library not available, skipping
test: " + t);
- throw new AssertionError("unreachable");
- }
- assumeTrue(devs != null && !devs.isEmpty(), "No network interfaces
found");
- return devs;
- }
-}
diff --git
a/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransportInstanceTest.java
b/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransportInstanceTest.java
index df4a925966..6ec59f99e6 100644
---
a/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransportInstanceTest.java
+++
b/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransportInstanceTest.java
@@ -21,12 +21,14 @@ package org.apache.plc4x.java.transport.rawsocket;
import org.apache.plc4x.java.spi.transports.api.exceptions.TransportException;
import
org.apache.plc4x.java.transport.rawsocket.config.RawSocketTransportConfiguration;
import org.apache.plc4x.java.utils.auditlog.api.AuditLog;
+import org.apache.plc4x.java.utils.testutils.RequirePcap;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.pcap4j.core.PcapHandle;
import org.pcap4j.core.PcapNetworkInterface;
+import org.pcap4j.core.Pcaps;
import org.pcap4j.util.MacAddress;
import java.util.List;
@@ -36,9 +38,11 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
/**
* Tests for RawSocketTransportInstance.
- * Note: These tests require pcap permissions (root/admin) to run.
- * They use assumptions to skip when permissions are not enough.
+ * Note: These tests require the pcap native library (skipped via {@link
RequirePcap} when
+ * absent, e.g. on Windows CI without Npcap) plus pcap permissions
(root/admin); assumptions
+ * skip individual tests when permissions are not enough.
*/
+@RequirePcap
class RawSocketTransportInstanceTest {
private PcapHandle handle;
@@ -51,8 +55,9 @@ class RawSocketTransportInstanceTest {
@BeforeEach
void setUp() {
try {
- // Find available network interface (skips the test if pcap native
libs are unavailable)
- List<PcapNetworkInterface> devs =
PcapTestSupport.findAllDevsOrSkip();
+ // Find available network interface
+ List<PcapNetworkInterface> devs = Pcaps.findAllDevs();
+ assumeTrue(devs != null && !devs.isEmpty(), "No network interfaces
found");
// Find an Ethernet-capable interface (not loopback, not tunnel)
PcapNetworkInterface selectedNif = null;
diff --git
a/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransportTest.java
b/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransportTest.java
index 6bc1d91f42..ef476d32a0 100644
---
a/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransportTest.java
+++
b/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/RawSocketTransportTest.java
@@ -23,15 +23,18 @@ import
org.apache.plc4x.java.spi.transports.api.config.TransportConfiguration;
import org.apache.plc4x.java.spi.transports.api.exceptions.TransportException;
import
org.apache.plc4x.java.transport.rawsocket.config.RawSocketTransportConfiguration;
import org.apache.plc4x.java.utils.auditlog.api.AuditLog;
+import org.apache.plc4x.java.utils.testutils.RequirePcap;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.pcap4j.core.PcapNetworkInterface;
+import org.pcap4j.core.Pcaps;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
// Timeout prevents pcap operations from hanging the entire test suite
@Timeout(value = 30, unit = TimeUnit.SECONDS)
@@ -41,7 +44,6 @@ class RawSocketTransportTest {
@BeforeEach
void setUp() {
- PcapTestSupport.configureNativeLibraryPath();
transport = new RawSocketTransport();
}
@@ -61,9 +63,11 @@ class RawSocketTransportTest {
}
@Test
+ @RequirePcap
void testCreateTransportInstance_dedicated() throws Exception {
// Skip if no network interfaces or no pcap permissions
- List<PcapNetworkInterface> devs = PcapTestSupport.findAllDevsOrSkip();
+ List<PcapNetworkInterface> devs = Pcaps.findAllDevs();
+ assumeTrue(devs != null && !devs.isEmpty(), "No network interfaces
found");
PcapNetworkInterface nif = devs.get(0);
@@ -89,8 +93,10 @@ class RawSocketTransportTest {
}
@Test
+ @RequirePcap
void testCreateTransportInstance_shared() throws Exception {
- List<PcapNetworkInterface> devs = PcapTestSupport.findAllDevsOrSkip();
+ List<PcapNetworkInterface> devs = Pcaps.findAllDevs();
+ assumeTrue(devs != null && !devs.isEmpty(), "No network interfaces
found");
PcapNetworkInterface nif = devs.get(0);
@@ -114,9 +120,11 @@ class RawSocketTransportTest {
}
@Test
+ @RequirePcap
//@Disabled("All of a sudden this test hangs ... investigate")
void testCreateTransportInstance_multipleShared() throws Exception {
- List<PcapNetworkInterface> devs = PcapTestSupport.findAllDevsOrSkip();
+ List<PcapNetworkInterface> devs = Pcaps.findAllDevs();
+ assumeTrue(devs != null && !devs.isEmpty(), "No network interfaces
found");
PcapNetworkInterface nif = devs.get(0);
@@ -156,8 +164,10 @@ class RawSocketTransportTest {
}
@Test
+ @RequirePcap
void testCreateTransportInstance_withVLAN() throws Exception {
- List<PcapNetworkInterface> devs = PcapTestSupport.findAllDevsOrSkip();
+ List<PcapNetworkInterface> devs = Pcaps.findAllDevs();
+ assumeTrue(devs != null && !devs.isEmpty(), "No network interfaces
found");
PcapNetworkInterface nif = devs.get(0);
@@ -183,8 +193,10 @@ class RawSocketTransportTest {
}
@Test
+ @RequirePcap
void testCreateTransportInstance_withCustomBPF() throws Exception {
- List<PcapNetworkInterface> devs = PcapTestSupport.findAllDevsOrSkip();
+ List<PcapNetworkInterface> devs = Pcaps.findAllDevs();
+ assumeTrue(devs != null && !devs.isEmpty(), "No network interfaces
found");
PcapNetworkInterface nif = devs.get(0);
@@ -209,8 +221,10 @@ class RawSocketTransportTest {
}
@Test
+ @RequirePcap
void testCreateTransportInstance_promiscuousMode() throws Exception {
- List<PcapNetworkInterface> devs = PcapTestSupport.findAllDevsOrSkip();
+ List<PcapNetworkInterface> devs = Pcaps.findAllDevs();
+ assumeTrue(devs != null && !devs.isEmpty(), "No network interfaces
found");
PcapNetworkInterface nif = devs.get(0);
@@ -235,10 +249,8 @@ class RawSocketTransportTest {
}
@Test
+ @RequirePcap
void testCreateTransportInstance_invalidInterface() {
- // Constructing the instance reaches pcap's native layer, so skip when
it's unavailable.
- PcapTestSupport.findAllDevsOrSkip();
-
RawSocketTransportConfiguration config = new
RawSocketTransportConfiguration();
config.interfaceName = "INVALID_INTERFACE_THAT_DOES_NOT_EXIST";
config.remoteAddress = "00:00:00:00:00:01";
diff --git
a/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/SharedRawSocketManagerTest.java
b/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/SharedRawSocketManagerTest.java
index e708ad382f..68ffd9fe43 100644
---
a/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/SharedRawSocketManagerTest.java
+++
b/plc4j/transports/raw-socket/src/test/java/org/apache/plc4x/java/transport/rawsocket/SharedRawSocketManagerTest.java
@@ -18,27 +18,34 @@
*/
package org.apache.plc4x.java.transport.rawsocket;
+import org.apache.plc4x.java.utils.testutils.RequirePcap;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pcap4j.core.PcapNetworkInterface;
+import org.pcap4j.core.Pcaps;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
/**
* Tests for SharedRawSocketManager.
- * Note: These tests require pcap permissions to run.
+ * Note: These tests require the pcap native library (skipped via {@link
RequirePcap} when
+ * absent, e.g. on Windows CI without Npcap) plus pcap permissions to run.
*/
+@RequirePcap
class SharedRawSocketManagerTest {
private SharedRawSocketManager manager;
private PcapNetworkInterface testInterface;
@BeforeEach
- void setUp() {
+ void setUp() throws Exception {
manager = new SharedRawSocketManager();
- testInterface = PcapTestSupport.findAllDevsOrSkip().get(0);
+ List<PcapNetworkInterface> devs = Pcaps.findAllDevs();
+ assumeTrue(devs != null && !devs.isEmpty(), "No network interfaces
found");
+ testInterface = devs.get(0);
}
@Test
diff --git
a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/java/utils/testutils/RequirePcapCondition.java
b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/java/utils/testutils/RequirePcapCondition.java
index 21f12047ee..e3612ffef1 100644
---
a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/java/utils/testutils/RequirePcapCondition.java
+++
b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/java/utils/testutils/RequirePcapCondition.java
@@ -26,6 +26,7 @@ import org.pcap4j.core.Pcaps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -35,6 +36,9 @@ public class RequirePcapCondition implements
ExecutionCondition {
@Override
public ConditionEvaluationResult
evaluateExecutionCondition(ExtensionContext extensionContext) {
+ // On macOS the bundled libpcap is too old, so point JNA at a
Homebrew-installed one
+ // before the native bindings are first loaded.
+ configureMacOsLibraryPath();
try {
String libVersion = Pcaps.libVersion();
Pattern pattern = Pattern.compile("^.*libpcap version
(?<version>\\d+\\.\\d+(?:\\.\\d+)?)[^\\d]?.*$");
@@ -43,16 +47,34 @@ public class RequirePcapCondition implements
ExecutionCondition {
String versionString = matcher.group("version");
return ConditionEvaluationResult.enabled("Found libpcap
version " + versionString);
}
- } catch (Exception e) {
- logger.info("Error detecting libpcap version.", e);
+ logger.info("Could not parse a libpcap version from '{}'",
libVersion);
+ } catch (Throwable t) {
+ // A missing native library surfaces as an Error (e.g.
NoClassDefFoundError /
+ // UnsatisfiedLinkError), not an Exception - so catch Throwable
here, otherwise the
+ // whole annotated test class errors out instead of being cleanly
disabled
+ // (e.g. on Windows CI without Npcap installed).
+ logger.info("Error detecting libpcap version.", t);
}
if (SystemUtils.IS_OS_WINDOWS) {
- System.out.println("DISABLED-RequirePcapCondition");
return ConditionEvaluationResult.disabled("Test disabled due to
missing or invalid Npcap version. Please install from here: https://npcap.com/
as this version supports all needed features.");
} else {
- System.out.println("DISABLED-RequirePcapCondition");
return ConditionEvaluationResult.disabled("Test disabled due to
missing or invalid libpcap version. Please install at least version 1.1.0 to
support all features.");
}
}
+ private static void configureMacOsLibraryPath() {
+ if (!SystemUtils.IS_OS_MAC) {
+ return;
+ }
+ // On an Intel Mac the libs are in:
"/usr/local/Cellar/libpcap/<version>/lib"
+ // On an M1 Mac the libs are in: "/opt/homebrew/opt/libpcap/lib"
+ if (new File("/usr/local/Cellar/libpcap/1.10.1/lib").exists()) {
+ System.getProperties().setProperty("jna.library.path",
"/usr/local/Cellar/libpcap/1.10.1/lib");
+ } else if (new File("/usr/local/Cellar/libpcap/1.10.5/lib").exists()) {
+ System.getProperties().setProperty("jna.library.path",
"/usr/local/Cellar/libpcap/1.10.5/lib");
+ } else if (new File("/opt/homebrew/opt/libpcap/lib").exists()) {
+ System.getProperties().setProperty("jna.library.path",
"/opt/homebrew/opt/libpcap/lib");
+ }
+ }
+
}