MapFieldTest.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. #region Copyright notice and license
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2015 Google Inc. All rights reserved.
  4. // https://developers.google.com/protocol-buffers/
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions are
  8. // met:
  9. //
  10. // * Redistributions of source code must retain the above copyright
  11. // notice, this list of conditions and the following disclaimer.
  12. // * Redistributions in binary form must reproduce the above
  13. // copyright notice, this list of conditions and the following disclaimer
  14. // in the documentation and/or other materials provided with the
  15. // distribution.
  16. // * Neither the name of Google Inc. nor the names of its
  17. // contributors may be used to endorse or promote products derived from
  18. // this software without specific prior written permission.
  19. //
  20. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. #endregion
  32. using System;
  33. using System.IO;
  34. using System.Collections.Generic;
  35. using Google.Protobuf.TestProtos;
  36. using NUnit.Framework;
  37. using System.Collections;
  38. using System.Linq;
  39. namespace Google.Protobuf.Collections
  40. {
  41. /// <summary>
  42. /// Tests for MapField which aren't reliant on the encoded format -
  43. /// tests for serialization/deserialization are part of GeneratedMessageTest.
  44. /// </summary>
  45. public class MapFieldTest
  46. {
  47. [Test]
  48. public void Clone_ClonesMessages()
  49. {
  50. var message = new ForeignMessage { C = 20 };
  51. var map = new MapField<string, ForeignMessage> { { "x", message } };
  52. var clone = map.Clone();
  53. map["x"].C = 30;
  54. Assert.AreEqual(20, clone["x"].C);
  55. }
  56. [Test]
  57. public void NullValuesProhibited()
  58. {
  59. TestNullValues<int?>(0);
  60. TestNullValues("");
  61. TestNullValues(new TestAllTypes());
  62. }
  63. private void TestNullValues<T>(T nonNullValue)
  64. {
  65. var map = new MapField<int, T>();
  66. var nullValue = (T) (object) null;
  67. Assert.Throws<ArgumentNullException>(() => map.Add(0, nullValue));
  68. Assert.Throws<ArgumentNullException>(() => map[0] = nullValue);
  69. map.Add(1, nonNullValue);
  70. map[1] = nonNullValue;
  71. }
  72. [Test]
  73. public void Add_ForbidsNullKeys()
  74. {
  75. var map = new MapField<string, ForeignMessage>();
  76. Assert.Throws<ArgumentNullException>(() => map.Add(null, new ForeignMessage()));
  77. }
  78. [Test]
  79. public void Indexer_ForbidsNullKeys()
  80. {
  81. var map = new MapField<string, ForeignMessage>();
  82. Assert.Throws<ArgumentNullException>(() => map[null] = new ForeignMessage());
  83. }
  84. [Test]
  85. public void AddPreservesInsertionOrder()
  86. {
  87. var map = new MapField<string, string>();
  88. map.Add("a", "v1");
  89. map.Add("b", "v2");
  90. map.Add("c", "v3");
  91. map.Remove("b");
  92. map.Add("d", "v4");
  93. CollectionAssert.AreEqual(new[] { "a", "c", "d" }, map.Keys);
  94. CollectionAssert.AreEqual(new[] { "v1", "v3", "v4" }, map.Values);
  95. }
  96. [Test]
  97. public void EqualityIsOrderInsensitive()
  98. {
  99. var map1 = new MapField<string, string>();
  100. map1.Add("a", "v1");
  101. map1.Add("b", "v2");
  102. var map2 = new MapField<string, string>();
  103. map2.Add("b", "v2");
  104. map2.Add("a", "v1");
  105. EqualityTester.AssertEquality(map1, map2);
  106. }
  107. [Test]
  108. public void EqualityIsKeySensitive()
  109. {
  110. var map1 = new MapField<string, string>();
  111. map1.Add("first key", "v1");
  112. map1.Add("second key", "v2");
  113. var map2 = new MapField<string, string>();
  114. map2.Add("third key", "v1");
  115. map2.Add("fourth key", "v2");
  116. EqualityTester.AssertInequality(map1, map2);
  117. }
  118. [Test]
  119. public void Equality_Simple()
  120. {
  121. var map = new MapField<string, string>();
  122. EqualityTester.AssertEquality(map, map);
  123. EqualityTester.AssertInequality(map, null);
  124. Assert.IsFalse(map.Equals(new object()));
  125. }
  126. [Test]
  127. public void EqualityIsValueSensitive()
  128. {
  129. // Note: Without some care, it's a little easier than one might
  130. // hope to see hash collisions, but only in some environments...
  131. var map1 = new MapField<string, string>();
  132. map1.Add("a", "first value");
  133. map1.Add("b", "second value");
  134. var map2 = new MapField<string, string>();
  135. map2.Add("a", "third value");
  136. map2.Add("b", "fourth value");
  137. EqualityTester.AssertInequality(map1, map2);
  138. }
  139. [Test]
  140. public void Add_Dictionary()
  141. {
  142. var map1 = new MapField<string, string>
  143. {
  144. { "x", "y" },
  145. { "a", "b" }
  146. };
  147. var map2 = new MapField<string, string>
  148. {
  149. { "before", "" },
  150. map1,
  151. { "after", "" }
  152. };
  153. var expected = new MapField<string, string>
  154. {
  155. { "before", "" },
  156. { "x", "y" },
  157. { "a", "b" },
  158. { "after", "" }
  159. };
  160. Assert.AreEqual(expected, map2);
  161. CollectionAssert.AreEqual(new[] { "before", "x", "a", "after" }, map2.Keys);
  162. }
  163. // General IDictionary<TKey, TValue> behavior tests
  164. [Test]
  165. public void Add_KeyAlreadyExists()
  166. {
  167. var map = new MapField<string, string>();
  168. map.Add("foo", "bar");
  169. Assert.Throws<ArgumentException>(() => map.Add("foo", "baz"));
  170. }
  171. [Test]
  172. public void Add_Pair()
  173. {
  174. var map = new MapField<string, string>();
  175. ICollection<KeyValuePair<string, string>> collection = map;
  176. collection.Add(NewKeyValuePair("x", "y"));
  177. Assert.AreEqual("y", map["x"]);
  178. Assert.Throws<ArgumentException>(() => collection.Add(NewKeyValuePair("x", "z")));
  179. }
  180. [Test]
  181. public void Contains_Pair()
  182. {
  183. var map = new MapField<string, string> { { "x", "y" } };
  184. ICollection<KeyValuePair<string, string>> collection = map;
  185. Assert.IsTrue(collection.Contains(NewKeyValuePair("x", "y")));
  186. Assert.IsFalse(collection.Contains(NewKeyValuePair("x", "z")));
  187. Assert.IsFalse(collection.Contains(NewKeyValuePair("z", "y")));
  188. }
  189. [Test]
  190. public void Remove_Key()
  191. {
  192. var map = new MapField<string, string>();
  193. map.Add("foo", "bar");
  194. Assert.AreEqual(1, map.Count);
  195. Assert.IsFalse(map.Remove("missing"));
  196. Assert.AreEqual(1, map.Count);
  197. Assert.IsTrue(map.Remove("foo"));
  198. Assert.AreEqual(0, map.Count);
  199. Assert.Throws<ArgumentNullException>(() => map.Remove(null));
  200. }
  201. [Test]
  202. public void Remove_Pair()
  203. {
  204. var map = new MapField<string, string>();
  205. map.Add("foo", "bar");
  206. ICollection<KeyValuePair<string, string>> collection = map;
  207. Assert.AreEqual(1, map.Count);
  208. Assert.IsFalse(collection.Remove(NewKeyValuePair("wrong key", "bar")));
  209. Assert.AreEqual(1, map.Count);
  210. Assert.IsFalse(collection.Remove(NewKeyValuePair("foo", "wrong value")));
  211. Assert.AreEqual(1, map.Count);
  212. Assert.IsTrue(collection.Remove(NewKeyValuePair("foo", "bar")));
  213. Assert.AreEqual(0, map.Count);
  214. Assert.Throws<ArgumentException>(() => collection.Remove(new KeyValuePair<string, string>(null, "")));
  215. }
  216. [Test]
  217. public void CopyTo_Pair()
  218. {
  219. var map = new MapField<string, string>();
  220. map.Add("foo", "bar");
  221. ICollection<KeyValuePair<string, string>> collection = map;
  222. KeyValuePair<string, string>[] array = new KeyValuePair<string, string>[3];
  223. collection.CopyTo(array, 1);
  224. Assert.AreEqual(NewKeyValuePair("foo", "bar"), array[1]);
  225. }
  226. [Test]
  227. public void Clear()
  228. {
  229. var map = new MapField<string, string> { { "x", "y" } };
  230. Assert.AreEqual(1, map.Count);
  231. map.Clear();
  232. Assert.AreEqual(0, map.Count);
  233. map.Add("x", "y");
  234. Assert.AreEqual(1, map.Count);
  235. }
  236. [Test]
  237. public void Indexer_Get()
  238. {
  239. var map = new MapField<string, string> { { "x", "y" } };
  240. Assert.AreEqual("y", map["x"]);
  241. Assert.Throws<KeyNotFoundException>(() => { var ignored = map["z"]; });
  242. }
  243. [Test]
  244. public void Indexer_Set()
  245. {
  246. var map = new MapField<string, string>();
  247. map["x"] = "y";
  248. Assert.AreEqual("y", map["x"]);
  249. map["x"] = "z"; // This won't throw, unlike Add.
  250. Assert.AreEqual("z", map["x"]);
  251. }
  252. [Test]
  253. public void GetEnumerator_NonGeneric()
  254. {
  255. IEnumerable map = new MapField<string, string> { { "x", "y" } };
  256. CollectionAssert.AreEqual(new[] { new KeyValuePair<string, string>("x", "y") },
  257. map.Cast<object>().ToList());
  258. }
  259. // Test for the explicitly-implemented non-generic IDictionary interface
  260. [Test]
  261. public void IDictionary_GetEnumerator()
  262. {
  263. IDictionary map = new MapField<string, string> { { "x", "y" } };
  264. var enumerator = map.GetEnumerator();
  265. // Commented assertions show an ideal situation - it looks like
  266. // the LinkedList enumerator doesn't throw when you ask for the current entry
  267. // at an inappropriate time; fixing this would be more work than it's worth.
  268. // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
  269. Assert.IsTrue(enumerator.MoveNext());
  270. Assert.AreEqual("x", enumerator.Key);
  271. Assert.AreEqual("y", enumerator.Value);
  272. Assert.AreEqual(new DictionaryEntry("x", "y"), enumerator.Current);
  273. Assert.AreEqual(new DictionaryEntry("x", "y"), enumerator.Entry);
  274. Assert.IsFalse(enumerator.MoveNext());
  275. // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
  276. enumerator.Reset();
  277. // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
  278. Assert.IsTrue(enumerator.MoveNext());
  279. Assert.AreEqual("x", enumerator.Key); // Assume the rest are okay
  280. }
  281. [Test]
  282. public void IDictionary_Add()
  283. {
  284. var map = new MapField<string, string> { { "x", "y" } };
  285. IDictionary dictionary = map;
  286. dictionary.Add("a", "b");
  287. Assert.AreEqual("b", map["a"]);
  288. Assert.Throws<ArgumentException>(() => dictionary.Add("a", "duplicate"));
  289. Assert.Throws<InvalidCastException>(() => dictionary.Add(new object(), "key is bad"));
  290. Assert.Throws<InvalidCastException>(() => dictionary.Add("value is bad", new object()));
  291. }
  292. [Test]
  293. public void IDictionary_Contains()
  294. {
  295. var map = new MapField<string, string> { { "x", "y" } };
  296. IDictionary dictionary = map;
  297. Assert.IsFalse(dictionary.Contains("a"));
  298. Assert.IsFalse(dictionary.Contains(5));
  299. // Surprising, but IDictionary.Contains is only about keys.
  300. Assert.IsFalse(dictionary.Contains(new DictionaryEntry("x", "y")));
  301. Assert.IsTrue(dictionary.Contains("x"));
  302. }
  303. [Test]
  304. public void IDictionary_Remove()
  305. {
  306. var map = new MapField<string, string> { { "x", "y" } };
  307. IDictionary dictionary = map;
  308. dictionary.Remove("a");
  309. Assert.AreEqual(1, dictionary.Count);
  310. dictionary.Remove(5);
  311. Assert.AreEqual(1, dictionary.Count);
  312. dictionary.Remove(new DictionaryEntry("x", "y"));
  313. Assert.AreEqual(1, dictionary.Count);
  314. dictionary.Remove("x");
  315. Assert.AreEqual(0, dictionary.Count);
  316. Assert.Throws<ArgumentNullException>(() => dictionary.Remove(null));
  317. }
  318. [Test]
  319. public void IDictionary_CopyTo()
  320. {
  321. var map = new MapField<string, string> { { "x", "y" } };
  322. IDictionary dictionary = map;
  323. var array = new DictionaryEntry[3];
  324. dictionary.CopyTo(array, 1);
  325. CollectionAssert.AreEqual(new[] { default(DictionaryEntry), new DictionaryEntry("x", "y"), default(DictionaryEntry) },
  326. array);
  327. var objectArray = new object[3];
  328. dictionary.CopyTo(objectArray, 1);
  329. CollectionAssert.AreEqual(new object[] { null, new DictionaryEntry("x", "y"), null },
  330. objectArray);
  331. }
  332. [Test]
  333. public void IDictionary_IsFixedSize()
  334. {
  335. var map = new MapField<string, string> { { "x", "y" } };
  336. IDictionary dictionary = map;
  337. Assert.IsFalse(dictionary.IsFixedSize);
  338. }
  339. [Test]
  340. public void IDictionary_Keys()
  341. {
  342. IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
  343. CollectionAssert.AreEqual(new[] { "x" }, dictionary.Keys);
  344. }
  345. [Test]
  346. public void IDictionary_Values()
  347. {
  348. IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
  349. CollectionAssert.AreEqual(new[] { "y" }, dictionary.Values);
  350. }
  351. [Test]
  352. public void IDictionary_IsSynchronized()
  353. {
  354. IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
  355. Assert.IsFalse(dictionary.IsSynchronized);
  356. }
  357. [Test]
  358. public void IDictionary_SyncRoot()
  359. {
  360. IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
  361. Assert.AreSame(dictionary, dictionary.SyncRoot);
  362. }
  363. [Test]
  364. public void IDictionary_Indexer_Get()
  365. {
  366. IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
  367. Assert.AreEqual("y", dictionary["x"]);
  368. Assert.IsNull(dictionary["a"]);
  369. Assert.IsNull(dictionary[5]);
  370. Assert.Throws<ArgumentNullException>(() => dictionary[null].GetHashCode());
  371. }
  372. [Test]
  373. public void IDictionary_Indexer_Set()
  374. {
  375. var map = new MapField<string, string> { { "x", "y" } };
  376. IDictionary dictionary = map;
  377. map["a"] = "b";
  378. Assert.AreEqual("b", map["a"]);
  379. map["a"] = "c";
  380. Assert.AreEqual("c", map["a"]);
  381. Assert.Throws<InvalidCastException>(() => dictionary[5] = "x");
  382. Assert.Throws<InvalidCastException>(() => dictionary["x"] = 5);
  383. Assert.Throws<ArgumentNullException>(() => dictionary[null] = "z");
  384. Assert.Throws<ArgumentNullException>(() => dictionary["x"] = null);
  385. }
  386. [Test]
  387. public void KeysReturnsLiveView()
  388. {
  389. var map = new MapField<string, string>();
  390. var keys = map.Keys;
  391. CollectionAssert.AreEqual(new string[0], keys);
  392. map["foo"] = "bar";
  393. map["x"] = "y";
  394. CollectionAssert.AreEqual(new[] { "foo", "x" }, keys);
  395. }
  396. [Test]
  397. public void ValuesReturnsLiveView()
  398. {
  399. var map = new MapField<string, string>();
  400. var values = map.Values;
  401. CollectionAssert.AreEqual(new string[0], values);
  402. map["foo"] = "bar";
  403. map["x"] = "y";
  404. CollectionAssert.AreEqual(new[] { "bar", "y" }, values);
  405. }
  406. // Just test keys - we know the implementation is the same for values
  407. [Test]
  408. public void ViewsAreReadOnly()
  409. {
  410. var map = new MapField<string, string>();
  411. var keys = map.Keys;
  412. Assert.IsTrue(keys.IsReadOnly);
  413. Assert.Throws<NotSupportedException>(() => keys.Clear());
  414. Assert.Throws<NotSupportedException>(() => keys.Remove("a"));
  415. Assert.Throws<NotSupportedException>(() => keys.Add("a"));
  416. }
  417. // Just test keys - we know the implementation is the same for values
  418. [Test]
  419. public void ViewCopyTo()
  420. {
  421. var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
  422. var keys = map.Keys;
  423. var array = new string[4];
  424. Assert.Throws<ArgumentException>(() => keys.CopyTo(array, 3));
  425. Assert.Throws<ArgumentOutOfRangeException>(() => keys.CopyTo(array, -1));
  426. keys.CopyTo(array, 1);
  427. CollectionAssert.AreEqual(new[] { null, "foo", "x", null }, array);
  428. }
  429. // Just test keys - we know the implementation is the same for values
  430. [Test]
  431. public void NonGenericViewCopyTo()
  432. {
  433. IDictionary map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
  434. ICollection keys = map.Keys;
  435. // Note the use of the Array type here rather than string[]
  436. Array array = new string[4];
  437. Assert.Throws<ArgumentException>(() => keys.CopyTo(array, 3));
  438. Assert.Throws<ArgumentOutOfRangeException>(() => keys.CopyTo(array, -1));
  439. keys.CopyTo(array, 1);
  440. CollectionAssert.AreEqual(new[] { null, "foo", "x", null }, array);
  441. }
  442. [Test]
  443. public void KeysContains()
  444. {
  445. var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
  446. var keys = map.Keys;
  447. Assert.IsTrue(keys.Contains("foo"));
  448. Assert.IsFalse(keys.Contains("bar")); // It's a value!
  449. Assert.IsFalse(keys.Contains("1"));
  450. // Keys can't be null, so we should prevent contains check
  451. Assert.Throws<ArgumentNullException>(() => keys.Contains(null));
  452. }
  453. [Test]
  454. public void KeysCopyTo()
  455. {
  456. var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
  457. var keys = map.Keys.ToArray(); // Uses CopyTo internally
  458. CollectionAssert.AreEquivalent(new[] { "foo", "x" }, keys);
  459. }
  460. [Test]
  461. public void ValuesContains()
  462. {
  463. var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
  464. var values = map.Values;
  465. Assert.IsTrue(values.Contains("bar"));
  466. Assert.IsFalse(values.Contains("foo")); // It's a key!
  467. Assert.IsFalse(values.Contains("1"));
  468. // Values can be null, so this makes sense
  469. Assert.IsFalse(values.Contains(null));
  470. }
  471. [Test]
  472. public void ValuesCopyTo()
  473. {
  474. var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
  475. var values = map.Values.ToArray(); // Uses CopyTo internally
  476. CollectionAssert.AreEquivalent(new[] { "bar", "y" }, values);
  477. }
  478. [Test]
  479. public void ToString_StringToString()
  480. {
  481. var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
  482. Assert.AreEqual("{ \"foo\": \"bar\", \"x\": \"y\" }", map.ToString());
  483. }
  484. [Test]
  485. public void ToString_UnsupportedKeyType()
  486. {
  487. var map = new MapField<byte, string> { { 10, "foo" } };
  488. Assert.Throws<ArgumentException>(() => map.ToString());
  489. }
  490. [Test]
  491. public void NaNValuesComparedBitwise()
  492. {
  493. var map1 = new MapField<string, double>
  494. {
  495. { "x", SampleNaNs.Regular },
  496. { "y", SampleNaNs.SignallingFlipped }
  497. };
  498. var map2 = new MapField<string, double>
  499. {
  500. { "x", SampleNaNs.Regular },
  501. { "y", SampleNaNs.PayloadFlipped }
  502. };
  503. var map3 = new MapField<string, double>
  504. {
  505. { "x", SampleNaNs.Regular },
  506. { "y", SampleNaNs.SignallingFlipped }
  507. };
  508. EqualityTester.AssertInequality(map1, map2);
  509. EqualityTester.AssertEquality(map1, map3);
  510. Assert.True(map1.Values.Contains(SampleNaNs.SignallingFlipped));
  511. Assert.False(map2.Values.Contains(SampleNaNs.SignallingFlipped));
  512. }
  513. // This wouldn't usually happen, as protos can't use doubles as map keys,
  514. // but let's be consistent.
  515. [Test]
  516. public void NaNKeysComparedBitwise()
  517. {
  518. var map = new MapField<double, string>
  519. {
  520. { SampleNaNs.Regular, "x" },
  521. { SampleNaNs.SignallingFlipped, "y" }
  522. };
  523. Assert.AreEqual("x", map[SampleNaNs.Regular]);
  524. Assert.AreEqual("y", map[SampleNaNs.SignallingFlipped]);
  525. string ignored;
  526. Assert.False(map.TryGetValue(SampleNaNs.PayloadFlipped, out ignored));
  527. }
  528. [Test]
  529. public void AddEntriesFrom_CodedInputStream()
  530. {
  531. // map will have string key and string value
  532. var keyTag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
  533. var valueTag = WireFormat.MakeTag(2, WireFormat.WireType.LengthDelimited);
  534. var memoryStream = new MemoryStream();
  535. var output = new CodedOutputStream(memoryStream);
  536. output.WriteLength(20); // total of keyTag + key + valueTag + value
  537. output.WriteTag(keyTag);
  538. output.WriteString("the_key");
  539. output.WriteTag(valueTag);
  540. output.WriteString("the_value");
  541. output.Flush();
  542. var field = new MapField<string,string>();
  543. var mapCodec = new MapField<string,string>.Codec(FieldCodec.ForString(keyTag, ""), FieldCodec.ForString(valueTag, ""), 10);
  544. var input = new CodedInputStream(memoryStream.ToArray());
  545. // test the legacy overload of AddEntriesFrom that takes a CodedInputStream
  546. field.AddEntriesFrom(input, mapCodec);
  547. CollectionAssert.AreEquivalent(new[] { "the_key" }, field.Keys);
  548. CollectionAssert.AreEquivalent(new[] { "the_value" }, field.Values);
  549. Assert.IsTrue(input.IsAtEnd);
  550. }
  551. #if !NET35
  552. [Test]
  553. public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys()
  554. {
  555. var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
  556. CollectionAssert.AreEquivalent(((IDictionary<string, string>)map).Keys, ((IReadOnlyDictionary<string, string>)map).Keys);
  557. }
  558. [Test]
  559. public void IDictionaryValues_Equals_IReadOnlyDictionaryValues()
  560. {
  561. var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
  562. CollectionAssert.AreEquivalent(((IDictionary<string, string>)map).Values, ((IReadOnlyDictionary<string, string>)map).Values);
  563. }
  564. #endif
  565. private static KeyValuePair<TKey, TValue> NewKeyValuePair<TKey, TValue>(TKey key, TValue value)
  566. {
  567. return new KeyValuePair<TKey, TValue>(key, value);
  568. }
  569. }
  570. }