// Copyright 2012 The Closure Library Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. goog.provide('goog.labs.structs.MapTest'); goog.setTestOnly('goog.labs.structs.MapTest'); goog.require('goog.labs.structs.Map'); goog.require('goog.testing.PropertyReplacer'); goog.require('goog.testing.jsunit'); var map; var stubs; function setUpPage() { stubs = new goog.testing.PropertyReplacer(); } function setUp() { map = new goog.labs.structs.Map(); } function testSet() { var key = 'test'; var value = 'value'; map.set(key, value); assertEquals(value, map.get(key)); } function testSetsWithSameKey() { var key = 'test'; var value = 'value'; var value2 = 'value2'; map.set(key, value); map.set(key, value2); assertEquals(value2, map.get(key)); } function testSetWithUndefinedValue() { var key = 'test'; map.set(key, undefined); assertUndefined(map.get(key)); } function testSetWithUnderUnderProtoUnderUnder() { var key = '__proto__'; var value = 'value'; var value2 = 'value2'; map.set(key, value); assertEquals(value, map.get(key)); map.set(key, value2); assertEquals(value2, map.get(key)); } function testSetWithBuiltInPropertyShadows() { var key = 'toString'; var value = 'value'; var key2 = 'hasOwnProperty'; var value2 = 'value2'; map.set(key, value); map.set(key2, value2); assertEquals(value, map.get(key)); assertEquals(value2, map.get(key2)); map.set(key, value2); map.set(key2, value); assertEquals(value2, map.get(key)); assertEquals(value, map.get(key2)); } function testGetBeforeSetOfUnderUnderProtoUnderUnder() { assertUndefined(map.get('__proto__')); } function testContainsKey() { assertFalse(map.containsKey('key')); assertFalse(map.containsKey('__proto__')); assertFalse(map.containsKey('toString')); assertFalse(map.containsKey('hasOwnProperty')); assertFalse(map.containsKey('key2')); assertFalse(map.containsKey('key3')); assertFalse(map.containsKey('key4')); map.set('key', 'v'); map.set('__proto__', 'v'); map.set('toString', 'v'); map.set('hasOwnProperty', 'v'); map.set('key2', undefined); map.set('key3', null); map.set('key4', ''); assertTrue(map.containsKey('key')); assertTrue(map.containsKey('__proto__')); assertTrue(map.containsKey('toString')); assertTrue(map.containsKey('hasOwnProperty')); assertTrue(map.containsKey('key2')); assertTrue(map.containsKey('key3')); assertTrue(map.containsKey('key4')); } function testContainsValueWithShadowKeys() { assertFalse(map.containsValue('v2')); assertFalse(map.containsValue('v3')); assertFalse(map.containsValue('v4')); map.set('__proto__', 'v2'); map.set('toString', 'v3'); map.set('hasOwnProperty', 'v4'); assertTrue(map.containsValue('v2')); assertTrue(map.containsValue('v3')); assertTrue(map.containsValue('v4')); assertFalse(map.containsValue(Object.prototype.toString)); assertFalse(map.containsValue(Object.prototype.hasOwnProperty)); } function testContainsValueWithNullAndUndefined() { assertFalse(map.containsValue(undefined)); assertFalse(map.containsValue(null)); map.set('key2', undefined); map.set('key3', null); assertTrue(map.containsValue(undefined)); assertTrue(map.containsValue(null)); } function testContainsValueWithNumber() { assertFalse(map.containsValue(-1)); assertFalse(map.containsValue(0)); assertFalse(map.containsValue(1)); map.set('key', -1); map.set('key2', 0); map.set('key3', 1); assertTrue(map.containsValue(-1)); assertTrue(map.containsValue(0)); assertTrue(map.containsValue(1)); } function testContainsValueWithNaN() { assertFalse(map.containsValue(NaN)); map.set('key', NaN); assertTrue(map.containsValue(NaN)); } function testContainsValueWithNegativeZero() { assertFalse(map.containsValue(-0)); map.set('key', -0); assertTrue(map.containsValue(-0)); assertFalse(map.containsValue(0)); map.set('key', 0); assertFalse(map.containsValue(-0)); assertTrue(map.containsValue(0)); } function testContainsValueWithStrings() { assertFalse(map.containsValue('')); assertFalse(map.containsValue('v')); map.set('key', ''); map.set('key2', 'v'); assertTrue(map.containsValue('')); assertTrue(map.containsValue('v')); } function testRemove() { map.set('key', 'v'); map.set('__proto__', 'v2'); map.set('toString', 'v3'); map.set('hasOwnProperty', 'v4'); map.set('key2', undefined); map.set('key3', null); map.set('key4', ''); assertFalse(map.remove('key do not exist')); assertTrue(map.remove('key')); assertFalse(map.containsKey('key')); assertFalse(map.remove('key')); assertTrue(map.remove('__proto__')); assertFalse(map.containsKey('__proto__')); assertFalse(map.remove('__proto__')); assertTrue(map.remove('toString')); assertFalse(map.containsKey('toString')); assertFalse(map.remove('toString')); assertTrue(map.remove('hasOwnProperty')); assertFalse(map.containsKey('hasOwnProperty')); assertFalse(map.remove('hasOwnProperty')); assertTrue(map.remove('key2')); assertFalse(map.containsKey('key2')); assertFalse(map.remove('key2')); assertTrue(map.remove('key3')); assertFalse(map.containsKey('key3')); assertFalse(map.remove('key3')); assertTrue('', map.remove('key4')); assertFalse(map.containsKey('key4')); assertFalse(map.remove('key4')); } function testGetCountAndIsEmpty() { assertEquals(0, map.getCount()); assertTrue(map.isEmpty()); map.set('key', 'v'); assertEquals(1, map.getCount()); map.set('__proto__', 'v2'); assertEquals(2, map.getCount()); map.set('toString', 'v3'); assertEquals(3, map.getCount()); map.set('hasOwnProperty', 'v4'); assertEquals(4, map.getCount()); map.set('key', 'a'); assertEquals(4, map.getCount()); map.set('__proto__', 'a2'); assertEquals(4, map.getCount()); map.set('toString', 'a3'); assertEquals(4, map.getCount()); map.set('hasOwnProperty', 'a4'); assertEquals(4, map.getCount()); map.remove('key'); assertEquals(3, map.getCount()); map.remove('__proto__'); assertEquals(2, map.getCount()); map.remove('toString'); assertEquals(1, map.getCount()); map.remove('hasOwnProperty'); assertEquals(0, map.getCount()); } function testClear() { map.set('key', 'v'); map.set('__proto__', 'v'); map.set('toString', 'v'); map.set('hasOwnProperty', 'v'); map.set('key2', undefined); map.set('key3', null); map.set('key4', ''); map.clear(); assertFalse(map.containsKey('key')); assertFalse(map.containsKey('__proto__')); assertFalse(map.containsKey('toString')); assertFalse(map.containsKey('hasOwnProperty')); assertFalse(map.containsKey('key2')); assertFalse(map.containsKey('key3')); assertFalse(map.containsKey('key4')); } function testGetEntries() { map.set('key', 'v'); map.set('__proto__', 'v'); map.set('toString', 'v'); map.set('hasOwnProperty', 'v'); map.set('key2', undefined); map.set('key3', null); map.set('key4', ''); var entries = map.getEntries(); assertEquals(7, entries.length); assertContainsEntry(['key', 'v'], entries); assertContainsEntry(['__proto__', 'v'], entries); assertContainsEntry(['toString', 'v'], entries); assertContainsEntry(['hasOwnProperty', 'v'], entries); assertContainsEntry(['key2', undefined], entries); assertContainsEntry(['key3', null], entries); assertContainsEntry(['key4', ''], entries); } function testGetKeys() { map.set('key', 'v'); map.set('__proto__', 'v'); map.set('toString', 'v'); map.set('hasOwnProperty', 'v'); map.set('key2', undefined); map.set('key3', null); map.set('k4', ''); var values = map.getKeys(); assertSameElements( ['key', '__proto__', 'toString', 'hasOwnProperty', 'key2', 'key3', 'k4'], values); } function testGetValues() { map.set('key', 'v'); map.set('__proto__', 'v'); map.set('toString', 'v'); map.set('hasOwnProperty', 'v'); map.set('key2', undefined); map.set('key3', null); map.set('key4', ''); var values = map.getValues(); assertSameElements(['v', 'v', 'v', 'v', undefined, null, ''], values); } function testAddAllToEmptyMap() { map.set('key', 'v'); map.set('key2', 'v2'); map.set('key3', 'v3'); map.set('key4', 'v4'); var map2 = new goog.labs.structs.Map(); map2.addAll(map); assertEquals(4, map2.getCount()); assertEquals('v', map2.get('key')); assertEquals('v2', map2.get('key2')); assertEquals('v3', map2.get('key3')); assertEquals('v4', map2.get('key4')); } function testAddAllToNonEmptyMap() { map.set('key', 'v'); map.set('key2', 'v2'); map.set('key3', 'v3'); map.set('key4', 'v4'); var map2 = new goog.labs.structs.Map(); map2.set('key0', 'o'); map2.set('key', 'o'); map2.set('key2', 'o2'); map2.set('key3', 'o3'); map2.addAll(map); assertEquals(5, map2.getCount()); assertEquals('o', map2.get('key0')); assertEquals('v', map2.get('key')); assertEquals('v2', map2.get('key2')); assertEquals('v3', map2.get('key3')); assertEquals('v4', map2.get('key4')); } function testClone() { map.set('key', 'v'); map.set('key2', 'v2'); map.set('key3', 'v3'); map.set('key4', 'v4'); var map2 = map.clone(); assertEquals(4, map2.getCount()); assertEquals('v', map2.get('key')); assertEquals('v2', map2.get('key2')); assertEquals('v3', map2.get('key3')); assertEquals('v4', map2.get('key4')); } function testMapWithModifiedObjectPrototype() { stubs.set(Object.prototype, 'toString', function() {}); stubs.set(Object.prototype, 'foo', function() {}); stubs.set(Object.prototype, 'field', 100); stubs.set(Object.prototype, 'fooKey', function() {}); map = new goog.labs.structs.Map(); map.set('key', 'v'); map.set('key2', 'v2'); map.set('fooKey', 'v3'); assertTrue(map.containsKey('key')); assertTrue(map.containsKey('key2')); assertTrue(map.containsKey('fooKey')); assertFalse(map.containsKey('toString')); assertFalse(map.containsKey('foo')); assertFalse(map.containsKey('field')); assertTrue(map.containsValue('v')); assertTrue(map.containsValue('v2')); assertTrue(map.containsValue('v3')); assertFalse(map.containsValue(100)); var entries = map.getEntries(); assertEquals(3, entries.length); assertContainsEntry(['key', 'v'], entries); assertContainsEntry(['key2', 'v2'], entries); assertContainsEntry(['fooKey', 'v3'], entries); } function assertContainsEntry(entry, entryList) { for (var i = 0; i < entryList.length; ++i) { if (entry[0] == entryList[i][0] && entry[1] === entryList[i][1]) { return; } } fail('Did not find entry: ' + entry + ' in: ' + entryList); }