spec/util_hashring_spec.lua
changeset 10011 de43ca319184
child 12798 249b01adc54a
equal deleted inserted replaced
10010:5a5fd234dec7 10011:de43ca319184
       
     1 local hashring = require "util.hashring";
       
     2 
       
     3 describe("util.hashring", function ()
       
     4 
       
     5 	local sha256 = require "util.hashes".sha256;
       
     6 
       
     7 	local ring = hashring.new(128, sha256);
       
     8 
       
     9 	it("should fail to get a node that does not exist", function ()
       
    10 		assert.is_nil(ring:get_node("foo"))
       
    11 	end);
       
    12 
       
    13 	it("should support adding nodes", function ()
       
    14 		ring:add_node("node1");
       
    15 	end);
       
    16 
       
    17 	it("should return a single node for all keys if only one node exists", function ()
       
    18 		for i = 1, 100 do
       
    19 			assert.is_equal("node1", ring:get_node(tostring(i)))
       
    20 		end
       
    21 	end);
       
    22 
       
    23 	it("should support adding a second node", function ()
       
    24 		ring:add_node("node2");
       
    25 	end);
       
    26 
       
    27 	it("should fail to remove a non-existent node", function ()
       
    28 		assert.is_falsy(ring:remove_node("node3"));
       
    29 	end);
       
    30 
       
    31 	it("should succeed to remove a node", function ()
       
    32 		assert.is_truthy(ring:remove_node("node1"));
       
    33 	end);
       
    34 
       
    35 	it("should return the only node for all keys", function ()
       
    36 		for i = 1, 100 do
       
    37 			assert.is_equal("node2", ring:get_node(tostring(i)))
       
    38 		end
       
    39 	end);
       
    40 
       
    41 	it("should support adding multiple nodes", function ()
       
    42 		ring:add_nodes({ "node1", "node3", "node4", "node5" });
       
    43 	end);
       
    44 
       
    45 	it("should disrupt a minimal number of keys on node removal", function ()
       
    46 		local orig_ring = ring:clone();
       
    47 		local node_tallies = {};
       
    48 
       
    49 		local n = 1000;
       
    50 
       
    51 		for i = 1, n do
       
    52 			local key = tostring(i);
       
    53 			local node = ring:get_node(key);
       
    54 			node_tallies[node] = (node_tallies[node] or 0) + 1;
       
    55 		end
       
    56 
       
    57 		--[[
       
    58 		for node, key_count in pairs(node_tallies) do
       
    59 			print(node, key_count, ("%.2f%%"):format((key_count/n)*100));
       
    60 		end
       
    61 		]]
       
    62 
       
    63 		ring:remove_node("node5");
       
    64 
       
    65 		local disrupted_keys = 0;
       
    66 		for i = 1, n do
       
    67 			local key = tostring(i);
       
    68 			if orig_ring:get_node(key) ~= ring:get_node(key) then
       
    69 				disrupted_keys = disrupted_keys + 1;
       
    70 			end
       
    71 		end
       
    72 		assert.is_equal(node_tallies["node5"], disrupted_keys);
       
    73 	end);
       
    74 
       
    75 	it("should support removing multiple nodes", function ()
       
    76 		ring:remove_nodes({"node2", "node3", "node4", "node5"});
       
    77 	end);
       
    78 
       
    79 	it("should return a single node for all keys if only one node remains", function ()
       
    80 		for i = 1, 100 do
       
    81 			assert.is_equal("node1", ring:get_node(tostring(i)))
       
    82 		end
       
    83 	end);
       
    84 
       
    85 end);