HashtableTest.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. // HashtableTest.cs - NUnit Test Cases for the System.Collections.Hashtable class
  2. //
  3. //
  4. // (C) Ximian, Inc. http://www.ximian.com
  5. //
  6. using System;
  7. using System.Collections;
  8. using System.IO;
  9. using System.Runtime.Serialization;
  10. using System.Runtime.Serialization.Formatters;
  11. using System.Runtime.Serialization.Formatters.Binary;
  12. using NUnit.Framework;
  13. namespace MonoTests.System.Collections {
  14. /// <summary>Hashtable test.</summary>
  15. [TestFixture]
  16. public class HashtableTest : Assertion {
  17. [Test]
  18. public void TestCtor1() {
  19. Hashtable h = new Hashtable();
  20. AssertNotNull("No hash table", h);
  21. }
  22. [Test]
  23. public void TestCtor2() {
  24. {
  25. bool errorThrown = false;
  26. try {
  27. Hashtable h = new Hashtable(null);
  28. } catch (ArgumentNullException) {
  29. errorThrown = true;
  30. }
  31. Assert("null hashtable error not thrown",
  32. errorThrown);
  33. }
  34. {
  35. string[] keys = {"this", "is", "a", "test"};
  36. char[] values = {'a', 'b', 'c', 'd'};
  37. Hashtable h1 = new Hashtable();
  38. for (int i = 0; i < keys.Length; i++) {
  39. h1[keys[i]] = values[i];
  40. }
  41. Hashtable h2 = new Hashtable(h1);
  42. for (int i = 0; i < keys.Length; i++) {
  43. AssertEquals("No match for key " + keys[i],
  44. values[i], h2[keys[i]]);
  45. }
  46. }
  47. }
  48. [Test]
  49. [ExpectedException (typeof (ArgumentOutOfRangeException))]
  50. public void TestCtor3 ()
  51. {
  52. Hashtable h = new Hashtable ();
  53. Hashtable hh = new Hashtable (h, Single.NaN);
  54. }
  55. [Test]
  56. [ExpectedException (typeof (ArgumentException))]
  57. public void TestCtor4 ()
  58. {
  59. Hashtable ht = new Hashtable (Int32.MaxValue, 0.1f, null, null);
  60. }
  61. // TODO - Ctors for capacity and load (how to test? any access?)
  62. // TODO - Ctors with IComparer, IHashCodeProvider, Serialization
  63. [Test]
  64. public void TestCount() {
  65. Hashtable h = new Hashtable();
  66. AssertEquals("new table - count zero", 0, h.Count);
  67. int max = 100;
  68. for (int i = 1; i <= max; i++) {
  69. h[i] = i;
  70. AssertEquals("Count wrong for " + i,
  71. i, h.Count);
  72. }
  73. for (int i = 1; i <= max; i++) {
  74. h[i] = i * 2;
  75. AssertEquals("Count shouldn't change at " + i,
  76. max, h.Count);
  77. }
  78. }
  79. [Test]
  80. public void TestIsFixedSize() {
  81. Hashtable h = new Hashtable();
  82. AssertEquals("hashtable not fixed by default",
  83. false, h.IsFixedSize);
  84. // TODO - any way to get a fixed-size hashtable?
  85. }
  86. public void TestIsReadOnly() {
  87. Hashtable h = new Hashtable();
  88. AssertEquals("hashtable not read-only by default",
  89. false, h.IsReadOnly);
  90. // TODO - any way to get a read-only hashtable?
  91. }
  92. [Test]
  93. public void TestIsSynchronized() {
  94. Hashtable h = new Hashtable();
  95. Assert("hashtable not synced by default", !h.IsSynchronized);
  96. Hashtable h2 = Hashtable.Synchronized(h);
  97. Assert("hashtable should by synced", h2.IsSynchronized);
  98. }
  99. [Test]
  100. public void TestItem() {
  101. {
  102. bool errorThrown = false;
  103. try {
  104. Hashtable h = new Hashtable();
  105. Object o = h[null];
  106. } catch (ArgumentNullException) {
  107. errorThrown = true;
  108. }
  109. Assert("null hashtable error not thrown",
  110. errorThrown);
  111. }
  112. // TODO - if read-only and/or fixed-size is possible,
  113. // test 'NotSupportedException' here
  114. {
  115. Hashtable h = new Hashtable();
  116. int max = 100;
  117. for (int i = 1; i <= max; i++) {
  118. h[i] = i;
  119. AssertEquals("value wrong for " + i,
  120. i, h[i]);
  121. }
  122. }
  123. }
  124. [Test]
  125. public void TestKeys() {
  126. string[] keys = {"this", "is", "a", "test"};
  127. char[] values1 = {'a', 'b', 'c', 'd'};
  128. char[] values2 = {'e', 'f', 'g', 'h'};
  129. Hashtable h1 = new Hashtable();
  130. for (int i = 0; i < keys.Length; i++) {
  131. h1[keys[i]] = values1[i];
  132. }
  133. AssertEquals("keys wrong size",
  134. keys.Length, h1.Keys.Count);
  135. for (int i = 0; i < keys.Length; i++) {
  136. h1[keys[i]] = values2[i];
  137. }
  138. AssertEquals("keys wrong size 2",
  139. keys.Length, h1.Keys.Count);
  140. }
  141. // TODO - SyncRoot
  142. [Test]
  143. public void TestValues() {
  144. string[] keys = {"this", "is", "a", "test"};
  145. char[] values1 = {'a', 'b', 'c', 'd'};
  146. char[] values2 = {'e', 'f', 'g', 'h'};
  147. Hashtable h1 = new Hashtable();
  148. for (int i = 0; i < keys.Length; i++) {
  149. h1[keys[i]] = values1[i];
  150. }
  151. AssertEquals("values wrong size",
  152. keys.Length, h1.Values.Count);
  153. for (int i = 0; i < keys.Length; i++) {
  154. h1[keys[i]] = values2[i];
  155. }
  156. AssertEquals("values wrong size 2",
  157. keys.Length, h1.Values.Count);
  158. }
  159. [Test]
  160. public void TestAdd() {
  161. {
  162. bool errorThrown = false;
  163. try {
  164. Hashtable h = new Hashtable();
  165. h.Add(null, "huh?");
  166. } catch (ArgumentNullException) {
  167. errorThrown = true;
  168. }
  169. Assert("null add error not thrown",
  170. errorThrown);
  171. }
  172. {
  173. bool errorThrown = false;
  174. try {
  175. Hashtable h = new Hashtable();
  176. h.Add('a', 1);
  177. h.Add('a', 2);
  178. } catch (ArgumentException) {
  179. errorThrown = true;
  180. }
  181. Assert("re-add error not thrown",
  182. errorThrown);
  183. }
  184. // TODO - hit NotSupportedException
  185. {
  186. Hashtable h = new Hashtable();
  187. int max = 100;
  188. for (int i = 1; i <= max; i++) {
  189. h.Add(i, i);
  190. AssertEquals("value wrong for " + i,
  191. i, h[i]);
  192. }
  193. }
  194. }
  195. [Test]
  196. public void TestClear() {
  197. // TODO - hit NotSupportedException
  198. Hashtable h = new Hashtable();
  199. AssertEquals("new table - count zero", 0, h.Count);
  200. int max = 100;
  201. for (int i = 1; i <= max; i++) {
  202. h[i] = i;
  203. }
  204. Assert("table don't gots stuff", h.Count > 0);
  205. h.Clear();
  206. AssertEquals("Table should be cleared",
  207. 0, h.Count);
  208. }
  209. [Test]
  210. public void TestClone() {
  211. {
  212. char[] c1 = {'a', 'b', 'c'};
  213. char[] c2 = {'d', 'e', 'f'};
  214. Hashtable h1 = new Hashtable();
  215. for (int i = 0; i < c1.Length; i++) {
  216. h1[c1[i]] = c2[i];
  217. }
  218. Hashtable h2 = (Hashtable)h1.Clone();
  219. AssertNotNull("got no clone!", h2);
  220. AssertNotNull("clone's got nothing!", h2[c1[0]]);
  221. for (int i = 0; i < c1.Length; i++) {
  222. AssertEquals("Hashtable match",
  223. h1[c1[i]], h2[c1[i]]);
  224. }
  225. }
  226. {
  227. char[] c1 = {'a', 'b', 'c'};
  228. char[] c20 = {'1', '2'};
  229. char[] c21 = {'3', '4'};
  230. char[] c22 = {'5', '6'};
  231. char[][] c2 = {c20, c21, c22};
  232. Hashtable h1 = new Hashtable();
  233. for (int i = 0; i < c1.Length; i++) {
  234. h1[c1[i]] = c2[i];
  235. }
  236. Hashtable h2 = (Hashtable)h1.Clone();
  237. AssertNotNull("got no clone!", h2);
  238. AssertNotNull("clone's got nothing!", h2[c1[0]]);
  239. for (int i = 0; i < c1.Length; i++) {
  240. AssertEquals("Hashtable match",
  241. h1[c1[i]], h2[c1[i]]);
  242. }
  243. ((char[])h1[c1[0]])[0] = 'z';
  244. AssertEquals("shallow copy", h1[c1[0]], h2[c1[0]]);
  245. }
  246. }
  247. [Test]
  248. public void TestContains() {
  249. {
  250. bool errorThrown = false;
  251. try {
  252. Hashtable h = new Hashtable();
  253. bool result = h.Contains(null);
  254. } catch (ArgumentNullException) {
  255. errorThrown = true;
  256. }
  257. Assert("null add error not thrown",
  258. errorThrown);
  259. }
  260. {
  261. Hashtable h = new Hashtable();
  262. h['a'] = "blue";
  263. Assert("'a'? it's in there!", h.Contains('a'));
  264. Assert("'b'? no way!", !h.Contains('b'));
  265. }
  266. }
  267. [Test]
  268. public void TestContainsKey() {
  269. {
  270. bool errorThrown = false;
  271. try {
  272. Hashtable h = new Hashtable();
  273. bool result = h.ContainsKey(null);
  274. } catch (ArgumentNullException) {
  275. errorThrown = true;
  276. }
  277. Assert("null add error not thrown",
  278. errorThrown);
  279. }
  280. {
  281. Hashtable h = new Hashtable();
  282. h['a'] = "blue";
  283. Assert("'a'? it's in there!", h.ContainsKey('a'));
  284. Assert("'b'? no way!", !h.ContainsKey('b'));
  285. }
  286. }
  287. [Test]
  288. public void TestContainsValue() {
  289. {
  290. Hashtable h = new Hashtable();
  291. h['a'] = "blue";
  292. Assert("blue? it's in there!",
  293. h.ContainsValue("blue"));
  294. Assert("green? no way!",
  295. !h.ContainsValue("green"));
  296. }
  297. }
  298. [Test]
  299. public void TestCopyTo() {
  300. {
  301. bool errorThrown = false;
  302. try {
  303. Hashtable h = new Hashtable();
  304. h.CopyTo(null, 0);
  305. } catch (ArgumentNullException) {
  306. errorThrown = true;
  307. }
  308. Assert("null hashtable error not thrown",
  309. errorThrown);
  310. }
  311. {
  312. bool errorThrown = false;
  313. try {
  314. Hashtable h = new Hashtable();
  315. Object[] o = new Object[1];
  316. h.CopyTo(o, -1);
  317. } catch (ArgumentOutOfRangeException) {
  318. errorThrown = true;
  319. }
  320. Assert("out of range error not thrown",
  321. errorThrown);
  322. }
  323. {
  324. bool errorThrown = false;
  325. try {
  326. Hashtable h = new Hashtable();
  327. Object[,] o = new Object[1,1];
  328. h.CopyTo(o, 1);
  329. } catch (ArgumentException) {
  330. errorThrown = true;
  331. }
  332. Assert("multi-dim array error not thrown",
  333. errorThrown);
  334. }
  335. {
  336. bool errorThrown = false;
  337. try {
  338. Hashtable h = new Hashtable();
  339. h['a'] = 1; // no error if table is empty
  340. Object[] o = new Object[5];
  341. h.CopyTo(o, 5);
  342. } catch (ArgumentException) {
  343. errorThrown = true;
  344. }
  345. Assert("no room in array error not thrown",
  346. errorThrown);
  347. }
  348. {
  349. bool errorThrown = false;
  350. try {
  351. Hashtable h = new Hashtable();
  352. h['a'] = 1;
  353. h['b'] = 2;
  354. h['c'] = 2;
  355. Object[] o = new Object[2];
  356. h.CopyTo(o, 0);
  357. } catch (ArgumentException) {
  358. errorThrown = true;
  359. }
  360. Assert("table too big error not thrown",
  361. errorThrown);
  362. }
  363. {
  364. bool errorThrown = false;
  365. try {
  366. Hashtable h = new Hashtable();
  367. h["blue"] = 1;
  368. h["green"] = 2;
  369. h["red"] = 3;
  370. Char[] o = new Char[3];
  371. h.CopyTo(o, 0);
  372. } catch (InvalidCastException) {
  373. errorThrown = true;
  374. }
  375. Assert("invalid cast error not thrown",
  376. errorThrown);
  377. }
  378. {
  379. Hashtable h = new Hashtable();
  380. h['a'] = 1;
  381. h['b'] = 2;
  382. DictionaryEntry[] o = new DictionaryEntry[2];
  383. h.CopyTo(o,0);
  384. AssertEquals("first copy fine.", 'a', o[0].Key);
  385. AssertEquals("first copy fine.", 1, o[0].Value);
  386. AssertEquals("second copy fine.", 'b', o[1].Key);
  387. AssertEquals("second copy fine.", 2, o[1].Value);
  388. }
  389. }
  390. [Test]
  391. public void TestGetEnumerator() {
  392. String[] s1 = {"this", "is", "a", "test"};
  393. Char[] c1 = {'a', 'b', 'c', 'd'};
  394. Hashtable h1 = new Hashtable();
  395. for (int i = 0; i < s1.Length; i++) {
  396. h1[s1[i]] = c1[i];
  397. }
  398. IDictionaryEnumerator en = h1.GetEnumerator();
  399. AssertNotNull("No enumerator", en);
  400. for (int i = 0; i < s1.Length; i++) {
  401. en.MoveNext();
  402. Assert("Not enumerating for " + en.Key,
  403. Array.IndexOf(s1, en.Key) >= 0);
  404. Assert("Not enumerating for " + en.Value,
  405. Array.IndexOf(c1, en.Value) >= 0);
  406. }
  407. }
  408. // TODO - GetObjectData
  409. // TODO - OnDeserialization
  410. [Test]
  411. public void TestSerialization () {
  412. Random r = new Random();
  413. string filename = "hashtable_" + r.Next(99999).ToString() + ".dat";
  414. Hashtable table1 = new Hashtable();
  415. Hashtable table2;
  416. Stream str;
  417. BinaryFormatter formatter = new BinaryFormatter();
  418. for (int i = 0; i < 100; i++) {
  419. table1[i] = "TestString Key: " + i.ToString();
  420. }
  421. str = File.OpenWrite(filename);
  422. formatter.Serialize(str, table1);
  423. str.Close();
  424. str = File.OpenRead(filename);
  425. table2 = (Hashtable) formatter.Deserialize(str);
  426. str.Close();
  427. File.Delete(filename);
  428. bool result;
  429. foreach (DictionaryEntry de in table1) {
  430. int key1 = (int) de.Key;
  431. string val1 = (string) de.Value;
  432. string val2 = (string) table2[key1];
  433. if (val2 != val1) {
  434. result = false;
  435. }
  436. }
  437. result = true;
  438. Assert("Binary Serialization Error", result);
  439. }
  440. [Test]
  441. public void TestRemove() {
  442. {
  443. bool errorThrown = false;
  444. try {
  445. Hashtable h = new Hashtable();
  446. h.Remove(null);
  447. } catch (ArgumentNullException) {
  448. errorThrown = true;
  449. }
  450. Assert("null hashtable error not thrown",
  451. errorThrown);
  452. }
  453. {
  454. string[] keys = {"this", "is", "a", "test"};
  455. char[] values = {'a', 'b', 'c', 'd'};
  456. Hashtable h = new Hashtable();
  457. for (int i = 0; i < keys.Length; i++) {
  458. h[keys[i]] = values[i];
  459. }
  460. AssertEquals("not enough in table",
  461. 4, h.Count);
  462. h.Remove("huh?");
  463. AssertEquals("not enough in table",
  464. 4, h.Count);
  465. h.Remove("this");
  466. AssertEquals("Wrong count in table",
  467. 3, h.Count);
  468. h.Remove("this");
  469. AssertEquals("Wrong count in table",
  470. 3, h.Count);
  471. }
  472. }
  473. [Test]
  474. public void TestSynchronized() {
  475. {
  476. bool errorThrown = false;
  477. try {
  478. Hashtable h = Hashtable.Synchronized(null);
  479. } catch (ArgumentNullException) {
  480. errorThrown = true;
  481. }
  482. Assert("null hashtable error not thrown",
  483. errorThrown);
  484. }
  485. {
  486. Hashtable h = new Hashtable();
  487. Assert("hashtable not synced by default",
  488. !h.IsSynchronized);
  489. Hashtable h2 = Hashtable.Synchronized(h);
  490. Assert("hashtable should by synced",
  491. h2.IsSynchronized);
  492. }
  493. }
  494. protected Hashtable ht;
  495. private static Random rnd;
  496. [SetUp]
  497. public void SetUp() {
  498. ht=new Hashtable();
  499. rnd=new Random();
  500. }
  501. private void SetDefaultData() {
  502. ht.Clear();
  503. ht.Add("k1","another");
  504. ht.Add("k2","yet");
  505. ht.Add("k3","hashtable");
  506. }
  507. [Test]
  508. public void TestAddRemoveClear() {
  509. ht.Clear();
  510. Assert(ht.Count==0);
  511. SetDefaultData();
  512. Assert(ht.Count==3);
  513. bool thrown=false;
  514. try {
  515. ht.Add("k2","cool");
  516. } catch (ArgumentException) {thrown=true;}
  517. Assert("Must throw ArgumentException!",thrown);
  518. ht["k2"]="cool";
  519. Assert(ht.Count==3);
  520. Assert(ht["k2"].Equals("cool"));
  521. }
  522. [Test]
  523. public void TestCopyTo2() {
  524. SetDefaultData();
  525. Object[] entries=new Object[ht.Count];
  526. ht.CopyTo(entries,0);
  527. Assert("Not an entry.",entries[0] is DictionaryEntry);
  528. }
  529. [Test]
  530. public void TestUnderHeavyLoad() {
  531. ht.Clear();
  532. int max=100000;
  533. String[] cache=new String[max*2];
  534. int n=0;
  535. for (int i=0;i<max;i++) {
  536. int id=rnd.Next()&0xFFFF;
  537. String key=""+id+"-key-"+id;
  538. String val="value-"+id;
  539. if (ht[key]==null) {
  540. ht[key]=val;
  541. cache[n]=key;
  542. cache[n+max]=val;
  543. n++;
  544. }
  545. }
  546. Assert(ht.Count==n);
  547. for (int i=0;i<n;i++) {
  548. String key=cache[i];
  549. String val=ht[key] as String;
  550. String err="ht[\""+key+"\"]=\""+val+
  551. "\", expected \""+cache[i+max]+"\"";
  552. Assert(err,val!=null && val.Equals(cache[i+max]));
  553. }
  554. int r1=(n/3);
  555. int r2=r1+(n/5);
  556. for (int i=r1;i<r2;i++) {
  557. ht.Remove(cache[i]);
  558. }
  559. for (int i=0;i<n;i++) {
  560. if (i>=r1 && i<r2) {
  561. Assert(ht[cache[i]]==null);
  562. } else {
  563. String key=cache[i];
  564. String val=ht[key] as String;
  565. String err="ht[\""+key+"\"]=\""+val+
  566. "\", expected \""+cache[i+max]+"\"";
  567. Assert(err,val!=null && val.Equals(cache[i+max]));
  568. }
  569. }
  570. ICollection keys=ht.Keys;
  571. int nKeys=0;
  572. foreach (Object key in keys) {
  573. Assert((key as String) != null);
  574. nKeys++;
  575. }
  576. Assert(nKeys==ht.Count);
  577. ICollection vals=ht.Values;
  578. int nVals=0;
  579. foreach (Object val in vals) {
  580. Assert((val as String) != null);
  581. nVals++;
  582. }
  583. Assert(nVals==ht.Count);
  584. }
  585. /// <summary>
  586. /// Test hashtable with CaseInsensitiveHashCodeProvider
  587. /// and CaseInsensitive comparer.
  588. /// </summary>
  589. [Test]
  590. public void TestCaseInsensitive ()
  591. {
  592. // Not very meaningfull test, just to make
  593. // sure that hcp is set properly set.
  594. Hashtable ciHashtable = new Hashtable(11,1.0f,CaseInsensitiveHashCodeProvider.Default,CaseInsensitiveComparer.Default);
  595. ciHashtable ["key1"] = "value";
  596. ciHashtable ["key2"] = "VALUE";
  597. Assert(ciHashtable ["key1"].Equals ("value"));
  598. Assert(ciHashtable ["key2"].Equals ("VALUE"));
  599. ciHashtable ["KEY1"] = "new_value";
  600. Assert(ciHashtable ["key1"].Equals ("new_value"));
  601. }
  602. [Test]
  603. public void TestCopyConstructor ()
  604. {
  605. SetDefaultData ();
  606. Hashtable htCopy = new Hashtable (ht);
  607. Assert(ht.Count == htCopy.Count);
  608. }
  609. [Test]
  610. public void TestEnumerator ()
  611. {
  612. SetDefaultData ();
  613. IEnumerator e = ht.GetEnumerator ();
  614. while (e.MoveNext ()) {}
  615. Assert (!e.MoveNext ());
  616. }
  617. }
  618. }