mirror of
https://github.com/oxen-io/oxen-mq.git
synced 2023-12-13 21:00:31 +01:00
31f64821f8
So that you can store addresses in unordered_sets _maps.
162 lines
7.2 KiB
C++
162 lines
7.2 KiB
C++
#include "oxenmq/address.h"
|
|
#include "common.h"
|
|
|
|
const std::string pk = "\xf1\x6b\xa5\x59\x10\x39\xf0\x89\xb4\x2a\x83\x41\x75\x09\x30\x94\x07\x4d\x0d\x93\x7a\x79\xe5\x3e\x5c\xe7\x30\xf9\x46\xe1\x4b\x88";
|
|
const std::string pk_hex = "f16ba5591039f089b42a834175093094074d0d937a79e53e5ce730f946e14b88";
|
|
const std::string pk_HEX = "F16BA5591039F089B42A834175093094074D0D937A79E53E5CE730F946E14B88";
|
|
const std::string pk_b32z = "6fi4kseo88aeupbkopyzknjo1odw4dcuxjh6kx1hhhax1tzbjqry";
|
|
const std::string pk_B32Z = "6FI4KSEO88AEUPBKOPYZKNJO1ODW4DCUXJH6KX1HHHAX1TZBJQRY";
|
|
const std::string pk_b64 = "8WulWRA58Im0KoNBdQkwlAdNDZN6eeU+XOcw+UbhS4g"; // NB: padding '=' omitted
|
|
|
|
TEST_CASE("tcp addresses", "[address][tcp]") {
|
|
address a{"tcp://1.2.3.4:5678"};
|
|
REQUIRE( a.host == "1.2.3.4" );
|
|
REQUIRE( a.port == 5678 );
|
|
REQUIRE_FALSE( a.curve() );
|
|
REQUIRE( a.tcp() );
|
|
REQUIRE( a.zmq_address() == "tcp://1.2.3.4:5678" );
|
|
REQUIRE( a.full_address() == "tcp://1.2.3.4:5678" );
|
|
REQUIRE( a.qr_address() == "TCP://1.2.3.4:5678" );
|
|
|
|
REQUIRE_THROWS_AS( address{"tcp://1:1:1"}, std::invalid_argument );
|
|
REQUIRE_THROWS_AS( address{"tcpz://localhost:123"}, std::invalid_argument );
|
|
REQUIRE_THROWS_AS( address{"tcp://abc"}, std::invalid_argument );
|
|
REQUIRE_THROWS_AS( address{"tcpz://localhost:0"}, std::invalid_argument );
|
|
REQUIRE_THROWS_AS( address{"tcpz://[::1:1080"}, std::invalid_argument );
|
|
|
|
address b = address::tcp("example.com", 80);
|
|
REQUIRE( b.host == "example.com" );
|
|
REQUIRE( b.port == 80 );
|
|
REQUIRE_FALSE( b.curve() );
|
|
REQUIRE( b.tcp() );
|
|
REQUIRE( b.zmq_address() == "tcp://example.com:80" );
|
|
REQUIRE( b.full_address() == "tcp://example.com:80" );
|
|
REQUIRE( b.qr_address() == "TCP://EXAMPLE.COM:80" );
|
|
|
|
address c{"tcp://[::1]:1111"};
|
|
REQUIRE( c.host == "[::1]" );
|
|
REQUIRE( c.port == 1111 );
|
|
}
|
|
|
|
TEST_CASE("unix sockets", "[address][ipc]") {
|
|
address a{"ipc:///path/to/foo"};
|
|
REQUIRE( a.socket == "/path/to/foo" );
|
|
REQUIRE_FALSE( a.curve() );
|
|
REQUIRE_FALSE( a.tcp() );
|
|
REQUIRE( a.zmq_address() == "ipc:///path/to/foo" );
|
|
REQUIRE( a.full_address() == "ipc:///path/to/foo" );
|
|
|
|
address b = address::ipc("../foo");
|
|
REQUIRE( b.socket == "../foo" );
|
|
REQUIRE_FALSE( b.curve() );
|
|
REQUIRE_FALSE( b.tcp() );
|
|
REQUIRE( b.zmq_address() == "ipc://../foo" );
|
|
REQUIRE( b.full_address() == "ipc://../foo" );
|
|
}
|
|
|
|
TEST_CASE("pubkey formats", "[address][curve][pubkey]") {
|
|
address a{"tcp+curve://a:1/" + pk_hex};
|
|
address b{"curve://a:1/" + pk_b32z};
|
|
address c{"curve://a:1/" + pk_b64};
|
|
address d{"CURVE://A:1/" + pk_B32Z};
|
|
REQUIRE( a.curve() );
|
|
REQUIRE( a.host == "a" );
|
|
REQUIRE( a.port == 1 );
|
|
REQUIRE((b.curve() && c.curve() && d.curve()));
|
|
REQUIRE( a.pubkey == pk );
|
|
REQUIRE( b.pubkey == pk );
|
|
REQUIRE( c.pubkey == pk );
|
|
REQUIRE( d.pubkey == pk );
|
|
|
|
address e{"ipc+curve://my.sock/" + pk_hex};
|
|
address f{"ipc+curve://../my.sock/" + pk_b32z};
|
|
address g{"ipc+curve:///my.sock/" + pk_B32Z};
|
|
address h{"ipc+curve://./my.sock/" + pk_b64};
|
|
REQUIRE( e.curve() );
|
|
REQUIRE( e.ipc() );
|
|
REQUIRE_FALSE( e.tcp() );
|
|
REQUIRE((f.curve() && g.curve() && h.curve()));
|
|
REQUIRE( e.socket == "my.sock" );
|
|
REQUIRE( f.socket == "../my.sock" );
|
|
REQUIRE( g.socket == "/my.sock" );
|
|
REQUIRE( h.socket == "./my.sock" );
|
|
REQUIRE( e.pubkey == pk );
|
|
REQUIRE( f.pubkey == pk );
|
|
REQUIRE( g.pubkey == pk );
|
|
REQUIRE( h.pubkey == pk );
|
|
|
|
REQUIRE( d.full_address(address::encoding::hex) == "curve://a:1/" + pk_hex );
|
|
REQUIRE( c.full_address(address::encoding::base32z) == "curve://a:1/" + pk_b32z );
|
|
REQUIRE( b.full_address(address::encoding::BASE32Z) == "curve://a:1/" + pk_B32Z );
|
|
REQUIRE( a.full_address(address::encoding::base64) == "curve://a:1/" + pk_b64 );
|
|
|
|
REQUIRE( h.full_address(address::encoding::hex) == "ipc+curve://./my.sock/" + pk_hex );
|
|
REQUIRE( g.full_address(address::encoding::base32z) == "ipc+curve:///my.sock/" + pk_b32z );
|
|
REQUIRE( f.full_address(address::encoding::BASE32Z) == "ipc+curve://../my.sock/" + pk_B32Z );
|
|
REQUIRE( e.full_address(address::encoding::base64) == "ipc+curve://my.sock/" + pk_b64 );
|
|
|
|
REQUIRE_THROWS_AS(address{"ipc+curve://my.sock/" + pk_hex.substr(0, 63)}, std::invalid_argument);
|
|
REQUIRE_THROWS_AS(address{"ipc+curve://my.sock/" + pk_b32z.substr(0, 51)}, std::invalid_argument);
|
|
REQUIRE_THROWS_AS(address{"ipc+curve://my.sock/" + pk_B32Z.substr(0, 51)}, std::invalid_argument);
|
|
REQUIRE_THROWS_AS(address{"ipc+curve://my.sock/" + pk_b64.substr(0, 42)}, std::invalid_argument);
|
|
REQUIRE_THROWS_AS(address{"ipc+curve://my.sock"}, std::invalid_argument);
|
|
REQUIRE_THROWS_AS(address{"ipc+curve://my.sock/"}, std::invalid_argument);
|
|
}
|
|
|
|
|
|
TEST_CASE("tcp QR-code friendly addresses", "[address][tcp][qr]") {
|
|
address a{"tcp://public.loki.foundation:12345"};
|
|
address a_qr{"TCP://PUBLIC.LOKI.FOUNDATION:12345"};
|
|
address b{"tcp://PUBLIC.LOKI.FOUNDATION:12345"};
|
|
REQUIRE( a == a_qr );
|
|
REQUIRE( a != b );
|
|
REQUIRE( a.host == "public.loki.foundation" );
|
|
REQUIRE( a.qr_address() == "TCP://PUBLIC.LOKI.FOUNDATION:12345" );
|
|
|
|
address c = address::tcp_curve("public.loki.foundation", 12345, pk);
|
|
REQUIRE( c.qr_address() == "CURVE://PUBLIC.LOKI.FOUNDATION:12345/" + pk_B32Z );
|
|
REQUIRE( address{"CURVE://PUBLIC.LOKI.FOUNDATION:12345/" + pk_B32Z} == c );
|
|
// We don't produce with upper-case hex, but we accept it:
|
|
REQUIRE( address{"CURVE://PUBLIC.LOKI.FOUNDATION:12345/" + pk_HEX} == c );
|
|
|
|
// lower case not permitted: ▾
|
|
REQUIRE_THROWS_AS(address{"CURVE://PUBLIC.LOKI.FOUNDATiON:12345/" + pk_B32Z}, std::invalid_argument);
|
|
// also only accept upper-base base32z and hex:
|
|
REQUIRE_THROWS_AS(address{"CURVE://PUBLIC.LOKI.FOUNDATION:12345/" + pk_b32z}, std::invalid_argument);
|
|
REQUIRE_THROWS_AS(address{"CURVE://PUBLIC.LOKI.FOUNDATION:12345/" + pk_hex}, std::invalid_argument);
|
|
// don't accept base64 even if it's upper-case (because case-converting it changes the value)
|
|
REQUIRE_THROWS_AS(address{"CURVE://PUBLIC.LOKI.FOUNDATION:12345/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}, std::invalid_argument);
|
|
REQUIRE_THROWS_AS(address{"CURVE://PUBLIC.LOKI.FOUNDATION:12345/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="}, std::invalid_argument);
|
|
}
|
|
|
|
TEST_CASE("address hashing", "[address][hash]") {
|
|
address a{"tcp://public.loki.foundation:12345"};
|
|
address b{"tcp+curve://public.loki.foundation:12345/" + pk_hex};
|
|
address c{"ipc:///tmp/some.sock"};
|
|
address d{"ipc:///tmp/some.other.sock"};
|
|
|
|
std::hash<oxenmq::address> hasher{};
|
|
REQUIRE( hasher(a) != hasher(b) );
|
|
REQUIRE( hasher(a) != hasher(c) );
|
|
REQUIRE( hasher(a) != hasher(d) );
|
|
REQUIRE( hasher(b) != hasher(c) );
|
|
REQUIRE( hasher(b) != hasher(d) );
|
|
REQUIRE( hasher(c) != hasher(d) );
|
|
|
|
std::unordered_set<oxenmq::address> set;
|
|
set.insert(a);
|
|
set.insert(b);
|
|
set.insert(c);
|
|
set.insert(d);
|
|
|
|
CHECK( set.size() == 4 );
|
|
std::unordered_map<oxenmq::address, int> count;
|
|
for (const auto& addr : set)
|
|
count[addr]++;
|
|
|
|
REQUIRE( count.size() == 4 );
|
|
CHECK( count[a] == 1 );
|
|
CHECK( count[b] == 1 );
|
|
CHECK( count[c] == 1 );
|
|
CHECK( count[d] == 1 );
|
|
}
|