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