spec/net_resolvers_service_spec.lua
author Kim Alvefur <zash@zash.se>
Wed, 27 Mar 2024 19:33:11 +0100
changeset 13471 c2a476f4712a
parent 12405 c029ddcad258
permissions -rw-r--r--
util.startup: Fix exiting on pidfile trouble prosody.shutdown() relies on prosody.main_thread, which has not been set yet at this point. Doing a clean shutdown might actually be harmful in case it tears down things set up by the conflicting Prosody, such as the very pidfile we were looking at. Thanks again SigmaTel71 for noticing
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);