Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Constructor changes from #13 (comment):
* Remove public IPAddressRange(IPAddress baseAddress, IPAddress subnetMask)
* Change public IPAddressRange(ICollection<IPAddress> beginEnd) to public IPAddressRange(IPAddress begin, IPAddress end)
* Add public static int SubnetMaskLength(IPAddress subnetMask) (and tests)
* Update XML help for public IPAddressRange(IPAddress baseAddress, int maskLength) to show example use of SubnetMaskLength()
  • Loading branch information
gregmac committed Jun 25, 2015
commit b411d3879cce4f8ba2db7ec2c09edc7c1df1d751
76 changes: 14 additions & 62 deletions IPAddressRange/IPAddressRange.Test/IPAddressRangeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,57 +33,6 @@ public void CtorTest_Single()
range.End.ToString().Is("192.168.0.88");
}



[TestMethod]
public void CtorTest_Array_Throws()
{
AssertEx.Throws<ArgumentNullException>(() => new IPAddressRange((IPAddress[])null));
AssertEx.Throws<ArgumentOutOfRangeException>(() => new IPAddressRange(new IPAddress[] {}));
AssertEx.Throws<ArgumentException>(() => new IPAddressRange(new[] {IPAddress.Loopback, IPAddress.IPv6Loopback}), "Should not allow mixing of ipv4 and v6");
}

[TestMethod]
public void CtorTest_Array()
{
var range = new IPAddressRange(new[] { IPAddress.Parse("192.168.0.80"), IPAddress.Parse("192.168.0.88") });
range.Begin.AddressFamily.Is(AddressFamily.InterNetwork);
range.Begin.ToString().Is("192.168.0.80");
range.End.AddressFamily.Is(AddressFamily.InterNetwork);
range.End.ToString().Is("192.168.0.88");
}

[TestMethod]
public void CtorTest_Array_Single()
{
var range = new IPAddressRange(new[] { IPAddress.Parse("192.168.0.80") });
range.Begin.AddressFamily.Is(AddressFamily.InterNetwork);
range.Begin.ToString().Is("192.168.0.80");
range.End.AddressFamily.Is(AddressFamily.InterNetwork);
range.End.ToString().Is("192.168.0.80");
}

[TestMethod]
public void CtorTest_Array_Two_Equal()
{
var range = new IPAddressRange(new[] { IPAddress.Parse("192.168.0.80"), IPAddress.Parse("192.168.0.80") });
range.Begin.AddressFamily.Is(AddressFamily.InterNetwork);
range.Begin.ToString().Is("192.168.0.80");
range.End.AddressFamily.Is(AddressFamily.InterNetwork);
range.End.ToString().Is("192.168.0.80");
}

[TestMethod]
public void CtorTest_Array_Middle_Ignored()
{
var range = new IPAddressRange(new[] { IPAddress.Parse("192.168.0.80"), IPAddress.Parse("192.168.0.254"), IPAddress.Parse("192.168.0.88") });
range.Begin.AddressFamily.Is(AddressFamily.InterNetwork);
range.Begin.ToString().Is("192.168.0.80");
range.End.AddressFamily.Is(AddressFamily.InterNetwork);
range.End.ToString().Is("192.168.0.88");
}


[TestMethod]
public void CtorTest_MaskLength()
{
Expand All @@ -94,17 +43,6 @@ public void CtorTest_MaskLength()
range.End.ToString().Is("192.168.0.255");
}


[TestMethod]
public void CtorTest_SubnetMask()
{
var range = new IPAddressRange(IPAddress.Parse("192.168.0.80"), IPAddress.Parse("255.255.255.0"));
range.Begin.AddressFamily.Is(AddressFamily.InterNetwork);
range.Begin.ToString().Is("192.168.0.0");
range.End.AddressFamily.Is(AddressFamily.InterNetwork);
range.End.ToString().Is("192.168.0.255");
}

[TestMethod]
public void ParseTest_IPv4_Uniaddress()
{
Expand Down Expand Up @@ -306,6 +244,20 @@ public void DeserializeTest()
range3.End.ToString().Is("::6");
}

[TestMethod]
public void SubnetMaskLengthTest_Valid()
{
var range = new IPAddressRange(IPAddress.Parse("192.168.75.23"), IPAddressRange.SubnetMaskLength(IPAddress.Parse("255.255.254.0")));
range.Begin.ToString().Is("192.168.74.0");
range.End.ToString().Is("192.168.75.255");
}

