map_test.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. // Copyright 2006 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. goog.provide('goog.structs.MapTest');
  15. goog.setTestOnly('goog.structs.MapTest');
  16. goog.require('goog.iter');
  17. goog.require('goog.structs');
  18. goog.require('goog.structs.Map');
  19. goog.require('goog.testing.jsunit');
  20. function stringifyMap(m) {
  21. var keys = goog.structs.getKeys(m);
  22. var s = '';
  23. for (var i = 0; i < keys.length; i++) {
  24. s += keys[i] + m[keys[i]];
  25. }
  26. return s;
  27. }
  28. function getMap() {
  29. var m = new goog.structs.Map;
  30. m.set('a', 0);
  31. m.set('b', 1);
  32. m.set('c', 2);
  33. m.set('d', 3);
  34. return m;
  35. }
  36. function testGetCount() {
  37. var m = getMap();
  38. assertEquals('count, should be 4', m.getCount(), 4);
  39. m.remove('d');
  40. assertEquals('count, should be 3', m.getCount(), 3);
  41. }
  42. function testKeys() {
  43. var m = getMap();
  44. assertEquals(
  45. 'getKeys, The keys should be a,b,c', m.getKeys().join(','), 'a,b,c,d');
  46. }
  47. function testValues() {
  48. var m = getMap();
  49. assertEquals(
  50. 'getValues, The values should be 0,1,2', m.getValues().join(','),
  51. '0,1,2,3');
  52. }
  53. function testContainsKey() {
  54. var m = getMap();
  55. assertTrue("containsKey, Should contain the 'a' key", m.containsKey('a'));
  56. assertFalse(
  57. "containsKey, Should not contain the 'e' key", m.containsKey('e'));
  58. }
  59. function testClear() {
  60. var m = getMap();
  61. m.clear();
  62. assertTrue('cleared so it should be empty', m.isEmpty());
  63. assertTrue("cleared so it should not contain 'a' key", !m.containsKey('a'));
  64. }
  65. function testAddAll() {
  66. var m = new goog.structs.Map;
  67. m.addAll({a: 0, b: 1, c: 2, d: 3});
  68. assertTrue('addAll so it should not be empty', !m.isEmpty());
  69. assertTrue("addAll so it should contain 'c' key", m.containsKey('c'));
  70. var m2 = new goog.structs.Map;
  71. m2.addAll(m);
  72. assertTrue('addAll so it should not be empty', !m2.isEmpty());
  73. assertTrue("addAll so it should contain 'c' key", m2.containsKey('c'));
  74. }
  75. function testConstructor() {
  76. var m = getMap();
  77. var m2 = new goog.structs.Map(m);
  78. assertTrue('constr with Map so it should not be empty', !m2.isEmpty());
  79. assertTrue(
  80. "constr with Map so it should contain 'c' key", m2.containsKey('c'));
  81. }
  82. function testConstructorWithVarArgs() {
  83. var m = new goog.structs.Map('a', 1);
  84. assertTrue('constr with var_args so it should not be empty', !m.isEmpty());
  85. assertEquals('constr with var_args', 1, m.get('a'));
  86. m = new goog.structs.Map('a', 1, 'b', 2);
  87. assertTrue('constr with var_args so it should not be empty', !m.isEmpty());
  88. assertEquals('constr with var_args', 1, m.get('a'));
  89. assertEquals('constr with var_args', 2, m.get('b'));
  90. assertThrows('Odd number of arguments is not allowed', function() {
  91. var m = new goog.structs.Map('a', 1, 'b');
  92. });
  93. }
  94. function testClone() {
  95. var m = getMap();
  96. var m2 = m.clone();
  97. assertTrue('clone so it should not be empty', !m2.isEmpty());
  98. assertTrue("clone so it should contain 'c' key", m2.containsKey('c'));
  99. }
  100. function testRemove() {
  101. var m = new goog.structs.Map();
  102. for (var i = 0; i < 1000; i++) {
  103. m.set(i, 'foo');
  104. }
  105. for (var i = 0; i < 1000; i++) {
  106. assertTrue(m.keys_.length <= 2 * m.getCount());
  107. m.remove(i);
  108. }
  109. assertTrue(m.isEmpty());
  110. assertEquals('', m.getKeys().join(''));
  111. }
  112. function testForEach() {
  113. var m = getMap();
  114. var s = '';
  115. goog.structs.forEach(m, function(val, key, m2) {
  116. assertNotUndefined(key);
  117. assertEquals(m, m2);
  118. s += key + val;
  119. });
  120. assertEquals(s, 'a0b1c2d3');
  121. }
  122. function testFilter() {
  123. var m = getMap();
  124. var m2 = goog.structs.filter(m, function(val, key, m3) {
  125. assertNotUndefined(key);
  126. assertEquals(m, m3);
  127. return val > 1;
  128. });
  129. assertEquals(stringifyMap(m2), 'c2d3');
  130. }
  131. function testMap() {
  132. var m = getMap();
  133. var m2 = goog.structs.map(m, function(val, key, m3) {
  134. assertNotUndefined(key);
  135. assertEquals(m, m3);
  136. return val * val;
  137. });
  138. assertEquals(stringifyMap(m2), 'a0b1c4d9');
  139. }
  140. function testSome() {
  141. var m = getMap();
  142. var b = goog.structs.some(m, function(val, key, m2) {
  143. assertNotUndefined(key);
  144. assertEquals(m, m2);
  145. return val > 1;
  146. });
  147. assertTrue(b);
  148. var b = goog.structs.some(m, function(val, key, m2) {
  149. assertNotUndefined(key);
  150. assertEquals(m, m2);
  151. return val > 100;
  152. });
  153. assertFalse(b);
  154. }
  155. function testEvery() {
  156. var m = getMap();
  157. var b = goog.structs.every(m, function(val, key, m2) {
  158. assertNotUndefined(key);
  159. assertEquals(m, m2);
  160. return val >= 0;
  161. });
  162. assertTrue(b);
  163. b = goog.structs.every(m, function(val, key, m2) {
  164. assertNotUndefined(key);
  165. assertEquals(m, m2);
  166. return val > 1;
  167. });
  168. assertFalse(b);
  169. }
  170. function testContainsValue() {
  171. var m = getMap();
  172. assertTrue(m.containsValue(3));
  173. assertFalse(m.containsValue(4));
  174. }
  175. function testObjectProperties() {
  176. var m = new goog.structs.Map;
  177. assertEquals(m.get('toString'), undefined);
  178. assertEquals(m.get('valueOf'), undefined);
  179. assertEquals(m.get('eval'), undefined);
  180. assertEquals(m.get('toSource'), undefined);
  181. assertEquals(m.get('prototype'), undefined);
  182. assertEquals(m.get(':foo'), undefined);
  183. m.set('toString', 'once');
  184. m.set('valueOf', 'upon');
  185. m.set('eval', 'a');
  186. m.set('toSource', 'midnight');
  187. m.set('prototype', 'dreary');
  188. m.set('hasOwnProperty', 'dark');
  189. m.set(':foo', 'happy');
  190. assertEquals(m.get('toString'), 'once');
  191. assertEquals(m.get('valueOf'), 'upon');
  192. assertEquals(m.get('eval'), 'a');
  193. assertEquals(m.get('toSource'), 'midnight');
  194. assertEquals(m.get('prototype'), 'dreary');
  195. assertEquals(m.get('hasOwnProperty'), 'dark');
  196. assertEquals(m.get(':foo'), 'happy');
  197. var keys = m.getKeys().join(',');
  198. assertEquals(
  199. keys, 'toString,valueOf,eval,toSource,prototype,hasOwnProperty,:foo');
  200. var values = m.getValues().join(',');
  201. assertEquals(values, 'once,upon,a,midnight,dreary,dark,happy');
  202. }
  203. function testDuplicateKeys() {
  204. var m = new goog.structs.Map;
  205. m.set('a', 1);
  206. m.set('b', 2);
  207. m.set('c', 3);
  208. m.set('d', 4);
  209. m.set('e', 5);
  210. m.set('f', 6);
  211. assertEquals(6, m.getKeys().length);
  212. m.set('foo', 1);
  213. assertEquals(7, m.getKeys().length);
  214. m.remove('foo');
  215. assertEquals(6, m.getKeys().length);
  216. m.set('foo', 2);
  217. assertEquals(7, m.getKeys().length);
  218. m.remove('foo');
  219. m.set('foo', 3);
  220. m.remove('foo');
  221. m.set('foo', 4);
  222. assertEquals(7, m.getKeys().length);
  223. }
  224. function testGetKeyIterator() {
  225. var m = new goog.structs.Map;
  226. m.set('a', 1);
  227. m.set('b', 2);
  228. m.set('c', 3);
  229. m.set('d', 4);
  230. m.set('e', 5);
  231. var iter = m.getKeyIterator();
  232. assertEquals('Should contain the keys', 'abcde', goog.iter.join(iter, ''));
  233. m.remove('b');
  234. m.remove('d');
  235. iter = m.getKeyIterator();
  236. assertEquals(
  237. 'Should not contain the removed keys', 'ace', goog.iter.join(iter, ''));
  238. }
  239. function testGetValueIterator() {
  240. var m = new goog.structs.Map;
  241. m.set('a', 1);
  242. m.set('b', 2);
  243. m.set('c', 3);
  244. m.set('d', 4);
  245. m.set('e', 5);
  246. var iter = m.getValueIterator();
  247. assertEquals('Should contain the values', '12345', goog.iter.join(iter, ''));
  248. m.remove('b');
  249. m.remove('d');
  250. iter = m.getValueIterator();
  251. assertEquals(
  252. 'Should not contain the removed keys', '135', goog.iter.join(iter, ''));
  253. }
  254. function testDefaultIterator() {
  255. // The default iterator should behave like the value iterator
  256. var m = new goog.structs.Map;
  257. m.set('a', 1);
  258. m.set('b', 2);
  259. m.set('c', 3);
  260. m.set('d', 4);
  261. m.set('e', 5);
  262. assertEquals('Should contain the values', '12345', goog.iter.join(m, ''));
  263. m.remove('b');
  264. m.remove('d');
  265. assertEquals(
  266. 'Should not contain the removed keys', '135', goog.iter.join(m, ''));
  267. }
  268. function testMutatedIterator() {
  269. var message = 'The map has changed since the iterator was created';
  270. var m = new goog.structs.Map;
  271. m.set('a', 1);
  272. m.set('b', 2);
  273. m.set('c', 3);
  274. m.set('d', 4);
  275. var iter = m.getValueIterator();
  276. m.set('e', 5);
  277. var ex = assertThrows(
  278. 'Expected an exception since the map has changed',
  279. function() { iter.next(); });
  280. assertEquals(message, ex.message);
  281. m = new goog.structs.Map;
  282. m.set('a', 1);
  283. m.set('b', 2);
  284. m.set('c', 3);
  285. m.set('d', 4);
  286. iter = m.getValueIterator();
  287. m.remove('d');
  288. var ex = assertThrows(
  289. 'Expected an exception since the map has changed',
  290. function() { iter.next(); });
  291. assertEquals(message, ex.message);
  292. m = new goog.structs.Map;
  293. m.set('a', 1);
  294. m.set('b', 2);
  295. m.set('c', 3);
  296. m.set('d', 4);
  297. iter = m.getValueIterator();
  298. m.set('d', 5);
  299. iter.next();
  300. // Changing an existing value is OK.
  301. iter.next();
  302. }
  303. function testTranspose() {
  304. var m = new goog.structs.Map;
  305. m.set('a', 1);
  306. m.set('b', 2);
  307. m.set('c', 3);
  308. m.set('d', 4);
  309. m.set('e', 5);
  310. var transposed = m.transpose();
  311. assertEquals(
  312. 'Should contain the keys', 'abcde', goog.iter.join(transposed, ''));
  313. }
  314. function testToObject() {
  315. Object.prototype.b = 0;
  316. try {
  317. var map = new goog.structs.Map();
  318. map.set('a', 0);
  319. var obj = map.toObject();
  320. assertTrue('object representation has key "a"', obj.hasOwnProperty('a'));
  321. assertFalse(
  322. 'object representation does not have key "b"', obj.hasOwnProperty('b'));
  323. assertEquals('value for key "a"', 0, obj['a']);
  324. } finally {
  325. delete Object.prototype.b;
  326. }
  327. }
  328. function testEqualsWithSameObject() {
  329. var map1 = getMap();
  330. assertTrue('maps are the same object', map1.equals(map1));
  331. }
  332. function testEqualsWithDifferentSizeMaps() {
  333. var map1 = getMap();
  334. var map2 = new goog.structs.Map();
  335. assertFalse('maps are different sizes', map1.equals(map2));
  336. }
  337. function testEqualsWithDefaultEqualityFn() {
  338. var map1 = new goog.structs.Map();
  339. var map2 = new goog.structs.Map();
  340. assertTrue('maps are both empty', map1.equals(map2));
  341. map1 = getMap();
  342. map2 = getMap();
  343. assertTrue('maps are the same', map1.equals(map2));
  344. map2.set('d', '3');
  345. assertFalse('maps have 3 and \'3\'', map1.equals(map2));
  346. }
  347. function testEqualsWithCustomEqualityFn() {
  348. var map1 = new goog.structs.Map();
  349. var map2 = new goog.structs.Map();
  350. map1.set('a', 0);
  351. map1.set('b', 1);
  352. map2.set('a', '0');
  353. map2.set('b', '1');
  354. var equalsFn = function(a, b) { return a == b };
  355. assertTrue('maps are equal with ==', map1.equals(map2, equalsFn));
  356. }