xref: /aosp_15_r20/external/protobuf/csharp/src/Google.Protobuf.Test/JsonParserTest.cs (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1*1b3f573fSAndroid Build Coastguard Worker #region Copyright notice and license
2*1b3f573fSAndroid Build Coastguard Worker // Protocol Buffers - Google's data interchange format
3*1b3f573fSAndroid Build Coastguard Worker // Copyright 2008 Google Inc.  All rights reserved.
4*1b3f573fSAndroid Build Coastguard Worker // https://developers.google.com/protocol-buffers/
5*1b3f573fSAndroid Build Coastguard Worker //
6*1b3f573fSAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without
7*1b3f573fSAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are
8*1b3f573fSAndroid Build Coastguard Worker // met:
9*1b3f573fSAndroid Build Coastguard Worker //
10*1b3f573fSAndroid Build Coastguard Worker //     * Redistributions of source code must retain the above copyright
11*1b3f573fSAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer.
12*1b3f573fSAndroid Build Coastguard Worker //     * Redistributions in binary form must reproduce the above
13*1b3f573fSAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer
14*1b3f573fSAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the
15*1b3f573fSAndroid Build Coastguard Worker // distribution.
16*1b3f573fSAndroid Build Coastguard Worker //     * Neither the name of Google Inc. nor the names of its
17*1b3f573fSAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from
18*1b3f573fSAndroid Build Coastguard Worker // this software without specific prior written permission.
19*1b3f573fSAndroid Build Coastguard Worker //
20*1b3f573fSAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*1b3f573fSAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*1b3f573fSAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*1b3f573fSAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*1b3f573fSAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*1b3f573fSAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*1b3f573fSAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*1b3f573fSAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*1b3f573fSAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*1b3f573fSAndroid Build Coastguard Worker #endregion
32*1b3f573fSAndroid Build Coastguard Worker 
33*1b3f573fSAndroid Build Coastguard Worker using Google.Protobuf.Reflection;
34*1b3f573fSAndroid Build Coastguard Worker using Google.Protobuf.TestProtos;
35*1b3f573fSAndroid Build Coastguard Worker using Google.Protobuf.WellKnownTypes;
36*1b3f573fSAndroid Build Coastguard Worker using NUnit.Framework;
37*1b3f573fSAndroid Build Coastguard Worker using ProtobufTestMessages.Proto2;
38*1b3f573fSAndroid Build Coastguard Worker using ProtobufTestMessages.Proto3;
39*1b3f573fSAndroid Build Coastguard Worker using System;
40*1b3f573fSAndroid Build Coastguard Worker using UnitTest.Issues.TestProtos;
41*1b3f573fSAndroid Build Coastguard Worker 
42*1b3f573fSAndroid Build Coastguard Worker namespace Google.Protobuf
43*1b3f573fSAndroid Build Coastguard Worker {
44*1b3f573fSAndroid Build Coastguard Worker     /// <summary>
45*1b3f573fSAndroid Build Coastguard Worker     /// Unit tests for JSON parsing.
46*1b3f573fSAndroid Build Coastguard Worker     /// </summary>
47*1b3f573fSAndroid Build Coastguard Worker     public class JsonParserTest
48*1b3f573fSAndroid Build Coastguard Worker     {
49*1b3f573fSAndroid Build Coastguard Worker         // Sanity smoke test
50*1b3f573fSAndroid Build Coastguard Worker         [Test]
AllTypesRoundtrip()51*1b3f573fSAndroid Build Coastguard Worker         public void AllTypesRoundtrip()
52*1b3f573fSAndroid Build Coastguard Worker         {
53*1b3f573fSAndroid Build Coastguard Worker             AssertRoundtrip(SampleMessages.CreateFullTestAllTypes());
54*1b3f573fSAndroid Build Coastguard Worker         }
55*1b3f573fSAndroid Build Coastguard Worker 
56*1b3f573fSAndroid Build Coastguard Worker         [Test]
Maps()57*1b3f573fSAndroid Build Coastguard Worker         public void Maps()
58*1b3f573fSAndroid Build Coastguard Worker         {
59*1b3f573fSAndroid Build Coastguard Worker             AssertRoundtrip(new TestMap { MapStringString = { { "with spaces", "bar" }, { "a", "b" } } });
60*1b3f573fSAndroid Build Coastguard Worker             AssertRoundtrip(new TestMap { MapInt32Int32 = { { 0, 1 }, { 2, 3 } } });
61*1b3f573fSAndroid Build Coastguard Worker             AssertRoundtrip(new TestMap { MapBoolBool = { { false, true }, { true, false } } });
62*1b3f573fSAndroid Build Coastguard Worker         }
63*1b3f573fSAndroid Build Coastguard Worker 
64*1b3f573fSAndroid Build Coastguard Worker         [Test]
65*1b3f573fSAndroid Build Coastguard Worker         [TestCase(" 1 ")]
66*1b3f573fSAndroid Build Coastguard Worker         [TestCase("+1")]
67*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1,000")]
68*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.5")]
IntegerMapKeysAreStrict(string keyText)69*1b3f573fSAndroid Build Coastguard Worker         public void IntegerMapKeysAreStrict(string keyText)
70*1b3f573fSAndroid Build Coastguard Worker         {
71*1b3f573fSAndroid Build Coastguard Worker             // Test that integer parsing is strict. We assume that if this is correct for int32,
72*1b3f573fSAndroid Build Coastguard Worker             // it's correct for other numeric key types.
73*1b3f573fSAndroid Build Coastguard Worker             var json = "{ \"mapInt32Int32\": { \"" + keyText + "\" : \"1\" } }";
74*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => JsonParser.Default.Parse<TestMap>(json));
75*1b3f573fSAndroid Build Coastguard Worker         }
76*1b3f573fSAndroid Build Coastguard Worker 
77*1b3f573fSAndroid Build Coastguard Worker         [Test]
OriginalFieldNameAccepted()78*1b3f573fSAndroid Build Coastguard Worker         public void OriginalFieldNameAccepted()
79*1b3f573fSAndroid Build Coastguard Worker         {
80*1b3f573fSAndroid Build Coastguard Worker             var json = "{ \"single_int32\": 10 }";
81*1b3f573fSAndroid Build Coastguard Worker             var expected = new TestAllTypes { SingleInt32 = 10 };
82*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expected, TestAllTypes.Parser.ParseJson(json));
83*1b3f573fSAndroid Build Coastguard Worker         }
84*1b3f573fSAndroid Build Coastguard Worker 
85*1b3f573fSAndroid Build Coastguard Worker         [Test]
SourceContextRoundtrip()86*1b3f573fSAndroid Build Coastguard Worker         public void SourceContextRoundtrip()
87*1b3f573fSAndroid Build Coastguard Worker         {
88*1b3f573fSAndroid Build Coastguard Worker             AssertRoundtrip(new SourceContext { FileName = "foo.proto" });
89*1b3f573fSAndroid Build Coastguard Worker         }
90*1b3f573fSAndroid Build Coastguard Worker 
91*1b3f573fSAndroid Build Coastguard Worker         [Test]
SingularWrappers_DefaultNonNullValues()92*1b3f573fSAndroid Build Coastguard Worker         public void SingularWrappers_DefaultNonNullValues()
93*1b3f573fSAndroid Build Coastguard Worker         {
94*1b3f573fSAndroid Build Coastguard Worker             var message = new TestWellKnownTypes
95*1b3f573fSAndroid Build Coastguard Worker             {
96*1b3f573fSAndroid Build Coastguard Worker                 StringField = "",
97*1b3f573fSAndroid Build Coastguard Worker                 BytesField = ByteString.Empty,
98*1b3f573fSAndroid Build Coastguard Worker                 BoolField = false,
99*1b3f573fSAndroid Build Coastguard Worker                 FloatField = 0f,
100*1b3f573fSAndroid Build Coastguard Worker                 DoubleField = 0d,
101*1b3f573fSAndroid Build Coastguard Worker                 Int32Field = 0,
102*1b3f573fSAndroid Build Coastguard Worker                 Int64Field = 0,
103*1b3f573fSAndroid Build Coastguard Worker                 Uint32Field = 0,
104*1b3f573fSAndroid Build Coastguard Worker                 Uint64Field = 0
105*1b3f573fSAndroid Build Coastguard Worker             };
106*1b3f573fSAndroid Build Coastguard Worker             AssertRoundtrip(message);
107*1b3f573fSAndroid Build Coastguard Worker         }
108*1b3f573fSAndroid Build Coastguard Worker 
109*1b3f573fSAndroid Build Coastguard Worker         [Test]
SingularWrappers_NonDefaultValues()110*1b3f573fSAndroid Build Coastguard Worker         public void SingularWrappers_NonDefaultValues()
111*1b3f573fSAndroid Build Coastguard Worker         {
112*1b3f573fSAndroid Build Coastguard Worker             var message = new TestWellKnownTypes
113*1b3f573fSAndroid Build Coastguard Worker             {
114*1b3f573fSAndroid Build Coastguard Worker                 StringField = "x",
115*1b3f573fSAndroid Build Coastguard Worker                 BytesField = ByteString.CopyFrom(1, 2, 3),
116*1b3f573fSAndroid Build Coastguard Worker                 BoolField = true,
117*1b3f573fSAndroid Build Coastguard Worker                 FloatField = 12.5f,
118*1b3f573fSAndroid Build Coastguard Worker                 DoubleField = 12.25d,
119*1b3f573fSAndroid Build Coastguard Worker                 Int32Field = 1,
120*1b3f573fSAndroid Build Coastguard Worker                 Int64Field = 2,
121*1b3f573fSAndroid Build Coastguard Worker                 Uint32Field = 3,
122*1b3f573fSAndroid Build Coastguard Worker                 Uint64Field = 4
123*1b3f573fSAndroid Build Coastguard Worker             };
124*1b3f573fSAndroid Build Coastguard Worker             AssertRoundtrip(message);
125*1b3f573fSAndroid Build Coastguard Worker         }
126*1b3f573fSAndroid Build Coastguard Worker 
127*1b3f573fSAndroid Build Coastguard Worker         [Test]
SingularWrappers_ExplicitNulls()128*1b3f573fSAndroid Build Coastguard Worker         public void SingularWrappers_ExplicitNulls()
129*1b3f573fSAndroid Build Coastguard Worker         {
130*1b3f573fSAndroid Build Coastguard Worker             // When we parse the "valueField": null part, we remember it... basically, it's one case
131*1b3f573fSAndroid Build Coastguard Worker             // where explicit default values don't fully roundtrip.
132*1b3f573fSAndroid Build Coastguard Worker             var message = new TestWellKnownTypes { ValueField = Value.ForNull() };
133*1b3f573fSAndroid Build Coastguard Worker             var json = new JsonFormatter(new JsonFormatter.Settings(true)).Format(message);
134*1b3f573fSAndroid Build Coastguard Worker             var parsed = JsonParser.Default.Parse<TestWellKnownTypes>(json);
135*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(message, parsed);
136*1b3f573fSAndroid Build Coastguard Worker         }
137*1b3f573fSAndroid Build Coastguard Worker 
138*1b3f573fSAndroid Build Coastguard Worker         [Test]
139*1b3f573fSAndroid Build Coastguard Worker         [TestCase(typeof(BoolValue), "true", true)]
140*1b3f573fSAndroid Build Coastguard Worker         [TestCase(typeof(Int32Value), "32", 32)]
141*1b3f573fSAndroid Build Coastguard Worker         [TestCase(typeof(Int64Value), "32", 32L)]
142*1b3f573fSAndroid Build Coastguard Worker         [TestCase(typeof(Int64Value), "\"32\"", 32L)]
143*1b3f573fSAndroid Build Coastguard Worker         [TestCase(typeof(UInt32Value), "32", 32U)]
144*1b3f573fSAndroid Build Coastguard Worker         [TestCase(typeof(UInt64Value), "\"32\"", 32UL)]
145*1b3f573fSAndroid Build Coastguard Worker         [TestCase(typeof(UInt64Value), "32", 32UL)]
146*1b3f573fSAndroid Build Coastguard Worker         [TestCase(typeof(StringValue), "\"foo\"", "foo")]
147*1b3f573fSAndroid Build Coastguard Worker         [TestCase(typeof(FloatValue), "1.5", 1.5f)]
148*1b3f573fSAndroid Build Coastguard Worker         [TestCase(typeof(DoubleValue), "1.5", 1.5d)]
Wrappers_Standalone(System.Type wrapperType, string json, object expectedValue)149*1b3f573fSAndroid Build Coastguard Worker         public void Wrappers_Standalone(System.Type wrapperType, string json, object expectedValue)
150*1b3f573fSAndroid Build Coastguard Worker         {
151*1b3f573fSAndroid Build Coastguard Worker             IMessage parsed = (IMessage)Activator.CreateInstance(wrapperType);
152*1b3f573fSAndroid Build Coastguard Worker             IMessage expected = (IMessage)Activator.CreateInstance(wrapperType);
153*1b3f573fSAndroid Build Coastguard Worker             JsonParser.Default.Merge(parsed, "null");
154*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expected, parsed);
155*1b3f573fSAndroid Build Coastguard Worker 
156*1b3f573fSAndroid Build Coastguard Worker             JsonParser.Default.Merge(parsed, json);
157*1b3f573fSAndroid Build Coastguard Worker             expected.Descriptor.Fields[WrappersReflection.WrapperValueFieldNumber].Accessor.SetValue(expected, expectedValue);
158*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expected, parsed);
159*1b3f573fSAndroid Build Coastguard Worker         }
160*1b3f573fSAndroid Build Coastguard Worker 
161*1b3f573fSAndroid Build Coastguard Worker         [Test]
ExplicitNullValue()162*1b3f573fSAndroid Build Coastguard Worker         public void ExplicitNullValue()
163*1b3f573fSAndroid Build Coastguard Worker         {
164*1b3f573fSAndroid Build Coastguard Worker             string json = "{\"valueField\": null}";
165*1b3f573fSAndroid Build Coastguard Worker             var message = JsonParser.Default.Parse<TestWellKnownTypes>(json);
166*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new TestWellKnownTypes { ValueField = Value.ForNull() }, message);
167*1b3f573fSAndroid Build Coastguard Worker         }
168*1b3f573fSAndroid Build Coastguard Worker 
169*1b3f573fSAndroid Build Coastguard Worker         [Test]
BytesWrapper_Standalone()170*1b3f573fSAndroid Build Coastguard Worker         public void BytesWrapper_Standalone()
171*1b3f573fSAndroid Build Coastguard Worker         {
172*1b3f573fSAndroid Build Coastguard Worker             ByteString data = ByteString.CopyFrom(1, 2, 3);
173*1b3f573fSAndroid Build Coastguard Worker             // Can't do this with attributes...
174*1b3f573fSAndroid Build Coastguard Worker             var parsed = JsonParser.Default.Parse<BytesValue>(WrapInQuotes(data.ToBase64()));
175*1b3f573fSAndroid Build Coastguard Worker             var expected = new BytesValue { Value = data };
176*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expected, parsed);
177*1b3f573fSAndroid Build Coastguard Worker         }
178*1b3f573fSAndroid Build Coastguard Worker 
179*1b3f573fSAndroid Build Coastguard Worker         [Test]
RepeatedWrappers()180*1b3f573fSAndroid Build Coastguard Worker         public void RepeatedWrappers()
181*1b3f573fSAndroid Build Coastguard Worker         {
182*1b3f573fSAndroid Build Coastguard Worker             var message = new RepeatedWellKnownTypes
183*1b3f573fSAndroid Build Coastguard Worker             {
184*1b3f573fSAndroid Build Coastguard Worker                 BoolField = { true, false },
185*1b3f573fSAndroid Build Coastguard Worker                 BytesField = { ByteString.CopyFrom(1, 2, 3), ByteString.CopyFrom(4, 5, 6), ByteString.Empty },
186*1b3f573fSAndroid Build Coastguard Worker                 DoubleField = { 12.5, -1.5, 0d },
187*1b3f573fSAndroid Build Coastguard Worker                 FloatField = { 123.25f, -20f, 0f },
188*1b3f573fSAndroid Build Coastguard Worker                 Int32Field = { int.MaxValue, int.MinValue, 0 },
189*1b3f573fSAndroid Build Coastguard Worker                 Int64Field = { long.MaxValue, long.MinValue, 0L },
190*1b3f573fSAndroid Build Coastguard Worker                 StringField = { "First", "Second", "" },
191*1b3f573fSAndroid Build Coastguard Worker                 Uint32Field = { uint.MaxValue, uint.MinValue, 0U },
192*1b3f573fSAndroid Build Coastguard Worker                 Uint64Field = { ulong.MaxValue, ulong.MinValue, 0UL },
193*1b3f573fSAndroid Build Coastguard Worker             };
194*1b3f573fSAndroid Build Coastguard Worker             AssertRoundtrip(message);
195*1b3f573fSAndroid Build Coastguard Worker         }
196*1b3f573fSAndroid Build Coastguard Worker 
197*1b3f573fSAndroid Build Coastguard Worker         [Test]
RepeatedField_NullElementProhibited()198*1b3f573fSAndroid Build Coastguard Worker         public void RepeatedField_NullElementProhibited()
199*1b3f573fSAndroid Build Coastguard Worker         {
200*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"repeated_foreign_message\": [null] }";
201*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
202*1b3f573fSAndroid Build Coastguard Worker         }
203*1b3f573fSAndroid Build Coastguard Worker 
204*1b3f573fSAndroid Build Coastguard Worker         [Test]
RepeatedField_NullOverallValueAllowed()205*1b3f573fSAndroid Build Coastguard Worker         public void RepeatedField_NullOverallValueAllowed()
206*1b3f573fSAndroid Build Coastguard Worker         {
207*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"repeated_foreign_message\": null }";
208*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new TestAllTypes(), TestAllTypes.Parser.ParseJson(json));
209*1b3f573fSAndroid Build Coastguard Worker         }
210*1b3f573fSAndroid Build Coastguard Worker 
211*1b3f573fSAndroid Build Coastguard Worker         [Test]
212*1b3f573fSAndroid Build Coastguard Worker         [TestCase("{ \"mapInt32Int32\": { \"10\": null }")]
213*1b3f573fSAndroid Build Coastguard Worker         [TestCase("{ \"mapStringString\": { \"abc\": null }")]
214*1b3f573fSAndroid Build Coastguard Worker         [TestCase("{ \"mapInt32ForeignMessage\": { \"10\": null }")]
MapField_NullValueProhibited(string json)215*1b3f573fSAndroid Build Coastguard Worker         public void MapField_NullValueProhibited(string json)
216*1b3f573fSAndroid Build Coastguard Worker         {
217*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestMap.Parser.ParseJson(json));
218*1b3f573fSAndroid Build Coastguard Worker         }
219*1b3f573fSAndroid Build Coastguard Worker 
220*1b3f573fSAndroid Build Coastguard Worker         [Test]
MapField_NullOverallValueAllowed()221*1b3f573fSAndroid Build Coastguard Worker         public void MapField_NullOverallValueAllowed()
222*1b3f573fSAndroid Build Coastguard Worker         {
223*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"mapInt32Int32\": null }";
224*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new TestMap(), TestMap.Parser.ParseJson(json));
225*1b3f573fSAndroid Build Coastguard Worker         }
226*1b3f573fSAndroid Build Coastguard Worker 
227*1b3f573fSAndroid Build Coastguard Worker         [Test]
IndividualWrapperTypes()228*1b3f573fSAndroid Build Coastguard Worker         public void IndividualWrapperTypes()
229*1b3f573fSAndroid Build Coastguard Worker         {
230*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new StringValue { Value = "foo" }, StringValue.Parser.ParseJson("\"foo\""));
231*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new Int32Value { Value = 1 }, Int32Value.Parser.ParseJson("1"));
232*1b3f573fSAndroid Build Coastguard Worker             // Can parse strings directly too
233*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new Int32Value { Value = 1 }, Int32Value.Parser.ParseJson("\"1\""));
234*1b3f573fSAndroid Build Coastguard Worker         }
235*1b3f573fSAndroid Build Coastguard Worker 
236*1b3f573fSAndroid Build Coastguard Worker         private static void AssertRoundtrip<T>(T message) where T : IMessage<T>, new()
237*1b3f573fSAndroid Build Coastguard Worker         {
238*1b3f573fSAndroid Build Coastguard Worker             var clone = message.Clone();
239*1b3f573fSAndroid Build Coastguard Worker             var json = JsonFormatter.Default.Format(message);
240*1b3f573fSAndroid Build Coastguard Worker             var parsed = JsonParser.Default.Parse<T>(json);
241*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(clone, parsed);
242*1b3f573fSAndroid Build Coastguard Worker         }
243*1b3f573fSAndroid Build Coastguard Worker 
244*1b3f573fSAndroid Build Coastguard Worker         [Test]
245*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0)]
246*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-0", 0)] // Not entirely clear whether we intend to allow this...
247*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1)]
248*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1", -1)]
249*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2147483647", 2147483647)]
250*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-2147483648", -2147483648)]
StringToInt32_Valid(string jsonValue, int expectedParsedValue)251*1b3f573fSAndroid Build Coastguard Worker         public void StringToInt32_Valid(string jsonValue, int expectedParsedValue)
252*1b3f573fSAndroid Build Coastguard Worker         {
253*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleInt32\": \"" + jsonValue + "\"}";
254*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
255*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleInt32);
256*1b3f573fSAndroid Build Coastguard Worker         }
257*1b3f573fSAndroid Build Coastguard Worker 
258*1b3f573fSAndroid Build Coastguard Worker         [Test]
259*1b3f573fSAndroid Build Coastguard Worker         [TestCase("+0")]
260*1b3f573fSAndroid Build Coastguard Worker         [TestCase(" 1")]
261*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1 ")]
262*1b3f573fSAndroid Build Coastguard Worker         [TestCase("00")]
263*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-00")]
264*1b3f573fSAndroid Build Coastguard Worker         [TestCase("--1")]
265*1b3f573fSAndroid Build Coastguard Worker         [TestCase("+1")]
266*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.5")]
267*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1e10")]
268*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2147483648")]
269*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-2147483649")]
StringToInt32_Invalid(string jsonValue)270*1b3f573fSAndroid Build Coastguard Worker         public void StringToInt32_Invalid(string jsonValue)
271*1b3f573fSAndroid Build Coastguard Worker         {
272*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleInt32\": \"" + jsonValue + "\"}";
273*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
274*1b3f573fSAndroid Build Coastguard Worker         }
275*1b3f573fSAndroid Build Coastguard Worker 
276*1b3f573fSAndroid Build Coastguard Worker         [Test]
277*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0U)]
278*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1U)]
279*1b3f573fSAndroid Build Coastguard Worker         [TestCase("4294967295", 4294967295U)]
StringToUInt32_Valid(string jsonValue, uint expectedParsedValue)280*1b3f573fSAndroid Build Coastguard Worker         public void StringToUInt32_Valid(string jsonValue, uint expectedParsedValue)
281*1b3f573fSAndroid Build Coastguard Worker         {
282*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleUint32\": \"" + jsonValue + "\"}";
283*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
284*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleUint32);
285*1b3f573fSAndroid Build Coastguard Worker         }
286*1b3f573fSAndroid Build Coastguard Worker 
287*1b3f573fSAndroid Build Coastguard Worker         // Assume that anything non-bounds-related is covered in the Int32 case
288*1b3f573fSAndroid Build Coastguard Worker         [Test]
289*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1")]
290*1b3f573fSAndroid Build Coastguard Worker         [TestCase("4294967296")]
StringToUInt32_Invalid(string jsonValue)291*1b3f573fSAndroid Build Coastguard Worker         public void StringToUInt32_Invalid(string jsonValue)
292*1b3f573fSAndroid Build Coastguard Worker         {
293*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleUint32\": \"" + jsonValue + "\"}";
294*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
295*1b3f573fSAndroid Build Coastguard Worker         }
296*1b3f573fSAndroid Build Coastguard Worker 
297*1b3f573fSAndroid Build Coastguard Worker         [Test]
298*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0L)]
299*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1L)]
300*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1", -1L)]
301*1b3f573fSAndroid Build Coastguard Worker         [TestCase("9223372036854775807", 9223372036854775807)]
302*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-9223372036854775808", -9223372036854775808)]
StringToInt64_Valid(string jsonValue, long expectedParsedValue)303*1b3f573fSAndroid Build Coastguard Worker         public void StringToInt64_Valid(string jsonValue, long expectedParsedValue)
304*1b3f573fSAndroid Build Coastguard Worker         {
305*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleInt64\": \"" + jsonValue + "\"}";
306*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
307*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleInt64);
308*1b3f573fSAndroid Build Coastguard Worker         }
309*1b3f573fSAndroid Build Coastguard Worker 
310*1b3f573fSAndroid Build Coastguard Worker         // Assume that anything non-bounds-related is covered in the Int32 case
311*1b3f573fSAndroid Build Coastguard Worker         [Test]
312*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-9223372036854775809")]
313*1b3f573fSAndroid Build Coastguard Worker         [TestCase("9223372036854775808")]
StringToInt64_Invalid(string jsonValue)314*1b3f573fSAndroid Build Coastguard Worker         public void StringToInt64_Invalid(string jsonValue)
315*1b3f573fSAndroid Build Coastguard Worker         {
316*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleInt64\": \"" + jsonValue + "\"}";
317*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
318*1b3f573fSAndroid Build Coastguard Worker         }
319*1b3f573fSAndroid Build Coastguard Worker 
320*1b3f573fSAndroid Build Coastguard Worker         [Test]
321*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0UL)]
322*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1UL)]
323*1b3f573fSAndroid Build Coastguard Worker         [TestCase("18446744073709551615", 18446744073709551615)]
StringToUInt64_Valid(string jsonValue, ulong expectedParsedValue)324*1b3f573fSAndroid Build Coastguard Worker         public void StringToUInt64_Valid(string jsonValue, ulong expectedParsedValue)
325*1b3f573fSAndroid Build Coastguard Worker         {
326*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleUint64\": \"" + jsonValue + "\"}";
327*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
328*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleUint64);
329*1b3f573fSAndroid Build Coastguard Worker         }
330*1b3f573fSAndroid Build Coastguard Worker 
331*1b3f573fSAndroid Build Coastguard Worker         // Assume that anything non-bounds-related is covered in the Int32 case
332*1b3f573fSAndroid Build Coastguard Worker         [Test]
333*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1")]
334*1b3f573fSAndroid Build Coastguard Worker         [TestCase("18446744073709551616")]
StringToUInt64_Invalid(string jsonValue)335*1b3f573fSAndroid Build Coastguard Worker         public void StringToUInt64_Invalid(string jsonValue)
336*1b3f573fSAndroid Build Coastguard Worker         {
337*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleUint64\": \"" + jsonValue + "\"}";
338*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
339*1b3f573fSAndroid Build Coastguard Worker         }
340*1b3f573fSAndroid Build Coastguard Worker 
341*1b3f573fSAndroid Build Coastguard Worker         [Test]
342*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0d)]
343*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1d)]
344*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.000000", 1d)]
345*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.0000000000000000000000001", 1d)] // We don't notice that we haven't preserved the exact value
346*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1", -1d)]
347*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1e1", 10d)]
348*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1e01", 10d)] // Leading decimals are allowed in exponents
349*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1E1", 10d)] // Either case is fine
350*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1e1", -10d)]
351*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.5e1", 15d)]
352*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1.5e1", -15d)]
353*1b3f573fSAndroid Build Coastguard Worker         [TestCase("15e-1", 1.5d)]
354*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-15e-1", -1.5d)]
355*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.79769e308", 1.79769e308)]
356*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1.79769e308", -1.79769e308)]
357*1b3f573fSAndroid Build Coastguard Worker         [TestCase("Infinity", double.PositiveInfinity)]
358*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-Infinity", double.NegativeInfinity)]
359*1b3f573fSAndroid Build Coastguard Worker         [TestCase("NaN", double.NaN)]
StringToDouble_Valid(string jsonValue, double expectedParsedValue)360*1b3f573fSAndroid Build Coastguard Worker         public void StringToDouble_Valid(string jsonValue, double expectedParsedValue)
361*1b3f573fSAndroid Build Coastguard Worker         {
362*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleDouble\": \"" + jsonValue + "\"}";
363*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
364*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleDouble);
365*1b3f573fSAndroid Build Coastguard Worker         }
366*1b3f573fSAndroid Build Coastguard Worker 
367*1b3f573fSAndroid Build Coastguard Worker         [Test]
368*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.7977e308")]
369*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1.7977e308")]
370*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1e309")]
371*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1,0")]
372*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.0.0")]
373*1b3f573fSAndroid Build Coastguard Worker         [TestCase("+1")]
374*1b3f573fSAndroid Build Coastguard Worker         [TestCase("00")]
375*1b3f573fSAndroid Build Coastguard Worker         [TestCase("01")]
376*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-00")]
377*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-01")]
378*1b3f573fSAndroid Build Coastguard Worker         [TestCase("--1")]
379*1b3f573fSAndroid Build Coastguard Worker         [TestCase(" Infinity")]
380*1b3f573fSAndroid Build Coastguard Worker         [TestCase(" -Infinity")]
381*1b3f573fSAndroid Build Coastguard Worker         [TestCase("NaN ")]
382*1b3f573fSAndroid Build Coastguard Worker         [TestCase("Infinity ")]
383*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-Infinity ")]
384*1b3f573fSAndroid Build Coastguard Worker         [TestCase(" NaN")]
385*1b3f573fSAndroid Build Coastguard Worker         [TestCase("INFINITY")]
386*1b3f573fSAndroid Build Coastguard Worker         [TestCase("nan")]
387*1b3f573fSAndroid Build Coastguard Worker         [TestCase("\u00BD")] // 1/2 as a single Unicode character. Just sanity checking...
StringToDouble_Invalid(string jsonValue)388*1b3f573fSAndroid Build Coastguard Worker         public void StringToDouble_Invalid(string jsonValue)
389*1b3f573fSAndroid Build Coastguard Worker         {
390*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleDouble\": \"" + jsonValue + "\"}";
391*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
392*1b3f573fSAndroid Build Coastguard Worker         }
393*1b3f573fSAndroid Build Coastguard Worker 
394*1b3f573fSAndroid Build Coastguard Worker         [Test]
395*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0f)]
396*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1f)]
397*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.000000", 1f)]
398*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1", -1f)]
399*1b3f573fSAndroid Build Coastguard Worker         [TestCase("3.402823e38", 3.402823e38f)]
400*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-3.402823e38", -3.402823e38f)]
401*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.5e1", 15f)]
402*1b3f573fSAndroid Build Coastguard Worker         [TestCase("15e-1", 1.5f)]
StringToFloat_Valid(string jsonValue, float expectedParsedValue)403*1b3f573fSAndroid Build Coastguard Worker         public void StringToFloat_Valid(string jsonValue, float expectedParsedValue)
404*1b3f573fSAndroid Build Coastguard Worker         {
405*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleFloat\": \"" + jsonValue + "\"}";
406*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
407*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleFloat);
408*1b3f573fSAndroid Build Coastguard Worker         }
409*1b3f573fSAndroid Build Coastguard Worker 
410*1b3f573fSAndroid Build Coastguard Worker         [Test]
411*1b3f573fSAndroid Build Coastguard Worker         [TestCase("3.402824e38")]
412*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-3.402824e38")]
413*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1,0")]
414*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.0.0")]
415*1b3f573fSAndroid Build Coastguard Worker         [TestCase("+1")]
416*1b3f573fSAndroid Build Coastguard Worker         [TestCase("00")]
417*1b3f573fSAndroid Build Coastguard Worker         [TestCase("--1")]
StringToFloat_Invalid(string jsonValue)418*1b3f573fSAndroid Build Coastguard Worker         public void StringToFloat_Invalid(string jsonValue)
419*1b3f573fSAndroid Build Coastguard Worker         {
420*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleFloat\": \"" + jsonValue + "\"}";
421*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
422*1b3f573fSAndroid Build Coastguard Worker         }
423*1b3f573fSAndroid Build Coastguard Worker 
424*1b3f573fSAndroid Build Coastguard Worker         [Test]
425*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0)]
426*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-0", 0)] // Not entirely clear whether we intend to allow this...
427*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1)]
428*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1", -1)]
429*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2147483647", 2147483647)]
430*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-2147483648", -2147483648)]
431*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1e1", 10)]
432*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1e1", -10)]
433*1b3f573fSAndroid Build Coastguard Worker         [TestCase("10.00", 10)]
434*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-10.00", -10)]
NumberToInt32_Valid(string jsonValue, int expectedParsedValue)435*1b3f573fSAndroid Build Coastguard Worker         public void NumberToInt32_Valid(string jsonValue, int expectedParsedValue)
436*1b3f573fSAndroid Build Coastguard Worker         {
437*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleInt32\": " + jsonValue + "}";
438*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
439*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleInt32);
440*1b3f573fSAndroid Build Coastguard Worker         }
441*1b3f573fSAndroid Build Coastguard Worker 
442*1b3f573fSAndroid Build Coastguard Worker         [Test]
443*1b3f573fSAndroid Build Coastguard Worker         [TestCase("+0", typeof(InvalidJsonException))]
444*1b3f573fSAndroid Build Coastguard Worker         [TestCase("00", typeof(InvalidJsonException))]
445*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-00", typeof(InvalidJsonException))]
446*1b3f573fSAndroid Build Coastguard Worker         [TestCase("--1", typeof(InvalidJsonException))]
447*1b3f573fSAndroid Build Coastguard Worker         [TestCase("+1", typeof(InvalidJsonException))]
448*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.5", typeof(InvalidProtocolBufferException))]
449*1b3f573fSAndroid Build Coastguard Worker         // Value is out of range
450*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1e10", typeof(InvalidProtocolBufferException))]
451*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2147483648", typeof(InvalidProtocolBufferException))]
452*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-2147483649", typeof(InvalidProtocolBufferException))]
NumberToInt32_Invalid(string jsonValue, System.Type expectedExceptionType)453*1b3f573fSAndroid Build Coastguard Worker         public void NumberToInt32_Invalid(string jsonValue, System.Type expectedExceptionType)
454*1b3f573fSAndroid Build Coastguard Worker         {
455*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleInt32\": " + jsonValue + "}";
456*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws(expectedExceptionType, () => TestAllTypes.Parser.ParseJson(json));
457*1b3f573fSAndroid Build Coastguard Worker         }
458*1b3f573fSAndroid Build Coastguard Worker 
459*1b3f573fSAndroid Build Coastguard Worker         [Test]
460*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0U)]
461*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1U)]
462*1b3f573fSAndroid Build Coastguard Worker         [TestCase("4294967295", 4294967295U)]
NumberToUInt32_Valid(string jsonValue, uint expectedParsedValue)463*1b3f573fSAndroid Build Coastguard Worker         public void NumberToUInt32_Valid(string jsonValue, uint expectedParsedValue)
464*1b3f573fSAndroid Build Coastguard Worker         {
465*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleUint32\": " + jsonValue + "}";
466*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
467*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleUint32);
468*1b3f573fSAndroid Build Coastguard Worker         }
469*1b3f573fSAndroid Build Coastguard Worker 
470*1b3f573fSAndroid Build Coastguard Worker         // Assume that anything non-bounds-related is covered in the Int32 case
471*1b3f573fSAndroid Build Coastguard Worker         [Test]
472*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1")]
473*1b3f573fSAndroid Build Coastguard Worker         [TestCase("4294967296")]
NumberToUInt32_Invalid(string jsonValue)474*1b3f573fSAndroid Build Coastguard Worker         public void NumberToUInt32_Invalid(string jsonValue)
475*1b3f573fSAndroid Build Coastguard Worker         {
476*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleUint32\": " + jsonValue + "}";
477*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
478*1b3f573fSAndroid Build Coastguard Worker         }
479*1b3f573fSAndroid Build Coastguard Worker 
480*1b3f573fSAndroid Build Coastguard Worker         [Test]
481*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0L)]
482*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1L)]
483*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1", -1L)]
484*1b3f573fSAndroid Build Coastguard Worker         // long.MaxValue isn't actually representable as a double. This string value is the highest
485*1b3f573fSAndroid Build Coastguard Worker         // representable value which isn't greater than long.MaxValue.
486*1b3f573fSAndroid Build Coastguard Worker         [TestCase("9223372036854774784", 9223372036854774784)]
487*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-9223372036854775808", -9223372036854775808)]
NumberToInt64_Valid(string jsonValue, long expectedParsedValue)488*1b3f573fSAndroid Build Coastguard Worker         public void NumberToInt64_Valid(string jsonValue, long expectedParsedValue)
489*1b3f573fSAndroid Build Coastguard Worker         {
490*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleInt64\": " + jsonValue + "}";
491*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
492*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleInt64);
493*1b3f573fSAndroid Build Coastguard Worker         }
494*1b3f573fSAndroid Build Coastguard Worker 
495*1b3f573fSAndroid Build Coastguard Worker         // Assume that anything non-bounds-related is covered in the Int32 case
496*1b3f573fSAndroid Build Coastguard Worker         [Test]
497*1b3f573fSAndroid Build Coastguard Worker         [TestCase("9223372036854775808")]
498*1b3f573fSAndroid Build Coastguard Worker         // Theoretical bound would be -9223372036854775809, but when that is parsed to a double
499*1b3f573fSAndroid Build Coastguard Worker         // we end up with the exact value of long.MinValue due to lack of precision. The value here
500*1b3f573fSAndroid Build Coastguard Worker         // is the "next double down".
501*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-9223372036854780000")]
NumberToInt64_Invalid(string jsonValue)502*1b3f573fSAndroid Build Coastguard Worker         public void NumberToInt64_Invalid(string jsonValue)
503*1b3f573fSAndroid Build Coastguard Worker         {
504*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleInt64\": " + jsonValue + "}";
505*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
506*1b3f573fSAndroid Build Coastguard Worker         }
507*1b3f573fSAndroid Build Coastguard Worker 
508*1b3f573fSAndroid Build Coastguard Worker         [Test]
509*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0UL)]
510*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1UL)]
511*1b3f573fSAndroid Build Coastguard Worker         // ulong.MaxValue isn't representable as a double. This value is the largest double within
512*1b3f573fSAndroid Build Coastguard Worker         // the range of ulong.
513*1b3f573fSAndroid Build Coastguard Worker         [TestCase("18446744073709549568", 18446744073709549568UL)]
NumberToUInt64_Valid(string jsonValue, ulong expectedParsedValue)514*1b3f573fSAndroid Build Coastguard Worker         public void NumberToUInt64_Valid(string jsonValue, ulong expectedParsedValue)
515*1b3f573fSAndroid Build Coastguard Worker         {
516*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleUint64\": " + jsonValue + "}";
517*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
518*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleUint64);
519*1b3f573fSAndroid Build Coastguard Worker         }
520*1b3f573fSAndroid Build Coastguard Worker 
521*1b3f573fSAndroid Build Coastguard Worker         // Assume that anything non-bounds-related is covered in the Int32 case
522*1b3f573fSAndroid Build Coastguard Worker         [Test]
523*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1")]
524*1b3f573fSAndroid Build Coastguard Worker         [TestCase("18446744073709551616")]
NumberToUInt64_Invalid(string jsonValue)525*1b3f573fSAndroid Build Coastguard Worker         public void NumberToUInt64_Invalid(string jsonValue)
526*1b3f573fSAndroid Build Coastguard Worker         {
527*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleUint64\": " + jsonValue + "}";
528*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
529*1b3f573fSAndroid Build Coastguard Worker         }
530*1b3f573fSAndroid Build Coastguard Worker 
531*1b3f573fSAndroid Build Coastguard Worker         [Test]
532*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0d)]
533*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1d)]
534*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.000000", 1d)]
535*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.0000000000000000000000001", 1d)] // We don't notice that we haven't preserved the exact value
536*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1", -1d)]
537*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1e1", 10d)]
538*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1e01", 10d)] // Leading decimals are allowed in exponents
539*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1E1", 10d)] // Either case is fine
540*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1e1", -10d)]
541*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.5e1", 15d)]
542*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1.5e1", -15d)]
543*1b3f573fSAndroid Build Coastguard Worker         [TestCase("15e-1", 1.5d)]
544*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-15e-1", -1.5d)]
545*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.79769e308", 1.79769e308)]
546*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1.79769e308", -1.79769e308)]
NumberToDouble_Valid(string jsonValue, double expectedParsedValue)547*1b3f573fSAndroid Build Coastguard Worker         public void NumberToDouble_Valid(string jsonValue, double expectedParsedValue)
548*1b3f573fSAndroid Build Coastguard Worker         {
549*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleDouble\": " + jsonValue + "}";
550*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
551*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleDouble);
552*1b3f573fSAndroid Build Coastguard Worker         }
553*1b3f573fSAndroid Build Coastguard Worker 
554*1b3f573fSAndroid Build Coastguard Worker         [Test]
555*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.7977e308")]
556*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1.7977e308")]
557*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1e309")]
558*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1,0")]
559*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.0.0")]
560*1b3f573fSAndroid Build Coastguard Worker         [TestCase("+1")]
561*1b3f573fSAndroid Build Coastguard Worker         [TestCase("00")]
562*1b3f573fSAndroid Build Coastguard Worker         [TestCase("--1")]
563*1b3f573fSAndroid Build Coastguard Worker         [TestCase("\u00BD")] // 1/2 as a single Unicode character. Just sanity checking...
NumberToDouble_Invalid(string jsonValue)564*1b3f573fSAndroid Build Coastguard Worker         public void NumberToDouble_Invalid(string jsonValue)
565*1b3f573fSAndroid Build Coastguard Worker         {
566*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleDouble\": " + jsonValue + "}";
567*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidJsonException>(() => TestAllTypes.Parser.ParseJson(json));
568*1b3f573fSAndroid Build Coastguard Worker         }
569*1b3f573fSAndroid Build Coastguard Worker 
570*1b3f573fSAndroid Build Coastguard Worker         [Test]
571*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0", 0f)]
572*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1", 1f)]
573*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.000000", 1f)]
574*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1", -1f)]
575*1b3f573fSAndroid Build Coastguard Worker         [TestCase("3.402823e38", 3.402823e38f)]
576*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-3.402823e38", -3.402823e38f)]
577*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.5e1", 15f)]
578*1b3f573fSAndroid Build Coastguard Worker         [TestCase("15e-1", 1.5f)]
NumberToFloat_Valid(string jsonValue, float expectedParsedValue)579*1b3f573fSAndroid Build Coastguard Worker         public void NumberToFloat_Valid(string jsonValue, float expectedParsedValue)
580*1b3f573fSAndroid Build Coastguard Worker         {
581*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleFloat\": " + jsonValue + "}";
582*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
583*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expectedParsedValue, parsed.SingleFloat);
584*1b3f573fSAndroid Build Coastguard Worker         }
585*1b3f573fSAndroid Build Coastguard Worker 
586*1b3f573fSAndroid Build Coastguard Worker         [Test]
587*1b3f573fSAndroid Build Coastguard Worker         [TestCase("3.402824e38", typeof(InvalidProtocolBufferException))]
588*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-3.402824e38", typeof(InvalidProtocolBufferException))]
589*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1,0", typeof(InvalidJsonException))]
590*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.0.0", typeof(InvalidJsonException))]
591*1b3f573fSAndroid Build Coastguard Worker         [TestCase("+1", typeof(InvalidJsonException))]
592*1b3f573fSAndroid Build Coastguard Worker         [TestCase("00", typeof(InvalidJsonException))]
593*1b3f573fSAndroid Build Coastguard Worker         [TestCase("--1", typeof(InvalidJsonException))]
NumberToFloat_Invalid(string jsonValue, System.Type expectedExceptionType)594*1b3f573fSAndroid Build Coastguard Worker         public void NumberToFloat_Invalid(string jsonValue, System.Type expectedExceptionType)
595*1b3f573fSAndroid Build Coastguard Worker         {
596*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleFloat\": " + jsonValue + "}";
597*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws(expectedExceptionType, () => TestAllTypes.Parser.ParseJson(json));
598*1b3f573fSAndroid Build Coastguard Worker         }
599*1b3f573fSAndroid Build Coastguard Worker 
600*1b3f573fSAndroid Build Coastguard Worker         // The simplest way of testing that the value has parsed correctly is to reformat it,
601*1b3f573fSAndroid Build Coastguard Worker         // as we trust the formatting. In many cases that will give the same result as the input,
602*1b3f573fSAndroid Build Coastguard Worker         // so in those cases we accept an expectedFormatted value of null. Sometimes the results
603*1b3f573fSAndroid Build Coastguard Worker         // will be different though, due to a different number of digits being provided.
604*1b3f573fSAndroid Build Coastguard Worker         [Test]
605*1b3f573fSAndroid Build Coastguard Worker         // Z offset
606*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123456789Z", null)]
607*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123456Z", null)]
608*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123Z", null)]
609*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23Z", null)]
610*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123456000Z", "2015-10-09T14:46:23.123456Z")]
611*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.1234560Z", "2015-10-09T14:46:23.123456Z")]
612*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123000000Z", "2015-10-09T14:46:23.123Z")]
613*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.1230Z", "2015-10-09T14:46:23.123Z")]
614*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.00Z", "2015-10-09T14:46:23Z")]
615*1b3f573fSAndroid Build Coastguard Worker 
616*1b3f573fSAndroid Build Coastguard Worker         // +00:00 offset
617*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123456789+00:00", "2015-10-09T14:46:23.123456789Z")]
618*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123456+00:00", "2015-10-09T14:46:23.123456Z")]
619*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123+00:00", "2015-10-09T14:46:23.123Z")]
620*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23+00:00", "2015-10-09T14:46:23Z")]
621*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123456000+00:00", "2015-10-09T14:46:23.123456Z")]
622*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.1234560+00:00", "2015-10-09T14:46:23.123456Z")]
623*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123000000+00:00", "2015-10-09T14:46:23.123Z")]
624*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.1230+00:00", "2015-10-09T14:46:23.123Z")]
625*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.00+00:00", "2015-10-09T14:46:23Z")]
626*1b3f573fSAndroid Build Coastguard Worker 
627*1b3f573fSAndroid Build Coastguard Worker         // Other offsets (assume by now that the subsecond handling is okay)
628*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T15:46:23.123456789+01:00", "2015-10-09T14:46:23.123456789Z")]
629*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T13:46:23.123456789-01:00", "2015-10-09T14:46:23.123456789Z")]
630*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T15:16:23.123456789+00:30", "2015-10-09T14:46:23.123456789Z")]
631*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:16:23.123456789-00:30", "2015-10-09T14:46:23.123456789Z")]
632*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T16:31:23.123456789+01:45", "2015-10-09T14:46:23.123456789Z")]
633*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T13:01:23.123456789-01:45", "2015-10-09T14:46:23.123456789Z")]
634*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-10T08:46:23.123456789+18:00", "2015-10-09T14:46:23.123456789Z")]
635*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-08T20:46:23.123456789-18:00", "2015-10-09T14:46:23.123456789Z")]
636*1b3f573fSAndroid Build Coastguard Worker 
637*1b3f573fSAndroid Build Coastguard Worker         // Leap years and min/max
638*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2016-02-29T14:46:23.123456789Z", null)]
639*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2000-02-29T14:46:23.123456789Z", null)]
640*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0001-01-01T00:00:00Z", null)]
641*1b3f573fSAndroid Build Coastguard Worker         [TestCase("9999-12-31T23:59:59.999999999Z", null)]
Timestamp_Valid(string jsonValue, string expectedFormatted)642*1b3f573fSAndroid Build Coastguard Worker         public void Timestamp_Valid(string jsonValue, string expectedFormatted)
643*1b3f573fSAndroid Build Coastguard Worker         {
644*1b3f573fSAndroid Build Coastguard Worker             expectedFormatted = expectedFormatted ?? jsonValue;
645*1b3f573fSAndroid Build Coastguard Worker             string json = WrapInQuotes(jsonValue);
646*1b3f573fSAndroid Build Coastguard Worker             var parsed = Timestamp.Parser.ParseJson(json);
647*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(WrapInQuotes(expectedFormatted), parsed.ToString());
648*1b3f573fSAndroid Build Coastguard Worker         }
649*1b3f573fSAndroid Build Coastguard Worker 
650*1b3f573fSAndroid Build Coastguard Worker         [Test]
651*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09 14:46:23.123456789Z", Description = "No T between date and time")]
652*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015/10/09T14:46:23.123456789Z", Description = "Wrong date separators")]
653*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14.46.23.123456789Z", Description = "Wrong time separators")]
654*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23,123456789Z", Description = "Wrong fractional second separators (valid ISO-8601 though)")]
655*1b3f573fSAndroid Build Coastguard Worker         [TestCase(" 2015-10-09T14:46:23.123456789Z", Description = "Whitespace at start")]
656*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123456789Z ", Description = "Whitespace at end")]
657*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.1234567890", Description = "Too many digits")]
658*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123456789", Description = "No offset")]
659*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-13-09T14:46:23.123456789Z", Description = "Invalid month")]
660*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-32T14:46:23.123456789Z", Description = "Invalid day")]
661*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T24:00:00.000000000Z", Description = "Invalid hour (valid ISO-8601 though)")]
662*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:60:23.123456789Z", Description = "Invalid minutes")]
663*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:60.123456789Z", Description = "Invalid seconds")]
664*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123456789+18:01", Description = "Offset too large (positive)")]
665*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123456789-18:01", Description = "Offset too large (negative)")]
666*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2015-10-09T14:46:23.123456789-00:00", Description = "Local offset (-00:00) makes no sense here")]
667*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0001-01-01T00:00:00+00:01", Description = "Value before earliest when offset applied")]
668*1b3f573fSAndroid Build Coastguard Worker         [TestCase("9999-12-31T23:59:59.999999999-00:01", Description = "Value after latest when offset applied")]
669*1b3f573fSAndroid Build Coastguard Worker         [TestCase("2100-02-29T14:46:23.123456789Z", Description = "Feb 29th on a non-leap-year")]
Timestamp_Invalid(string jsonValue)670*1b3f573fSAndroid Build Coastguard Worker         public void Timestamp_Invalid(string jsonValue)
671*1b3f573fSAndroid Build Coastguard Worker         {
672*1b3f573fSAndroid Build Coastguard Worker             string json = WrapInQuotes(jsonValue);
673*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => Timestamp.Parser.ParseJson(json));
674*1b3f573fSAndroid Build Coastguard Worker         }
675*1b3f573fSAndroid Build Coastguard Worker 
676*1b3f573fSAndroid Build Coastguard Worker         [Test]
StructValue_Null()677*1b3f573fSAndroid Build Coastguard Worker         public void StructValue_Null()
678*1b3f573fSAndroid Build Coastguard Worker         {
679*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new Value { NullValue = 0 }, Value.Parser.ParseJson("null"));
680*1b3f573fSAndroid Build Coastguard Worker         }
681*1b3f573fSAndroid Build Coastguard Worker 
682*1b3f573fSAndroid Build Coastguard Worker         [Test]
StructValue_String()683*1b3f573fSAndroid Build Coastguard Worker         public void StructValue_String()
684*1b3f573fSAndroid Build Coastguard Worker         {
685*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new Value { StringValue = "hi" }, Value.Parser.ParseJson("\"hi\""));
686*1b3f573fSAndroid Build Coastguard Worker         }
687*1b3f573fSAndroid Build Coastguard Worker 
688*1b3f573fSAndroid Build Coastguard Worker         [Test]
StructValue_Bool()689*1b3f573fSAndroid Build Coastguard Worker         public void StructValue_Bool()
690*1b3f573fSAndroid Build Coastguard Worker         {
691*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new Value { BoolValue = true }, Value.Parser.ParseJson("true"));
692*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new Value { BoolValue = false }, Value.Parser.ParseJson("false"));
693*1b3f573fSAndroid Build Coastguard Worker         }
694*1b3f573fSAndroid Build Coastguard Worker 
695*1b3f573fSAndroid Build Coastguard Worker         [Test]
StructValue_List()696*1b3f573fSAndroid Build Coastguard Worker         public void StructValue_List()
697*1b3f573fSAndroid Build Coastguard Worker         {
698*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(Value.ForList(Value.ForNumber(1), Value.ForString("x")), Value.Parser.ParseJson("[1, \"x\"]"));
699*1b3f573fSAndroid Build Coastguard Worker         }
700*1b3f573fSAndroid Build Coastguard Worker 
701*1b3f573fSAndroid Build Coastguard Worker         [Test]
Value_List_WithNullElement()702*1b3f573fSAndroid Build Coastguard Worker         public void Value_List_WithNullElement()
703*1b3f573fSAndroid Build Coastguard Worker         {
704*1b3f573fSAndroid Build Coastguard Worker             var expected = Value.ForList(Value.ForString("x"), Value.ForNull(), Value.ForString("y"));
705*1b3f573fSAndroid Build Coastguard Worker             var actual = Value.Parser.ParseJson("[\"x\", null, \"y\"]");
706*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expected, actual);
707*1b3f573fSAndroid Build Coastguard Worker         }
708*1b3f573fSAndroid Build Coastguard Worker 
709*1b3f573fSAndroid Build Coastguard Worker         [Test]
StructValue_NullElement()710*1b3f573fSAndroid Build Coastguard Worker         public void StructValue_NullElement()
711*1b3f573fSAndroid Build Coastguard Worker         {
712*1b3f573fSAndroid Build Coastguard Worker             var expected = Value.ForStruct(new Struct { Fields = { { "x", Value.ForNull() } } });
713*1b3f573fSAndroid Build Coastguard Worker             var actual = Value.Parser.ParseJson("{ \"x\": null }");
714*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expected, actual);
715*1b3f573fSAndroid Build Coastguard Worker         }
716*1b3f573fSAndroid Build Coastguard Worker 
717*1b3f573fSAndroid Build Coastguard Worker         [Test]
ParseListValue()718*1b3f573fSAndroid Build Coastguard Worker         public void ParseListValue()
719*1b3f573fSAndroid Build Coastguard Worker         {
720*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new ListValue { Values = { Value.ForNumber(1), Value.ForString("x") } }, ListValue.Parser.ParseJson("[1, \"x\"]"));
721*1b3f573fSAndroid Build Coastguard Worker         }
722*1b3f573fSAndroid Build Coastguard Worker 
723*1b3f573fSAndroid Build Coastguard Worker         [Test]
StructValue_Struct()724*1b3f573fSAndroid Build Coastguard Worker         public void StructValue_Struct()
725*1b3f573fSAndroid Build Coastguard Worker         {
726*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(
727*1b3f573fSAndroid Build Coastguard Worker                 Value.ForStruct(new Struct { Fields = { { "x", Value.ForNumber(1) }, { "y", Value.ForString("z") } } }),
728*1b3f573fSAndroid Build Coastguard Worker                 Value.Parser.ParseJson("{ \"x\": 1, \"y\": \"z\" }"));
729*1b3f573fSAndroid Build Coastguard Worker         }
730*1b3f573fSAndroid Build Coastguard Worker 
731*1b3f573fSAndroid Build Coastguard Worker         [Test]
ParseStruct()732*1b3f573fSAndroid Build Coastguard Worker         public void ParseStruct()
733*1b3f573fSAndroid Build Coastguard Worker         {
734*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new Struct { Fields = { { "x", Value.ForNumber(1) }, { "y", Value.ForString("z") } } },
735*1b3f573fSAndroid Build Coastguard Worker                 Struct.Parser.ParseJson("{ \"x\": 1, \"y\": \"z\" }"));
736*1b3f573fSAndroid Build Coastguard Worker         }
737*1b3f573fSAndroid Build Coastguard Worker 
738*1b3f573fSAndroid Build Coastguard Worker         // TODO for duration parsing: upper and lower bounds.
739*1b3f573fSAndroid Build Coastguard Worker         // +/- 315576000000 seconds
740*1b3f573fSAndroid Build Coastguard Worker 
741*1b3f573fSAndroid Build Coastguard Worker         [Test]
742*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.123456789s", null)]
743*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.123456s", null)]
744*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.123s", null)]
745*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.12300s", "1.123s")]
746*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.12345s", "1.123450s")]
747*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1s", null)]
748*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1.123456789s", null)]
749*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1.123456s", null)]
750*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1.123s", null)]
751*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-1s", null)]
752*1b3f573fSAndroid Build Coastguard Worker         [TestCase("0.123s", null)]
753*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-0.123s", null)]
754*1b3f573fSAndroid Build Coastguard Worker         [TestCase("123456.123s", null)]
755*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-123456.123s", null)]
756*1b3f573fSAndroid Build Coastguard Worker         // Upper and lower bounds
757*1b3f573fSAndroid Build Coastguard Worker         [TestCase("315576000000s", null)]
758*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-315576000000s", null)]
Duration_Valid(string jsonValue, string expectedFormatted)759*1b3f573fSAndroid Build Coastguard Worker         public void Duration_Valid(string jsonValue, string expectedFormatted)
760*1b3f573fSAndroid Build Coastguard Worker         {
761*1b3f573fSAndroid Build Coastguard Worker             expectedFormatted = expectedFormatted ?? jsonValue;
762*1b3f573fSAndroid Build Coastguard Worker             string json = WrapInQuotes(jsonValue);
763*1b3f573fSAndroid Build Coastguard Worker             var parsed = Duration.Parser.ParseJson(json);
764*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(WrapInQuotes(expectedFormatted), parsed.ToString());
765*1b3f573fSAndroid Build Coastguard Worker         }
766*1b3f573fSAndroid Build Coastguard Worker 
767*1b3f573fSAndroid Build Coastguard Worker         // The simplest way of testing that the value has parsed correctly is to reformat it,
768*1b3f573fSAndroid Build Coastguard Worker         // as we trust the formatting. In many cases that will give the same result as the input,
769*1b3f573fSAndroid Build Coastguard Worker         // so in those cases we accept an expectedFormatted value of null. Sometimes the results
770*1b3f573fSAndroid Build Coastguard Worker         // will be different though, due to a different number of digits being provided.
771*1b3f573fSAndroid Build Coastguard Worker         [Test]
772*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.1234567890s", Description = "Too many digits")]
773*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.123456789", Description = "No suffix")]
774*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.123456789ss", Description = "Too much suffix")]
775*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.123456789S", Description = "Upper case suffix")]
776*1b3f573fSAndroid Build Coastguard Worker         [TestCase("+1.123456789s", Description = "Leading +")]
777*1b3f573fSAndroid Build Coastguard Worker         [TestCase(".123456789s", Description = "No integer before the fraction")]
778*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1,123456789s", Description = "Comma as decimal separator")]
779*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1x1.123456789s", Description = "Non-digit in integer part")]
780*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.1x3456789s", Description = "Non-digit in fractional part")]
781*1b3f573fSAndroid Build Coastguard Worker         [TestCase(" 1.123456789s", Description = "Whitespace before fraction")]
782*1b3f573fSAndroid Build Coastguard Worker         [TestCase("1.123456789s ", Description = "Whitespace after value")]
783*1b3f573fSAndroid Build Coastguard Worker         [TestCase("01.123456789s", Description = "Leading zero (positive)")]
784*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-01.123456789s", Description = "Leading zero (negative)")]
785*1b3f573fSAndroid Build Coastguard Worker         [TestCase("--0.123456789s", Description = "Double minus sign")]
786*1b3f573fSAndroid Build Coastguard Worker         // Violate upper/lower bounds in various ways
787*1b3f573fSAndroid Build Coastguard Worker         [TestCase("315576000001s", Description = "Integer part too large")]
788*1b3f573fSAndroid Build Coastguard Worker         [TestCase("3155760000000s", Description = "Integer part too long (positive)")]
789*1b3f573fSAndroid Build Coastguard Worker         [TestCase("-3155760000000s", Description = "Integer part too long (negative)")]
Duration_Invalid(string jsonValue)790*1b3f573fSAndroid Build Coastguard Worker         public void Duration_Invalid(string jsonValue)
791*1b3f573fSAndroid Build Coastguard Worker         {
792*1b3f573fSAndroid Build Coastguard Worker             string json = WrapInQuotes(jsonValue);
793*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => Duration.Parser.ParseJson(json));
794*1b3f573fSAndroid Build Coastguard Worker         }
795*1b3f573fSAndroid Build Coastguard Worker 
796*1b3f573fSAndroid Build Coastguard Worker         // Not as many tests for field masks as I'd like; more to be added when we have more
797*1b3f573fSAndroid Build Coastguard Worker         // detailed specifications.
798*1b3f573fSAndroid Build Coastguard Worker 
799*1b3f573fSAndroid Build Coastguard Worker         [Test]
800*1b3f573fSAndroid Build Coastguard Worker         [TestCase("")]
801*1b3f573fSAndroid Build Coastguard Worker         [TestCase("foo", "foo")]
802*1b3f573fSAndroid Build Coastguard Worker         [TestCase("foo,bar", "foo", "bar")]
803*1b3f573fSAndroid Build Coastguard Worker         [TestCase("foo.bar", "foo.bar")]
804*1b3f573fSAndroid Build Coastguard Worker         [TestCase("fooBar", "foo_bar")]
805*1b3f573fSAndroid Build Coastguard Worker         [TestCase("fooBar.bazQux", "foo_bar.baz_qux")]
FieldMask_Valid(string jsonValue, params string[] expectedPaths)806*1b3f573fSAndroid Build Coastguard Worker         public void FieldMask_Valid(string jsonValue, params string[] expectedPaths)
807*1b3f573fSAndroid Build Coastguard Worker         {
808*1b3f573fSAndroid Build Coastguard Worker             string json = WrapInQuotes(jsonValue);
809*1b3f573fSAndroid Build Coastguard Worker             var parsed = FieldMask.Parser.ParseJson(json);
810*1b3f573fSAndroid Build Coastguard Worker             CollectionAssert.AreEqual(expectedPaths, parsed.Paths);
811*1b3f573fSAndroid Build Coastguard Worker         }
812*1b3f573fSAndroid Build Coastguard Worker 
813*1b3f573fSAndroid Build Coastguard Worker         [Test]
814*1b3f573fSAndroid Build Coastguard Worker         [TestCase("foo_bar")]
FieldMask_Invalid(string jsonValue)815*1b3f573fSAndroid Build Coastguard Worker         public void FieldMask_Invalid(string jsonValue)
816*1b3f573fSAndroid Build Coastguard Worker         {
817*1b3f573fSAndroid Build Coastguard Worker             string json = WrapInQuotes(jsonValue);
818*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => FieldMask.Parser.ParseJson(json));
819*1b3f573fSAndroid Build Coastguard Worker         }
820*1b3f573fSAndroid Build Coastguard Worker 
821*1b3f573fSAndroid Build Coastguard Worker         [Test]
Any_RegularMessage()822*1b3f573fSAndroid Build Coastguard Worker         public void Any_RegularMessage()
823*1b3f573fSAndroid Build Coastguard Worker         {
824*1b3f573fSAndroid Build Coastguard Worker             var registry = TypeRegistry.FromMessages(TestAllTypes.Descriptor);
825*1b3f573fSAndroid Build Coastguard Worker             var formatter = new JsonFormatter(new JsonFormatter.Settings(false, TypeRegistry.FromMessages(TestAllTypes.Descriptor)));
826*1b3f573fSAndroid Build Coastguard Worker             var message = new TestAllTypes { SingleInt32 = 10, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 } };
827*1b3f573fSAndroid Build Coastguard Worker             var original = Any.Pack(message);
828*1b3f573fSAndroid Build Coastguard Worker             var json = formatter.Format(original); // This is tested in JsonFormatterTest
829*1b3f573fSAndroid Build Coastguard Worker             var parser = new JsonParser(new JsonParser.Settings(10, registry));
830*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(original, parser.Parse<Any>(json));
831*1b3f573fSAndroid Build Coastguard Worker             string valueFirstJson = "{ \"singleInt32\": 10, \"singleNestedMessage\": { \"bb\": 20 }, \"@type\": \"type.googleapis.com/protobuf_unittest3.TestAllTypes\" }";
832*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(original, parser.Parse<Any>(valueFirstJson));
833*1b3f573fSAndroid Build Coastguard Worker         }
834*1b3f573fSAndroid Build Coastguard Worker 
835*1b3f573fSAndroid Build Coastguard Worker         [Test]
Any_CustomPrefix()836*1b3f573fSAndroid Build Coastguard Worker         public void Any_CustomPrefix()
837*1b3f573fSAndroid Build Coastguard Worker         {
838*1b3f573fSAndroid Build Coastguard Worker             var registry = TypeRegistry.FromMessages(TestAllTypes.Descriptor);
839*1b3f573fSAndroid Build Coastguard Worker             var message = new TestAllTypes { SingleInt32 = 10 };
840*1b3f573fSAndroid Build Coastguard Worker             var original = Any.Pack(message, "custom.prefix/middle-part");
841*1b3f573fSAndroid Build Coastguard Worker             var parser = new JsonParser(new JsonParser.Settings(10, registry));
842*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"@type\": \"custom.prefix/middle-part/protobuf_unittest3.TestAllTypes\", \"singleInt32\": 10 }";
843*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(original, parser.Parse<Any>(json));
844*1b3f573fSAndroid Build Coastguard Worker         }
845*1b3f573fSAndroid Build Coastguard Worker 
846*1b3f573fSAndroid Build Coastguard Worker         [Test]
Any_UnknownType()847*1b3f573fSAndroid Build Coastguard Worker         public void Any_UnknownType()
848*1b3f573fSAndroid Build Coastguard Worker         {
849*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"@type\": \"type.googleapis.com/bogus\" }";
850*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidOperationException>(() => Any.Parser.ParseJson(json));
851*1b3f573fSAndroid Build Coastguard Worker         }
852*1b3f573fSAndroid Build Coastguard Worker 
853*1b3f573fSAndroid Build Coastguard Worker         [Test]
Any_NoTypeUrl()854*1b3f573fSAndroid Build Coastguard Worker         public void Any_NoTypeUrl()
855*1b3f573fSAndroid Build Coastguard Worker         {
856*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"foo\": \"bar\" }";
857*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => Any.Parser.ParseJson(json));
858*1b3f573fSAndroid Build Coastguard Worker         }
859*1b3f573fSAndroid Build Coastguard Worker 
860*1b3f573fSAndroid Build Coastguard Worker         [Test]
Any_WellKnownType()861*1b3f573fSAndroid Build Coastguard Worker         public void Any_WellKnownType()
862*1b3f573fSAndroid Build Coastguard Worker         {
863*1b3f573fSAndroid Build Coastguard Worker             var registry = TypeRegistry.FromMessages(Timestamp.Descriptor);
864*1b3f573fSAndroid Build Coastguard Worker             var formatter = new JsonFormatter(new JsonFormatter.Settings(false, registry));
865*1b3f573fSAndroid Build Coastguard Worker             var timestamp = new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp();
866*1b3f573fSAndroid Build Coastguard Worker             var original = Any.Pack(timestamp);
867*1b3f573fSAndroid Build Coastguard Worker             var json = formatter.Format(original); // This is tested in JsonFormatterTest
868*1b3f573fSAndroid Build Coastguard Worker             var parser = new JsonParser(new JsonParser.Settings(10, registry));
869*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(original, parser.Parse<Any>(json));
870*1b3f573fSAndroid Build Coastguard Worker             string valueFirstJson = "{ \"value\": \"1673-06-19T12:34:56Z\", \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\" }";
871*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(original, parser.Parse<Any>(valueFirstJson));
872*1b3f573fSAndroid Build Coastguard Worker         }
873*1b3f573fSAndroid Build Coastguard Worker 
874*1b3f573fSAndroid Build Coastguard Worker         [Test]
Any_Nested()875*1b3f573fSAndroid Build Coastguard Worker         public void Any_Nested()
876*1b3f573fSAndroid Build Coastguard Worker         {
877*1b3f573fSAndroid Build Coastguard Worker             var registry = TypeRegistry.FromMessages(TestWellKnownTypes.Descriptor, TestAllTypes.Descriptor);
878*1b3f573fSAndroid Build Coastguard Worker             var formatter = new JsonFormatter(new JsonFormatter.Settings(false, registry));
879*1b3f573fSAndroid Build Coastguard Worker             var parser = new JsonParser(new JsonParser.Settings(10, registry));
880*1b3f573fSAndroid Build Coastguard Worker             var doubleNestedMessage = new TestAllTypes { SingleInt32 = 20 };
881*1b3f573fSAndroid Build Coastguard Worker             var nestedMessage = Any.Pack(doubleNestedMessage);
882*1b3f573fSAndroid Build Coastguard Worker             var message = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) };
883*1b3f573fSAndroid Build Coastguard Worker             var json = formatter.Format(message);
884*1b3f573fSAndroid Build Coastguard Worker             // Use the descriptor-based parser just for a change.
885*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(message, parser.Parse(json, TestWellKnownTypes.Descriptor));
886*1b3f573fSAndroid Build Coastguard Worker         }
887*1b3f573fSAndroid Build Coastguard Worker 
888*1b3f573fSAndroid Build Coastguard Worker         [Test]
DataAfterObject()889*1b3f573fSAndroid Build Coastguard Worker         public void DataAfterObject()
890*1b3f573fSAndroid Build Coastguard Worker         {
891*1b3f573fSAndroid Build Coastguard Worker             string json = "{} 10";
892*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidJsonException>(() => TestAllTypes.Parser.ParseJson(json));
893*1b3f573fSAndroid Build Coastguard Worker         }
894*1b3f573fSAndroid Build Coastguard Worker 
895*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
896*1b3f573fSAndroid Build Coastguard Worker         /// JSON equivalent to <see cref="CodedInputStreamTest.MaliciousRecursion"/>
897*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
898*1b3f573fSAndroid Build Coastguard Worker         [Test]
MaliciousRecursion()899*1b3f573fSAndroid Build Coastguard Worker         public void MaliciousRecursion()
900*1b3f573fSAndroid Build Coastguard Worker         {
901*1b3f573fSAndroid Build Coastguard Worker             string data64 = CodedInputStreamTest.MakeRecursiveMessage(64).ToString();
902*1b3f573fSAndroid Build Coastguard Worker             string data65 = CodedInputStreamTest.MakeRecursiveMessage(65).ToString();
903*1b3f573fSAndroid Build Coastguard Worker 
904*1b3f573fSAndroid Build Coastguard Worker             var parser64 = new JsonParser(new JsonParser.Settings(64));
905*1b3f573fSAndroid Build Coastguard Worker             CodedInputStreamTest.AssertMessageDepth(parser64.Parse<TestRecursiveMessage>(data64), 64);
906*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => parser64.Parse<TestRecursiveMessage>(data65));
907*1b3f573fSAndroid Build Coastguard Worker 
908*1b3f573fSAndroid Build Coastguard Worker             var parser63 = new JsonParser(new JsonParser.Settings(63));
909*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => parser63.Parse<TestRecursiveMessage>(data64));
910*1b3f573fSAndroid Build Coastguard Worker         }
911*1b3f573fSAndroid Build Coastguard Worker 
912*1b3f573fSAndroid Build Coastguard Worker         [Test]
913*1b3f573fSAndroid Build Coastguard Worker         [TestCase("AQI")]
914*1b3f573fSAndroid Build Coastguard Worker         [TestCase("_-==")]
Bytes_InvalidBase64(string badBase64)915*1b3f573fSAndroid Build Coastguard Worker         public void Bytes_InvalidBase64(string badBase64)
916*1b3f573fSAndroid Build Coastguard Worker         {
917*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleBytes\": \"" + badBase64 + "\" }";
918*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
919*1b3f573fSAndroid Build Coastguard Worker         }
920*1b3f573fSAndroid Build Coastguard Worker 
921*1b3f573fSAndroid Build Coastguard Worker         [Test]
922*1b3f573fSAndroid Build Coastguard Worker         [TestCase("\"FOREIGN_BAR\"", TestProtos.ForeignEnum.ForeignBar)]
923*1b3f573fSAndroid Build Coastguard Worker         [TestCase("5", TestProtos.ForeignEnum.ForeignBar)]
924*1b3f573fSAndroid Build Coastguard Worker         [TestCase("100", (TestProtos.ForeignEnum)100)]
EnumValid(string value, TestProtos.ForeignEnum expectedValue)925*1b3f573fSAndroid Build Coastguard Worker         public void EnumValid(string value, TestProtos.ForeignEnum expectedValue)
926*1b3f573fSAndroid Build Coastguard Worker         {
927*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleForeignEnum\": " + value + " }";
928*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypes.Parser.ParseJson(json);
929*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(new TestAllTypes { SingleForeignEnum = expectedValue }, parsed);
930*1b3f573fSAndroid Build Coastguard Worker         }
931*1b3f573fSAndroid Build Coastguard Worker 
932*1b3f573fSAndroid Build Coastguard Worker         [Test]
933*1b3f573fSAndroid Build Coastguard Worker         [TestCase("\"NOT_A_VALID_VALUE\"")]
934*1b3f573fSAndroid Build Coastguard Worker         [TestCase("5.5")]
Enum_Invalid(string value)935*1b3f573fSAndroid Build Coastguard Worker         public void Enum_Invalid(string value)
936*1b3f573fSAndroid Build Coastguard Worker         {
937*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"singleForeignEnum\": " + value + " }";
938*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
939*1b3f573fSAndroid Build Coastguard Worker         }
940*1b3f573fSAndroid Build Coastguard Worker 
941*1b3f573fSAndroid Build Coastguard Worker         [Test]
OneofDuplicate_Invalid()942*1b3f573fSAndroid Build Coastguard Worker         public void OneofDuplicate_Invalid()
943*1b3f573fSAndroid Build Coastguard Worker         {
944*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"oneofString\": \"x\", \"oneofUint32\": 10 }";
945*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
946*1b3f573fSAndroid Build Coastguard Worker         }
947*1b3f573fSAndroid Build Coastguard Worker 
948*1b3f573fSAndroid Build Coastguard Worker         [Test]
UnknownField_NotIgnored()949*1b3f573fSAndroid Build Coastguard Worker         public void UnknownField_NotIgnored()
950*1b3f573fSAndroid Build Coastguard Worker         {
951*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"unknownField\": 10, \"singleString\": \"x\" }";
952*1b3f573fSAndroid Build Coastguard Worker             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
953*1b3f573fSAndroid Build Coastguard Worker         }
954*1b3f573fSAndroid Build Coastguard Worker 
955*1b3f573fSAndroid Build Coastguard Worker         [Test]
Proto2_DefaultValuesPreserved()956*1b3f573fSAndroid Build Coastguard Worker         public void Proto2_DefaultValuesPreserved()
957*1b3f573fSAndroid Build Coastguard Worker         {
958*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"FieldName13\": 0 }";
959*1b3f573fSAndroid Build Coastguard Worker             var parsed = TestAllTypesProto2.Parser.ParseJson(json);
960*1b3f573fSAndroid Build Coastguard Worker             Assert.False(parsed.HasFieldName10);
961*1b3f573fSAndroid Build Coastguard Worker             Assert.True(parsed.HasFieldName13);
962*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, parsed.FieldName13);
963*1b3f573fSAndroid Build Coastguard Worker         }
964*1b3f573fSAndroid Build Coastguard Worker 
965*1b3f573fSAndroid Build Coastguard Worker         [Test]
966*1b3f573fSAndroid Build Coastguard Worker         [TestCase("5")]
967*1b3f573fSAndroid Build Coastguard Worker         [TestCase("\"text\"")]
968*1b3f573fSAndroid Build Coastguard Worker         [TestCase("[0, 1, 2]")]
969*1b3f573fSAndroid Build Coastguard Worker         [TestCase("{ \"a\": { \"b\": 10 } }")]
UnknownField_Ignored(string value)970*1b3f573fSAndroid Build Coastguard Worker         public void UnknownField_Ignored(string value)
971*1b3f573fSAndroid Build Coastguard Worker         {
972*1b3f573fSAndroid Build Coastguard Worker             var parser = new JsonParser(JsonParser.Settings.Default.WithIgnoreUnknownFields(true));
973*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"unknownField\": " + value + ", \"singleString\": \"x\" }";
974*1b3f573fSAndroid Build Coastguard Worker             var actual = parser.Parse<TestAllTypes>(json);
975*1b3f573fSAndroid Build Coastguard Worker             var expected = new TestAllTypes { SingleString = "x" };
976*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(expected, actual);
977*1b3f573fSAndroid Build Coastguard Worker         }
978*1b3f573fSAndroid Build Coastguard Worker 
979*1b3f573fSAndroid Build Coastguard Worker         [Test]
NullValueOutsideStruct_NullLiteral()980*1b3f573fSAndroid Build Coastguard Worker         public void NullValueOutsideStruct_NullLiteral()
981*1b3f573fSAndroid Build Coastguard Worker         {
982*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"nullValue\": null }";
983*1b3f573fSAndroid Build Coastguard Worker             var message = NullValueOutsideStruct.Parser.ParseJson(json);
984*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(NullValueOutsideStruct.ValueOneofCase.NullValue, message.ValueCase);
985*1b3f573fSAndroid Build Coastguard Worker         }
986*1b3f573fSAndroid Build Coastguard Worker 
987*1b3f573fSAndroid Build Coastguard Worker         [Test]
NullValueNotInOneof_NullLiteral()988*1b3f573fSAndroid Build Coastguard Worker         public void NullValueNotInOneof_NullLiteral()
989*1b3f573fSAndroid Build Coastguard Worker         {
990*1b3f573fSAndroid Build Coastguard Worker             // We'd only normally see this with FormatDefaultValues set to true.
991*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"nullValue\": null }";
992*1b3f573fSAndroid Build Coastguard Worker             var message = NullValueNotInOneof.Parser.ParseJson(json);
993*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(NullValue.NullValue, message.NullValue);
994*1b3f573fSAndroid Build Coastguard Worker         }
995*1b3f573fSAndroid Build Coastguard Worker 
996*1b3f573fSAndroid Build Coastguard Worker         // NullValue used to only be converted to the null literal when part of a struct.
997*1b3f573fSAndroid Build Coastguard Worker         // Otherwise, it would end up as a string "NULL_VALUE" (the name of the enum value).
998*1b3f573fSAndroid Build Coastguard Worker         // We still parse that form, for compatibility.
999*1b3f573fSAndroid Build Coastguard Worker         [Test]
NullValueOutsideStruct_Compatibility()1000*1b3f573fSAndroid Build Coastguard Worker         public void NullValueOutsideStruct_Compatibility()
1001*1b3f573fSAndroid Build Coastguard Worker         {
1002*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"nullValue\": \"NULL_VALUE\" }";
1003*1b3f573fSAndroid Build Coastguard Worker             var message = NullValueOutsideStruct.Parser.ParseJson(json);
1004*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(NullValueOutsideStruct.ValueOneofCase.NullValue, message.ValueCase);
1005*1b3f573fSAndroid Build Coastguard Worker         }
1006*1b3f573fSAndroid Build Coastguard Worker 
1007*1b3f573fSAndroid Build Coastguard Worker         [Test]
NullValueNotInOneof_Compatibility()1008*1b3f573fSAndroid Build Coastguard Worker         public void NullValueNotInOneof_Compatibility()
1009*1b3f573fSAndroid Build Coastguard Worker         {
1010*1b3f573fSAndroid Build Coastguard Worker             // We'd only normally see this with FormatDefaultValues set to true.
1011*1b3f573fSAndroid Build Coastguard Worker             string json = "{ \"nullValue\": \"NULL_VALUE\" }";
1012*1b3f573fSAndroid Build Coastguard Worker             var message = NullValueNotInOneof.Parser.ParseJson(json);
1013*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(NullValue.NullValue, message.NullValue);
1014*1b3f573fSAndroid Build Coastguard Worker         }
1015*1b3f573fSAndroid Build Coastguard Worker 
1016*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
1017*1b3f573fSAndroid Build Coastguard Worker         /// Various tests use strings which have quotes round them for parsing or as the result
1018*1b3f573fSAndroid Build Coastguard Worker         /// of formatting, but without those quotes being specified in the tests (for the sake of readability).
1019*1b3f573fSAndroid Build Coastguard Worker         /// This method simply returns the input, wrapped in double quotes.
1020*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
WrapInQuotes(string text)1021*1b3f573fSAndroid Build Coastguard Worker         internal static string WrapInQuotes(string text)
1022*1b3f573fSAndroid Build Coastguard Worker         {
1023*1b3f573fSAndroid Build Coastguard Worker             return '"' + text + '"';
1024*1b3f573fSAndroid Build Coastguard Worker         }
1025*1b3f573fSAndroid Build Coastguard Worker 
1026*1b3f573fSAndroid Build Coastguard Worker         [Test]
ParseAllNullValues()1027*1b3f573fSAndroid Build Coastguard Worker         public void ParseAllNullValues()
1028*1b3f573fSAndroid Build Coastguard Worker         {
1029*1b3f573fSAndroid Build Coastguard Worker             string json = @"{
1030*1b3f573fSAndroid Build Coastguard Worker   ""optionalInt32"": null,
1031*1b3f573fSAndroid Build Coastguard Worker   ""optionalInt64"": null,
1032*1b3f573fSAndroid Build Coastguard Worker   ""optionalUint32"": null,
1033*1b3f573fSAndroid Build Coastguard Worker   ""optionalUint64"": null,
1034*1b3f573fSAndroid Build Coastguard Worker   ""optionalSint32"": null,
1035*1b3f573fSAndroid Build Coastguard Worker   ""optionalSint64"": null,
1036*1b3f573fSAndroid Build Coastguard Worker   ""optionalFixed32"": null,
1037*1b3f573fSAndroid Build Coastguard Worker   ""optionalFixed64"": null,
1038*1b3f573fSAndroid Build Coastguard Worker   ""optionalSfixed32"": null,
1039*1b3f573fSAndroid Build Coastguard Worker   ""optionalSfixed64"": null,
1040*1b3f573fSAndroid Build Coastguard Worker   ""optionalFloat"": null,
1041*1b3f573fSAndroid Build Coastguard Worker   ""optionalDouble"": null,
1042*1b3f573fSAndroid Build Coastguard Worker   ""optionalBool"": null,
1043*1b3f573fSAndroid Build Coastguard Worker   ""optionalString"": null,
1044*1b3f573fSAndroid Build Coastguard Worker   ""optionalBytes"": null,
1045*1b3f573fSAndroid Build Coastguard Worker   ""optionalNestedEnum"": null,
1046*1b3f573fSAndroid Build Coastguard Worker   ""optionalNestedMessage"": null,
1047*1b3f573fSAndroid Build Coastguard Worker   ""repeatedInt32"": null,
1048*1b3f573fSAndroid Build Coastguard Worker   ""repeatedInt64"": null,
1049*1b3f573fSAndroid Build Coastguard Worker   ""repeatedUint32"": null,
1050*1b3f573fSAndroid Build Coastguard Worker   ""repeatedUint64"": null,
1051*1b3f573fSAndroid Build Coastguard Worker   ""repeatedSint32"": null,
1052*1b3f573fSAndroid Build Coastguard Worker   ""repeatedSint64"": null,
1053*1b3f573fSAndroid Build Coastguard Worker   ""repeatedFixed32"": null,
1054*1b3f573fSAndroid Build Coastguard Worker   ""repeatedFixed64"": null,
1055*1b3f573fSAndroid Build Coastguard Worker   ""repeatedSfixed32"": null,
1056*1b3f573fSAndroid Build Coastguard Worker   ""repeatedSfixed64"": null,
1057*1b3f573fSAndroid Build Coastguard Worker   ""repeatedFloat"": null,
1058*1b3f573fSAndroid Build Coastguard Worker   ""repeatedDouble"": null,
1059*1b3f573fSAndroid Build Coastguard Worker   ""repeatedBool"": null,
1060*1b3f573fSAndroid Build Coastguard Worker   ""repeatedString"": null,
1061*1b3f573fSAndroid Build Coastguard Worker   ""repeatedBytes"": null,
1062*1b3f573fSAndroid Build Coastguard Worker   ""repeatedNestedEnum"": null,
1063*1b3f573fSAndroid Build Coastguard Worker   ""repeatedNestedMessage"": null,
1064*1b3f573fSAndroid Build Coastguard Worker   ""mapInt32Int32"": null,
1065*1b3f573fSAndroid Build Coastguard Worker   ""mapBoolBool"": null,
1066*1b3f573fSAndroid Build Coastguard Worker   ""mapStringNestedMessage"": null
1067*1b3f573fSAndroid Build Coastguard Worker }";
1068*1b3f573fSAndroid Build Coastguard Worker 
1069*1b3f573fSAndroid Build Coastguard Worker             TestAllTypesProto3 message = new TestAllTypesProto3();
1070*1b3f573fSAndroid Build Coastguard Worker 
1071*1b3f573fSAndroid Build Coastguard Worker             message.OptionalInt32 = 1;
1072*1b3f573fSAndroid Build Coastguard Worker             message.OptionalInt64 = 1;
1073*1b3f573fSAndroid Build Coastguard Worker             message.OptionalUint32 = 1;
1074*1b3f573fSAndroid Build Coastguard Worker             message.OptionalUint64 = 1;
1075*1b3f573fSAndroid Build Coastguard Worker             message.OptionalSint32 = 1;
1076*1b3f573fSAndroid Build Coastguard Worker             message.OptionalSint64 = 1;
1077*1b3f573fSAndroid Build Coastguard Worker             message.OptionalFixed32 = 1;
1078*1b3f573fSAndroid Build Coastguard Worker             message.OptionalFixed64 = 1;
1079*1b3f573fSAndroid Build Coastguard Worker             message.OptionalSfixed32 = 1;
1080*1b3f573fSAndroid Build Coastguard Worker             message.OptionalSfixed64 = 1;
1081*1b3f573fSAndroid Build Coastguard Worker             message.OptionalFloat = 1;
1082*1b3f573fSAndroid Build Coastguard Worker             message.OptionalDouble = 1;
1083*1b3f573fSAndroid Build Coastguard Worker             message.OptionalBool = true;
1084*1b3f573fSAndroid Build Coastguard Worker             message.OptionalString = "1";
1085*1b3f573fSAndroid Build Coastguard Worker             message.OptionalBytes = ByteString.CopyFrom(new byte[] { 1 });
1086*1b3f573fSAndroid Build Coastguard Worker             message.OptionalNestedEnum = TestAllTypesProto3.Types.NestedEnum.Bar;
1087*1b3f573fSAndroid Build Coastguard Worker             message.OptionalNestedMessage = new TestAllTypesProto3.Types.NestedMessage();
1088*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedInt32.Add(1);
1089*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedInt64.Add(1);
1090*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedUint32.Add(1);
1091*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedUint64.Add(1);
1092*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedSint32.Add(1);
1093*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedSint64.Add(1);
1094*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedFixed32.Add(1);
1095*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedFixed64.Add(1);
1096*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedSfixed32.Add(1);
1097*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedSfixed64.Add(1);
1098*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedFloat.Add(1);
1099*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedDouble.Add(1);
1100*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedBool.Add(true);
1101*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedString.Add("1");
1102*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedBytes.Add(ByteString.CopyFrom(new byte[] { 1 }));
1103*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedNestedEnum.Add(TestAllTypesProto3.Types.NestedEnum.Bar);
1104*1b3f573fSAndroid Build Coastguard Worker             message.RepeatedNestedMessage.Add(new TestAllTypesProto3.Types.NestedMessage());
1105*1b3f573fSAndroid Build Coastguard Worker             message.MapInt32Int32.Add(1, 1);
1106*1b3f573fSAndroid Build Coastguard Worker             message.MapBoolBool.Add(true, true);
1107*1b3f573fSAndroid Build Coastguard Worker             message.MapStringNestedMessage.Add(" ", new TestAllTypesProto3.Types.NestedMessage());
1108*1b3f573fSAndroid Build Coastguard Worker 
1109*1b3f573fSAndroid Build Coastguard Worker             JsonParser.Default.Merge(message, json);
1110*1b3f573fSAndroid Build Coastguard Worker 
1111*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalInt32);
1112*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalInt64);
1113*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalUint32);
1114*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalUint64);
1115*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalSint32);
1116*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalSint64);
1117*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalFixed32);
1118*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalFixed64);
1119*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalSfixed32);
1120*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalSfixed64);
1121*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalFloat);
1122*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.OptionalDouble);
1123*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(false, message.OptionalBool);
1124*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual("", message.OptionalString);
1125*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(ByteString.Empty, message.OptionalBytes);
1126*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(TestAllTypesProto3.Types.NestedEnum.Foo, message.OptionalNestedEnum);
1127*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(null, message.OptionalNestedMessage);
1128*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedInt32.Count);
1129*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedInt64.Count);
1130*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedUint32.Count);
1131*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedUint64.Count);
1132*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedSint32.Count);
1133*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedSint64.Count);
1134*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedFixed32.Count);
1135*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedFixed64.Count);
1136*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedSfixed32.Count);
1137*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedFloat.Count);
1138*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedDouble.Count);
1139*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedBool.Count);
1140*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedString.Count);
1141*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedBytes.Count);
1142*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedNestedEnum.Count);
1143*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.RepeatedNestedMessage.Count);
1144*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.MapInt32Int32.Count);
1145*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.MapBoolBool.Count);
1146*1b3f573fSAndroid Build Coastguard Worker             Assert.AreEqual(0, message.MapStringNestedMessage.Count);
1147*1b3f573fSAndroid Build Coastguard Worker         }
1148*1b3f573fSAndroid Build Coastguard Worker     }
1149*1b3f573fSAndroid Build Coastguard Worker }