/** * @license * Copyright Larry Diamond 2018 All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/larrydiamond/typescriptcollectionsframework/LICENSE */ import {Test, TestBoolean, TestString, TestNumber} from 'jasts'; import {AllFieldHashable} from "../src/AllFieldHashable"; import {Collectable} from "../src/Collectable"; import {Collections} from "../src/Collections"; import {Comparator} from "../src/Comparator"; import {HashMap} from "../src/HashMap"; import {Hashable} from "../src/Hashable"; import {ImmutableMap} from "../src/ImmutableMap"; import {ImmutableSet} from "../src/ImmutableSet"; import {JIterator} from "../src/JIterator"; import {LinkedHashMap} from "../src/LinkedHashMap"; import {JMap} from "../src/JMap"; import {MapEntry} from "../src/MapEntry"; import {NavigableHashMap} from "../src/NavigableHash"; import {SkipListMap} from "../src/SkipList"; import {TreeMap} from "../src/TreeMap"; // PetStoreProduct will be used in testing class PetStoreProduct { private productName:string; private price:number; public constructor (iName:string, iPrice:number) { this.productName = iName; this.price = iPrice; } public getProductName ():string { return this.productName; } public getPrice():number { return this.price; } } const alphabeticalSortPetStoreProduct:Comparator = { compare(o1:PetStoreProduct, o2:PetStoreProduct) : number { if (o1 === o2) return 0; if (o1 === undefined) return -1; if (o1 === null) return -1; if (o2 === undefined) return 1; if (o2 === null) return 1; if (o1.getProductName() === o2.getProductName()) return 0; if (o1.getProductName() === undefined) return -1; if (o1.getProductName() === null) return -1; if (o2.getProductName() === undefined) return 1; if (o2.getProductName() === null) return 1; if (o1.getProductName() < o2.getProductName()) return -1; return 1; } }; const product2:PetStoreProduct = new PetStoreProduct("ChewToy", 14.99); const product1:PetStoreProduct = new PetStoreProduct("Catnip", 4.99); const product3:PetStoreProduct = new PetStoreProduct("Goldfish", 9.99); const productNotAvailable:PetStoreProduct = new PetStoreProduct("Bananas", 1.99); // Wanted to show a class in the value object but anything would work fine class ValueClass { private blah1:number; private blah2:string; } describe("Test Map functionality", function() { it("Test empty maps", function() { testEmptyStringStringMap (Collections.emptyMap()); testEmptyStringNumberMap (Collections.emptyMap()); testEmptyPetStoreProductAndValueClassMap (Collections.emptyMap()); testEmptyStringStringMap (new HashMap ()); testEmptyStringStringMap (new HashMap (new AllFieldHashable())); testEmptyStringNumberMap (new HashMap ()); testEmptyStringNumberMap (new HashMap (new AllFieldHashable())); testEmptyPetStoreProductAndValueClassMap (new HashMap ()); testEmptyPetStoreProductAndValueClassMap (new HashMap (new AllFieldHashable())); testEmptyStringStringMap (new LinkedHashMap ()); testEmptyStringStringMap (new LinkedHashMap (new AllFieldHashable())); testEmptyStringNumberMap (new LinkedHashMap ()); testEmptyStringNumberMap (new LinkedHashMap (new AllFieldHashable())); testEmptyPetStoreProductAndValueClassMap (new LinkedHashMap ()); testEmptyPetStoreProductAndValueClassMap (new LinkedHashMap (new AllFieldHashable())); testEmptyStringStringMap (new TreeMap (Collections.getStringComparator())); testEmptyStringNumberMap (new TreeMap (Collections.getStringComparator())); testEmptyPetStoreProductAndValueClassMap (new TreeMap (alphabeticalSortPetStoreProduct)); testEmptyStringStringMap (new SkipListMap (Collections.getStringComparator())); testEmptyStringNumberMap (new SkipListMap (Collections.getStringComparator())); testEmptyPetStoreProductAndValueClassMap (new SkipListMap (alphabeticalSortPetStoreProduct)); testEmptyStringStringMap (new NavigableHashMap (Collections.getStringComparator())); testEmptyStringNumberMap (new NavigableHashMap (Collections.getStringComparator())); testEmptyPetStoreProductAndValueClassMap (new NavigableHashMap (alphabeticalSortPetStoreProduct)); }); it("Test adding to empty maps", function() { testAddingOneEntryStringStringMap (new HashMap (), "HashMap default"); testAddingOneEntryStringStringMap (new HashMap (new AllFieldHashable()), "HashMap AllFieldHashable"); testAddingOneEntryStringNumberMap (new HashMap ()); testAddingOneEntryStringNumberMap (new HashMap (new AllFieldHashable())); testAddingOneEntryPetStoreProductAndValueClassMap (new HashMap ()); testAddingOneEntryPetStoreProductAndValueClassMap (new HashMap (new AllFieldHashable())); testAddingOneEntryStringStringMap (new LinkedHashMap (), "LinkedHashMap default"); testAddingOneEntryStringStringMap (new LinkedHashMap (new AllFieldHashable()), "LinkedHashMap AllFieldHashable"); testAddingOneEntryStringNumberMap (new LinkedHashMap ()); testAddingOneEntryStringNumberMap (new LinkedHashMap (new AllFieldHashable())); testAddingOneEntryPetStoreProductAndValueClassMap (new LinkedHashMap ()); testAddingOneEntryPetStoreProductAndValueClassMap (new LinkedHashMap (new AllFieldHashable())); testAddingOneEntryStringStringMap (new TreeMap (Collections.getStringComparator()), "TreeMap"); testAddingOneEntryStringNumberMap (new TreeMap (Collections.getStringComparator())); testAddingOneEntryPetStoreProductAndValueClassMap (new TreeMap (alphabeticalSortPetStoreProduct)); testAddingOneEntryStringStringMap (new SkipListMap (Collections.getStringComparator()), "SkipListMap"); testAddingOneEntryStringNumberMap (new SkipListMap (Collections.getStringComparator())); testAddingOneEntryPetStoreProductAndValueClassMap (new SkipListMap (alphabeticalSortPetStoreProduct)); testAddingOneEntryStringStringMap (new NavigableHashMap (Collections.getStringComparator()), "NavigableHashMap"); testAddingOneEntryStringNumberMap (new NavigableHashMap (Collections.getStringComparator())); testAddingOneEntryPetStoreProductAndValueClassMap (new NavigableHashMap (alphabeticalSortPetStoreProduct)); }); it("Test adding two items to empty maps", function() { testAddingTwoEntriesStringStringMap (new HashMap ()); testAddingTwoEntriesStringStringMap (new HashMap (new AllFieldHashable())); testAddingTwoEntriesStringNumberMap (new HashMap ()); testAddingTwoEntriesStringNumberMap (new HashMap (new AllFieldHashable())); testAddingTwoEntriesPetStoreProductAndValueClassMap (new HashMap ()); testAddingTwoEntriesPetStoreProductAndValueClassMap (new HashMap (new AllFieldHashable())); testAddingTwoEntriesStringStringMap (new LinkedHashMap ()); testAddingTwoEntriesStringStringMap (new LinkedHashMap (new AllFieldHashable())); testAddingTwoEntriesStringNumberMap (new LinkedHashMap ()); testAddingTwoEntriesStringNumberMap (new LinkedHashMap (new AllFieldHashable())); testAddingTwoEntriesPetStoreProductAndValueClassMap (new LinkedHashMap ()); testAddingTwoEntriesPetStoreProductAndValueClassMap (new LinkedHashMap (new AllFieldHashable())); testAddingTwoEntriesStringStringMap (new TreeMap (Collections.getStringComparator())); testAddingTwoEntriesStringNumberMap (new TreeMap (Collections.getStringComparator())); testAddingTwoEntriesPetStoreProductAndValueClassMap (new TreeMap (alphabeticalSortPetStoreProduct)); testAddingTwoEntriesStringStringMap (new SkipListMap (Collections.getStringComparator())); testAddingTwoEntriesStringNumberMap (new SkipListMap (Collections.getStringComparator())); testAddingTwoEntriesPetStoreProductAndValueClassMap (new SkipListMap (alphabeticalSortPetStoreProduct)); testAddingTwoEntriesStringStringMap (new NavigableHashMap (Collections.getStringComparator())); testAddingTwoEntriesStringNumberMap (new NavigableHashMap (Collections.getStringComparator())); testAddingTwoEntriesPetStoreProductAndValueClassMap (new NavigableHashMap (alphabeticalSortPetStoreProduct)); }); it("Test clearing maps", function() { testClearingStringStringMap (new HashMap ()); testClearingStringStringMap (new HashMap (new AllFieldHashable())); testClearingStringNumberMap (new HashMap ()); testClearingStringNumberMap (new HashMap (new AllFieldHashable())); testClearingPetStoreProductAndValueClassMap (new HashMap ()); testClearingPetStoreProductAndValueClassMap (new HashMap (new AllFieldHashable())); testClearingStringStringMap (new LinkedHashMap ()); testClearingStringStringMap (new LinkedHashMap (new AllFieldHashable())); testClearingStringNumberMap (new LinkedHashMap ()); testClearingStringNumberMap (new LinkedHashMap (new AllFieldHashable())); testClearingPetStoreProductAndValueClassMap (new LinkedHashMap ()); testClearingPetStoreProductAndValueClassMap (new LinkedHashMap (new AllFieldHashable())); testClearingStringStringMap (new TreeMap (Collections.getStringComparator())); testClearingStringNumberMap (new TreeMap (Collections.getStringComparator())); testClearingPetStoreProductAndValueClassMap (new TreeMap (alphabeticalSortPetStoreProduct)); testClearingStringStringMap (new SkipListMap (Collections.getStringComparator())); testClearingStringNumberMap (new SkipListMap (Collections.getStringComparator())); testClearingPetStoreProductAndValueClassMap (new SkipListMap (alphabeticalSortPetStoreProduct)); testClearingStringStringMap (new NavigableHashMap (Collections.getStringComparator())); testClearingStringNumberMap (new NavigableHashMap (Collections.getStringComparator())); testClearingPetStoreProductAndValueClassMap (new NavigableHashMap (alphabeticalSortPetStoreProduct)); }); it("Test replacing entries", function() { testMapEntryReplacement (new HashMap ()); testMapEntryReplacement (new HashMap (new AllFieldHashable())); testMapEntryReplacement (new LinkedHashMap ()); testMapEntryReplacement (new LinkedHashMap (new AllFieldHashable())); testMapEntryReplacement (new TreeMap (Collections.getStringComparator())); testMapEntryReplacement (new SkipListMap (Collections.getStringComparator())); testMapEntryReplacement (new NavigableHashMap (Collections.getStringComparator())); }); it("Test copy constructor", function() { testCopyConstructor (new HashMap (new AllFieldHashable(), populateTestData (new HashMap (new AllFieldHashable())))); testCopyConstructor (new LinkedHashMap (new AllFieldHashable(), populateTestData (new LinkedHashMap (new AllFieldHashable())))); testCopyConstructor (new TreeMap (Collections.getStringComparator(), populateTestData (new TreeMap (Collections.getStringComparator())))); testCopyConstructor (new SkipListMap (Collections.getStringComparator(), populateTestData (new SkipListMap (Collections.getStringComparator())))); testCopyConstructor (new NavigableHashMap (Collections.getStringComparator(), populateTestData (new NavigableHashMap (Collections.getStringComparator())))); }); // it("Test JSON stringify", function() { // testJsonStringify (new HashMap ()); // testJsonStringify (new LinkedHashMap ()); // testJsonStringify (new TreeMap (Collections.getStringComparator())); // testJsonStringify (new SkipListMap (Collections.getStringComparator())); // }); }); function testEmptyStringStringMap (map:ImmutableMap) : void { TestNumber.equals ("Testing empty string string map size", map.size(), 0); TestBoolean.true ("Testing empty string string map isEmpty", map.isEmpty()); TestBoolean.false ("Testing non existent key is not contained", map.containsKey ("not going to find it")); expect (map.isEmpty ()).toEqual(true); expect (map.size ()).toEqual(0); expect ('[]').toEqual (JSON.stringify(map)); expect (false).toEqual (map.containsValue(null)); expect (false).toEqual (map.containsValue(undefined)); expect (false).toEqual (map.containsValue("notfound")); const keyset:ImmutableSet = map.keySet(); let count:number = 0; const iter:JIterator = keyset.iterator(); for (; iter.hasNext(); ) { const p:string = iter.next(); count = count + 1; } expect (count).toEqual (0); const entryset:ImmutableSet> = map.entrySet(); let count2:number = 0; const iter2:JIterator> = entryset.iterator(); for (; iter2.hasNext(); ) { const p2:MapEntry = iter2.next(); count2 = count2 + 1; } expect (count2).toEqual (0); const keyset3:ImmutableSet = map.keySet(); let count3:number = 0; const tsi3:Iterator = keyset3[Symbol.iterator](); let tmp3:IteratorResult = tsi3.next(); while (!tmp3.done) { count3 = count + 1; tmp3 = tsi3.next(); } expect (count3).toEqual (0); const entryset4:ImmutableSet> = map.entrySet(); let count4:number = 0; const tsi4:Iterator> = entryset4[Symbol.iterator](); let tmp4:IteratorResult> = tsi4.next(); while (!tmp4.done) { count4 = count4 + 1; tmp4 = tsi4.next(); } expect (count4).toEqual (0); } function testEmptyStringNumberMap (map:ImmutableMap) : void { expect (map.isEmpty ()).toEqual(true); expect (map.size ()).toEqual(0); TestBoolean.false ("Testing non existent key is not contained", map.containsKey ("not going to find it")); } function testEmptyPetStoreProductAndValueClassMap (map:ImmutableMap) : void { expect (map.isEmpty ()).toEqual(true); expect (map.size ()).toEqual(0); } function testAddingOneEntryStringStringMap (map:JMap, typestring:string) : void { expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); expect (map.remove("bogus")).toEqual (null); expect (undefined).toEqual(map.put("testkey", "testvalue")); expect (map.size ()).toEqual(1); expect (map.isEmpty ()).toEqual(false); expect ("testvalue").toEqual (map.get ("testkey")); TestString.undefined ("Getting key not in map will return undefined " + typestring, map.get ("key not found")); expect (undefined).toEqual (map.get ("key not found")); TestBoolean.false ("Testing non existent key is not contained", map.containsKey ("not going to find it")); expect ('[{\"key\":\"testkey\",\"value\":\"testvalue\"}]').toEqual (JSON.stringify(map)); expect (false).toEqual (map.containsValue(null)); expect (false).toEqual (map.containsValue(undefined)); expect (false).toEqual (map.containsValue("notfound")); expect (false).toEqual (map.containsValue("testkey")); expect (true).toEqual (map.containsValue("testvalue")); } function testAddingOneEntryStringNumberMap (map:JMap) : void { expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); expect (undefined).toEqual(map.put("testkey", 1)); expect (map.size ()).toEqual(1); expect (map.isEmpty ()).toEqual(false); expect (1).toEqual (map.get ("testkey")); expect (undefined).toEqual (map.get ("key not found")); TestBoolean.false ("Testing non existent key is not contained", map.containsKey ("not going to find it")); TestBoolean.true ("Testing known key is contained", map.containsKey ("testkey")); const keyset:ImmutableSet = map.keySet(); let count:number = 0; const iter:JIterator = keyset.iterator(); for (; iter.hasNext(); ) { const p:string = iter.next(); count = count + 1; } expect (count).toEqual (1); const entryset:ImmutableSet> = map.entrySet(); let count2:number = 0; const iter2:JIterator> = entryset.iterator(); for (; iter2.hasNext(); ) { const p2:MapEntry = iter2.next(); count2 = count2 + 1; } expect (count2).toEqual (1); const keyset3:ImmutableSet = map.keySet(); let count3:number = 0; const tsi3:Iterator = keyset3[Symbol.iterator](); let tmp3:IteratorResult = tsi3.next(); while (!tmp3.done) { count3 = count3 + 1; tmp3 = tsi3.next(); } expect (count3).toEqual (1); const entryset4:ImmutableSet> = map.entrySet(); let count4:number = 0; const tsi4:Iterator> = entryset4[Symbol.iterator](); let tmp4:IteratorResult> = tsi4.next(); while (!tmp4.done) { count4 = count4 + 1; tmp4 = tsi4.next(); } expect (count4).toEqual (1); } function testAddingOneEntryPetStoreProductAndValueClassMap (map:JMap) : void { expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); expect (undefined).toEqual(map.put(product1, new ValueClass())); expect (map.size ()).toEqual(1); expect (map.isEmpty ()).toEqual(false); } function testAddingTwoEntriesStringStringMap (map:JMap) : void { expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); expect (undefined).toEqual(map.put("testkey", "testvalue")); expect (map.size ()).toEqual(1); expect (map.isEmpty ()).toEqual(false); expect (undefined).toEqual(map.put("secondkey", "secondvalue")); expect (map.size ()).toEqual(2); expect (map.isEmpty ()).toEqual(false); expect ("testvalue").toEqual (map.get ("testkey")); expect (undefined).toEqual (map.get ("key not found")); TestBoolean.false ("Testing non existent key is not contained", map.containsKey ("not going to find it")); TestBoolean.true ("Testing known key is contained", map.containsKey ("testkey")); } function testAddingTwoEntriesStringNumberMap (map:JMap) : void { expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); expect (undefined).toEqual(map.put("testkey", 1)); expect (map.size ()).toEqual(1); expect (map.isEmpty ()).toEqual(false); expect (undefined).toEqual(map.put("secondkey", 1)); expect (map.size ()).toEqual(2); expect (map.isEmpty ()).toEqual(false); expect (1).toEqual (map.get ("secondkey")); expect (undefined).toEqual (map.get ("key not found")); TestBoolean.false ("Testing non existent key is not contained", map.containsKey ("not going to find it")); TestBoolean.true ("Testing known key is contained", map.containsKey ("testkey")); } function testAddingTwoEntriesPetStoreProductAndValueClassMap (map:JMap) : void { expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); expect (undefined).toEqual(map.put(product1, new ValueClass())); expect (map.size ()).toEqual(1); expect (map.isEmpty ()).toEqual(false); expect (undefined).toEqual(map.put(product2, new ValueClass())); expect (map.size ()).toEqual(2); expect (map.isEmpty ()).toEqual(false); } function testClearingStringStringMap (map:JMap) : void { expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); expect (undefined).toEqual(map.put("testkey", "testvalue")); expect (map.size ()).toEqual(1); expect (map.isEmpty ()).toEqual(false); expect (undefined).toEqual(map.put("secondkey", "secondvalue")); expect (map.size ()).toEqual(2); expect (map.isEmpty ()).toEqual(false); expect ("testvalue").toEqual (map.get ("testkey")); expect (undefined).toEqual (map.get ("key not found")); expect (undefined).toEqual(map.clear()); expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); expect (undefined).toEqual (map.get ("testkey")); expect (undefined).toEqual (map.get ("key not found")); TestBoolean.false ("Testing non existent key is not contained", map.containsKey ("not going to find it")); TestBoolean.false ("Testing cleared map does not find key", map.containsKey ("testkey")); } function testClearingStringNumberMap (map:JMap) : void { expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); expect (undefined).toEqual(map.put("testkey", 1)); expect (map.size ()).toEqual(1); expect (map.isEmpty ()).toEqual(false); expect (undefined).toEqual(map.put("secondkey", 1)); expect (map.size ()).toEqual(2); expect (map.isEmpty ()).toEqual(false); expect (undefined).toEqual(map.clear()); expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); TestBoolean.false ("Testing non existent key is not contained", map.containsKey ("not going to find it")); TestBoolean.false ("Testing cleared map does not find key", map.containsKey ("testkey")); } function testClearingPetStoreProductAndValueClassMap (map:JMap) : void { expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); expect (undefined).toEqual(map.put(product1, new ValueClass())); expect (map.size ()).toEqual(1); expect (map.isEmpty ()).toEqual(false); expect (undefined).toEqual(map.put(product2, new ValueClass())); expect (map.size ()).toEqual(2); expect (map.isEmpty ()).toEqual(false); expect (undefined).toEqual(map.clear()); expect (map.size ()).toEqual(0); expect (map.isEmpty ()).toEqual(true); } function testMapEntryReplacement (map:JMap) : void { expect (map.put ("ChewToy", 14.99)).toEqual(undefined); expect (map.put ("Catnip", 4.99)).toEqual(undefined); expect (map.get ("ChewToy")).toEqual (14.99); expect (map.get ("Catnip")).toEqual (4.99); expect (map.put ("Catnip", 9.99)).toEqual(4.99); expect (map.get ("Catnip")).toEqual (9.99); // This one should change to the new value expect (map.get ("ChewToy")).toEqual (14.99); // This one didnt change expect (false).toEqual (map.containsValue(null)); expect (false).toEqual (map.containsValue(undefined)); expect (false).toEqual (map.containsValue(100)); expect (true).toEqual (map.containsValue(14.99)); }; function populateTestData (map:JMap) : JMap { map.put ("ChewToy", 14.99); map.put ("Leash", 9.99); map.put ("Catnip", 4.99); return map; }; function testCopyConstructor (map:JMap) : void { expect (map.get ("Leash")).toEqual (9.99); expect (map.get ("ChewToy")).toEqual (14.99); expect (map.get ("Catnip")).toEqual (4.99); expect (map.get ("Bananas")).toEqual (undefined); expect (map.size()).toEqual (3); };