[TestMethod]
public void SubnetMaskLengthTest_Invalid()
{
AssertEx.Throws<ArgumentException>(() =>
new IPAddressRange(IPAddress.Parse("192.168.75.23"), IPAddressRange.SubnetMaskLength(IPAddress.Parse("255.255.54.0"))));
}

[TestMethod]
public void Enumerate_IPv4()
Expand Down
56 changes: 26 additions & 30 deletions IPAddressRange/IPAddressRange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,14 @@ public IPAddressRange(IPAddress singleAddress)
}

/// <summary>
/// Create a new range based on the first and last IPs in an array.
/// Throws an exception if the array is empty or null. All but the first and last values
/// are ignored. Passing a single value is equivalent to a range of one address.
/// Create a new range from a begin and end address.
/// Throws an exception if Begin comes after End, or the
/// addresses are not in the same family.
/// </summary>
/// <param name="beginEnd"></param>
public IPAddressRange(ICollection<IPAddress> beginEnd)
public IPAddressRange(IPAddress begin, IPAddress end)
{
if (beginEnd == null) throw new ArgumentNullException("beginEnd");
if (beginEnd.Count == 0) throw new ArgumentOutOfRangeException("beginEnd", "Array contains no elements");

Begin = beginEnd.First();
End = beginEnd.Last();
Begin = begin;
End = end;

if (Begin.AddressFamily != End.AddressFamily) throw new ArgumentException("Elements must be of the same address family", "beginEnd");

Expand All @@ -51,8 +47,11 @@ public IPAddressRange(ICollection<IPAddress> beginEnd)
if (!Bits.LE(endBytes, beginBytes)) throw new ArgumentException("Begin must be smaller than the End", "beginEnd");
}


/// <summary>
/// Creates a range from a base address and mask bits
/// Creates a range from a base address and mask bits.
/// This can also be used with <see cref="SubnetMaskLength"/> to create a
/// range based on a subnet mask.
/// </summary>
/// <param name="baseAddress"></param>
/// <param name="maskLength"></param>
Expand All @@ -66,21 +65,6 @@ public IPAddressRange(IPAddress baseAddress, int maskLength)
Begin = new IPAddress(baseAdrBytes);
End = new IPAddress(Bits.Or(baseAdrBytes, Bits.Not(maskBytes)));
}

/// <summary>
/// Creates a range from a base address and subnet mask.
/// </summary>
/// <param name="baseAddress"></param>
/// <param name="subnetMask"></param>
public IPAddressRange(IPAddress baseAddress, IPAddress subnetMask)
{
var baseAdrBytes = baseAddress.GetAddressBytes();
var maskBytes = subnetMask.GetAddressBytes();
baseAdrBytes = Bits.And(baseAdrBytes, maskBytes);

Begin = new IPAddress(baseAdrBytes);
End = new IPAddress(Bits.Or(baseAdrBytes, Bits.Not(maskBytes)));
}

[Obsolete("Use IPAddressRange.Parse static method instead.")]
public IPAddressRange(string ipRangeString)
Expand Down Expand Up @@ -155,17 +139,16 @@ public static IPAddressRange Parse(string ipRangeString)
return new IPAddressRange(IPAddress.Parse(match.Groups["singleAddr"].Value));

if (!string.IsNullOrEmpty(match.Groups["begin"].Value))
return new IPAddressRange(new[]
{
return new IPAddressRange(
IPAddress.Parse(match.Groups["begin"].Value),
IPAddress.Parse(match.Groups["end"].Value)
});
);


if (!string.IsNullOrEmpty(match.Groups["bitmaskAddr"].Value))
return new IPAddressRange(
IPAddress.Parse(match.Groups["bitmaskAddr"].Value),
IPAddress.Parse(match.Groups["bitmaskMask"].Value));
SubnetMaskLength(IPAddress.Parse(match.Groups["bitmaskMask"].Value)));
}

throw new FormatException("Unknown IP range string.");
Expand All @@ -185,6 +168,19 @@ public static bool TryParse(string ipRangeString, out IPAddressRange ipRange)
}
}

/// <summary>
/// Takes a subnetmask (eg, "255.255.254.0") and returns the CIDR bit length of that
/// address. Throws an exception if the passed address is not valid as a subnet mask.
/// </summary>
/// <param name="subnetMask">The subnet mask to use</param>
/// <returns></returns>
public static int SubnetMaskLength(IPAddress subnetMask)
{
var length = Bits.GetBitMaskLength(subnetMask.GetAddressBytes());
if (length == null) throw new ArgumentException("Not a valid subnet mask", "subnetMask");
return length.Value;
}

public IEnumerator<IPAddress> GetEnumerator()
{
var first = Begin.GetAddressBytes();
Expand Down