From d1b6acc57a4f04fcc320d395e3ad72dd13b4c54e Mon Sep 17 00:00:00 2001 From: Lee Stutzman Date: Fri, 3 Apr 2026 03:13:35 +0100 Subject: [PATCH] CODEBASE: Replace ipExists() linear scan with O(1) Map.has() (#2621) --- src/Server/AllServers.ts | 7 +----- test/jest/Server/AllServers.test.ts | 35 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/Server/AllServers.ts b/src/Server/AllServers.ts index a7a956171..24720489e 100644 --- a/src/Server/AllServers.ts +++ b/src/Server/AllServers.ts @@ -89,12 +89,7 @@ export const disconnectServers = (server1: BaseServer, server2: BaseServer) => { }; export function ipExists(ip: string): boolean { - for (const server of AllServers.values()) { - if (server.ip === ip) { - return true; - } - } - return false; + return AllServers.has(ip); } export function createUniqueRandomIp(): IPAddress { diff --git a/test/jest/Server/AllServers.test.ts b/test/jest/Server/AllServers.test.ts index e93ee9d48..6d30d1a63 100644 --- a/test/jest/Server/AllServers.test.ts +++ b/test/jest/Server/AllServers.test.ts @@ -6,6 +6,7 @@ import { saveAllServers, renameServer, GetServer, + ipExists, } from "../../../src/Server/AllServers"; import { Server } from "../../../src/Server/Server"; import { IPAddress } from "../../../src/Types/strings"; @@ -38,6 +39,40 @@ describe("AllServers can be saved and loaded", () => { }); }); +describe("ipExists", () => { + beforeEach(() => { + prestigeAllServers(); + }); + + it("returns true for an IP that exists in AllServers", () => { + const server = new Server({ hostname: "test-server", ip: "10.20.30.40" as IPAddress }); + AddToAllServers(server); + expect(ipExists("10.20.30.40")).toBe(true); + }); + + it("returns false for an IP that does not exist", () => { + expect(ipExists("99.99.99.99")).toBe(false); + }); + + it("does not use linear scan (performance: uses Map.has, not iteration)", () => { + // Add a server so the map is non-empty + const server = new Server({ hostname: "perf-test", ip: "1.1.1.1" as IPAddress }); + AddToAllServers(server); + + // Spy on Map.prototype.values to detect if ipExists iterates + const valuesSpy = jest.spyOn(Map.prototype, "values"); + + ipExists("1.1.1.1"); + ipExists("2.2.2.2"); + + // With the fix (Map.has), values() should NOT be called by ipExists + // With the bug (for...of iteration), values() WOULD be called + expect(valuesSpy).not.toHaveBeenCalled(); + + valuesSpy.mockRestore(); + }); +}); + describe("renameServer tests", () => { it("rename to self edge case", () => { prestigeAllServers();