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 }