Initial Commit - Sonnet 4.5
This commit is contained in:
324
tests/HashFunctions.test.ts
Normal file
324
tests/HashFunctions.test.ts
Normal file
@@ -0,0 +1,324 @@
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import { DefaultHashFunction } from "../src/hash-functions/DefaultHashFunction.ts";
|
||||
import { NumericHashFunction } from "../src/hash-functions/NumericHashFunction.ts";
|
||||
|
||||
describe("DefaultHashFunction", () => {
|
||||
const hashFn = new DefaultHashFunction<unknown>();
|
||||
const capacity = 16;
|
||||
|
||||
describe("basic types", () => {
|
||||
it("should hash string keys", () => {
|
||||
const hash1 = hashFn.hash("hello", capacity);
|
||||
const hash2 = hashFn.hash("world", capacity);
|
||||
|
||||
expect(hash1).toBeGreaterThanOrEqual(0);
|
||||
expect(hash1).toBeLessThan(capacity);
|
||||
expect(hash2).toBeGreaterThanOrEqual(0);
|
||||
expect(hash2).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash number keys", () => {
|
||||
const hash1 = hashFn.hash(42, capacity);
|
||||
const hash2 = hashFn.hash(3.14, capacity);
|
||||
const hash3 = hashFn.hash(0, capacity);
|
||||
const hash4 = hashFn.hash(-10, capacity);
|
||||
|
||||
expect(hash1).toBeGreaterThanOrEqual(0);
|
||||
expect(hash1).toBeLessThan(capacity);
|
||||
expect(hash2).toBeGreaterThanOrEqual(0);
|
||||
expect(hash3).toBeGreaterThanOrEqual(0);
|
||||
expect(hash4).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
|
||||
it("should hash boolean keys", () => {
|
||||
const hashTrue = hashFn.hash(true, capacity);
|
||||
const hashFalse = hashFn.hash(false, capacity);
|
||||
|
||||
expect(hashTrue).toBeGreaterThanOrEqual(0);
|
||||
expect(hashTrue).toBeLessThan(capacity);
|
||||
expect(hashFalse).toBeGreaterThanOrEqual(0);
|
||||
expect(hashFalse).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash null", () => {
|
||||
const hash = hashFn.hash(null, capacity);
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash undefined", () => {
|
||||
const hash = hashFn.hash(undefined, capacity);
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
});
|
||||
|
||||
describe("object types", () => {
|
||||
it("should hash simple objects", () => {
|
||||
const obj = { name: "Alice", age: 30 };
|
||||
const hash = hashFn.hash(obj, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash arrays", () => {
|
||||
const arr = [1, 2, 3, 4, 5];
|
||||
const hash = hashFn.hash(arr, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash nested objects", () => {
|
||||
const nested = {
|
||||
user: {
|
||||
name: "Bob",
|
||||
address: {
|
||||
city: "NYC",
|
||||
zip: "10001"
|
||||
}
|
||||
}
|
||||
};
|
||||
const hash = hashFn.hash(nested, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should handle circular references gracefully", () => {
|
||||
const circular: any = { name: "test" };
|
||||
circular.self = circular; // Create circular reference
|
||||
|
||||
// Should not throw, should fall back to Object.prototype.toString
|
||||
const hash = hashFn.hash(circular, capacity);
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash Date objects", () => {
|
||||
const date = new Date("2024-01-01");
|
||||
const hash = hashFn.hash(date, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash RegExp objects", () => {
|
||||
const regex = /test/g;
|
||||
const hash = hashFn.hash(regex, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash Error objects", () => {
|
||||
const error = new Error("Test error");
|
||||
const hash = hashFn.hash(error, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
});
|
||||
|
||||
describe("special values", () => {
|
||||
it("should hash empty string", () => {
|
||||
const hash = hashFn.hash("", capacity);
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash empty object", () => {
|
||||
const hash = hashFn.hash({}, capacity);
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash empty array", () => {
|
||||
const hash = hashFn.hash([], capacity);
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash symbols", () => {
|
||||
const sym = Symbol("test");
|
||||
const hash = hashFn.hash(sym, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash bigint", () => {
|
||||
const bigInt = BigInt(12345678901234567890n);
|
||||
const hash = hashFn.hash(bigInt, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
});
|
||||
|
||||
describe("consistency", () => {
|
||||
it("should return same hash for same key", () => {
|
||||
const key = "test-key";
|
||||
const hash1 = hashFn.hash(key, capacity);
|
||||
const hash2 = hashFn.hash(key, capacity);
|
||||
|
||||
expect(hash1).toBe(hash2);
|
||||
});
|
||||
|
||||
it("should return different hashes for different keys (usually)", () => {
|
||||
const hash1 = hashFn.hash("key1", capacity);
|
||||
const hash2 = hashFn.hash("key2", capacity);
|
||||
|
||||
// Note: They COULD collide, but unlikely
|
||||
expect(hash1).toBeGreaterThanOrEqual(0);
|
||||
expect(hash2).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
|
||||
it("should handle different capacities", () => {
|
||||
const key = "test";
|
||||
const hash8 = hashFn.hash(key, 8);
|
||||
const hash16 = hashFn.hash(key, 16);
|
||||
const hash32 = hashFn.hash(key, 32);
|
||||
|
||||
expect(hash8).toBeLessThan(8);
|
||||
expect(hash16).toBeLessThan(16);
|
||||
expect(hash32).toBeLessThan(32);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("NumericHashFunction", () => {
|
||||
const hashFn = new NumericHashFunction();
|
||||
const capacity = 16;
|
||||
|
||||
describe("normal numbers", () => {
|
||||
it("should hash positive integers", () => {
|
||||
const hash1 = hashFn.hash(42, capacity);
|
||||
const hash2 = hashFn.hash(100, capacity);
|
||||
|
||||
expect(hash1).toBeGreaterThanOrEqual(0);
|
||||
expect(hash1).toBeLessThan(capacity);
|
||||
expect(hash2).toBeGreaterThanOrEqual(0);
|
||||
expect(hash2).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash negative integers", () => {
|
||||
const hash = hashFn.hash(-42, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash zero", () => {
|
||||
const hash = hashFn.hash(0, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash floating point numbers", () => {
|
||||
const hash1 = hashFn.hash(3.14159, capacity);
|
||||
const hash2 = hashFn.hash(2.71828, capacity);
|
||||
|
||||
expect(hash1).toBeGreaterThanOrEqual(0);
|
||||
expect(hash1).toBeLessThan(capacity);
|
||||
expect(hash2).toBeGreaterThanOrEqual(0);
|
||||
expect(hash2).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash very large numbers", () => {
|
||||
const hash = hashFn.hash(Number.MAX_SAFE_INTEGER, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should hash very small numbers", () => {
|
||||
const hash = hashFn.hash(Number.MIN_VALUE, capacity);
|
||||
|
||||
expect(hash).toBeGreaterThanOrEqual(0);
|
||||
expect(hash).toBeLessThan(capacity);
|
||||
});
|
||||
});
|
||||
|
||||
describe("special numeric values", () => {
|
||||
it("should handle Infinity", () => {
|
||||
const hash = hashFn.hash(Infinity, capacity);
|
||||
|
||||
// Should return 0 for non-finite numbers
|
||||
expect(hash).toBe(0);
|
||||
});
|
||||
|
||||
it("should handle negative Infinity", () => {
|
||||
const hash = hashFn.hash(-Infinity, capacity);
|
||||
|
||||
// Should return 0 for non-finite numbers
|
||||
expect(hash).toBe(0);
|
||||
});
|
||||
|
||||
it("should handle NaN", () => {
|
||||
const hash = hashFn.hash(NaN, capacity);
|
||||
|
||||
// Should return 0 for non-finite numbers
|
||||
expect(hash).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("consistency", () => {
|
||||
it("should return same hash for same number", () => {
|
||||
const num = 42;
|
||||
const hash1 = hashFn.hash(num, capacity);
|
||||
const hash2 = hashFn.hash(num, capacity);
|
||||
|
||||
expect(hash1).toBe(hash2);
|
||||
});
|
||||
|
||||
it("should handle different capacities", () => {
|
||||
const num = 42;
|
||||
const hash8 = hashFn.hash(num, 8);
|
||||
const hash16 = hashFn.hash(num, 16);
|
||||
const hash32 = hashFn.hash(num, 32);
|
||||
|
||||
expect(hash8).toBeLessThan(8);
|
||||
expect(hash16).toBeLessThan(16);
|
||||
expect(hash32).toBeLessThan(32);
|
||||
});
|
||||
|
||||
it("should distribute numbers evenly", () => {
|
||||
const hashes = new Set<number>();
|
||||
|
||||
// Hash 100 sequential numbers
|
||||
for (let i = 0; i < 100; i++) {
|
||||
hashes.add(hashFn.hash(i, capacity));
|
||||
}
|
||||
|
||||
// Should have good distribution (not all in one bucket)
|
||||
expect(hashes.size).toBeGreaterThan(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("negative numbers", () => {
|
||||
it("should hash negative numbers correctly", () => {
|
||||
const hash1 = hashFn.hash(-1, capacity);
|
||||
const hash2 = hashFn.hash(-100, capacity);
|
||||
const hash3 = hashFn.hash(-3.14, capacity);
|
||||
|
||||
expect(hash1).toBeGreaterThanOrEqual(0);
|
||||
expect(hash1).toBeLessThan(capacity);
|
||||
expect(hash2).toBeGreaterThanOrEqual(0);
|
||||
expect(hash2).toBeLessThan(capacity);
|
||||
expect(hash3).toBeGreaterThanOrEqual(0);
|
||||
expect(hash3).toBeLessThan(capacity);
|
||||
});
|
||||
|
||||
it("should handle same absolute value differently for positive and negative", () => {
|
||||
const hashPos = hashFn.hash(42, capacity);
|
||||
const hashNeg = hashFn.hash(-42, capacity);
|
||||
|
||||
// They should hash to the same bucket (due to Math.abs in implementation)
|
||||
expect(hashPos).toBe(hashNeg);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
362
tests/HashMap.test.ts
Normal file
362
tests/HashMap.test.ts
Normal file
@@ -0,0 +1,362 @@
|
||||
import { describe, it, expect, beforeEach } from "bun:test";
|
||||
import { HashMap, NumericHashFunction } from "../src/index.ts";
|
||||
import type { IHashFunction } from "../src/index.ts";
|
||||
|
||||
describe("HashMap", () => {
|
||||
let map: HashMap<string, number>;
|
||||
|
||||
beforeEach(() => {
|
||||
map = new HashMap<string, number>();
|
||||
});
|
||||
|
||||
describe("constructor", () => {
|
||||
it("should create an empty map with default capacity", () => {
|
||||
expect(map.size).toBe(0);
|
||||
expect(map.capacity).toBe(16);
|
||||
});
|
||||
|
||||
it("should create a map with custom initial capacity", () => {
|
||||
const customMap = new HashMap<string, number>(32);
|
||||
expect(customMap.capacity).toBe(32);
|
||||
});
|
||||
|
||||
it("should throw error for invalid capacity", () => {
|
||||
expect(() => new HashMap<string, number>(0)).toThrow();
|
||||
expect(() => new HashMap<string, number>(-1)).toThrow();
|
||||
});
|
||||
|
||||
it("should throw error for invalid load factor", () => {
|
||||
expect(() => new HashMap<string, number>(16, 0)).toThrow();
|
||||
expect(() => new HashMap<string, number>(16, 1.5)).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("set and get", () => {
|
||||
it("should set and get a value", () => {
|
||||
map.set("key1", 100);
|
||||
expect(map.get("key1")).toBe(100);
|
||||
});
|
||||
|
||||
it("should update existing value", () => {
|
||||
map.set("key1", 100);
|
||||
map.set("key1", 200);
|
||||
expect(map.get("key1")).toBe(200);
|
||||
expect(map.size).toBe(1);
|
||||
});
|
||||
|
||||
it("should return undefined for non-existent key", () => {
|
||||
expect(map.get("nonexistent")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should handle multiple key-value pairs", () => {
|
||||
map.set("a", 1);
|
||||
map.set("b", 2);
|
||||
map.set("c", 3);
|
||||
|
||||
expect(map.get("a")).toBe(1);
|
||||
expect(map.get("b")).toBe(2);
|
||||
expect(map.get("c")).toBe(3);
|
||||
expect(map.size).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe("has", () => {
|
||||
it("should return true for existing key", () => {
|
||||
map.set("key1", 100);
|
||||
expect(map.has("key1")).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false for non-existent key", () => {
|
||||
expect(map.has("nonexistent")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("delete", () => {
|
||||
it("should delete existing key", () => {
|
||||
map.set("key1", 100);
|
||||
expect(map.delete("key1")).toBe(true);
|
||||
expect(map.has("key1")).toBe(false);
|
||||
expect(map.size).toBe(0);
|
||||
});
|
||||
|
||||
it("should return false for non-existent key", () => {
|
||||
expect(map.delete("nonexistent")).toBe(false);
|
||||
});
|
||||
|
||||
it("should handle deletion from chain", () => {
|
||||
// Add multiple items that might collide
|
||||
map.set("a", 1);
|
||||
map.set("b", 2);
|
||||
map.set("c", 3);
|
||||
|
||||
map.delete("b");
|
||||
expect(map.has("b")).toBe(false);
|
||||
expect(map.has("a")).toBe(true);
|
||||
expect(map.has("c")).toBe(true);
|
||||
expect(map.size).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("clear", () => {
|
||||
it("should remove all entries", () => {
|
||||
map.set("a", 1);
|
||||
map.set("b", 2);
|
||||
map.set("c", 3);
|
||||
|
||||
map.clear();
|
||||
expect(map.size).toBe(0);
|
||||
expect(map.has("a")).toBe(false);
|
||||
expect(map.has("b")).toBe(false);
|
||||
expect(map.has("c")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("size", () => {
|
||||
it("should track size correctly", () => {
|
||||
expect(map.size).toBe(0);
|
||||
|
||||
map.set("a", 1);
|
||||
expect(map.size).toBe(1);
|
||||
|
||||
map.set("b", 2);
|
||||
expect(map.size).toBe(2);
|
||||
|
||||
map.delete("a");
|
||||
expect(map.size).toBe(1);
|
||||
|
||||
map.clear();
|
||||
expect(map.size).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("keys", () => {
|
||||
it("should iterate over all keys", () => {
|
||||
map.set("a", 1);
|
||||
map.set("b", 2);
|
||||
map.set("c", 3);
|
||||
|
||||
const keys = Array.from(map.keys());
|
||||
expect(keys).toHaveLength(3);
|
||||
expect(keys).toContain("a");
|
||||
expect(keys).toContain("b");
|
||||
expect(keys).toContain("c");
|
||||
});
|
||||
|
||||
it("should return empty iterator for empty map", () => {
|
||||
const keys = Array.from(map.keys());
|
||||
expect(keys).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("values", () => {
|
||||
it("should iterate over all values", () => {
|
||||
map.set("a", 1);
|
||||
map.set("b", 2);
|
||||
map.set("c", 3);
|
||||
|
||||
const values = Array.from(map.values());
|
||||
expect(values).toHaveLength(3);
|
||||
expect(values).toContain(1);
|
||||
expect(values).toContain(2);
|
||||
expect(values).toContain(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe("entries", () => {
|
||||
it("should iterate over all entries", () => {
|
||||
map.set("a", 1);
|
||||
map.set("b", 2);
|
||||
|
||||
const entries = Array.from(map.entries());
|
||||
expect(entries).toHaveLength(2);
|
||||
expect(entries).toContainEqual(["a", 1]);
|
||||
expect(entries).toContainEqual(["b", 2]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("forEach", () => {
|
||||
it("should iterate with forEach", () => {
|
||||
map.set("a", 1);
|
||||
map.set("b", 2);
|
||||
map.set("c", 3);
|
||||
|
||||
const result: [string, number][] = [];
|
||||
map.forEach((value, key) => {
|
||||
result.push([key, value]);
|
||||
});
|
||||
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result).toContainEqual(["a", 1]);
|
||||
expect(result).toContainEqual(["b", 2]);
|
||||
expect(result).toContainEqual(["c", 3]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("iterable", () => {
|
||||
it("should work with for...of", () => {
|
||||
map.set("a", 1);
|
||||
map.set("b", 2);
|
||||
|
||||
const entries: [string, number][] = [];
|
||||
for (const entry of map) {
|
||||
entries.push(entry);
|
||||
}
|
||||
|
||||
expect(entries).toHaveLength(2);
|
||||
expect(entries).toContainEqual(["a", 1]);
|
||||
expect(entries).toContainEqual(["b", 2]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("resizing", () => {
|
||||
it("should resize when load factor exceeds threshold", () => {
|
||||
const smallMap = new HashMap<string, number>(4, 0.75);
|
||||
expect(smallMap.capacity).toBe(4);
|
||||
|
||||
// Add enough items to trigger resize
|
||||
for (let i = 0; i < 10; i++) {
|
||||
smallMap.set(`key${i}`, i);
|
||||
}
|
||||
|
||||
expect(smallMap.size).toBe(10);
|
||||
expect(smallMap.capacity).toBeGreaterThan(4);
|
||||
|
||||
// Verify all items are still accessible
|
||||
for (let i = 0; i < 10; i++) {
|
||||
expect(smallMap.get(`key${i}`)).toBe(i);
|
||||
}
|
||||
});
|
||||
|
||||
it("should maintain all entries after resize", () => {
|
||||
const smallMap = new HashMap<string, number>(2, 0.5);
|
||||
|
||||
const entries = [
|
||||
["a", 1],
|
||||
["b", 2],
|
||||
["c", 3],
|
||||
["d", 4],
|
||||
["e", 5],
|
||||
] as const;
|
||||
|
||||
for (const [key, value] of entries) {
|
||||
smallMap.set(key, value);
|
||||
}
|
||||
|
||||
for (const [key, value] of entries) {
|
||||
expect(smallMap.get(key)).toBe(value);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("custom hash function", () => {
|
||||
it("should work with NumericHashFunction", () => {
|
||||
const numMap = new HashMap<number, string>(
|
||||
16,
|
||||
0.75,
|
||||
new NumericHashFunction()
|
||||
);
|
||||
|
||||
numMap.set(123, "value1");
|
||||
numMap.set(456, "value2");
|
||||
|
||||
expect(numMap.get(123)).toBe("value1");
|
||||
expect(numMap.get(456)).toBe("value2");
|
||||
});
|
||||
|
||||
it("should work with custom hash function", () => {
|
||||
class SimpleHashFunction implements IHashFunction<string> {
|
||||
hash(key: string, capacity: number): number {
|
||||
return key.length % capacity;
|
||||
}
|
||||
}
|
||||
|
||||
const customMap = new HashMap<string, string>(
|
||||
8,
|
||||
0.75,
|
||||
new SimpleHashFunction()
|
||||
);
|
||||
|
||||
customMap.set("hi", "short");
|
||||
customMap.set("hello", "medium");
|
||||
|
||||
expect(customMap.get("hi")).toBe("short");
|
||||
expect(customMap.get("hello")).toBe("medium");
|
||||
});
|
||||
});
|
||||
|
||||
describe("edge cases", () => {
|
||||
it("should handle null values", () => {
|
||||
const nullMap = new HashMap<string, null>();
|
||||
nullMap.set("key", null);
|
||||
expect(nullMap.get("key")).toBeNull();
|
||||
expect(nullMap.has("key")).toBe(true);
|
||||
});
|
||||
|
||||
it("should handle undefined values", () => {
|
||||
const undefinedMap = new HashMap<string, undefined>();
|
||||
undefinedMap.set("key", undefined);
|
||||
expect(undefinedMap.has("key")).toBe(true);
|
||||
});
|
||||
|
||||
it("should handle empty string keys", () => {
|
||||
map.set("", 100);
|
||||
expect(map.get("")).toBe(100);
|
||||
});
|
||||
|
||||
it("should handle numeric keys", () => {
|
||||
const numMap = new HashMap<number, string>();
|
||||
numMap.set(0, "zero");
|
||||
numMap.set(1, "one");
|
||||
numMap.set(-1, "negative one");
|
||||
|
||||
expect(numMap.get(0)).toBe("zero");
|
||||
expect(numMap.get(1)).toBe("one");
|
||||
expect(numMap.get(-1)).toBe("negative one");
|
||||
});
|
||||
|
||||
it("should handle large number of entries", () => {
|
||||
const largeMap = new HashMap<number, number>();
|
||||
const count = 1000;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
largeMap.set(i, i * 2);
|
||||
}
|
||||
|
||||
expect(largeMap.size).toBe(count);
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
expect(largeMap.get(i)).toBe(i * 2);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("collision handling", () => {
|
||||
it("should handle hash collisions correctly", () => {
|
||||
// Create a map with small capacity to increase collision probability
|
||||
const collisionMap = new HashMap<string, number>(2, 0.99);
|
||||
|
||||
collisionMap.set("a", 1);
|
||||
collisionMap.set("b", 2);
|
||||
collisionMap.set("c", 3);
|
||||
collisionMap.set("d", 4);
|
||||
|
||||
expect(collisionMap.size).toBe(4);
|
||||
expect(collisionMap.get("a")).toBe(1);
|
||||
expect(collisionMap.get("b")).toBe(2);
|
||||
expect(collisionMap.get("c")).toBe(3);
|
||||
expect(collisionMap.get("d")).toBe(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe("toString", () => {
|
||||
it("should provide readable string representation", () => {
|
||||
map.set("a", 1);
|
||||
map.set("b", 2);
|
||||
|
||||
const str = map.toString();
|
||||
expect(str).toContain("HashMap");
|
||||
expect(str).toContain("2"); // size
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user