// Copyright 2009 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.StringSetTest'); goog.setTestOnly('goog.structs.StringSetTest'); goog.require('goog.array'); goog.require('goog.iter'); goog.require('goog.structs.StringSet'); goog.require('goog.testing.asserts'); goog.require('goog.testing.jsunit'); var TEST_VALUES = [ '', ' ', ' ', 'true', 'null', 'undefined', '0', 'new', 'constructor', 'prototype', '__proto__', 'set', 'hasOwnProperty', 'toString', 'valueOf' ]; var TEST_VALUES_WITH_DUPLICATES = [ '', '', ' ', ' ', 'true', true, 'null', null, 'undefined', undefined, '0', 0, 'new', 'constructor', 'prototype', '__proto__', 'set', 'hasOwnProperty', 'toString', 'valueOf' ]; function testConstructor() { var empty = new goog.structs.StringSet; assertSameElements('elements in empty set', [], empty.getValues()); var s = new goog.structs.StringSet(TEST_VALUES_WITH_DUPLICATES); assertSameElements( 'duplicates are filtered out by their string value', TEST_VALUES, s.getValues()); } function testConstructorAssertsThatObjectPrototypeHasNoEnumerableKeys() { assertNotThrows(goog.structs.StringSet); Object.prototype.foo = 0; try { assertThrows(goog.structs.StringSet); } finally { delete Object.prototype.foo; } assertNotThrows(goog.structs.StringSet); } function testOverridingObjectPrototypeToStringIsSafe() { var originalToString = Object.prototype.toString; Object.prototype.toString = function() { return 'object'; }; try { assertEquals(0, new goog.structs.StringSet().getCount()); assertFalse(new goog.structs.StringSet().contains('toString')); } finally { Object.prototype.toString = originalToString; } } function testAdd() { var s = new goog.structs.StringSet; goog.array.forEach(TEST_VALUES_WITH_DUPLICATES, s.add, s); assertSameElements(TEST_VALUES, s.getValues()); } function testAddArray() { var s = new goog.structs.StringSet; s.addArray(TEST_VALUES_WITH_DUPLICATES); assertSameElements('added elements from array', TEST_VALUES, s.getValues()); } function testAddSet() { var s = new goog.structs.StringSet; s.addSet(new goog.structs.StringSet([1, 2])); assertSameElements('empty set + {1, 2}', ['1', '2'], s.getValues()); s.addSet(new goog.structs.StringSet([2, 3])); assertSameElements('{1, 2} + {2, 3}', ['1', '2', '3'], s.getValues()); } function testClear() { var s = new goog.structs.StringSet([1, 2]); s.clear(); assertSameElements('cleared set', [], s.getValues()); } function testClone() { var s = new goog.structs.StringSet([1, 2]); var c = s.clone(); assertSameElements('elements in clone', ['1', '2'], c.getValues()); s.add(3); assertSameElements( 'changing the original set does not affect the clone', ['1', '2'], c.getValues()); } function testContains() { var e = new goog.structs.StringSet; goog.array.forEach(TEST_VALUES, function(element) { assertFalse('empty set does not contain ' + element, e.contains(element)); }); var s = new goog.structs.StringSet(TEST_VALUES); goog.array.forEach(TEST_VALUES_WITH_DUPLICATES, function(element) { assertTrue('s contains ' + element, s.contains(element)); }); assertFalse('s does not contain 42', s.contains(42)); } function testContainsArray() { var s = new goog.structs.StringSet(TEST_VALUES); assertTrue('set contains empty array', s.containsArray([])); assertTrue( 'set contains all elements of itself with some duplication', s.containsArray(TEST_VALUES_WITH_DUPLICATES)); assertFalse('set does not contain 42', s.containsArray([42])); } function testEquals() { var s = new goog.structs.StringSet([1, 2]); assertTrue('set equals to itself', s.equals(s)); assertTrue('set equals to its clone', s.equals(s.clone())); assertFalse( 'set does not equal to its subset', s.equals(new goog.structs.StringSet([1]))); assertFalse( 'set does not equal to its superset', s.equals(new goog.structs.StringSet([1, 2, 3]))); } function testForEach() { var s = new goog.structs.StringSet(TEST_VALUES); var values = []; var context = {}; s.forEach(function(value, key, stringSet) { assertEquals('context of forEach callback', context, this); values.push(value); assertUndefined('key argument of forEach callback', key); assertEquals('set argument of forEach callback', s, stringSet); }, context); assertSameElements('values passed to forEach callback', TEST_VALUES, values); } function testGetCount() { var empty = new goog.structs.StringSet; assertEquals('count(empty set)', 0, empty.getCount()); var s = new goog.structs.StringSet(TEST_VALUES); assertEquals('count(non-empty set)', TEST_VALUES.length, s.getCount()); } function testGetDifference() { var s1 = new goog.structs.StringSet([1, 2]); var s2 = new goog.structs.StringSet([2, 3]); assertSameElements( '{1, 2} - {2, 3}', ['1'], s1.getDifference(s2).getValues()); } function testGetIntersection() { var s1 = new goog.structs.StringSet([1, 2]); var s2 = new goog.structs.StringSet([2, 3]); assertSameElements( '{1, 2} * {2, 3}', ['2'], s1.getIntersection(s2).getValues()); } function testGetSymmetricDifference() { var s1 = new goog.structs.StringSet([1, 2]); var s2 = new goog.structs.StringSet([2, 3]); assertSameElements( '{1, 2} sym.diff. {2, 3}', ['1', '3'], s1.getSymmetricDifference(s2).getValues()); } function testGetUnion() { var s1 = new goog.structs.StringSet([1, 2]); var s2 = new goog.structs.StringSet([2, 3]); assertSameElements( '{1, 2} + {2, 3}', ['1', '2', '3'], s1.getUnion(s2).getValues()); } function testIsDisjoint() { var s = new goog.structs.StringSet; var s12 = new goog.structs.StringSet([1, 2]); var s23 = new goog.structs.StringSet([2, 3]); var s34 = new goog.structs.StringSet([3, 4]); assertTrue('{} and {1, 2} are disjoint', s.isDisjoint(s12)); assertTrue('{1, 2} and {3, 4} are disjoint', s12.isDisjoint(s34)); assertFalse('{1, 2} and {2, 3} are not disjoint', s12.isDisjoint(s23)); } function testIsEmpty() { assertTrue('empty set', new goog.structs.StringSet().isEmpty()); assertFalse('non-empty set', new goog.structs.StringSet(['']).isEmpty()); } function testIsSubsetOf() { var s1 = new goog.structs.StringSet([1]); var s12 = new goog.structs.StringSet([1, 2]); var s123 = new goog.structs.StringSet([1, 2, 3]); var s23 = new goog.structs.StringSet([2, 3]); assertTrue('{1, 2} is subset of {1, 2}', s12.isSubsetOf(s12)); assertTrue('{1, 2} is subset of {1, 2, 3}', s12.isSubsetOf(s123)); assertFalse('{1, 2} is not subset of {1}', s12.isSubsetOf(s1)); assertFalse('{1, 2} is not subset of {2, 3}', s12.isSubsetOf(s23)); } function testIsSupersetOf() { var s1 = new goog.structs.StringSet([1]); var s12 = new goog.structs.StringSet([1, 2]); var s123 = new goog.structs.StringSet([1, 2, 3]); var s23 = new goog.structs.StringSet([2, 3]); assertTrue('{1, 2} is superset of {1}', s12.isSupersetOf(s1)); assertTrue('{1, 2} is superset of {1, 2}', s12.isSupersetOf(s12)); assertFalse('{1, 2} is not superset of {1, 2, 3}', s12.isSupersetOf(s123)); assertFalse('{1, 2} is not superset of {2, 3}', s12.isSupersetOf(s23)); } function testRemove() { var n = new goog.structs.StringSet([1, 2]); assertFalse('3 not removed from {1, 2}', n.remove(3)); assertSameElements('set == {1, 2}', ['1', '2'], n.getValues()); assertTrue('2 removed from {1, 2}', n.remove(2)); assertSameElements('set == {1}', ['1'], n.getValues()); assertTrue('"1" removed from {1}', n.remove('1')); assertSameElements('set == {}', [], n.getValues()); var s = new goog.structs.StringSet(TEST_VALUES); goog.array.forEach(TEST_VALUES, s.remove, s); assertSameElements('all special values have been removed', [], s.getValues()); } function testRemoveArray() { var s = new goog.structs.StringSet(TEST_VALUES); s.removeArray(TEST_VALUES.slice(0, TEST_VALUES.length - 2)); assertSameElements( 'removed elements from array', TEST_VALUES.slice(TEST_VALUES.length - 2), s.getValues()); } function testRemoveSet() { var s1 = new goog.structs.StringSet([1, 2]); var s2 = new goog.structs.StringSet([2, 3]); s1.removeSet(s2); assertSameElements('{1, 2} - {2, 3}', ['1'], s1.getValues()); } function testIterator() { var s = new goog.structs.StringSet(TEST_VALUES_WITH_DUPLICATES); var values = []; goog.iter.forEach(s, function(value) { values.push(value); }); assertSameElements( '__iterator__ takes all elements once', TEST_VALUES, values); }