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