From 6032fc08cf47d9d8b0c8feac90acfc63bc6d52eb Mon Sep 17 00:00:00 2001 From: Ryan Vail Date: Tue, 13 Oct 2015 19:32:34 -0600 Subject: [PATCH] Cleaned up Subnet.java and added/extended unit tests. Subnet.java - Reordered modifiers to standard java lang spec order - Improved equals() with checks for null and this - Improved hashCode() by using all member vars used in equals(). - Added braces to all if/else statements - Added constructor argument checks to ensure valid objects are created. - Renamed member variables to clearly identify what they are - Added javadoc - Added @Nullable and @Nonnull as appropriate SubnetTest.java Fleshed out tests to cover all methods and cover more corner cases PS2: minor javadoc error fix Change-Id: I2b8097b096ee707ade064f6e583f72aba244e509 Signed-off-by: Ryan Vail --- .../packetcable/provider/Subnet.java | 186 +++++++--- .../packetcable/provider/SubnetTest.java | 334 +++++++++++++++++- 2 files changed, 461 insertions(+), 59 deletions(-) diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Subnet.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Subnet.java index c0db407..b8caf65 100644 --- a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Subnet.java +++ b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Subnet.java @@ -1,93 +1,190 @@ package org.opendaylight.controller.packetcable.provider; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.math.BigInteger; +import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + /** * @author c3oe.de, based on snippets from Scott Plante, John Kugelmann */ public class Subnet { - final private int bytesSubnetCount; - final private BigInteger bigMask; - final private BigInteger bigSubnetMasked; - final private int prefixLen; + /** Minimum length of a v4 or v6 subnet mask */ + private final static int MIN_MASK_BITS = 0; + + /** Maximum length of a v4 subnet mask */ + private final static int MAX_MASK_BITS_V4 = 32; + + /** Maximum length of a v6 subnet mask */ + private final static int MAX_MASK_BITS_V6 = 128; + + /** The length of the subnet prefix */ + private final int prefixLen; - /** For use via format "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57" */ - public Subnet( final InetAddress subnetAddress, final int bits ) + /** The subnet mask */ + private final BigInteger mask; + + /** The actual routing prefix leading to this subnet */ + private final BigInteger routingPrefix; + + /** The number of bytes in an address. Will be 4 or 16 corresponding to ipv4 and ipv6 respectively */ + private final int addressByteCount; + + /** + * Generates a Subnet from CIDR style notation.
+ * Eg. "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57" + * @param subnetAddress An address in this subnet or the routing prefix leading to this subnet. + * @param prefixLength The number of prefix bits that are set, must be between [0..32] for ipv4 and [0..128] for ipv6 + * @throws NullPointerException if the subnetAddress is null + * @throws IllegalArgumentException if the bits argument is not in the allowable range. + * @see http://wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation + */ + public Subnet(@Nonnull final InetAddress subnetAddress, final int prefixLength ) + { + checkNotNull(subnetAddress, "subnetAddress can not be null"); + final int maxMaskBits = (subnetAddress instanceof Inet4Address ? MAX_MASK_BITS_V4 : MAX_MASK_BITS_V6); + checkArgument(prefixLength >= MIN_MASK_BITS && prefixLength <= maxMaskBits, "The prefixLength must be in range [%s..%s] but was %s", MIN_MASK_BITS, maxMaskBits, prefixLength); + + this.prefixLen = prefixLength; + this.addressByteCount = subnetAddress.getAddress().length; // 4 or 16 + this.mask = BigInteger.valueOf( -1 ).shiftLeft(this.addressByteCount * 8 - prefixLength); + + // ensure subnetAddress is properly masked and is not an address in the subnet + this.routingPrefix = new BigInteger( subnetAddress.getAddress() ).and( this.mask); + } + + /** + * Generates a subnet from an address and subnet mask. The old ipv4 way. + * Eg: "192.168.0.0/255.255.255.0" or single address with no subnet + * @param subnetAddress An address in the subnet or the routing prefix leading to this subnet. + * @param subnetMask The subnet mask or null. If null the subnet will be a host identifier. + * */ + public Subnet(@Nonnull final InetAddress subnetAddress, @Nullable final InetAddress subnetMask ) { - this.prefixLen = bits; - this.bytesSubnetCount = subnetAddress.getAddress().length; // 4 or 16 - this.bigMask = BigInteger.valueOf( -1 ).shiftLeft( this.bytesSubnetCount*8 - bits ); // mask = -1 << 32 - bits - this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask ); + this(subnetAddress, maskToPrefixLen(subnetAddress, subnetMask)); } - /** For use via format "192.168.0.0/255.255.255.0" or single address */ - public Subnet( final InetAddress subnetAddress, final InetAddress mask ) + /** + * Helper method that computes the prefix length an address and subnet mask pair. + * @param subnetAddress An address in the subnet + * @param subnetMask The mask or null. Expected to be CIDR compliant (mask is a continuous prefix). + * If null this will return the length of a host identifier. + * @return The prefix length + * @throws NullPointerException if subnetAddress is null + * @throws IllegalArgumentException if subnetMask is not null and + * either (subnetAddress and subnetMask are not the same type) + * or (if subnetMask is not CIDR compliant). + */ + private static int maskToPrefixLen(@Nonnull final InetAddress subnetAddress, @Nullable final InetAddress subnetMask) { - this.bytesSubnetCount = subnetAddress.getAddress().length; - this.bigMask = null == mask ? BigInteger.valueOf( -1 ) : new BigInteger( mask.getAddress() ); // no mask given case is handled here. - this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask ); - int lowestSetBit = bigMask.getLowestSetBit(); - this.prefixLen = lowestSetBit == -1 ? 0 : 32 - lowestSetBit; + checkNotNull(subnetAddress, "subnetAddress can not be null"); + if (subnetMask == null) { + return (subnetAddress instanceof Inet4Address ? MAX_MASK_BITS_V4 : MAX_MASK_BITS_V6); + } + else { + // address and mask must both be ipv4 or ipv6 + checkArgument(subnetAddress.getClass().equals(subnetMask.getClass())); + + // validate subnet mask. All leading bits should be set + final BigInteger m = new BigInteger(subnetMask.getAddress()); + final BigInteger allOnes = BigInteger.valueOf(-1); + final int rightMostBit = m.getLowestSetBit(); + final BigInteger validSubnet = allOnes.shiftLeft(rightMostBit); + + checkArgument(validSubnet.equals(m), "Subnet should have contiguous prefix bits, mask: %s(%s)", subnetMask); + + return (subnetAddress instanceof Inet4Address + ? MAX_MASK_BITS_V4 - rightMostBit + : MAX_MASK_BITS_V6 - rightMostBit); + } } /** * Subnet factory method. - * @param subnetMask format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0" + * @param addressAndSubnetStr format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0" * or single address or "2001:db8:85a3:880:0:0:0:0/57" * @return a new instance * @throws UnknownHostException thrown if unsupported subnet mask. */ - public static Subnet createInstance( final String subnetMask ) + public static Subnet createInstance(@Nonnull final String addressAndSubnetStr ) throws UnknownHostException { - final String[] stringArr = subnetMask.split("/"); - if ( 2 > stringArr.length ) - return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), null); - else if ( stringArr[ 1 ].contains(".") || stringArr[ 1 ].contains(":") ) - return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), InetAddress.getByName( stringArr[ 1 ] ) ); - else - return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), Integer.parseInt( stringArr[ 1 ] ) ); + final String[] stringArr = addressAndSubnetStr.split("/"); + if ( 2 > stringArr.length ) { + return new Subnet(InetAddress.getByName(stringArr[0]), null); + } + else if ( stringArr[ 1 ].contains(".") || stringArr[ 1 ].contains(":") ) { + return new Subnet(InetAddress.getByName(stringArr[0]), InetAddress.getByName(stringArr[1])); + } + else { + return new Subnet(InetAddress.getByName(stringArr[0]), Integer.parseInt(stringArr[1])); + } } + /** + * Returns the length of the routing prefix length. + * @return the routing prefix length. + */ public int getPrefixLen() { return prefixLen; } - public boolean isInNet( final InetAddress address ) + /** + * Determins if the passed in address is contained in this subnet. + * @param address The address to test. + * @return true if the address is in this subnet. + */ + public boolean isInNet(@Nonnull final InetAddress address ) { + checkNotNull(address, "address must not be null"); + final byte[] bytesAddress = address.getAddress(); - if ( this.bytesSubnetCount != bytesAddress.length ) + if ( this.addressByteCount != bytesAddress.length ) { return false; + } final BigInteger bigAddress = new BigInteger( bytesAddress ); - return bigAddress.and( this.bigMask ).equals( this.bigSubnetMasked ); + return bigAddress.and(this.mask).equals(this.routingPrefix); } @Override final public boolean equals( Object obj ) { - if ( ! (obj instanceof Subnet) ) - return false; + if (null == obj) return false; + if (this == obj) return true; + if (!(obj instanceof Subnet)) return false; + final Subnet other = (Subnet)obj; - return this.bigSubnetMasked.equals( other.bigSubnetMasked ) && - this.bigMask.equals( other.bigMask ) && - this.bytesSubnetCount == other.bytesSubnetCount; + return this.prefixLen == other.prefixLen && + this.routingPrefix.equals(other.routingPrefix) && + this.mask.equals(other.mask) && + this.addressByteCount == other.addressByteCount; } @Override final public int hashCode() { - return this.bytesSubnetCount; + return new HashCodeBuilder(997, 311) + .append(prefixLen) + .append(mask) + .append(routingPrefix) + .append(addressByteCount) + .build(); } @Override public String toString() { final StringBuilder buf = new StringBuilder(); - bigInteger2IpString( buf, this.bigSubnetMasked, this.bytesSubnetCount ); + bigInteger2IpString( buf, this.routingPrefix, this.addressByteCount); buf.append( '/' ); - bigInteger2IpString( buf, this.bigMask, this.bytesSubnetCount ); + bigInteger2IpString( buf, this.mask, this.addressByteCount); return buf.toString(); } @@ -101,13 +198,16 @@ public class Subnet int integer; for ( int i = 0; i < displayBytes; i++ ) { - if ( 0 < i && ! isIPv4 && i % 2 == 0 ) - buf.append( ':' ); - else if ( 0 < i && isIPv4 ) - buf.append( '.' ); + if ( 0 < i && ! isIPv4 && i % 2 == 0 ) { + buf.append(':'); + } + else if ( 0 < i && isIPv4 ) { + buf.append('.'); + } integer = 0xFF & (i < diffLen ? fillByte : bytes[ i - diffLen ]); - if ( ! isIPv4 && 0x10 > integer ) - buf.append( '0' ); + if ( ! isIPv4 && 0x10 > integer ) { + buf.append('0'); + } buf.append( isIPv4 ? integer : Integer.toHexString( integer ) ); } } diff --git a/packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/SubnetTest.java b/packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/SubnetTest.java index 229c7d7..b0360ad 100644 --- a/packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/SubnetTest.java +++ b/packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/SubnetTest.java @@ -1,30 +1,332 @@ package org.opendaylight.controller.packetcable.provider; +import com.google.common.net.InetAddresses; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +public class SubnetTest { -import java.net.UnknownHostException; + // Various address class level prefix lengths + private static final int CLASS_A = 8; + private static final int CLASS_B = 16; + private static final int CLASS_C = 24; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.Spy; -import org.mockito.runners.MockitoJUnitRunner; + private InetAddress addressV4 = null; + private InetAddress addressV6 = null; -import com.google.common.net.InetAddresses; + private InetAddress v4MaskClassA; + private InetAddress v4MaskClassB; + private InetAddress v4MaskClassC; -@RunWith(MockitoJUnitRunner.class) -public class SubnetTest { + @Before + public final void setup() + { + addressV4 = InetAddresses.forString("192.168.0.1"); + addressV6 = InetAddresses.forString("2001:db8::1"); + + v4MaskClassA = InetAddresses.forString("255.0.0.0"); + v4MaskClassB = InetAddresses.forString("255.255.0.0"); + v4MaskClassC = InetAddresses.forString("255.255.255.0"); + } + + @After + public final void tearDown() + { + addressV4 = null; + addressV6 = null; + + v4MaskClassA = null; + v4MaskClassB = null; + v4MaskClassC = null; + } + + @Test + public final void testCtorCidr() + { + assertThat(new Subnet(addressV4, 24), is(notNullValue())); + assertThat(new Subnet(addressV6, 24), is(notNullValue())); + } + + @Test + public final void testCtorAddressAndMask() + { + assertThat(new Subnet(addressV4, InetAddresses.forString("255.255.255.0")), is(notNullValue())); + assertThat(new Subnet(addressV4, null), is(notNullValue())); + } + + @Test(expected = IllegalArgumentException.class) + public final void testSubnetCtorCidrBadMaskv4_1() + { + new Subnet(addressV4, -1); + } + + @Test(expected = IllegalArgumentException.class) + public final void testSubnetCtorCidrBadMaskv4_2() + { + new Subnet(addressV4, 33); + } + + @Test(expected = IllegalArgumentException.class) + public final void testSubnetCtorCidrBadMaskv6_1() + { + new Subnet(addressV6, -1); + } + + @Test(expected = IllegalArgumentException.class) + public final void testSubnetCtorCidrBadMaskv6_2() + { + new Subnet(addressV6, 129); + } + + @Test + public final void testGetPrefixLen() + { + Subnet subnet = new Subnet(addressV4, CLASS_C); + assertThat(subnet, is(notNullValue()) ); + assertThat(subnet.getPrefixLen(), is(CLASS_C) ); + + subnet = new Subnet(addressV4, CLASS_B); + assertThat(subnet, is(notNullValue()) ); + assertThat(subnet.getPrefixLen(), is(CLASS_B) ); + + subnet = new Subnet(addressV4, CLASS_A); + assertThat(subnet, is(notNullValue()) ); + assertThat(subnet.getPrefixLen(), is(CLASS_A) ); + + subnet = new Subnet(addressV4, v4MaskClassC); + assertThat(subnet, is(notNullValue()) ); + assertThat(subnet.getPrefixLen(), is(CLASS_C) ); + + subnet = new Subnet(addressV4, v4MaskClassB); + assertThat(subnet, is(notNullValue()) ); + assertThat(subnet.getPrefixLen(), is(CLASS_B) ); + + subnet = new Subnet(addressV4, v4MaskClassA); + assertThat(subnet, is(notNullValue()) ); + assertThat(subnet.getPrefixLen(), is(CLASS_A) ); + + } + + @Test + public final void testSubnetCtorCidrAllValidMasks() + { + // validating no exceptions are thrown for valid masks + for (int iMask = 0; iMask < 33; ++iMask) { + final Subnet subnet = new Subnet(addressV4, iMask); + assertThat(subnet.getPrefixLen(), is(iMask) ); + } + + for (int iMask = 0; iMask < 129; ++iMask) { + final Subnet subnet = new Subnet(addressV6, iMask); + assertThat(subnet.getPrefixLen(), is(iMask) ); + } + } + + + @Test + public final void testEquals() + { + final Subnet s41 = new Subnet(addressV4, 24); + final Subnet s42 = new Subnet(addressV4, 24); + final Subnet s43 = new Subnet(addressV4, 16); + + final Subnet s61 = new Subnet(addressV6, 24); + final Subnet s62 = new Subnet(addressV6, 56); + final Subnet s63 = new Subnet(addressV6, 56); + + assertThat(s41, is(equalTo(s41))); + assertThat(s41, is(equalTo(s42))); + assertThat(s41, is(not(equalTo(s43)))); + assertThat(s41, is(not(equalTo(s61)))); + assertThat(s41, is(not(equalTo(s62)))); + assertThat(s41, is(not(equalTo(s63)))); + assertThat(s41, is(not(equalTo(null)))); + assertNotEquals(s41, "random string"); + + assertThat(s42, is(equalTo(s41))); + assertThat(s42, is(equalTo(s42))); + assertThat(s42, is(not(equalTo(s43)))); + assertThat(s42, is(not(equalTo(s61)))); + assertThat(s42, is(not(equalTo(s62)))); + assertThat(s42, is(not(equalTo(s63)))); + assertThat(s42, is(not(equalTo(null)))); + assertNotEquals(s42, "random string"); + + assertThat(s43, is(not(equalTo(s41)))); + assertThat(s43, is(not(equalTo(s42)))); + assertThat(s43, is(equalTo(s43))); + assertThat(s43, is(not(equalTo(s61)))); + assertThat(s43, is(not(equalTo(s62)))); + assertThat(s43, is(not(equalTo(s63)))); + assertThat(s43, is(not(equalTo(null)))); + assertNotEquals(s43, "random string"); + + assertThat(s61, is(not(equalTo(s41)))); + assertThat(s61, is(not(equalTo(s42)))); + assertThat(s61, is(not(equalTo(s43)))); + assertThat(s61, is(equalTo(s61))); + assertThat(s61, is(not(equalTo(s62)))); + assertThat(s61, is(not(equalTo(s63)))); + assertThat(s61, is(not(equalTo(null)))); + assertNotEquals(s61, "random string"); + + assertThat(s62, is(not(equalTo(s41)))); + assertThat(s62, is(not(equalTo(s42)))); + assertThat(s62, is(not(equalTo(s43)))); + assertThat(s62, is(not(equalTo(s61)))); + assertThat(s62, is(equalTo(s62))); + assertThat(s62, is(equalTo(s63))); + assertThat(s62, is(not(equalTo(null)))); + assertNotEquals(s62, "random string"); + + assertThat(s63, is(not(equalTo(s41)))); + assertThat(s63, is(not(equalTo(s42)))); + assertThat(s63, is(not(equalTo(s43)))); + assertThat(s63, is(not(equalTo(s61)))); + assertThat(s63, is(equalTo(s62))); + assertThat(s63, is(equalTo(s63))); + assertThat(s63, is(not(equalTo(null)))); + assertNotEquals(s63, "random string"); + } + + @Test + public final void testHashcode() + { + final Subnet s41 = new Subnet(addressV4, 24); + final Subnet s42 = new Subnet(addressV4, 24); + final Subnet s43 = new Subnet(addressV4, 16); + + final Subnet s61 = new Subnet(addressV6, 24); + final Subnet s62 = new Subnet(addressV6, 56); + final Subnet s63 = new Subnet(addressV6, 56); + + assertThat(s41.hashCode(), is(equalTo(s41.hashCode()))); + assertThat(s41.hashCode(), is(equalTo(s42.hashCode()))); + assertThat(s41.hashCode(), is(not(equalTo(s43.hashCode())))); + assertThat(s41.hashCode(), is(not(equalTo(s61.hashCode())))); + assertThat(s41.hashCode(), is(not(equalTo(s62.hashCode())))); + assertThat(s41.hashCode(), is(not(equalTo(s63.hashCode())))); + + assertThat(s42.hashCode(), is(equalTo(s41.hashCode()))); + assertThat(s42.hashCode(), is(equalTo(s42.hashCode()))); + assertThat(s42.hashCode(), is(not(equalTo(s43.hashCode())))); + assertThat(s42.hashCode(), is(not(equalTo(s61.hashCode())))); + assertThat(s42.hashCode(), is(not(equalTo(s62.hashCode())))); + assertThat(s42.hashCode(), is(not(equalTo(s63.hashCode())))); + + assertThat(s43.hashCode(), is(not(equalTo(s41.hashCode())))); + assertThat(s43.hashCode(), is(not(equalTo(s42.hashCode())))); + assertThat(s43.hashCode(), is(equalTo(s43.hashCode()))); + assertThat(s43.hashCode(), is(not(equalTo(s61.hashCode())))); + assertThat(s43.hashCode(), is(not(equalTo(s62.hashCode())))); + assertThat(s43.hashCode(), is(not(equalTo(s63.hashCode())))); + + assertThat(s61.hashCode(), is(not(equalTo(s41.hashCode())))); + assertThat(s61.hashCode(), is(not(equalTo(s42.hashCode())))); + assertThat(s61.hashCode(), is(not(equalTo(s43.hashCode())))); + assertThat(s61.hashCode(), is(equalTo(s61.hashCode()))); + assertThat(s61.hashCode(), is(not(equalTo(s62.hashCode())))); + assertThat(s61.hashCode(), is(not(equalTo(s63.hashCode())))); + + assertThat(s62.hashCode(), is(not(equalTo(s41.hashCode())))); + assertThat(s62.hashCode(), is(not(equalTo(s42.hashCode())))); + assertThat(s62.hashCode(), is(not(equalTo(s43.hashCode())))); + assertThat(s62.hashCode(), is(not(equalTo(s61.hashCode())))); + assertThat(s62.hashCode(), is(equalTo(s62.hashCode()))); + assertThat(s62.hashCode(), is(equalTo(s63.hashCode()))); + + assertThat(s63.hashCode(), is(not(equalTo(s41.hashCode())))); + assertThat(s63.hashCode(), is(not(equalTo(s42.hashCode())))); + assertThat(s63.hashCode(), is(not(equalTo(s43.hashCode())))); + assertThat(s63.hashCode(), is(not(equalTo(s61.hashCode())))); + assertThat(s63.hashCode(), is(equalTo(s62.hashCode()))); + assertThat(s63.hashCode(), is(equalTo(s63.hashCode()))); + } @Test public final void testCreateInstance() throws UnknownHostException { - Subnet localSubnet = Subnet.createInstance("192.168.0.0/255.255.255.0"); - assertNotNull(localSubnet); - assertEquals("192.168.0.0/255.255.255.0", localSubnet.toString()); - assertEquals(Subnet.createInstance("192.168.0.0/255.255.255.0"), localSubnet); + Subnet subnet = Subnet.createInstance("192.168.0.0/255.255.255.0"); + assertThat(subnet, is(notNullValue(Subnet.class))); + assertThat(subnet.toString(), is("192.168.0.0/255.255.255.0")); + assertThat(subnet, is(equalTo(Subnet.createInstance("192.168.0.0/255.255.255.0")))); + assertThat(subnet, is(equalTo(Subnet.createInstance("192.168.0.0/24")))); + assertThat(subnet, is(equalTo(Subnet.createInstance("192.168.0.10/255.255.255.0")))); + assertThat(subnet, is(equalTo(Subnet.createInstance("192.168.0.10/24")))); + + subnet = Subnet.createInstance("192.168.0.1"); + assertThat(subnet, is(notNullValue(Subnet.class))); + assertThat(subnet.toString(), is("192.168.0.1/255.255.255.255")); + assertThat(subnet, is(equalTo(Subnet.createInstance("192.168.0.1")))); + assertThat(subnet, is(equalTo(Subnet.createInstance("192.168.0.1/32")))); + assertThat(subnet, is(equalTo(Subnet.createInstance("192.168.0.1/255.255.255.255")))); + + subnet = Subnet.createInstance("192.168.0.0/8"); + assertThat(subnet, is(notNullValue(Subnet.class))); + assertThat(subnet.toString(), is("192.0.0.0/255.0.0.0")); + assertThat(subnet, is(equalTo(Subnet.createInstance("192.168.0.0/8")))); + assertThat(subnet, is(equalTo(Subnet.createInstance("192.175.0.10/8")))); + assertThat(subnet, is(equalTo(Subnet.createInstance("192.10.0.0/255.0.0.0")))); + assertThat(subnet, is(equalTo(Subnet.createInstance("192.1.0.100/255.0.0.0")))); + + } + + @Test + public final void testIsInNet() + { + Subnet subnet = new Subnet(addressV4, CLASS_C); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.0.1"))); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.0.100"))); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.0.255"))); + assertFalse(subnet.isInNet(InetAddresses.forString("192.168.1.1"))); + assertFalse(subnet.isInNet(InetAddresses.forString("192.167.0.255"))); + assertFalse(subnet.isInNet(InetAddresses.forString("191.168.0.1"))); + assertFalse(subnet.isInNet(addressV6)); + + subnet = new Subnet(addressV4, CLASS_B); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.0.1"))); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.0.100"))); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.0.255"))); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.1.1"))); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.1.255"))); + assertFalse(subnet.isInNet(InetAddresses.forString("192.167.0.255"))); + assertFalse(subnet.isInNet(InetAddresses.forString("191.168.0.1"))); + assertFalse(subnet.isInNet(addressV6)); + + subnet = new Subnet(addressV4, CLASS_A); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.0.1"))); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.0.100"))); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.0.255"))); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.1.1"))); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.1.255"))); + assertTrue(subnet.isInNet(InetAddresses.forString("192.167.0.255"))); + assertFalse(subnet.isInNet(InetAddresses.forString("191.168.0.1"))); + assertFalse(subnet.isInNet(addressV6)); + + subnet = new Subnet(addressV4, 32); + assertTrue(subnet.isInNet(InetAddresses.forString("192.168.0.1"))); + assertFalse(subnet.isInNet(InetAddresses.forString("192.168.0.100"))); + assertFalse(subnet.isInNet(InetAddresses.forString("192.168.0.255"))); + assertFalse(subnet.isInNet(InetAddresses.forString("192.168.1.1"))); + assertFalse(subnet.isInNet(InetAddresses.forString("192.168.1.255"))); + assertFalse(subnet.isInNet(InetAddresses.forString("192.167.0.255"))); + assertFalse(subnet.isInNet(InetAddresses.forString("191.168.0.1"))); + assertFalse(subnet.isInNet(addressV6)); + + subnet = new Subnet(addressV6, 64); + assertTrue(subnet.isInNet(InetAddresses.forString("2001:db8::1"))); + assertTrue(subnet.isInNet(InetAddresses.forString("2001:db8::100"))); + assertTrue(subnet.isInNet(InetAddresses.forString("2001:db8::ffff"))); + assertFalse(subnet.isInNet(InetAddresses.forString("2001:db7::1"))); + assertFalse(subnet.isInNet(InetAddresses.forString("2000:db8::"))); + assertTrue(subnet.isInNet(InetAddresses.forString("2001:db8:0:0:1::1"))); + assertFalse(subnet.isInNet(addressV4)); + } } -- 2.36.6