using RackPeek.Domain.Discovery;
using RackPeek.Domain.Resources.Services.Networking;
namespace Tests.Discovery;
///
/// Which addresses a block actually sweeps. Getting the edges wrong either wastes
/// probes on the network/broadcast addresses or — worse — skips real hosts on the
/// point-to-point prefixes where every address is a host.
///
public class NetworkScanTargetTests {
private static List Targets(string cidr) =>
NetworkScanner.EnumerateTargets(Cidr.Parse(cidr)).ToList();
[Fact]
public void A_24_sweeps_the_254_host_addresses() {
List targets = Targets("192.168.1.0/24");
Assert.Equal(254, targets.Count);
Assert.Equal("192.168.1.1", targets.First());
Assert.Equal("192.168.1.254", targets.Last());
Assert.DoesNotContain("192.168.1.0", targets);
Assert.DoesNotContain("192.168.1.255", targets);
}
[Fact]
public void A_30_has_two_hosts_between_network_and_broadcast() =>
Assert.Equal(["10.0.0.1", "10.0.0.2"], Targets("10.0.0.0/30"));
[Fact]
public void A_31_is_point_to_point_where_both_addresses_are_hosts() =>
// RFC 3021: /31 has no network or broadcast address.
Assert.Equal(["10.0.0.0", "10.0.0.1"], Targets("10.0.0.0/31"));
[Fact]
public void A_32_is_exactly_the_one_address() =>
Assert.Equal(["127.0.0.1"], Targets("127.0.0.1/32"));
[Fact]
public void A_16_sweeps_the_full_65534_hosts() =>
Assert.Equal(65_534, Targets("10.20.0.0/16").Count);
[Fact]
public void A_block_at_the_top_of_the_address_space_does_not_wrap() {
List targets = Targets("255.255.255.252/30");
Assert.Equal(["255.255.255.253", "255.255.255.254"], targets);
}
[Fact]
public void The_offered_ip_need_not_be_the_network_address() =>
// People type their own address plus a prefix; Cidr.Parse masks it down.
Assert.Equal(254, Targets("192.168.1.37/24").Count);
}