From 1f0dafc78779e5c20d381acfd8751d20dca4dece Mon Sep 17 00:00:00 2001 From: kishore Date: Wed, 8 Jan 2025 19:39:07 +0530 Subject: [PATCH 1/4] MANGO-1817 - fix build methods in IpNetworkBuilder to get the Local IP address, Broadcast and SubnetMask assigned to the NIC. MANGO-1818 - Deprecate withReuseAddress in IpNetworkBuilder as this flag would be set based on the OS MANGO-1832 - Add new method to build the network from the interface name in IpNetworkBuilder Add Unit Tests for the above feature IpNetworkBuilderTest Remove usage withReuseAddress in ahoc/IPMasterTest and adhoc/MultipleLocalDevices Change BACnet4J revision from 6.0.1-SNAPSHOT to 6.1.0-SNAPSHOT --- pom.xml | 2 +- .../bacnet4j/npdu/ip/IpNetworkBuilder.java | 23 +-- .../bacnet4j/npdu/ip/IpNetworkUtils.java | 136 +++++++++++++++++- .../bacnet4j/adhoc/IpMasterTest.java | 15 +- .../bacnet4j/adhoc/MultipleLocalDevices.java | 4 +- .../npdu/ip/IpNetworkBuilderTest.java | 87 +++++++++++ 6 files changed, 247 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index e64e13a3..af3afa8c 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ https://www.infiniteautomation.com/ - 6.0.1-SNAPSHOT + 6.1.0-SNAPSHOT UTF-8 additional-deployment-repository diff --git a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java index 42760a59..1664ed89 100644 --- a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java +++ b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java @@ -30,8 +30,6 @@ import static com.serotonin.bacnet4j.npdu.ip.IpNetworkUtils.toIpAddrString; -import org.apache.commons.lang3.StringUtils; - import com.serotonin.bacnet4j.type.constructed.Address; import com.serotonin.bacnet4j.util.BACnetUtils; @@ -41,10 +39,12 @@ public class IpNetworkBuilder { private String subnetMask; private int port = IpNetwork.DEFAULT_PORT; private int localNetworkNumber = Address.LOCAL_NETWORK; - private boolean reuseAddress = false; + private boolean reuseAddress = (System.getProperty("os.name").contains("Windows")) ? false : true; public IpNetworkBuilder withLocalBindAddress(final String localBindAddress) { this.localBindAddress = localBindAddress; + this.broadcastAddress = IpNetworkUtils.getLocalBroadcastAddressString(localBindAddress); + this.subnetMask = IpNetworkUtils.getSubnetMask(localBindAddress); return this; } @@ -60,7 +60,7 @@ public IpNetworkBuilder withLocalBindAddress(final String localBindAddress) { public IpNetworkBuilder withBroadcast(final String broadcastAddress, final int networkPrefixLength) { this.broadcastAddress = broadcastAddress; this.subnetMask = toIpAddrString(IpNetworkUtils.createMask(networkPrefixLength)); - + this.localBindAddress = IpNetworkUtils.getIPAddressString(this.broadcastAddress); return this; } @@ -83,7 +83,7 @@ public IpNetworkBuilder withSubnet(final String subnetAddress, final int network final long subnet = IpNetworkUtils.bytesToLong(BACnetUtils.dottedStringToBytes(subnetAddress)); this.broadcastAddress = toIpAddrString(subnet | negMask); - + this.localBindAddress = IpNetworkUtils.getIPAddressString(this.broadcastAddress); return this; } @@ -97,11 +97,18 @@ public IpNetworkBuilder withLocalNetworkNumber(final int localNetworkNumber) { return this; } - public IpNetworkBuilder withReuseAddress(final boolean reuseAddress) { - this.reuseAddress = reuseAddress; + // private IpNetworkBuilder withReuseAddress(final boolean reuseAddress) { + // this.reuseAddress = reuseAddress; + // return this; + // } + + public IpNetworkBuilder withInterfaceName(final String ifaceName ){ + this.localBindAddress = IpNetworkUtils.getIPAddressString(ifaceName); + this.broadcastAddress = IpNetworkUtils.getLocalBroadcastAddressString(ifaceName); + this.subnetMask = IpNetworkUtils.getSubnetMask(ifaceName); return this; } - + public String getLocalBindAddress() { return localBindAddress; } diff --git a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java index a2f199e4..d1e5c1e4 100644 --- a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java +++ b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java @@ -35,7 +35,9 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.serotonin.bacnet4j.type.constructed.Address; import com.serotonin.bacnet4j.type.primitive.OctetString; @@ -158,16 +160,40 @@ public static Address toAddress(final int networkNumber, final InetSocketAddress return toAddress(networkNumber, addr.getAddress().getAddress(), addr.getPort()); } - public static List getLocalInterfaceAddresses() { + /** + * Convenient method to get the deails of Network Interface card + * Details are stored in a dictionary containing key and values + * key (int) - NIC Card Index as per the OS + * Values (ArrayList of String) of size 4 in the order + * Values[0] - Interface Name + * Values[1] - IP4 Address assigned to the NIC + * Values[2] - Broadcast Address + * Values[3] - Subnet Mask + * @return Map> + */ + public static Map> getLocalInterfaceAddresses() { try { - final List result = new ArrayList<>(); + List ifaceAddresses = new ArrayList<>(); + Map> ifaceDetails = new HashMap<>(); for (final NetworkInterface iface : Collections.list(NetworkInterface.getNetworkInterfaces())) { for (final InterfaceAddress addr : iface.getInterfaceAddresses()) { - if (!addr.getAddress().isLoopbackAddress() && addr.getAddress().isSiteLocalAddress()) - result.add(addr); + if (!addr.getAddress().isLoopbackAddress() && addr.getAddress().isSiteLocalAddress()){ + ifaceAddresses.add(iface.getName()); + ifaceAddresses.add(addr.getAddress().getHostName()); + ifaceAddresses.add(addr.getBroadcast().getHostName()); + final int networkPrefixLength = addr.getNetworkPrefixLength(); + final long subnetMask = createMask(networkPrefixLength); + ifaceAddresses.add(toIpAddrString(subnetMask)); + final List values = new ArrayList<>(); + for (String sValue:ifaceAddresses){ + values.add(sValue); + } + ifaceDetails.put(iface.getIndex(), values); + } } + ifaceAddresses.clear(); } - return result; + return ifaceDetails; } catch (final Exception e) { // Should never happen, so just wrap in a RuntimeException throw new RuntimeException(e); @@ -199,4 +225,104 @@ public static String toIpAddrString(final long addr) { sb.append(addr & 0xFF); return sb.toString(); } + + + /** + * Method to return the IP Address in dotted string based on + * the broadcast Address string or IP Address string. + * Throws exception if the Broadcast Address or IP address is + * not configured in any of the available Network Interface + * + * @param host + * @return IPAddress + */ + public static String getIPAddressString(String host) + { + try{ + String ipAdd = "0.0.0.0"; + int interfaceIndex = -1; + for (Map.Entry> item: getLocalInterfaceAddresses().entrySet()){ + if (item.getValue().contains(host)){ + interfaceIndex = item.getKey(); + // IP Address is stored in the index 1 + return item.getValue().get(1); + } + } + if (interfaceIndex == -1) + { + throw new IllegalArgumentException(host + " is not configured in any interfaces."); + } + return ipAdd; + + }catch (final Exception e) { + // Should never happen, so just wrap in a RuntimeException + throw new RuntimeException(e); + } + } + + /** + * Method to return the Broadcast IP Address configured + // for the corresponding interface based on + * the local IP Address string. + * Throws exception if the IP address is + * not configured in any of the available Network Interface. + * + * @param host + * @return BroadcastAddress + */ + public static String getLocalBroadcastAddressString(String host) + { + try{ + String broadcastAdd = "255.255.255.255"; + int interfaceIndex = -1; + for (Map.Entry> item: getLocalInterfaceAddresses().entrySet()){ + if (item.getValue().contains(host)){ + interfaceIndex = item.getKey(); + // Broadcast Address is stored in the index 2 + return item.getValue().get(2); + } + } + if (interfaceIndex == -1) + throw new IllegalArgumentException(host + " is not configured in any interfaces."); + + return broadcastAdd; + + }catch (final Exception e) { + // Should never happen, so just wrap in a RuntimeException + throw new RuntimeException(e); + } + } + + + /** + * Method to return the the Subnet Mask configured + * for the corresponding interface based on the + * local IP Address string. + * Throws exception if the IP address is + * not configured in any of the available Network Interface. + * + * @param host + * @return String SubnetMask + */ + public static String getSubnetMask(String host) + { + try{ + String subnetMaskAdd = "255.255.255.0"; + int interfaceIndex = -1; + for (Map.Entry> item: getLocalInterfaceAddresses().entrySet()){ + if (item.getValue().contains(host)){ + interfaceIndex = item.getKey(); + return item.getValue().get(3); + } + } + if (interfaceIndex == -1) + throw new IllegalArgumentException(host + "is not configured in any interfaces."); + + return subnetMaskAdd; + + }catch (final Exception e) { + // Should never happen, so just wrap in a RuntimeException + throw new RuntimeException(e); + } + } } diff --git a/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java b/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java index 58328bbd..ed027a0e 100644 --- a/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java +++ b/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java @@ -6,6 +6,9 @@ package com.serotonin.bacnet4j.adhoc; +import java.util.List; +import java.util.Map; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,6 +18,7 @@ import com.serotonin.bacnet4j.exception.BACnetException; import com.serotonin.bacnet4j.npdu.Network; import com.serotonin.bacnet4j.npdu.ip.IpNetworkBuilder; +import com.serotonin.bacnet4j.npdu.ip.IpNetworkUtils; import com.serotonin.bacnet4j.service.unconfirmed.WhoIsRequest; import com.serotonin.bacnet4j.transport.DefaultTransport; import com.serotonin.bacnet4j.transport.Transport; @@ -34,12 +38,15 @@ public static void main(final String[] args) throws Exception { } public LocalDevice createIpLocalDevice() throws Exception { - Network network =network = new IpNetworkBuilder() - .withLocalBindAddress("0.0.0.0") - .withBroadcast("255.255.255.255", 24) + Map> interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); + String ifaceName = interfaceDetails.get(0).get(0); + Network network = new IpNetworkBuilder() + .withInterfaceName(ifaceName) + // .withLocalBindAddress("0.0.0.0") + // .withBroadcast("255.255.255.255", 24) .withPort(47808) .withLocalNetworkNumber(5) - .withReuseAddress(true) + // .withReuseAddress(true) .build(); Transport transport = new DefaultTransport(network); diff --git a/src/test/java/com/serotonin/bacnet4j/adhoc/MultipleLocalDevices.java b/src/test/java/com/serotonin/bacnet4j/adhoc/MultipleLocalDevices.java index 8956ee9f..cad62cad 100644 --- a/src/test/java/com/serotonin/bacnet4j/adhoc/MultipleLocalDevices.java +++ b/src/test/java/com/serotonin/bacnet4j/adhoc/MultipleLocalDevices.java @@ -38,7 +38,7 @@ public static void main(final String[] args) throws Exception { IpNetwork networkOne = new IpNetworkBuilder() .withLocalBindAddress(bindAddress1) .withBroadcast("255.255.255.255", 24) - .withLocalNetworkNumber(1).withPort(47808).withReuseAddress(false).build(); + .withLocalNetworkNumber(1).withPort(47808).build(); Transport transportOne = new DefaultTransport(networkOne); LocalDevice localDeviceOne = new LocalDevice(1, transportOne); @@ -60,7 +60,7 @@ public static void main(final String[] args) throws Exception { IpNetwork networkTwo = new IpNetworkBuilder() .withLocalBindAddress(bindAddress2) .withBroadcast("255.255.255.255", 24) - .withLocalNetworkNumber(1).withPort(47808).withReuseAddress(false).build(); + .withLocalNetworkNumber(1).withPort(47808).build(); Transport transportTwo = new DefaultTransport(networkTwo); LocalDevice localDeviceTwo = new LocalDevice(2, transportTwo); diff --git a/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java b/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java index cf3f5a33..066baa9f 100644 --- a/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java +++ b/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java @@ -1,6 +1,13 @@ package com.serotonin.bacnet4j.npdu.ip; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Random; import org.junit.Test; @@ -46,4 +53,84 @@ public void withBroadcast19() { assertEquals("192.168.223.255", builder.getBroadcastAddress()); assertEquals("255.255.224.0", builder.getSubnetMask()); } + + @Test + public void withLocalIPAddress(){ + try { + Random rand = new Random(); + Map> interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); + List keys = new ArrayList<>(interfaceDetails.keySet()); + final int interfaceIndex = keys.get(rand.nextInt(keys.size())); + String IPAddress = interfaceDetails.get(interfaceIndex).get(1); + final IpNetworkBuilder builder = new IpNetworkBuilder().withLocalBindAddress(IPAddress); + assertEquals(IPAddress,builder.getLocalBindAddress()); + assertEquals(interfaceDetails.get(interfaceIndex).get(2), builder.getBroadcastAddress()); + assertEquals(interfaceDetails.get(interfaceIndex).get(3), builder.getSubnetMask()); + System.out.println(IPAddress); + + }catch (final Exception e) { + // Should never happen, so just wrap in a RuntimeException + throw new RuntimeException(e); + } + } + @Test + public void withBroadcast(){ + try { + Random rand = new Random(); + Map> interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); + List keys = new ArrayList<>(interfaceDetails.keySet()); + final int interfaceIndex = keys.get(rand.nextInt(keys.size())); + String IPAddress = interfaceDetails.get(interfaceIndex).get(2); + final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast(IPAddress, 24); + assertEquals(IPAddress,builder.getBroadcastAddress()); + assertEquals(interfaceDetails.get(interfaceIndex).get(1), builder.getLocalBindAddress()); + assertEquals(interfaceDetails.get(interfaceIndex).get(3), builder.getSubnetMask()); + System.out.println(IPAddress); + + }catch (final Exception e) { + // Should never happen, so just wrap in a RuntimeException + throw new RuntimeException(e); + } + + } + + + @Test + public void withLocalBindAddress_IncorrectIP(){ + String IPAddress = "1.1.1.1"; + Exception exception = assertThrows(RuntimeException.class,() -> { + final IpNetworkBuilder builder = new IpNetworkBuilder().withLocalBindAddress(IPAddress); + }); + String actualMsg = exception.getMessage(); + System.out.println(actualMsg); + assertTrue((actualMsg.contains("IllegalArgument"))); + } + + @Test + public void verifyReuseAddress(){ + final IpNetworkBuilder builder = new IpNetworkBuilder(); + if (System.getProperty("os.name").contains("Windows")) + + assertTrue(!builder.isReuseAddress());//reuseAddress = false; + else + assertTrue(builder.isReuseAddress()); + System.out.println(builder.isReuseAddress()); + } + + @Test + public void withIterfaceName(){ + Random rand = new Random(); + Map> interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); + List keys = new ArrayList<>(interfaceDetails.keySet()); + System.out.println(keys); + final int interfaceIndex = keys.get(rand.nextInt(keys.size())); + String ifaceName = interfaceDetails.get(interfaceIndex).get(0); + final IpNetworkBuilder builder = new IpNetworkBuilder().withInterfaceName(ifaceName); + assertEquals(interfaceDetails.get(interfaceIndex).get(1), builder.getLocalBindAddress()); + assertEquals(interfaceDetails.get(interfaceIndex).get(2),builder.getBroadcastAddress()); + assertEquals(interfaceDetails.get(interfaceIndex).get(3), builder.getSubnetMask()); + System.out.println("Local Bind Address : " + interfaceDetails.get(interfaceIndex).get(1) + + " BroadcastAddress : " + interfaceDetails.get(interfaceIndex).get(2) + " SubnetMask: "+ interfaceDetails.get(interfaceIndex).get(3)); + + } } From 88711bf1afac04564938bf40bcf2789f965f1fa9 Mon Sep 17 00:00:00 2001 From: kishore Date: Tue, 14 Jan 2025 13:08:56 +0530 Subject: [PATCH 2/4] Incorporated the changes as per the review comments. --- .../bacnet4j/npdu/ip/IpNetworkBuilder.java | 11 +-- .../bacnet4j/npdu/ip/IpNetworkUtils.java | 2 +- .../bacnet4j/adhoc/IpMasterTest.java | 7 +- .../npdu/ip/IpNetworkBuilderTest.java | 78 ++++++++----------- 4 files changed, 39 insertions(+), 59 deletions(-) diff --git a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java index 1664ed89..3cf5a2ee 100644 --- a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java +++ b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java @@ -30,6 +30,8 @@ import static com.serotonin.bacnet4j.npdu.ip.IpNetworkUtils.toIpAddrString; +import org.apache.commons.lang3.SystemUtils; + import com.serotonin.bacnet4j.type.constructed.Address; import com.serotonin.bacnet4j.util.BACnetUtils; @@ -39,7 +41,7 @@ public class IpNetworkBuilder { private String subnetMask; private int port = IpNetwork.DEFAULT_PORT; private int localNetworkNumber = Address.LOCAL_NETWORK; - private boolean reuseAddress = (System.getProperty("os.name").contains("Windows")) ? false : true; + final private boolean reuseAddress = (SystemUtils.IS_OS_WINDOWS) ? false : true; public IpNetworkBuilder withLocalBindAddress(final String localBindAddress) { this.localBindAddress = localBindAddress; @@ -97,12 +99,7 @@ public IpNetworkBuilder withLocalNetworkNumber(final int localNetworkNumber) { return this; } - // private IpNetworkBuilder withReuseAddress(final boolean reuseAddress) { - // this.reuseAddress = reuseAddress; - // return this; - // } - - public IpNetworkBuilder withInterfaceName(final String ifaceName ){ + public IpNetworkBuilder withInterfaceName(final String ifaceName ){ this.localBindAddress = IpNetworkUtils.getIPAddressString(ifaceName); this.broadcastAddress = IpNetworkUtils.getLocalBroadcastAddressString(ifaceName); this.subnetMask = IpNetworkUtils.getSubnetMask(ifaceName); diff --git a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java index d1e5c1e4..233e056a 100644 --- a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java +++ b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java @@ -316,7 +316,7 @@ public static String getSubnetMask(String host) } } if (interfaceIndex == -1) - throw new IllegalArgumentException(host + "is not configured in any interfaces."); + throw new IllegalArgumentException(host + " is not configured in any interfaces."); return subnetMaskAdd; diff --git a/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java b/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java index ed027a0e..702353d8 100644 --- a/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java +++ b/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java @@ -6,6 +6,7 @@ package com.serotonin.bacnet4j.adhoc; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -39,14 +40,12 @@ public static void main(final String[] args) throws Exception { public LocalDevice createIpLocalDevice() throws Exception { Map> interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); - String ifaceName = interfaceDetails.get(0).get(0); + List keys = new ArrayList<>(interfaceDetails.keySet()); + String ifaceName = interfaceDetails.get(keys.get(0)).get(0); Network network = new IpNetworkBuilder() .withInterfaceName(ifaceName) - // .withLocalBindAddress("0.0.0.0") - // .withBroadcast("255.255.255.255", 24) .withPort(47808) .withLocalNetworkNumber(5) - // .withReuseAddress(true) .build(); Transport transport = new DefaultTransport(network); diff --git a/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java b/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java index 066baa9f..c849b9f4 100644 --- a/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java +++ b/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java @@ -9,9 +9,14 @@ import java.util.Map; import java.util.Random; +import org.junit.Before; import org.junit.Test; public class IpNetworkBuilderTest { + + int interfaceIndex; + Map> interfaceDetails; + @Test public void withSubnet16() { final IpNetworkBuilder builder = new IpNetworkBuilder().withSubnet("192.168.0.0", 16); @@ -54,53 +59,40 @@ public void withBroadcast19() { assertEquals("255.255.224.0", builder.getSubnetMask()); } + @Before public void initialize(){ + Random rand = new Random(); + interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); + List keys = new ArrayList<>(interfaceDetails.keySet()); + interfaceIndex = keys.get(rand.nextInt(keys.size())); + } + @Test - public void withLocalIPAddress(){ - try { - Random rand = new Random(); - Map> interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); - List keys = new ArrayList<>(interfaceDetails.keySet()); - final int interfaceIndex = keys.get(rand.nextInt(keys.size())); - String IPAddress = interfaceDetails.get(interfaceIndex).get(1); - final IpNetworkBuilder builder = new IpNetworkBuilder().withLocalBindAddress(IPAddress); - assertEquals(IPAddress,builder.getLocalBindAddress()); - assertEquals(interfaceDetails.get(interfaceIndex).get(2), builder.getBroadcastAddress()); - assertEquals(interfaceDetails.get(interfaceIndex).get(3), builder.getSubnetMask()); - System.out.println(IPAddress); - - }catch (final Exception e) { - // Should never happen, so just wrap in a RuntimeException - throw new RuntimeException(e); - } + public void withLocalIPAddress() throws RuntimeException{ + + String IPAddress = interfaceDetails.get(interfaceIndex).get(1); + final IpNetworkBuilder builder = new IpNetworkBuilder().withLocalBindAddress(IPAddress); + assertEquals(IPAddress,builder.getLocalBindAddress()); + assertEquals(interfaceDetails.get(interfaceIndex).get(2), builder.getBroadcastAddress()); + assertEquals(interfaceDetails.get(interfaceIndex).get(3), builder.getSubnetMask()); } + @Test - public void withBroadcast(){ - try { - Random rand = new Random(); - Map> interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); - List keys = new ArrayList<>(interfaceDetails.keySet()); - final int interfaceIndex = keys.get(rand.nextInt(keys.size())); - String IPAddress = interfaceDetails.get(interfaceIndex).get(2); - final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast(IPAddress, 24); - assertEquals(IPAddress,builder.getBroadcastAddress()); - assertEquals(interfaceDetails.get(interfaceIndex).get(1), builder.getLocalBindAddress()); - assertEquals(interfaceDetails.get(interfaceIndex).get(3), builder.getSubnetMask()); - System.out.println(IPAddress); + public void withBroadcast() throws RuntimeException{ + + String IPAddress = interfaceDetails.get(interfaceIndex).get(2); + final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast(IPAddress, 24); + assertEquals(IPAddress,builder.getBroadcastAddress()); + assertEquals(interfaceDetails.get(interfaceIndex).get(1), builder.getLocalBindAddress()); + assertEquals(interfaceDetails.get(interfaceIndex).get(3), builder.getSubnetMask()); - }catch (final Exception e) { - // Should never happen, so just wrap in a RuntimeException - throw new RuntimeException(e); - } - } @Test - public void withLocalBindAddress_IncorrectIP(){ + public void withLocalBindAddress_IncorrectIP() throws RuntimeException{ String IPAddress = "1.1.1.1"; Exception exception = assertThrows(RuntimeException.class,() -> { - final IpNetworkBuilder builder = new IpNetworkBuilder().withLocalBindAddress(IPAddress); - }); + final IpNetworkBuilder builder = new IpNetworkBuilder().withLocalBindAddress(IPAddress);}); String actualMsg = exception.getMessage(); System.out.println(actualMsg); assertTrue((actualMsg.contains("IllegalArgument"))); @@ -110,27 +102,19 @@ public void withLocalBindAddress_IncorrectIP(){ public void verifyReuseAddress(){ final IpNetworkBuilder builder = new IpNetworkBuilder(); if (System.getProperty("os.name").contains("Windows")) - assertTrue(!builder.isReuseAddress());//reuseAddress = false; else assertTrue(builder.isReuseAddress()); - System.out.println(builder.isReuseAddress()); + } @Test - public void withIterfaceName(){ - Random rand = new Random(); - Map> interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); - List keys = new ArrayList<>(interfaceDetails.keySet()); - System.out.println(keys); - final int interfaceIndex = keys.get(rand.nextInt(keys.size())); + public void withIterfaceName() throws RuntimeException{ String ifaceName = interfaceDetails.get(interfaceIndex).get(0); final IpNetworkBuilder builder = new IpNetworkBuilder().withInterfaceName(ifaceName); assertEquals(interfaceDetails.get(interfaceIndex).get(1), builder.getLocalBindAddress()); assertEquals(interfaceDetails.get(interfaceIndex).get(2),builder.getBroadcastAddress()); assertEquals(interfaceDetails.get(interfaceIndex).get(3), builder.getSubnetMask()); - System.out.println("Local Bind Address : " + interfaceDetails.get(interfaceIndex).get(1) + - " BroadcastAddress : " + interfaceDetails.get(interfaceIndex).get(2) + " SubnetMask: "+ interfaceDetails.get(interfaceIndex).get(3)); } } From f8afa56e6e6941405ec2f2c9cf82d785d4c978fd Mon Sep 17 00:00:00 2001 From: kishore Date: Tue, 21 Jan 2025 16:43:22 +0530 Subject: [PATCH 3/4] Improvement - The details of NIC are stored in Record format instead of List of strings. Improvement - Improve the methods in IpNetworkUtils.java Improvement - Improve the formatting of the comments using HTML List, parameter and return definition Improvement - Improve the build methods in IPMaster.java Improvement - pom.xml - Change the source and target java version to 21 from 1.8 to accommodate record type --- pom.xml | 4 +- .../bacnet4j/npdu/ip/IpNetworkUtils.java | 136 +++++++++--------- .../bacnet4j/adhoc/IpMasterTest.java | 12 +- .../npdu/ip/IpNetworkBuilderTest.java | 32 ++--- 4 files changed, 94 insertions(+), 90 deletions(-) diff --git a/pom.xml b/pom.xml index af3afa8c..83c826e9 100644 --- a/pom.xml +++ b/pom.xml @@ -48,8 +48,8 @@ maven-compiler-plugin 3.1 - 1.8 - 1.8 + 21 + 21 diff --git a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java index 233e056a..a5d153fe 100644 --- a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java +++ b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java @@ -35,9 +35,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import com.serotonin.bacnet4j.type.constructed.Address; import com.serotonin.bacnet4j.type.primitive.OctetString; @@ -160,38 +158,58 @@ public static Address toAddress(final int networkNumber, final InetSocketAddress return toAddress(networkNumber, addr.getAddress().getAddress(), addr.getPort()); } + + /** + * Following details of the NIC (Network Interface Card) are stored in this record: + *
    + *
  • Integer format of index value of the NIC assigned by the OS
  • + *
  • String format of the name of the NIC
  • + *
  • String format of the IP4 Address assigned to the NIC
  • + *
  • String format of the the broadcast Address of the NIC
  • + *
  • String format of the SubnetMask of the NIC
  • + *
  • Integer format of the Network Prefix Length of the NIC
  • + *
