func TestRtt_sortNodesByDistanceFrom(t *testing.T) { dir, server := testServer(t) defer os.RemoveAll(dir) defer server.Shutdown() codec := rpcClient(t, server) defer codec.Close() testutil.WaitForLeader(t, server.RPC, "dc1") seedCoordinates(t, codec, server) nodes := structs.Nodes{ &structs.Node{Node: "apple"}, &structs.Node{Node: "node1"}, &structs.Node{Node: "node2"}, &structs.Node{Node: "node3"}, &structs.Node{Node: "node4"}, &structs.Node{Node: "node5"}, } // The zero value for the source should not trigger any sorting. var source structs.QuerySource if err := server.sortNodesByDistanceFrom(source, nodes); err != nil { t.Fatalf("err: %v", err) } verifyNodeSort(t, nodes, "apple,node1,node2,node3,node4,node5") // Same for a source in some other DC. source.Node = "node1" source.Datacenter = "dc2" if err := server.sortNodesByDistanceFrom(source, nodes); err != nil { t.Fatalf("err: %v", err) } verifyNodeSort(t, nodes, "apple,node1,node2,node3,node4,node5") // Same for a source node in our DC that we have no coordinate for. source.Node = "apple" source.Datacenter = "dc1" if err := server.sortNodesByDistanceFrom(source, nodes); err != nil { t.Fatalf("err: %v", err) } verifyNodeSort(t, nodes, "apple,node1,node2,node3,node4,node5") // Set source to legit values relative to node1 but disable coordinates. source.Node = "node1" source.Datacenter = "dc1" server.config.DisableCoordinates = true if err := server.sortNodesByDistanceFrom(source, nodes); err != nil { t.Fatalf("err: %v", err) } verifyNodeSort(t, nodes, "apple,node1,node2,node3,node4,node5") // Now enable coordinates and sort relative to node1, note that apple // doesn't have any seeded coordinate info so it should end up at the // end, despite its lexical hegemony. server.config.DisableCoordinates = false if err := server.sortNodesByDistanceFrom(source, nodes); err != nil { t.Fatalf("err: %v", err) } verifyNodeSort(t, nodes, "node1,node4,node5,node2,node3,apple") }
func TestRtt_sortNodesByDistanceFrom_CheckServiceNodes(t *testing.T) { dir, server := testServer(t) defer os.RemoveAll(dir) defer server.Shutdown() codec := rpcClient(t, server) defer codec.Close() testutil.WaitForLeader(t, server.RPC, "dc1") seedCoordinates(t, codec, server) nodes := structs.CheckServiceNodes{ structs.CheckServiceNode{Node: &structs.Node{Node: "apple"}}, structs.CheckServiceNode{Node: &structs.Node{Node: "node1"}}, structs.CheckServiceNode{Node: &structs.Node{Node: "node2"}}, structs.CheckServiceNode{Node: &structs.Node{Node: "node3"}}, structs.CheckServiceNode{Node: &structs.Node{Node: "node4"}}, structs.CheckServiceNode{Node: &structs.Node{Node: "node5"}}, } // Now sort relative to node1, note that apple doesn't have any // seeded coordinate info so it should end up at the end, despite // its lexical hegemony. var source structs.QuerySource source.Node = "node1" source.Datacenter = "dc1" if err := server.sortNodesByDistanceFrom(source, nodes); err != nil { t.Fatalf("err: %v", err) } verifyCheckServiceNodeSort(t, nodes, "node1,node4,node5,node2,node3,apple") // Try another sort from node2. Note that node5 and node3 are the // same distance away so the stable sort should preserve the order // they were in from the previous sort. source.Node = "node2" source.Datacenter = "dc1" if err := server.sortNodesByDistanceFrom(source, nodes); err != nil { t.Fatalf("err: %v", err) } verifyCheckServiceNodeSort(t, nodes, "node2,node5,node3,node4,node1,apple") // Let's exercise the stable sort explicitly to make sure we didn't // just get lucky. nodes[1], nodes[2] = nodes[2], nodes[1] if err := server.sortNodesByDistanceFrom(source, nodes); err != nil { t.Fatalf("err: %v", err) } verifyCheckServiceNodeSort(t, nodes, "node2,node3,node5,node4,node1,apple") }