view spec/util_hashring_spec.lua @ 12473:bb85be686a01

mod_s2s: Distinguish DANE TLSA errors from generic cert chain errors Otherwise it would just report "is not trusted" unless you inspect the logs. This message is sent to to the remote server, and will hopefully show up in their logs, allowing the admin to fix their DANE setup.
author Kim Alvefur <zash@zash.se>
date Mon, 25 Apr 2022 14:41:54 +0200
parents de43ca319184
children 249b01adc54a
line wrap: on
line source

local hashring = require "util.hashring";

describe("util.hashring", function ()

	local sha256 = require "util.hashes".sha256;

	local ring = hashring.new(128, sha256);

	it("should fail to get a node that does not exist", function ()
		assert.is_nil(ring:get_node("foo"))
	end);

	it("should support adding nodes", function ()
		ring:add_node("node1");
	end);

	it("should return a single node for all keys if only one node exists", function ()
		for i = 1, 100 do
			assert.is_equal("node1", ring:get_node(tostring(i)))
		end
	end);

	it("should support adding a second node", function ()
		ring:add_node("node2");
	end);

	it("should fail to remove a non-existent node", function ()
		assert.is_falsy(ring:remove_node("node3"));
	end);

	it("should succeed to remove a node", function ()
		assert.is_truthy(ring:remove_node("node1"));
	end);

	it("should return the only node for all keys", function ()
		for i = 1, 100 do
			assert.is_equal("node2", ring:get_node(tostring(i)))
		end
	end);

	it("should support adding multiple nodes", function ()
		ring:add_nodes({ "node1", "node3", "node4", "node5" });
	end);

	it("should disrupt a minimal number of keys on node removal", function ()
		local orig_ring = ring:clone();
		local node_tallies = {};

		local n = 1000;

		for i = 1, n do
			local key = tostring(i);
			local node = ring:get_node(key);
			node_tallies[node] = (node_tallies[node] or 0) + 1;
		end

		--[[
		for node, key_count in pairs(node_tallies) do
			print(node, key_count, ("%.2f%%"):format((key_count/n)*100));
		end
		]]

		ring:remove_node("node5");

		local disrupted_keys = 0;
		for i = 1, n do
			local key = tostring(i);
			if orig_ring:get_node(key) ~= ring:get_node(key) then
				disrupted_keys = disrupted_keys + 1;
			end
		end
		assert.is_equal(node_tallies["node5"], disrupted_keys);
	end);

	it("should support removing multiple nodes", function ()
		ring:remove_nodes({"node2", "node3", "node4", "node5"});
	end);

	it("should return a single node for all keys if only one node remains", function ()
		for i = 1, 100 do
			assert.is_equal("node1", ring:get_node(tostring(i)))
		end
	end);

end);