66#include < cppcoro/net/ip_address.hpp>
77
88#include " doctest/cppcoro_doctest.h"
9+ #include < string_view>
910
1011TEST_SUITE_BEGIN (" ip_address" );
1112
@@ -31,15 +32,58 @@ TEST_CASE("to_string")
3132
3233TEST_CASE (" from_string" )
3334{
34- CHECK (ip_address::from_string (" " ) == std::nullopt );
35- CHECK (ip_address::from_string (" foo" ) == std::nullopt );
36- CHECK (ip_address::from_string (" 192.168.0.1" ) == std::nullopt );
37- CHECK (ip_address::from_string (" 192.168.0.1asdf" ) == std::nullopt );
38-
39- CHECK (ip_address::from_string (" 192.168.0.1" ) == ipv4_address (192 , 168 , 0 , 1 ));
40- CHECK (ip_address::from_string (" ::192.168.0.1" ) == ipv6_address (0 , 0 , 0 , 0 , 0 , 0 , 0xc0a8 , 0x1 ));
41- CHECK (ip_address::from_string (" aabb:ccdd:11:2233:102:304:506:708" ) ==
42- ipv6_address{ 0xAABBCCDD00112233 , 0x0102030405060708 });
35+ CHECK (ip_address::from_string (" " ) == std::nullopt );
36+ CHECK (ip_address::from_string (" foo" ) == std::nullopt );
37+ CHECK (ip_address::from_string (" 192.168.0.1" ) == std::nullopt );
38+ CHECK (ip_address::from_string (" 192.168.0.1asdf" ) == std::nullopt );
39+
40+ CHECK (ip_address::from_string (" 192.168.0.1" ) == ipv4_address (192 , 168 , 0 , 1 ));
41+ CHECK (ip_address::from_string (" ::192.168.0.1" ) == ipv6_address (0 , 0 , 0 , 0 , 0 , 0 , 0xc0a8 , 0x1 ));
42+ CHECK (ip_address::from_string (" aabb:ccdd:11:2233:102:304:506:708" ) ==
43+ ipv6_address{ 0xAABBCCDD00112233 , 0x0102030405060708 });
44+ }
45+
46+ TEST_CASE (" round-trip and ordering" )
47+ {
48+ // Round-trip: to_string(from_string(s)) yields canonical string, and parsing back preserves value
49+ auto check_round_trip = [](std::string_view s) {
50+ auto p = ip_address::from_string (s);
51+ REQUIRE (p.has_value ());
52+ auto canon = p->to_string ();
53+ auto p2 = ip_address::from_string (canon);
54+ REQUIRE (p2.has_value ());
55+ CHECK (*p == *p2);
56+ // Canonical string should be stable
57+ CHECK (p2->to_string () == canon);
58+ };
59+
60+ // IPv4
61+ check_round_trip (" 0.0.0.0" );
62+ check_round_trip (" 255.255.255.255" );
63+
64+ // IPv6 (mixed case input should parse and normalise to lower-case hex without leading zeros)
65+ check_round_trip (" ::" );
66+ check_round_trip (" ::1" );
67+ check_round_trip (" FFFF:0000:0000:0000:0000:0000:0000:0001" );
68+ check_round_trip (" ::192.168.0.1" );
69+
70+ // Ordering: IPv4 sorts less than IPv6
71+ ip_address v4 = ipv4_address{127 , 0 , 0 , 1 };
72+ ip_address v6 = ipv6_address{0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 }; // ::1
73+ CHECK (v4 < v6);
74+
75+ // Ordering within same family
76+ CHECK (ipv4_address{1 , 1 , 1 , 1 } < ipv4_address{1 , 1 , 1 , 2 });
77+ CHECK (ipv6_address{0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } < ipv6_address{0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 });
78+
79+ // Reject trailing/leading whitespace
80+ CHECK (ip_address::from_string (" 192.168.0.1 " ) == std::nullopt );
81+ CHECK (ip_address::from_string (" \t ::1" ) == std::nullopt );
82+
83+ // Reject malformed IPv6
84+ CHECK (ip_address::from_string (" ::::" ) == std::nullopt );
85+ CHECK (ip_address::from_string (" gggg::1" ) == std::nullopt );
86+ CHECK (ip_address::from_string (" 12345::1" ) == std::nullopt );
4387}
4488
4589TEST_SUITE_END ();
0 commit comments