+ */ + public static record InterfaceInfo(int index, + String interfaceName, + String localIPAddress, + String broadcastAddress, + String subnetMask, + int networkPrefixLength) {} + + /** * Convenient method to get the deails of Network Interface card - * Details are stored in a dictionary containing key and values - * key (int) - NIC Card Index as per the OS - * Values (ArrayList of String) of size 4 in the order - * Values[0] - Interface Name - * Values[1] - IP4 Address assigned to the NIC - * Values[2] - Broadcast Address - * Values[3] - Subnet Mask - * @return Map> + *

+ * Values of the following parameters of each NIC are stored in record format: + *

    + *
  • index (int) - NIC Card Index assigned by the OS + *
  • Name of the NIC (String) + *
  • IP4 Address assigned to the NIC (String) + *
  • Broadcast Address of the NIC (String) + *
  • SubnetMask of the NIC calculated based on the NetworkPrefixLength (String) + *
  • Network Prefix Length of the NIC (int) + *
+ * @return the list of records of all NIC available in this device */ - public static Map> getLocalInterfaceAddresses() { + public static List getLocalInterfaceAddresses() { try { - List ifaceAddresses = new ArrayList<>(); - Map> ifaceDetails = new HashMap<>(); + List ifaceDetails = new ArrayList<>(); for (final NetworkInterface iface : Collections.list(NetworkInterface.getNetworkInterfaces())) { for (final InterfaceAddress addr : iface.getInterfaceAddresses()) { if (!addr.getAddress().isLoopbackAddress() && addr.getAddress().isSiteLocalAddress()){ - ifaceAddresses.add(iface.getName()); - ifaceAddresses.add(addr.getAddress().getHostName()); - ifaceAddresses.add(addr.getBroadcast().getHostName()); + String ifaceName = iface.getName(); + String IPAddress = addr.getAddress().getHostName(); + String broadcastAddress = addr.getBroadcast().getHostName(); final int networkPrefixLength = addr.getNetworkPrefixLength(); final long subnetMask = createMask(networkPrefixLength); - ifaceAddresses.add(toIpAddrString(subnetMask)); - final List values = new ArrayList<>(); - for (String sValue:ifaceAddresses){ - values.add(sValue); - } - ifaceDetails.put(iface.getIndex(), values); + String networkMask = toIpAddrString(subnetMask); + int ifaceIndex = iface.getIndex(); + InterfaceInfo ifaceInfo = new InterfaceInfo(ifaceIndex, ifaceName, IPAddress, broadcastAddress, networkMask, networkPrefixLength); + ifaceDetails.add(ifaceInfo); } } - ifaceAddresses.clear(); + } return ifaceDetails; } catch (final Exception e) { @@ -234,25 +252,19 @@ public static String toIpAddrString(final long addr) { * not configured in any of the available Network Interface * * @param host - * @return IPAddress + * @return the IP Address assigned to the NIC */ public static String getIPAddressString(String host) { try{ - String ipAdd = "0.0.0.0"; - int interfaceIndex = -1; - for (Map.Entry> item: getLocalInterfaceAddresses().entrySet()){ - if (item.getValue().contains(host)){ - interfaceIndex = item.getKey(); - // IP Address is stored in the index 1 - return item.getValue().get(1); - } - } - if (interfaceIndex == -1) - { - throw new IllegalArgumentException(host + " is not configured in any interfaces."); + for (InterfaceInfo info:getLocalInterfaceAddresses()){ + if (info.localIPAddress().equals(host) || + info.interfaceName().equals(host) || + info.broadcastAddress().equals(host)) + return info.localIPAddress(); } - return ipAdd; + throw new IllegalArgumentException(host + " is not configured in any interfaces."); + }catch (final Exception e) { // Should never happen, so just wrap in a RuntimeException @@ -262,9 +274,9 @@ public static String getIPAddressString(String host) /** * Method to return the Broadcast IP Address configured - // for the corresponding interface based on - * the local IP Address string. - * Throws exception if the IP address is + * for the corresponding interface based on the + * IP Address string or name of the NIC. + * Throws exception if the IP address or interface name is * not configured in any of the available Network Interface. * * @param host @@ -273,20 +285,17 @@ public static String getIPAddressString(String host) public static String getLocalBroadcastAddressString(String host) { try{ - String broadcastAdd = "255.255.255.255"; - int interfaceIndex = -1; - for (Map.Entry> item: getLocalInterfaceAddresses().entrySet()){ - if (item.getValue().contains(host)){ - interfaceIndex = item.getKey(); - // Broadcast Address is stored in the index 2 - return item.getValue().get(2); - } + for (InterfaceInfo info:getLocalInterfaceAddresses()){ + if (info.localIPAddress().equals(host) || + (info.broadcastAddress() != null && + info.broadcastAddress().equals(host)) || + info.interfaceName().equals(host)) + return info.broadcastAddress(); + } - if (interfaceIndex == -1) + throw new IllegalArgumentException(host + " is not configured in any interfaces."); - return broadcastAdd; - }catch (final Exception e) { // Should never happen, so just wrap in a RuntimeException throw new RuntimeException(e); @@ -297,28 +306,27 @@ public static String getLocalBroadcastAddressString(String host) /** * Method to return the the Subnet Mask configured * for the corresponding interface based on the - * local IP Address string. - * Throws exception if the IP address is - * not configured in any of the available Network Interface. + * IP Address string or interface name. + * Throws IllegalArguement exception if the IP address or + * interface name is not configured in any of the + * available Network Interface. * * @param host - * @return String SubnetMask + * @return SubnetMask of the NIC */ public static String getSubnetMask(String host) { try{ - String subnetMaskAdd = "255.255.255.0"; - int interfaceIndex = -1; - for (Map.Entry> item: getLocalInterfaceAddresses().entrySet()){ - if (item.getValue().contains(host)){ - interfaceIndex = item.getKey(); - return item.getValue().get(3); - } + + for (InterfaceInfo info:getLocalInterfaceAddresses()){ + if (info.localIPAddress().equals(host) || + info.interfaceName().equals(host) || + info.broadcastAddress().equals(host)) + return info.subnetMask(); } - if (interfaceIndex == -1) throw new IllegalArgumentException(host + " is not configured in any interfaces."); - return subnetMaskAdd; + }catch (final Exception e) { // Should never happen, so just wrap in a RuntimeException diff --git a/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java b/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java index 702353d8..5fc1daf2 100644 --- a/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java +++ b/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java @@ -6,9 +6,9 @@ package com.serotonin.bacnet4j.adhoc; -import java.util.ArrayList; + import java.util.List; -import java.util.Map; +import java.util.Random; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,11 +39,11 @@ public static void main(final String[] args) throws Exception { } public LocalDevice createIpLocalDevice() throws Exception { - Map> interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); - List keys = new ArrayList<>(interfaceDetails.keySet()); - String ifaceName = interfaceDetails.get(keys.get(0)).get(0); + Random rand = new Random(); + List interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); + final IpNetworkUtils.InterfaceInfo efaceInfo = interfaceDetails.get(rand.nextInt(interfaceDetails.size())); Network network = new IpNetworkBuilder() - .withInterfaceName(ifaceName) + .withInterfaceName(efaceInfo.interfaceName()) .withPort(47808) .withLocalNetworkNumber(5) .build(); diff --git a/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java b/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java index c849b9f4..906bf045 100644 --- a/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java +++ b/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java @@ -4,9 +4,7 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; -import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Random; import org.junit.Before; @@ -14,8 +12,8 @@ public class IpNetworkBuilderTest { - int interfaceIndex; - Map> interfaceDetails; + IpNetworkUtils.InterfaceInfo efaceInfo; + List interfaceDetails; @Test public void withSubnet16() { @@ -62,29 +60,27 @@ public void withBroadcast19() { @Before public void initialize(){ Random rand = new Random(); interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); - List keys = new ArrayList<>(interfaceDetails.keySet()); - interfaceIndex = keys.get(rand.nextInt(keys.size())); + efaceInfo = interfaceDetails.get(rand.nextInt(interfaceDetails.size())); } @Test public void withLocalIPAddress() throws RuntimeException{ - String IPAddress = interfaceDetails.get(interfaceIndex).get(1); + String IPAddress = efaceInfo.localIPAddress(); final IpNetworkBuilder builder = new IpNetworkBuilder().withLocalBindAddress(IPAddress); assertEquals(IPAddress,builder.getLocalBindAddress()); - assertEquals(interfaceDetails.get(interfaceIndex).get(2), builder.getBroadcastAddress()); - assertEquals(interfaceDetails.get(interfaceIndex).get(3), builder.getSubnetMask()); + assertEquals(efaceInfo.broadcastAddress(), builder.getBroadcastAddress()); + assertEquals(efaceInfo.subnetMask(), builder.getSubnetMask()); } @Test public void withBroadcast() throws RuntimeException{ - String IPAddress = interfaceDetails.get(interfaceIndex).get(2); - final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast(IPAddress, 24); + String IPAddress = efaceInfo.broadcastAddress(); + final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast(IPAddress, efaceInfo.networkPrefixLength()); assertEquals(IPAddress,builder.getBroadcastAddress()); - assertEquals(interfaceDetails.get(interfaceIndex).get(1), builder.getLocalBindAddress()); - assertEquals(interfaceDetails.get(interfaceIndex).get(3), builder.getSubnetMask()); - + assertEquals(efaceInfo.localIPAddress(), builder.getLocalBindAddress()); + assertEquals(efaceInfo.subnetMask(), builder.getSubnetMask()); } @@ -110,11 +106,11 @@ public void verifyReuseAddress(){ @Test public void withIterfaceName() throws RuntimeException{ - String ifaceName = interfaceDetails.get(interfaceIndex).get(0); + String ifaceName = efaceInfo.interfaceName(); final IpNetworkBuilder builder = new IpNetworkBuilder().withInterfaceName(ifaceName); - assertEquals(interfaceDetails.get(interfaceIndex).get(1), builder.getLocalBindAddress()); - assertEquals(interfaceDetails.get(interfaceIndex).get(2),builder.getBroadcastAddress()); - assertEquals(interfaceDetails.get(interfaceIndex).get(3), builder.getSubnetMask()); + assertEquals(efaceInfo.localIPAddress(), builder.getLocalBindAddress()); + assertEquals(efaceInfo.broadcastAddress(),builder.getBroadcastAddress()); + assertEquals(efaceInfo.subnetMask(), builder.getSubnetMask()); } } From 83ac3017020fff806572d2f06bda2e5823595b9c Mon Sep 17 00:00:00 2001 From: kishore Date: Thu, 30 Jan 2025 22:34:05 +0530 Subject: [PATCH 4/4] fix - test failure in BBMDTest.java fix - test failure in IpNetworkBuilderTest.java improvement in comments incoporate review comments --- pom.xml | 13 ++- .../bacnet4j/npdu/ip/IpNetworkBuilder.java | 19 +++- .../bacnet4j/npdu/ip/IpNetworkUtils.java | 14 +-- .../bacnet4j/adhoc/IpMasterTest.java | 17 ++- .../serotonin/bacnet4j/npdu/ip/BBMDTest.java | 21 +++- .../npdu/ip/IpNetworkBuilderTest.java | 104 +++++++++++------- 6 files changed, 119 insertions(+), 69 deletions(-) diff --git a/pom.xml b/pom.xml index 83c826e9..8e3b5bed 100644 --- a/pom.xml +++ b/pom.xml @@ -48,8 +48,8 @@ maven-compiler-plugin 3.1 - 21 - 21 + 17 + 17
@@ -139,10 +139,15 @@ org.mockito mockito-core - 3.0.0 + 5.15.2 + test + + + org.mockito + mockito-junit-jupiter + 5.15.2 test - org.slf4j slf4j-simple diff --git a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java index 3cf5a2ee..cf5bec6c 100644 --- a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java +++ b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilder.java @@ -45,8 +45,11 @@ public class IpNetworkBuilder { public IpNetworkBuilder withLocalBindAddress(final String localBindAddress) { this.localBindAddress = localBindAddress; - this.broadcastAddress = IpNetworkUtils.getLocalBroadcastAddressString(localBindAddress); - this.subnetMask = IpNetworkUtils.getSubnetMask(localBindAddress); + if (this.broadcastAddress == null) + this.broadcastAddress = IpNetworkUtils.getLocalBroadcastAddressString(localBindAddress); + if (this.subnetMask == null) + this.subnetMask = IpNetworkUtils.getSubnetMask(localBindAddress); + return this; } @@ -62,7 +65,9 @@ public IpNetworkBuilder withLocalBindAddress(final String localBindAddress) { public IpNetworkBuilder withBroadcast(final String broadcastAddress, final int networkPrefixLength) { this.broadcastAddress = broadcastAddress; this.subnetMask = toIpAddrString(IpNetworkUtils.createMask(networkPrefixLength)); - this.localBindAddress = IpNetworkUtils.getIPAddressString(this.broadcastAddress); + if (this.localBindAddress == null || + this.localBindAddress == IpNetwork.DEFAULT_BIND_IP) + this.localBindAddress = IpNetworkUtils.getIPAddressString(this.broadcastAddress); return this; } @@ -83,9 +88,11 @@ public IpNetworkBuilder withSubnet(final String subnetAddress, final int network final long negMask = ~subnetMask & 0xFFFFFFFFL; final long subnet = IpNetworkUtils.bytesToLong(BACnetUtils.dottedStringToBytes(subnetAddress)); - - this.broadcastAddress = toIpAddrString(subnet | negMask); - this.localBindAddress = IpNetworkUtils.getIPAddressString(this.broadcastAddress); + if (this.broadcastAddress == null) + this.broadcastAddress = toIpAddrString(subnet | negMask); + if (this.localBindAddress == null || + this.localBindAddress == IpNetwork.DEFAULT_BIND_IP) + this.localBindAddress = IpNetworkUtils.getIPAddressString(this.broadcastAddress); return this; } diff --git a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java index a5d153fe..114d7b89 100644 --- a/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java +++ b/src/main/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkUtils.java @@ -170,7 +170,7 @@ public static Address toAddress(final int networkNumber, final InetSocketAddress *
  • Integer format of the Network Prefix Length of the NIC
  • * */ - public static record InterfaceInfo(int index, + public record InterfaceInfo(int index, String interfaceName, String localIPAddress, String broadcastAddress, @@ -183,12 +183,12 @@ public static record InterfaceInfo(int index, *

    * Values of the following parameters of each NIC are stored in record format: *

      - *
    • index (int) - NIC Card Index assigned by the OS - *
    • Name of the NIC (String) - *
    • IP4 Address assigned to the NIC (String) - *
    • Broadcast Address of the NIC (String) - *
    • SubnetMask of the NIC calculated based on the NetworkPrefixLength (String) - *
    • Network Prefix Length of the NIC (int) + *
    • index (int) - NIC Card Index assigned by the OS
    • + *
    • Name of the NIC (String)
    • + *
    • IP4 Address assigned to the NIC (String)
    • + *
    • Broadcast Address of the NIC (String)
    • + *
    • SubnetMask of the NIC calculated based on the NetworkPrefixLength (String)
    • + *
    • Network Prefix Length of the NIC (int)
    • *
    * @return the list of records of all NIC available in this device */ diff --git a/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java b/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java index 5fc1daf2..0aaef442 100644 --- a/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java +++ b/src/test/java/com/serotonin/bacnet4j/adhoc/IpMasterTest.java @@ -7,12 +7,6 @@ package com.serotonin.bacnet4j.adhoc; -import java.util.List; -import java.util.Random; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.serotonin.bacnet4j.LocalDevice; import com.serotonin.bacnet4j.RemoteDevice; import com.serotonin.bacnet4j.event.IAmListener; @@ -26,6 +20,11 @@ import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier; import com.serotonin.bacnet4j.type.primitive.CharacterString; import com.serotonin.bacnet4j.util.DiscoveryUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + /** * Example of creating an Ip Master @@ -39,11 +38,11 @@ public static void main(final String[] args) throws Exception { } public LocalDevice createIpLocalDevice() throws Exception { - Random rand = new Random(); + List interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); - final IpNetworkUtils.InterfaceInfo efaceInfo = interfaceDetails.get(rand.nextInt(interfaceDetails.size())); + final IpNetworkUtils.InterfaceInfo interfaceInfo = interfaceDetails.get(0); Network network = new IpNetworkBuilder() - .withInterfaceName(efaceInfo.interfaceName()) + .withInterfaceName(interfaceInfo.interfaceName()) .withPort(47808) .withLocalNetworkNumber(5) .build(); diff --git a/src/test/java/com/serotonin/bacnet4j/npdu/ip/BBMDTest.java b/src/test/java/com/serotonin/bacnet4j/npdu/ip/BBMDTest.java index e99af4a8..bf6d64d9 100644 --- a/src/test/java/com/serotonin/bacnet4j/npdu/ip/BBMDTest.java +++ b/src/test/java/com/serotonin/bacnet4j/npdu/ip/BBMDTest.java @@ -1,6 +1,9 @@ package com.serotonin.bacnet4j.npdu.ip; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mockStatic; import java.io.IOException; import java.net.DatagramPacket; @@ -17,6 +20,9 @@ import org.junit.Assume; import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; import com.serotonin.bacnet4j.LocalDevice; import com.serotonin.bacnet4j.RemoteDevice; @@ -27,9 +33,10 @@ import lohbihler.warp.WarpClock; +@ExtendWith(MockitoExtension.class) public class BBMDTest { static final int port = 0xBAC0; - + private MockedStatic mockedUtil; private final WarpClock clock = new WarpClock(); boolean canRun; @@ -465,9 +472,17 @@ private static DatagramPacket packet(final int function, final String payload, f } private LDInfo createLocalDevice(final int subnet, final int addr) throws Exception { + mockedUtil = mockStatic(IpNetworkUtils.class, CALLS_REAL_METHODS); + final String ipAddress = "127.0." + subnet + "." + addr; + final String broadcastAdd = "127.0." + subnet + "." + "255"; + final String subnetMask = "255.255.255.0"; + mockedUtil.when(()->IpNetworkUtils.getIPAddressString(anyString())).thenReturn(ipAddress); + mockedUtil.when(()->IpNetworkUtils.getLocalBroadcastAddressString(anyString())).thenReturn(broadcastAdd); + mockedUtil.when(()->IpNetworkUtils.getSubnetMask(anyString())).thenReturn(subnetMask); + final LDInfo info = new LDInfo(); - info.network = new IpNetworkBuilder().withLocalBindAddress("127.0." + subnet + "." + addr) // + info.network = new IpNetworkBuilder().withLocalBindAddress(ipAddress) // .withSubnet("127.0." + subnet + ".0", 24) // .withLocalNetworkNumber(1) // .build(); @@ -487,7 +502,7 @@ public void iAmReceived(final RemoteDevice d) { }); allSockets.add(info.network.getSocket()); - + mockedUtil.close(); return info; } diff --git a/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java b/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java index 906bf045..58a5ba1c 100644 --- a/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java +++ b/src/test/java/com/serotonin/bacnet4j/npdu/ip/IpNetworkBuilderTest.java @@ -1,86 +1,111 @@ package com.serotonin.bacnet4j.npdu.ip; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; -import java.util.Random; -import org.junit.Before; -import org.junit.Test; +import static org.junit.Assert.*; +import static org.mockito.Answers.CALLS_REAL_METHODS; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mockStatic; + +@ExtendWith(MockitoExtension.class) public class IpNetworkBuilderTest { - IpNetworkUtils.InterfaceInfo efaceInfo; + IpNetworkUtils.InterfaceInfo interfaceInfo; List interfaceDetails; @Test public void withSubnet16() { - final IpNetworkBuilder builder = new IpNetworkBuilder().withSubnet("192.168.0.0", 16); - assertEquals("192.168.255.255", builder.getBroadcastAddress()); - assertEquals("255.255.0.0", builder.getSubnetMask()); + try(MockedStatic mockedUtil = mockStatic(IpNetworkUtils.class, CALLS_REAL_METHODS)){ + mockedUtil.when(()->IpNetworkUtils.getIPAddressString(anyString())).thenReturn(IpNetwork.DEFAULT_BIND_IP); + final IpNetworkBuilder builder = new IpNetworkBuilder().withSubnet("192.168.0.0", 16); + + assertEquals("192.168.255.255", builder.getBroadcastAddress()); + assertEquals("255.255.0.0",builder.getSubnetMask()); + } } @Test public void withBroadcast16() { - final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast("192.168.255.255", 16); - assertEquals("192.168.255.255", builder.getBroadcastAddress()); - assertEquals("255.255.0.0", builder.getSubnetMask()); + try(MockedStatic mockedUtil = mockStatic(IpNetworkUtils.class, CALLS_REAL_METHODS)){ + mockedUtil.when(()->IpNetworkUtils.getIPAddressString(anyString())).thenReturn(IpNetwork.DEFAULT_BIND_IP); + final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast("192.168.255.255", 16); + assertEquals("192.168.255.255", builder.getBroadcastAddress()); + assertEquals("255.255.0.0", builder.getSubnetMask()); + } + } @Test public void withSubnet24() { - final IpNetworkBuilder builder = new IpNetworkBuilder().withSubnet("192.168.2.0", 24); - assertEquals("192.168.2.255", builder.getBroadcastAddress()); - assertEquals("255.255.255.0", builder.getSubnetMask()); + try(MockedStatic mockedUtil = mockStatic(IpNetworkUtils.class, CALLS_REAL_METHODS)){ + mockedUtil.when(()->IpNetworkUtils.getIPAddressString(anyString())).thenReturn(IpNetwork.DEFAULT_BIND_IP); + final IpNetworkBuilder builder = new IpNetworkBuilder().withSubnet("192.168.2.0", 24); + assertEquals("192.168.2.255", builder.getBroadcastAddress()); + assertEquals("255.255.255.0", builder.getSubnetMask()); + } } @Test public void withBroadcast24() { - final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast("192.168.4.255", 24); - assertEquals("192.168.4.255", builder.getBroadcastAddress()); - assertEquals("255.255.255.0", builder.getSubnetMask()); + try(MockedStatic mockedUtil = mockStatic(IpNetworkUtils.class, CALLS_REAL_METHODS)){ + mockedUtil.when(()->IpNetworkUtils.getIPAddressString(anyString())).thenReturn(IpNetwork.DEFAULT_BIND_IP); + final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast("192.168.4.255", 24); + assertEquals("192.168.4.255", builder.getBroadcastAddress()); + assertEquals("255.255.255.0", builder.getSubnetMask()); + } } @Test public void withSubnet19() { - final IpNetworkBuilder builder = new IpNetworkBuilder().withSubnet("192.168.192.0", 19); - assertEquals("192.168.223.255", builder.getBroadcastAddress()); - assertEquals("255.255.224.0", builder.getSubnetMask()); + try(MockedStatic mockedUtil = mockStatic(IpNetworkUtils.class, CALLS_REAL_METHODS)){ + mockedUtil.when(()->IpNetworkUtils.getIPAddressString(anyString())).thenReturn(IpNetwork.DEFAULT_BIND_IP); + final IpNetworkBuilder builder = new IpNetworkBuilder().withSubnet("192.168.192.0", 19); + assertEquals("192.168.223.255", builder.getBroadcastAddress()); + assertEquals("255.255.224.0", builder.getSubnetMask()); + } } @Test public void withBroadcast19() { - final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast("192.168.223.255", 19); - assertEquals("192.168.223.255", builder.getBroadcastAddress()); - assertEquals("255.255.224.0", builder.getSubnetMask()); + try(MockedStatic mockedUtil = mockStatic(IpNetworkUtils.class, CALLS_REAL_METHODS)){ + mockedUtil.when(()->IpNetworkUtils.getIPAddressString(anyString())).thenReturn(IpNetwork.DEFAULT_BIND_IP); + final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast("192.168.223.255", 19); + assertEquals("192.168.223.255", builder.getBroadcastAddress()); + assertEquals("255.255.224.0", builder.getSubnetMask()); + } } - @Before public void initialize(){ - Random rand = new Random(); + @Before + public void initialize(){ interfaceDetails = IpNetworkUtils.getLocalInterfaceAddresses(); - efaceInfo = interfaceDetails.get(rand.nextInt(interfaceDetails.size())); + interfaceInfo = interfaceDetails.get(0); } @Test public void withLocalIPAddress() throws RuntimeException{ - String IPAddress = efaceInfo.localIPAddress(); + String IPAddress = interfaceInfo.localIPAddress(); final IpNetworkBuilder builder = new IpNetworkBuilder().withLocalBindAddress(IPAddress); assertEquals(IPAddress,builder.getLocalBindAddress()); - assertEquals(efaceInfo.broadcastAddress(), builder.getBroadcastAddress()); - assertEquals(efaceInfo.subnetMask(), builder.getSubnetMask()); + assertEquals(interfaceInfo.broadcastAddress(), builder.getBroadcastAddress()); + assertEquals(interfaceInfo.subnetMask(), builder.getSubnetMask()); } @Test public void withBroadcast() throws RuntimeException{ - String IPAddress = efaceInfo.broadcastAddress(); - final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast(IPAddress, efaceInfo.networkPrefixLength()); + String IPAddress = interfaceInfo.broadcastAddress(); + final IpNetworkBuilder builder = new IpNetworkBuilder().withBroadcast(IPAddress, interfaceInfo.networkPrefixLength()); assertEquals(IPAddress,builder.getBroadcastAddress()); - assertEquals(efaceInfo.localIPAddress(), builder.getLocalBindAddress()); - assertEquals(efaceInfo.subnetMask(), builder.getSubnetMask()); + assertEquals(interfaceInfo.localIPAddress(), builder.getLocalBindAddress()); + assertEquals(interfaceInfo.subnetMask(), builder.getSubnetMask()); } @@ -90,7 +115,6 @@ public void withLocalBindAddress_IncorrectIP() throws RuntimeException{ Exception exception = assertThrows(RuntimeException.class,() -> { final IpNetworkBuilder builder = new IpNetworkBuilder().withLocalBindAddress(IPAddress);}); String actualMsg = exception.getMessage(); - System.out.println(actualMsg); assertTrue((actualMsg.contains("IllegalArgument"))); } @@ -106,11 +130,11 @@ public void verifyReuseAddress(){ @Test public void withIterfaceName() throws RuntimeException{ - String ifaceName = efaceInfo.interfaceName(); + String ifaceName = interfaceInfo.interfaceName(); final IpNetworkBuilder builder = new IpNetworkBuilder().withInterfaceName(ifaceName); - assertEquals(efaceInfo.localIPAddress(), builder.getLocalBindAddress()); - assertEquals(efaceInfo.broadcastAddress(),builder.getBroadcastAddress()); - assertEquals(efaceInfo.subnetMask(), builder.getSubnetMask()); + assertEquals(interfaceInfo.localIPAddress(), builder.getLocalBindAddress()); + assertEquals(interfaceInfo.broadcastAddress(),builder.getBroadcastAddress()); + assertEquals(interfaceInfo.subnetMask(), builder.getSubnetMask()); } }