blob: daa8850cd7551aae9ad621207eb9e9d7c41cfb83 [file] [log] [blame]
// Copyright 2006 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.structs.MapTest');
goog.setTestOnly('goog.structs.MapTest');
goog.require('goog.iter');
goog.require('goog.structs');
goog.require('goog.structs.Map');
goog.require('goog.testing.jsunit');
function stringifyMap(m) {
var keys = goog.structs.getKeys(m);
var s = '';
for (var i = 0; i < keys.length; i++) {
s += keys[i] + m[keys[i]];
}
return s;
}
function getMap() {
var m = new goog.structs.Map;
m.set('a', 0);
m.set('b', 1);
m.set('c', 2);
m.set('d', 3);
return m;
}
function testGetCount() {
var m = getMap();
assertEquals('count, should be 4', m.getCount(), 4);
m.remove('d');
assertEquals('count, should be 3', m.getCount(), 3);
}
function testKeys() {
var m = getMap();
assertEquals('getKeys, The keys should be a,b,c', m.getKeys().join(','),
'a,b,c,d');
}
function testValues() {
var m = getMap();
assertEquals('getValues, The values should be 0,1,2',
m.getValues().join(','), '0,1,2,3');
}
function testContainsKey() {
var m = getMap();
assertTrue("containsKey, Should contain the 'a' key", m.containsKey('a'));
assertFalse("containsKey, Should not contain the 'e' key",
m.containsKey('e'));
}
function testClear() {
var m = getMap();
m.clear();
assertTrue('cleared so it should be empty', m.isEmpty());
assertTrue("cleared so it should not contain 'a' key", !m.containsKey('a'));
}
function testAddAll() {
var m = new goog.structs.Map;
m.addAll({a: 0, b: 1, c: 2, d: 3});
assertTrue('addAll so it should not be empty', !m.isEmpty());
assertTrue("addAll so it should contain 'c' key", m.containsKey('c'));
var m2 = new goog.structs.Map;
m2.addAll(m);
assertTrue('addAll so it should not be empty', !m2.isEmpty());
assertTrue("addAll so it should contain 'c' key", m2.containsKey('c'));
}
function testConstructor() {
var m = getMap();
var m2 = new goog.structs.Map(m);
assertTrue('constr with Map so it should not be empty', !m2.isEmpty());
assertTrue("constr with Map so it should contain 'c' key",
m2.containsKey('c'));
}
function testConstructorWithVarArgs() {
var m = new goog.structs.Map('a', 1);
assertTrue('constr with var_args so it should not be empty', !m.isEmpty());
assertEquals('constr with var_args', 1, m.get('a'));
m = new goog.structs.Map('a', 1, 'b', 2);
assertTrue('constr with var_args so it should not be empty', !m.isEmpty());
assertEquals('constr with var_args', 1, m.get('a'));
assertEquals('constr with var_args', 2, m.get('b'));
assertThrows('Odd number of arguments is not allowed', function() {
var m = new goog.structs.Map('a', 1, 'b');
});
}
function testClone() {
var m = getMap();
var m2 = m.clone();
assertTrue('clone so it should not be empty', !m2.isEmpty());
assertTrue("clone so it should contain 'c' key", m2.containsKey('c'));
}
function testRemove() {
var m = new goog.structs.Map();
for (var i = 0; i < 1000; i++) {
m.set(i, 'foo');
}
for (var i = 0; i < 1000; i++) {
assertTrue(m.keys_.length <= 2 * m.getCount());
m.remove(i);
}
assertTrue(m.isEmpty());
assertEquals('', m.getKeys().join(''));
}
function testForEach() {
var m = getMap();
var s = '';
goog.structs.forEach(m, function(val, key, m2) {
assertNotUndefined(key);
assertEquals(m, m2);
s += key + val;
});
assertEquals(s, 'a0b1c2d3');
}
function testFilter() {
var m = getMap();
var m2 = goog.structs.filter(m, function(val, key, m3) {
assertNotUndefined(key);
assertEquals(m, m3);
return val > 1;
});
assertEquals(stringifyMap(m2), 'c2d3');
}
function testMap() {
var m = getMap();
var m2 = goog.structs.map(m, function(val, key, m3) {
assertNotUndefined(key);
assertEquals(m, m3);
return val * val;
});
assertEquals(stringifyMap(m2), 'a0b1c4d9');
}
function testSome() {
var m = getMap();
var b = goog.structs.some(m, function(val, key, m2) {
assertNotUndefined(key);
assertEquals(m, m2);
return val > 1;
});
assertTrue(b);
var b = goog.structs.some(m, function(val, key, m2) {
assertNotUndefined(key);
assertEquals(m, m2);
return val > 100;
});
assertFalse(b);
}
function testEvery() {
var m = getMap();
var b = goog.structs.every(m, function(val, key, m2) {
assertNotUndefined(key);
assertEquals(m, m2);
return val >= 0;
});
assertTrue(b);
b = goog.structs.every(m, function(val, key, m2) {
assertNotUndefined(key);
assertEquals(m, m2);
return val > 1;
});
assertFalse(b);
}
function testContainsValue() {
var m = getMap();
assertTrue(m.containsValue(3));
assertFalse(m.containsValue(4));
}
function testObjectProperties() {
var m = new goog.structs.Map;
assertEquals(m.get('toString'), undefined);
assertEquals(m.get('valueOf'), undefined);
assertEquals(m.get('eval'), undefined);
assertEquals(m.get('toSource'), undefined);
assertEquals(m.get('prototype'), undefined);
assertEquals(m.get(':foo'), undefined);
m.set('toString', 'once');
m.set('valueOf', 'upon');
m.set('eval', 'a');
m.set('toSource', 'midnight');
m.set('prototype', 'dreary');
m.set('hasOwnProperty', 'dark');
m.set(':foo', 'happy');
assertEquals(m.get('toString'), 'once');
assertEquals(m.get('valueOf'), 'upon');
assertEquals(m.get('eval'), 'a');
assertEquals(m.get('toSource'), 'midnight');
assertEquals(m.get('prototype'), 'dreary');
assertEquals(m.get('hasOwnProperty'), 'dark');
assertEquals(m.get(':foo'), 'happy');
var keys = m.getKeys().join(',');
assertEquals(keys,
'toString,valueOf,eval,toSource,prototype,hasOwnProperty,:foo');
var values = m.getValues().join(',');
assertEquals(values, 'once,upon,a,midnight,dreary,dark,happy');
}
function testDuplicateKeys() {
var m = new goog.structs.Map;
m.set('a', 1);
m.set('b', 2);
m.set('c', 3);
m.set('d', 4);
m.set('e', 5);
m.set('f', 6);
assertEquals(6, m.getKeys().length);
m.set('foo', 1);
assertEquals(7, m.getKeys().length);
m.remove('foo');
assertEquals(6, m.getKeys().length);
m.set('foo', 2);
assertEquals(7, m.getKeys().length);
m.remove('foo');
m.set('foo', 3);
m.remove('foo');
m.set('foo', 4);
assertEquals(7, m.getKeys().length);
}
function testGetKeyIterator() {
var m = new goog.structs.Map;
m.set('a', 1);
m.set('b', 2);
m.set('c', 3);
m.set('d', 4);
m.set('e', 5);
var iter = m.getKeyIterator();
assertEquals('Should contain the keys', 'abcde', goog.iter.join(iter, ''));
m.remove('b');
m.remove('d');
iter = m.getKeyIterator();
assertEquals('Should not contain the removed keys',
'ace', goog.iter.join(iter, ''));
}
function testGetValueIterator() {
var m = new goog.structs.Map;
m.set('a', 1);
m.set('b', 2);
m.set('c', 3);
m.set('d', 4);
m.set('e', 5);
var iter = m.getValueIterator();
assertEquals('Should contain the values', '12345', goog.iter.join(iter, ''));
m.remove('b');
m.remove('d');
iter = m.getValueIterator();
assertEquals('Should not contain the removed keys',
'135', goog.iter.join(iter, ''));
}
function testDefaultIterator() {
// The default iterator should behave like the value iterator
var m = new goog.structs.Map;
m.set('a', 1);
m.set('b', 2);
m.set('c', 3);
m.set('d', 4);
m.set('e', 5);
assertEquals('Should contain the values', '12345', goog.iter.join(m, ''));
m.remove('b');
m.remove('d');
assertEquals('Should not contain the removed keys',
'135', goog.iter.join(m, ''));
}
function testMutatedIterator() {
var message = 'The map has changed since the iterator was created';
var m = new goog.structs.Map;
m.set('a', 1);
m.set('b', 2);
m.set('c', 3);
m.set('d', 4);
var iter = m.getValueIterator();
m.set('e', 5);
var ex = assertThrows('Expected an exception since the map has changed',
function() {
iter.next();
});
assertEquals(message, ex.message);
m = new goog.structs.Map;
m.set('a', 1);
m.set('b', 2);
m.set('c', 3);
m.set('d', 4);
iter = m.getValueIterator();
m.remove('d');
var ex = assertThrows('Expected an exception since the map has changed',
function() {
iter.next();
});
assertEquals(message, ex.message);
m = new goog.structs.Map;
m.set('a', 1);
m.set('b', 2);
m.set('c', 3);
m.set('d', 4);
iter = m.getValueIterator();
m.set('d', 5);
iter.next();
// Changing an existing value is OK.
iter.next();
}
function testTranspose() {
var m = new goog.structs.Map;
m.set('a', 1);
m.set('b', 2);
m.set('c', 3);
m.set('d', 4);
m.set('e', 5);
var transposed = m.transpose();
assertEquals('Should contain the keys', 'abcde',
goog.iter.join(transposed, ''));
}
function testToObject() {
Object.prototype.b = 0;
try {
var map = new goog.structs.Map();
map.set('a', 0);
var obj = map.toObject();
assertTrue('object representation has key "a"', obj.hasOwnProperty('a'));
assertFalse('object representation does not have key "b"',
obj.hasOwnProperty('b'));
assertEquals('value for key "a"', 0, obj['a']);
} finally {
delete Object.prototype.b;
}
}
function testEqualsWithSameObject() {
var map1 = getMap();
assertTrue('maps are the same object', map1.equals(map1));
}
function testEqualsWithDifferentSizeMaps() {
var map1 = getMap();
var map2 = new goog.structs.Map();
assertFalse('maps are different sizes', map1.equals(map2));
}
function testEqualsWithDefaultEqualityFn() {
var map1 = new goog.structs.Map();
var map2 = new goog.structs.Map();
assertTrue('maps are both empty', map1.equals(map2));
map1 = getMap();
map2 = getMap();
assertTrue('maps are the same', map1.equals(map2));
map2.set('d', '3');
assertFalse('maps have 3 and \'3\'', map1.equals(map2));
}
function testEqualsWithCustomEqualityFn() {
var map1 = new goog.structs.Map();
var map2 = new goog.structs.Map();
map1.set('a', 0);
map1.set('b', 1);
map2.set('a', '0');
map2.set('b', '1');
var equalsFn = function(a, b) { return a == b };
assertTrue('maps are equal with ==', map1.equals(map2, equalsFn));
}