spec/net_resolvers_service_spec.lua
author Kim Alvefur <zash@zash.se>
Sun, 24 Mar 2024 21:32:00 +0100
changeset 13468 2dbc169aae6a
parent 12405 c029ddcad258
permissions -rw-r--r--
util.startup: Abort before initialization of logging when started as root Prevents creation of log files owned by the root user which could be inaccessible once started correctly.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12405
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
local set = require "util.set";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     3
insulate("net.resolvers.service", function ()
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     4
	local adns = {
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     5
		resolver = function ()
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     6
			return {
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
				lookup = function (_, cb, qname, qtype, qclass)
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
					if qname == "_xmpp-server._tcp.example.com"
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     9
					   and (qtype or "SRV") == "SRV"
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    10
					   and (qclass or "IN") == "IN" then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
						cb({
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    12
							{ -- 60+35+60
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    13
								srv = { target = "xmpp0-a.example.com", port = 5228, priority = 0, weight = 60 };
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    14
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    15
							{
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    16
								srv = { target = "xmpp0-b.example.com", port = 5216, priority = 0, weight = 35 };
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    18
							{
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    19
								srv = { target = "xmpp0-c.example.com", port = 5200, priority = 0, weight = 0 };
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    20
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
							{
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    22
								srv = { target = "xmpp0-d.example.com", port = 5256, priority = 0, weight = 120 };
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    23
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    24
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    25
							{
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
								srv = { target = "xmpp1-a.example.com", port = 5273, priority = 1, weight = 30 };
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    27
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
							{
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    29
								srv = { target = "xmpp1-b.example.com", port = 5274, priority = 1, weight = 30 };
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    30
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    31
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    32
							{
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
								srv = { target = "xmpp2.example.com", port = 5275, priority = 2, weight = 0 };
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    34
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    35
						});
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    36
					elseif qname == "_xmpp-server._tcp.single.example.com"
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    37
					   and (qtype or "SRV") == "SRV"
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    38
					   and (qclass or "IN") == "IN" then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    39
						cb({
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    40
							{
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    41
								srv = { target = "xmpp0-a.example.com", port = 5269, priority = 0, weight = 0 };
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    42
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    43
						});
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    44
					elseif qname == "_xmpp-server._tcp.half.example.com"
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    45
					   and (qtype or "SRV") == "SRV"
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    46
					   and (qclass or "IN") == "IN" then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    47
						cb({
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    48
							{
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    49
								srv = { target = "xmpp0-a.example.com", port = 5269, priority = 0, weight = 0 };
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    50
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    51
							{
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    52
								srv = { target = "xmpp0-b.example.com", port = 5270, priority = 0, weight = 1 };
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    53
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    54
						});
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    55
					elseif qtype == "A" then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    56
						local l = qname:match("%-(%a)%.example.com$") or "1";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    57
						local d = ("%d"):format(l:byte())
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    58
						cb({
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    59
							{
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    60
								a = "127.0.0."..d;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    61
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    62
						});
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
					elseif qtype == "AAAA" then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    64
						local l = qname:match("%-(%a)%.example.com$") or "1";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    65
						local d = ("%04d"):format(l:byte())
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    66
						cb({
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    67
							{
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
								aaaa = "fdeb:9619:649e:c7d9::"..d;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    69
							};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    70
						});
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    71
					else
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    72
						cb(nil);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    73
					end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    74
				end;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    75
			};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    76
		end;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    77
	};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    78
	package.loaded["net.adns"] = mock(adns);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    79
	local resolver = require "net.resolvers.service";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    80
	math.randomseed(os.time());
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    81
	it("works for 99% of deployments", function ()
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    82
		-- Most deployments only have a single SRV record, let's make
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    83
		-- sure that works okay
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    84
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    85
		local expected_targets = set.new({
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    86
			-- xmpp0-a
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    87
			"tcp4  127.0.0.97  5269";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    88
			"tcp6  fdeb:9619:649e:c7d9::0097  5269";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    89
		});
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    90
		local received_targets = set.new({});
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    91
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    92
		local r = resolver.new("single.example.com", "xmpp-server");
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    93
		local done = false;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    94
		local function handle_target(...)
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    95
			if ... == nil then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    96
				done = true;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    97
				-- No more targets
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    98
				return;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    99
			end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   100
			received_targets:add(table.concat({ ... }, "  ", 1, 3));
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   101
		end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   102
		r:next(handle_target);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   103
		while not done do
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   104
			r:next(handle_target);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   105
		end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   106
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   107
		-- We should have received all expected targets, and no unexpected
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   108
		-- ones:
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   109
		assert.truthy(set.xor(received_targets, expected_targets):empty());
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   110
	end);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   111
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   112
	it("supports A/AAAA fallback", function ()
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   113
		-- Many deployments don't have any SRV records, so we should
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   114
		-- fall back to A/AAAA records instead when that is the case
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   115
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   116
		local expected_targets = set.new({
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   117
			-- xmpp0-a
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   118
			"tcp4  127.0.0.97  5269";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   119
			"tcp6  fdeb:9619:649e:c7d9::0097  5269";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   120
		});
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   121
		local received_targets = set.new({});
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   122
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   123
		local r = resolver.new("xmpp0-a.example.com", "xmpp-server", "tcp", { default_port = 5269 });
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   124
		local done = false;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   125
		local function handle_target(...)
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   126
			if ... == nil then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   127
				done = true;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   128
				-- No more targets
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   129
				return;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   130
			end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   131
			received_targets:add(table.concat({ ... }, "  ", 1, 3));
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   132
		end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   133
		r:next(handle_target);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   134
		while not done do
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   135
			r:next(handle_target);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   136
		end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   137
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   138
		-- We should have received all expected targets, and no unexpected
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   139
		-- ones:
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   140
		assert.truthy(set.xor(received_targets, expected_targets):empty());
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   141
	end);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   142
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   143
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   144
	it("works", function ()
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   145
		local expected_targets = set.new({
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   146
			-- xmpp0-a
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   147
			"tcp4  127.0.0.97  5228";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   148
			"tcp6  fdeb:9619:649e:c7d9::0097  5228";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   149
			"tcp4  127.0.0.97  5273";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   150
			"tcp6  fdeb:9619:649e:c7d9::0097  5273";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   151
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   152
			-- xmpp0-b
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   153
			"tcp4  127.0.0.98  5274";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   154
			"tcp6  fdeb:9619:649e:c7d9::0098  5274";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   155
			"tcp4  127.0.0.98  5216";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   156
			"tcp6  fdeb:9619:649e:c7d9::0098  5216";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   157
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   158
			-- xmpp0-c
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   159
			"tcp4  127.0.0.99  5200";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   160
			"tcp6  fdeb:9619:649e:c7d9::0099  5200";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   161
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   162
			-- xmpp0-d
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   163
			"tcp4  127.0.0.100  5256";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   164
			"tcp6  fdeb:9619:649e:c7d9::0100  5256";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   165
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   166
			-- xmpp2
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   167
			"tcp4  127.0.0.49  5275";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   168
			"tcp6  fdeb:9619:649e:c7d9::0049  5275";
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   169
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   170
		});
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   171
		local received_targets = set.new({});
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   172
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   173
		local r = resolver.new("example.com", "xmpp-server");
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   174
		local done = false;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   175
		local function handle_target(...)
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   176
			if ... == nil then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   177
				done = true;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   178
				-- No more targets
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   179
				return;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   180
			end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   181
			received_targets:add(table.concat({ ... }, "  ", 1, 3));
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   182
		end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   183
		r:next(handle_target);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   184
		while not done do
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   185
			r:next(handle_target);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   186
		end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   187
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   188
		-- We should have received all expected targets, and no unexpected
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   189
		-- ones:
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   190
		assert.truthy(set.xor(received_targets, expected_targets):empty());
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   191
	end);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   192
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   193
	it("balances across weights correctly #slow", function ()
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   194
		-- This mimics many repeated connections to 'example.com' (mock
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   195
		-- records defined above), and records the port number of the
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   196
		-- first target. Therefore it (should) only return priority
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   197
		-- 0 records, and the input data is constructed such that the
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   198
		-- last two digits of the port number represent the percentage
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   199
		-- of times that record should (on average) be picked first.
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   200
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   201
		-- To prevent random test failures, we test across a handful
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   202
		-- of fixed (randomly selected) seeds.
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   203
		for _, seed in ipairs({ 8401877, 3943829, 7830992 }) do
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   204
			math.randomseed(seed);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   205
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   206
			local results = {};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   207
			local function run()
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   208
				local run_results = {};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   209
				local r = resolver.new("example.com", "xmpp-server");
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   210
				local function record_target(...)
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   211
					if ... == nil then
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   212
						-- No more targets
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   213
						return;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   214
					end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   215
					run_results = { ... };
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   216
				end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   217
				r:next(record_target);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   218
				return run_results[3];
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   219
			end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   220
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   221
			for _ = 1, 1000 do
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   222
				local port = run();
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   223
				results[port] = (results[port] or 0) + 1;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   224
			end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   225
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   226
			local ports = {};
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   227
			for port in pairs(results) do
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   228
				table.insert(ports, port);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   229
			end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   230
			table.sort(ports);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   231
			for _, port in ipairs(ports) do
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   232
				--print("PORT", port, tostring((results[port]/1000) * 100).."% hits (expected "..tostring(port-5200).."%)");
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   233
				local hit_pct = (results[port]/1000) * 100;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   234
				local expected_pct = port - 5200;
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   235
				--print(hit_pct, expected_pct, math.abs(hit_pct - expected_pct));
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   236
				assert.is_true(math.abs(hit_pct - expected_pct) < 5);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   237
			end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   238
			--print("---");
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   239
		end
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   240
	end);
c029ddcad258 net.resolvers.service: Honour record 'weight' when picking SRV targets
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   241
end);