FieldAccessTest.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  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 Google.Protobuf.TestProtos;
  33. using Proto2 = Google.Protobuf.TestProtos.Proto2;
  34. using NUnit.Framework;
  35. using System;
  36. using System.Collections;
  37. using System.Collections.Generic;
  38. using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;
  39. using ProtobufUnittest;
  40. namespace Google.Protobuf.Reflection
  41. {
  42. public class FieldAccessTest
  43. {
  44. [Test]
  45. public void GetValue()
  46. {
  47. var message = SampleMessages.CreateFullTestAllTypes();
  48. var fields = TestProtos.TestAllTypes.Descriptor.Fields;
  49. Assert.AreEqual(message.SingleBool, fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(message));
  50. Assert.AreEqual(message.SingleBytes, fields[TestProtos.TestAllTypes.SingleBytesFieldNumber].Accessor.GetValue(message));
  51. Assert.AreEqual(message.SingleDouble, fields[TestProtos.TestAllTypes.SingleDoubleFieldNumber].Accessor.GetValue(message));
  52. Assert.AreEqual(message.SingleFixed32, fields[TestProtos.TestAllTypes.SingleFixed32FieldNumber].Accessor.GetValue(message));
  53. Assert.AreEqual(message.SingleFixed64, fields[TestProtos.TestAllTypes.SingleFixed64FieldNumber].Accessor.GetValue(message));
  54. Assert.AreEqual(message.SingleFloat, fields[TestProtos.TestAllTypes.SingleFloatFieldNumber].Accessor.GetValue(message));
  55. Assert.AreEqual(message.SingleForeignEnum, fields[TestProtos.TestAllTypes.SingleForeignEnumFieldNumber].Accessor.GetValue(message));
  56. Assert.AreEqual(message.SingleForeignMessage, fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor.GetValue(message));
  57. Assert.AreEqual(message.SingleImportEnum, fields[TestProtos.TestAllTypes.SingleImportEnumFieldNumber].Accessor.GetValue(message));
  58. Assert.AreEqual(message.SingleImportMessage, fields[TestProtos.TestAllTypes.SingleImportMessageFieldNumber].Accessor.GetValue(message));
  59. Assert.AreEqual(message.SingleInt32, fields[TestProtos.TestAllTypes.SingleInt32FieldNumber].Accessor.GetValue(message));
  60. Assert.AreEqual(message.SingleInt64, fields[TestProtos.TestAllTypes.SingleInt64FieldNumber].Accessor.GetValue(message));
  61. Assert.AreEqual(message.SingleNestedEnum, fields[TestProtos.TestAllTypes.SingleNestedEnumFieldNumber].Accessor.GetValue(message));
  62. Assert.AreEqual(message.SingleNestedMessage, fields[TestProtos.TestAllTypes.SingleNestedMessageFieldNumber].Accessor.GetValue(message));
  63. Assert.AreEqual(message.SinglePublicImportMessage, fields[TestProtos.TestAllTypes.SinglePublicImportMessageFieldNumber].Accessor.GetValue(message));
  64. Assert.AreEqual(message.SingleSint32, fields[TestProtos.TestAllTypes.SingleSint32FieldNumber].Accessor.GetValue(message));
  65. Assert.AreEqual(message.SingleSint64, fields[TestProtos.TestAllTypes.SingleSint64FieldNumber].Accessor.GetValue(message));
  66. Assert.AreEqual(message.SingleString, fields[TestProtos.TestAllTypes.SingleStringFieldNumber].Accessor.GetValue(message));
  67. Assert.AreEqual(message.SingleSfixed32, fields[TestProtos.TestAllTypes.SingleSfixed32FieldNumber].Accessor.GetValue(message));
  68. Assert.AreEqual(message.SingleSfixed64, fields[TestProtos.TestAllTypes.SingleSfixed64FieldNumber].Accessor.GetValue(message));
  69. Assert.AreEqual(message.SingleUint32, fields[TestProtos.TestAllTypes.SingleUint32FieldNumber].Accessor.GetValue(message));
  70. Assert.AreEqual(message.SingleUint64, fields[TestProtos.TestAllTypes.SingleUint64FieldNumber].Accessor.GetValue(message));
  71. Assert.AreEqual(message.OneofBytes, fields[TestProtos.TestAllTypes.OneofBytesFieldNumber].Accessor.GetValue(message));
  72. Assert.AreEqual(message.OneofString, fields[TestProtos.TestAllTypes.OneofStringFieldNumber].Accessor.GetValue(message));
  73. Assert.AreEqual(message.OneofNestedMessage, fields[TestProtos.TestAllTypes.OneofNestedMessageFieldNumber].Accessor.GetValue(message));
  74. Assert.AreEqual(message.OneofUint32, fields[TestProtos.TestAllTypes.OneofUint32FieldNumber].Accessor.GetValue(message));
  75. // Just one example for repeated fields - they're all just returning the list
  76. var list = (IList) fields[TestProtos.TestAllTypes.RepeatedInt32FieldNumber].Accessor.GetValue(message);
  77. Assert.AreEqual(message.RepeatedInt32, list);
  78. Assert.AreEqual(message.RepeatedInt32[0], list[0]); // Just in case there was any doubt...
  79. // Just a single map field, for the same reason
  80. var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };
  81. fields = TestMap.Descriptor.Fields;
  82. var dictionary = (IDictionary) fields[TestMap.MapStringStringFieldNumber].Accessor.GetValue(mapMessage);
  83. Assert.AreEqual(mapMessage.MapStringString, dictionary);
  84. Assert.AreEqual("value1", dictionary["key1"]);
  85. }
  86. [Test]
  87. public void GetValue_IncorrectType()
  88. {
  89. IMessage message = SampleMessages.CreateFullTestAllTypes();
  90. var fields = message.Descriptor.Fields;
  91. Assert.Throws<InvalidCastException>(() => fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(new TestMap()));
  92. }
  93. [Test]
  94. public void HasValue_Proto3_Message()
  95. {
  96. var message = new TestAllTypes();
  97. var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor;
  98. Assert.False(accessor.HasValue(message));
  99. message.SingleForeignMessage = new ForeignMessage();
  100. Assert.True(accessor.HasValue(message));
  101. message.SingleForeignMessage = null;
  102. Assert.False(accessor.HasValue(message));
  103. }
  104. [Test]
  105. public void HasValue_Proto3_Oneof()
  106. {
  107. TestAllTypes message = new TestAllTypes();
  108. var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.OneofStringFieldNumber].Accessor;
  109. Assert.False(accessor.HasValue(message));
  110. // Even though it's the default value, we still have a value.
  111. message.OneofString = "";
  112. Assert.True(accessor.HasValue(message));
  113. message.OneofString = "hello";
  114. Assert.True(accessor.HasValue(message));
  115. message.OneofUint32 = 10;
  116. Assert.False(accessor.HasValue(message));
  117. }
  118. [Test]
  119. public void HasValue_Proto3_Primitive_Optional()
  120. {
  121. var message = new TestProto3Optional();
  122. var accessor = ((IMessage) message).Descriptor.Fields[TestProto3Optional.OptionalInt64FieldNumber].Accessor;
  123. Assert.IsFalse(accessor.HasValue(message));
  124. message.OptionalInt64 = 5L;
  125. Assert.IsTrue(accessor.HasValue(message));
  126. message.ClearOptionalInt64();
  127. Assert.IsFalse(accessor.HasValue(message));
  128. message.OptionalInt64 = 0L;
  129. Assert.IsTrue(accessor.HasValue(message));
  130. }
  131. [Test]
  132. public void HasValue_Proto3_Primitive_NotOptional()
  133. {
  134. IMessage message = SampleMessages.CreateFullTestAllTypes();
  135. var fields = message.Descriptor.Fields;
  136. Assert.Throws<InvalidOperationException>(() => fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.HasValue(message));
  137. }
  138. [Test]
  139. public void HasValue_Proto3_Repeated()
  140. {
  141. var message = new TestAllTypes();
  142. var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.RepeatedBoolFieldNumber].Accessor;
  143. Assert.Throws<InvalidOperationException>(() => accessor.HasValue(message));
  144. }
  145. [Test]
  146. public void HasValue_Proto2_Primitive()
  147. {
  148. var message = new Proto2.TestAllTypes();
  149. var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OptionalInt64FieldNumber].Accessor;
  150. Assert.IsFalse(accessor.HasValue(message));
  151. message.OptionalInt64 = 5L;
  152. Assert.IsTrue(accessor.HasValue(message));
  153. message.ClearOptionalInt64();
  154. Assert.IsFalse(accessor.HasValue(message));
  155. message.OptionalInt64 = 0L;
  156. Assert.IsTrue(accessor.HasValue(message));
  157. }
  158. [Test]
  159. public void HasValue_Proto2_Message()
  160. {
  161. var message = new Proto2.TestAllTypes();
  162. var field = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OptionalForeignMessageFieldNumber];
  163. Assert.False(field.Accessor.HasValue(message));
  164. message.OptionalForeignMessage = new Proto2.ForeignMessage();
  165. Assert.True(field.Accessor.HasValue(message));
  166. message.OptionalForeignMessage = null;
  167. Assert.False(field.Accessor.HasValue(message));
  168. }
  169. [Test]
  170. public void HasValue_Proto2_Oneof()
  171. {
  172. var message = new Proto2.TestAllTypes();
  173. var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OneofStringFieldNumber].Accessor;
  174. Assert.False(accessor.HasValue(message));
  175. // Even though it's the default value, we still have a value.
  176. message.OneofString = "";
  177. Assert.True(accessor.HasValue(message));
  178. message.OneofString = "hello";
  179. Assert.True(accessor.HasValue(message));
  180. message.OneofUint32 = 10;
  181. Assert.False(accessor.HasValue(message));
  182. }
  183. [Test]
  184. public void HasValue_Proto2_Repeated()
  185. {
  186. var message = new Proto2.TestAllTypes();
  187. var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.RepeatedBoolFieldNumber].Accessor;
  188. Assert.Throws<InvalidOperationException>(() => accessor.HasValue(message));
  189. }
  190. [Test]
  191. public void SetValue_SingleFields()
  192. {
  193. // Just a sample (primitives, messages, enums, strings, byte strings)
  194. var message = SampleMessages.CreateFullTestAllTypes();
  195. var fields = TestProtos.TestAllTypes.Descriptor.Fields;
  196. fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, false);
  197. fields[TestProtos.TestAllTypes.SingleInt32FieldNumber].Accessor.SetValue(message, 500);
  198. fields[TestProtos.TestAllTypes.SingleStringFieldNumber].Accessor.SetValue(message, "It's a string");
  199. fields[TestProtos.TestAllTypes.SingleBytesFieldNumber].Accessor.SetValue(message, ByteString.CopyFrom(99, 98, 97));
  200. fields[TestProtos.TestAllTypes.SingleForeignEnumFieldNumber].Accessor.SetValue(message, ForeignEnum.ForeignFoo);
  201. fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor.SetValue(message, new ForeignMessage { C = 12345 });
  202. fields[TestProtos.TestAllTypes.SingleDoubleFieldNumber].Accessor.SetValue(message, 20150701.5);
  203. var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())
  204. {
  205. SingleBool = false,
  206. SingleInt32 = 500,
  207. SingleString = "It's a string",
  208. SingleBytes = ByteString.CopyFrom(99, 98, 97),
  209. SingleForeignEnum = ForeignEnum.ForeignFoo,
  210. SingleForeignMessage = new ForeignMessage { C = 12345 },
  211. SingleDouble = 20150701.5
  212. };
  213. Assert.AreEqual(expected, message);
  214. }
  215. [Test]
  216. public void SetValue_SingleFields_WrongType()
  217. {
  218. IMessage message = SampleMessages.CreateFullTestAllTypes();
  219. var fields = message.Descriptor.Fields;
  220. Assert.Throws<InvalidCastException>(() => fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, "This isn't a bool"));
  221. }
  222. [Test]
  223. public void SetValue_MapFields()
  224. {
  225. IMessage message = new TestMap();
  226. var fields = message.Descriptor.Fields;
  227. Assert.Throws<InvalidOperationException>(() => fields[TestMap.MapStringStringFieldNumber].Accessor.SetValue(message, new Dictionary<string, string>()));
  228. }
  229. [Test]
  230. public void SetValue_RepeatedFields()
  231. {
  232. IMessage message = SampleMessages.CreateFullTestAllTypes();
  233. var fields = message.Descriptor.Fields;
  234. Assert.Throws<InvalidOperationException>(() => fields[TestProtos.TestAllTypes.RepeatedDoubleFieldNumber].Accessor.SetValue(message, new double[10]));
  235. }
  236. [Test]
  237. public void Oneof()
  238. {
  239. var message = new TestAllTypes();
  240. var descriptor = TestProtos.TestAllTypes.Descriptor;
  241. Assert.AreEqual(1, descriptor.Oneofs.Count);
  242. var oneof = descriptor.Oneofs[0];
  243. Assert.AreEqual("oneof_field", oneof.Name);
  244. Assert.IsNull(oneof.Accessor.GetCaseFieldDescriptor(message));
  245. message.OneofString = "foo";
  246. Assert.AreSame(descriptor.Fields[TestProtos.TestAllTypes.OneofStringFieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
  247. message.OneofUint32 = 10;
  248. Assert.AreSame(descriptor.Fields[TestProtos.TestAllTypes.OneofUint32FieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
  249. oneof.Accessor.Clear(message);
  250. Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
  251. }
  252. [Test]
  253. public void Clear()
  254. {
  255. var message = SampleMessages.CreateFullTestAllTypes();
  256. var fields = TestProtos.TestAllTypes.Descriptor.Fields;
  257. fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.Clear(message);
  258. fields[TestProtos.TestAllTypes.SingleInt32FieldNumber].Accessor.Clear(message);
  259. fields[TestProtos.TestAllTypes.SingleStringFieldNumber].Accessor.Clear(message);
  260. fields[TestProtos.TestAllTypes.SingleBytesFieldNumber].Accessor.Clear(message);
  261. fields[TestProtos.TestAllTypes.SingleForeignEnumFieldNumber].Accessor.Clear(message);
  262. fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor.Clear(message);
  263. fields[TestProtos.TestAllTypes.RepeatedDoubleFieldNumber].Accessor.Clear(message);
  264. var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())
  265. {
  266. SingleBool = false,
  267. SingleInt32 = 0,
  268. SingleString = "",
  269. SingleBytes = ByteString.Empty,
  270. SingleForeignEnum = 0,
  271. SingleForeignMessage = null,
  272. };
  273. expected.RepeatedDouble.Clear();
  274. Assert.AreEqual(expected, message);
  275. // Separately, maps.
  276. var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };
  277. fields = TestMap.Descriptor.Fields;
  278. fields[TestMap.MapStringStringFieldNumber].Accessor.Clear(mapMessage);
  279. Assert.AreEqual(0, mapMessage.MapStringString.Count);
  280. }
  281. [Test]
  282. public void Clear_Proto3Optional()
  283. {
  284. TestProto3Optional message = new TestProto3Optional
  285. {
  286. OptionalInt32 = 0,
  287. OptionalNestedMessage = new TestProto3Optional.Types.NestedMessage()
  288. };
  289. var primitiveField = TestProto3Optional.Descriptor.Fields[TestProto3Optional.OptionalInt32FieldNumber];
  290. var messageField = TestProto3Optional.Descriptor.Fields[TestProto3Optional.OptionalNestedMessageFieldNumber];
  291. Assert.True(message.HasOptionalInt32);
  292. Assert.NotNull(message.OptionalNestedMessage);
  293. primitiveField.Accessor.Clear(message);
  294. messageField.Accessor.Clear(message);
  295. Assert.False(message.HasOptionalInt32);
  296. Assert.Null(message.OptionalNestedMessage);
  297. }
  298. [Test]
  299. public void Clear_Proto3_Oneof()
  300. {
  301. var message = new TestAllTypes();
  302. var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.OneofUint32FieldNumber].Accessor;
  303. // The field accessor Clear method only affects a oneof if the current case is the one being cleared.
  304. message.OneofString = "hello";
  305. Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
  306. accessor.Clear(message);
  307. Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
  308. message.OneofUint32 = 100;
  309. Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
  310. accessor.Clear(message);
  311. Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
  312. }
  313. [Test]
  314. public void Clear_Proto2_Oneof()
  315. {
  316. var message = new Proto2.TestAllTypes();
  317. var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OneofUint32FieldNumber].Accessor;
  318. // The field accessor Clear method only affects a oneof if the current case is the one being cleared.
  319. message.OneofString = "hello";
  320. Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
  321. accessor.Clear(message);
  322. Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
  323. message.OneofUint32 = 100;
  324. Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
  325. accessor.Clear(message);
  326. Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
  327. }
  328. [Test]
  329. public void FieldDescriptor_ByName()
  330. {
  331. var descriptor = TestProtos.TestAllTypes.Descriptor;
  332. Assert.AreSame(
  333. descriptor.Fields[TestProtos.TestAllTypes.SingleBoolFieldNumber],
  334. descriptor.Fields["single_bool"]);
  335. }
  336. [Test]
  337. public void FieldDescriptor_NotFound()
  338. {
  339. var descriptor = TestProtos.TestAllTypes.Descriptor;
  340. Assert.Throws<KeyNotFoundException>(() => descriptor.Fields[999999].ToString());
  341. Assert.Throws<KeyNotFoundException>(() => descriptor.Fields["not found"].ToString());
  342. }
  343. [Test]
  344. public void GetExtensionValue()
  345. {
  346. var message = SampleMessages.CreateFullTestAllExtensions();
  347. // test that the reflector works, since the reflector just runs through IExtendableMessage
  348. Assert.AreEqual(message.GetExtension(OptionalBoolExtension), Proto2.TestAllExtensions.Descriptor.FindFieldByNumber(OptionalBoolExtension.FieldNumber).Accessor.GetValue(message));
  349. }
  350. [Test]
  351. public void GetRepeatedExtensionValue()
  352. {
  353. // check to make sure repeated accessor uses GetOrRegister
  354. var message = new Proto2.TestAllExtensions();
  355. Assert.IsNull(message.GetExtension(RepeatedBoolExtension));
  356. Assert.IsNotNull(Proto2.TestAllExtensions.Descriptor.FindFieldByNumber(RepeatedBoolExtension.FieldNumber).Accessor.GetValue(message));
  357. Assert.IsNotNull(message.GetExtension(RepeatedBoolExtension));
  358. message.ClearExtension(RepeatedBoolExtension);
  359. Assert.IsNull(message.GetExtension(RepeatedBoolExtension));
  360. }
  361. [Test]
  362. public void HasPresence()
  363. {
  364. // Proto3
  365. var fields = TestProtos.TestAllTypes.Descriptor.Fields;
  366. Assert.IsFalse(fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].HasPresence);
  367. Assert.IsTrue(fields[TestProtos.TestAllTypes.OneofBytesFieldNumber].HasPresence);
  368. Assert.IsTrue(fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].HasPresence);
  369. Assert.IsFalse(fields[TestProtos.TestAllTypes.RepeatedBoolFieldNumber].HasPresence);
  370. fields = TestMap.Descriptor.Fields;
  371. Assert.IsFalse(fields[TestMap.MapBoolBoolFieldNumber].HasPresence);
  372. fields = TestProto3Optional.Descriptor.Fields;
  373. Assert.IsTrue(fields[TestProto3Optional.OptionalBoolFieldNumber].HasPresence);
  374. // Proto2
  375. fields = Proto2.TestAllTypes.Descriptor.Fields;
  376. Assert.IsTrue(fields[Proto2.TestAllTypes.OptionalBoolFieldNumber].HasPresence);
  377. Assert.IsTrue(fields[Proto2.TestAllTypes.OneofBytesFieldNumber].HasPresence);
  378. Assert.IsTrue(fields[Proto2.TestAllTypes.OptionalForeignMessageFieldNumber].HasPresence);
  379. Assert.IsFalse(fields[Proto2.TestAllTypes.RepeatedBoolFieldNumber].HasPresence);
  380. fields = Proto2.TestRequired.Descriptor.Fields;
  381. Assert.IsTrue(fields[Proto2.TestRequired.AFieldNumber].HasPresence);
  382. }
  383. }
  384. }