1ffe3c632Sopenharmony_ci#region Copyright notice and license 2ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format 3ffe3c632Sopenharmony_ci// Copyright 2008 Google Inc. All rights reserved. 4ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/ 5ffe3c632Sopenharmony_ci// 6ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 7ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are 8ffe3c632Sopenharmony_ci// met: 9ffe3c632Sopenharmony_ci// 10ffe3c632Sopenharmony_ci// * Redistributions of source code must retain the above copyright 11ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer. 12ffe3c632Sopenharmony_ci// * Redistributions in binary form must reproduce the above 13ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer 14ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the 15ffe3c632Sopenharmony_ci// distribution. 16ffe3c632Sopenharmony_ci// * Neither the name of Google Inc. nor the names of its 17ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from 18ffe3c632Sopenharmony_ci// this software without specific prior written permission. 19ffe3c632Sopenharmony_ci// 20ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31ffe3c632Sopenharmony_ci#endregion 32ffe3c632Sopenharmony_ci 33ffe3c632Sopenharmony_ciusing System; 34ffe3c632Sopenharmony_ciusing Google.Protobuf.TestProtos; 35ffe3c632Sopenharmony_ciusing NUnit.Framework; 36ffe3c632Sopenharmony_ciusing UnitTest.Issues.TestProtos; 37ffe3c632Sopenharmony_ciusing Google.Protobuf.WellKnownTypes; 38ffe3c632Sopenharmony_ciusing Google.Protobuf.Reflection; 39ffe3c632Sopenharmony_ci 40ffe3c632Sopenharmony_ciusing static Google.Protobuf.JsonParserTest; // For WrapInQuotes 41ffe3c632Sopenharmony_ciusing System.IO; 42ffe3c632Sopenharmony_ciusing Google.Protobuf.Collections; 43ffe3c632Sopenharmony_ciusing ProtobufUnittest; 44ffe3c632Sopenharmony_ci 45ffe3c632Sopenharmony_cinamespace Google.Protobuf 46ffe3c632Sopenharmony_ci{ 47ffe3c632Sopenharmony_ci /// <summary> 48ffe3c632Sopenharmony_ci /// Tests for the JSON formatter. Note that in these tests, double quotes are replaced with apostrophes 49ffe3c632Sopenharmony_ci /// for the sake of readability (embedding \" everywhere is painful). See the AssertJson method for details. 50ffe3c632Sopenharmony_ci /// </summary> 51ffe3c632Sopenharmony_ci public class JsonFormatterTest 52ffe3c632Sopenharmony_ci { 53ffe3c632Sopenharmony_ci [Test] 54ffe3c632Sopenharmony_ci public void DefaultValues_WhenOmitted() 55ffe3c632Sopenharmony_ci { 56ffe3c632Sopenharmony_ci var formatter = JsonFormatter.Default; 57ffe3c632Sopenharmony_ci 58ffe3c632Sopenharmony_ci AssertJson("{ }", formatter.Format(new ForeignMessage())); 59ffe3c632Sopenharmony_ci AssertJson("{ }", formatter.Format(new TestAllTypes())); 60ffe3c632Sopenharmony_ci AssertJson("{ }", formatter.Format(new TestMap())); 61ffe3c632Sopenharmony_ci } 62ffe3c632Sopenharmony_ci 63ffe3c632Sopenharmony_ci [Test] 64ffe3c632Sopenharmony_ci public void DefaultValues_WhenIncluded() 65ffe3c632Sopenharmony_ci { 66ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); 67ffe3c632Sopenharmony_ci AssertJson("{ 'c': 0 }", formatter.Format(new ForeignMessage())); 68ffe3c632Sopenharmony_ci } 69ffe3c632Sopenharmony_ci 70ffe3c632Sopenharmony_ci [Test] 71ffe3c632Sopenharmony_ci public void EnumAllowAlias() 72ffe3c632Sopenharmony_ci { 73ffe3c632Sopenharmony_ci var message = new TestEnumAllowAlias 74ffe3c632Sopenharmony_ci { 75ffe3c632Sopenharmony_ci Value = TestEnumWithDupValue.Foo2, 76ffe3c632Sopenharmony_ci }; 77ffe3c632Sopenharmony_ci var actualText = JsonFormatter.Default.Format(message); 78ffe3c632Sopenharmony_ci var expectedText = "{ 'value': 'FOO1' }"; 79ffe3c632Sopenharmony_ci AssertJson(expectedText, actualText); 80ffe3c632Sopenharmony_ci } 81ffe3c632Sopenharmony_ci 82ffe3c632Sopenharmony_ci [Test] 83ffe3c632Sopenharmony_ci public void EnumAsInt() 84ffe3c632Sopenharmony_ci { 85ffe3c632Sopenharmony_ci var message = new TestAllTypes 86ffe3c632Sopenharmony_ci { 87ffe3c632Sopenharmony_ci SingleForeignEnum = ForeignEnum.ForeignBar, 88ffe3c632Sopenharmony_ci RepeatedForeignEnum = { ForeignEnum.ForeignBaz, (ForeignEnum) 100, ForeignEnum.ForeignFoo } 89ffe3c632Sopenharmony_ci }; 90ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatEnumsAsIntegers(true)); 91ffe3c632Sopenharmony_ci var actualText = formatter.Format(message); 92ffe3c632Sopenharmony_ci var expectedText = "{ " + 93ffe3c632Sopenharmony_ci "'singleForeignEnum': 5, " + 94ffe3c632Sopenharmony_ci "'repeatedForeignEnum': [ 6, 100, 4 ]" + 95ffe3c632Sopenharmony_ci " }"; 96ffe3c632Sopenharmony_ci AssertJson(expectedText, actualText); 97ffe3c632Sopenharmony_ci } 98ffe3c632Sopenharmony_ci 99ffe3c632Sopenharmony_ci [Test] 100ffe3c632Sopenharmony_ci public void AllSingleFields() 101ffe3c632Sopenharmony_ci { 102ffe3c632Sopenharmony_ci var message = new TestAllTypes 103ffe3c632Sopenharmony_ci { 104ffe3c632Sopenharmony_ci SingleBool = true, 105ffe3c632Sopenharmony_ci SingleBytes = ByteString.CopyFrom(1, 2, 3, 4), 106ffe3c632Sopenharmony_ci SingleDouble = 23.5, 107ffe3c632Sopenharmony_ci SingleFixed32 = 23, 108ffe3c632Sopenharmony_ci SingleFixed64 = 1234567890123, 109ffe3c632Sopenharmony_ci SingleFloat = 12.25f, 110ffe3c632Sopenharmony_ci SingleForeignEnum = ForeignEnum.ForeignBar, 111ffe3c632Sopenharmony_ci SingleForeignMessage = new ForeignMessage { C = 10 }, 112ffe3c632Sopenharmony_ci SingleImportEnum = ImportEnum.ImportBaz, 113ffe3c632Sopenharmony_ci SingleImportMessage = new ImportMessage { D = 20 }, 114ffe3c632Sopenharmony_ci SingleInt32 = 100, 115ffe3c632Sopenharmony_ci SingleInt64 = 3210987654321, 116ffe3c632Sopenharmony_ci SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo, 117ffe3c632Sopenharmony_ci SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 }, 118ffe3c632Sopenharmony_ci SinglePublicImportMessage = new PublicImportMessage { E = 54 }, 119ffe3c632Sopenharmony_ci SingleSfixed32 = -123, 120ffe3c632Sopenharmony_ci SingleSfixed64 = -12345678901234, 121ffe3c632Sopenharmony_ci SingleSint32 = -456, 122ffe3c632Sopenharmony_ci SingleSint64 = -12345678901235, 123ffe3c632Sopenharmony_ci SingleString = "test\twith\ttabs", 124ffe3c632Sopenharmony_ci SingleUint32 = uint.MaxValue, 125ffe3c632Sopenharmony_ci SingleUint64 = ulong.MaxValue, 126ffe3c632Sopenharmony_ci }; 127ffe3c632Sopenharmony_ci var actualText = JsonFormatter.Default.Format(message); 128ffe3c632Sopenharmony_ci 129ffe3c632Sopenharmony_ci // Fields in numeric order 130ffe3c632Sopenharmony_ci var expectedText = "{ " + 131ffe3c632Sopenharmony_ci "'singleInt32': 100, " + 132ffe3c632Sopenharmony_ci "'singleInt64': '3210987654321', " + 133ffe3c632Sopenharmony_ci "'singleUint32': 4294967295, " + 134ffe3c632Sopenharmony_ci "'singleUint64': '18446744073709551615', " + 135ffe3c632Sopenharmony_ci "'singleSint32': -456, " + 136ffe3c632Sopenharmony_ci "'singleSint64': '-12345678901235', " + 137ffe3c632Sopenharmony_ci "'singleFixed32': 23, " + 138ffe3c632Sopenharmony_ci "'singleFixed64': '1234567890123', " + 139ffe3c632Sopenharmony_ci "'singleSfixed32': -123, " + 140ffe3c632Sopenharmony_ci "'singleSfixed64': '-12345678901234', " + 141ffe3c632Sopenharmony_ci "'singleFloat': 12.25, " + 142ffe3c632Sopenharmony_ci "'singleDouble': 23.5, " + 143ffe3c632Sopenharmony_ci "'singleBool': true, " + 144ffe3c632Sopenharmony_ci "'singleString': 'test\\twith\\ttabs', " + 145ffe3c632Sopenharmony_ci "'singleBytes': 'AQIDBA==', " + 146ffe3c632Sopenharmony_ci "'singleNestedMessage': { 'bb': 35 }, " + 147ffe3c632Sopenharmony_ci "'singleForeignMessage': { 'c': 10 }, " + 148ffe3c632Sopenharmony_ci "'singleImportMessage': { 'd': 20 }, " + 149ffe3c632Sopenharmony_ci "'singleNestedEnum': 'FOO', " + 150ffe3c632Sopenharmony_ci "'singleForeignEnum': 'FOREIGN_BAR', " + 151ffe3c632Sopenharmony_ci "'singleImportEnum': 'IMPORT_BAZ', " + 152ffe3c632Sopenharmony_ci "'singlePublicImportMessage': { 'e': 54 }" + 153ffe3c632Sopenharmony_ci " }"; 154ffe3c632Sopenharmony_ci AssertJson(expectedText, actualText); 155ffe3c632Sopenharmony_ci } 156ffe3c632Sopenharmony_ci 157ffe3c632Sopenharmony_ci [Test] 158ffe3c632Sopenharmony_ci public void WithFormatDefaultValues_DoesNotAffectMessageFields() 159ffe3c632Sopenharmony_ci { 160ffe3c632Sopenharmony_ci var message = new TestAllTypes(); 161ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); 162ffe3c632Sopenharmony_ci var json = formatter.Format(message); 163ffe3c632Sopenharmony_ci Assert.IsFalse(json.Contains("\"singleNestedMessage\"")); 164ffe3c632Sopenharmony_ci Assert.IsFalse(json.Contains("\"singleForeignMessage\"")); 165ffe3c632Sopenharmony_ci Assert.IsFalse(json.Contains("\"singleImportMessage\"")); 166ffe3c632Sopenharmony_ci } 167ffe3c632Sopenharmony_ci 168ffe3c632Sopenharmony_ci [Test] 169ffe3c632Sopenharmony_ci public void WithFormatDefaultValues_DoesNotAffectProto3OptionalFields() 170ffe3c632Sopenharmony_ci { 171ffe3c632Sopenharmony_ci var message = new TestProto3Optional(); 172ffe3c632Sopenharmony_ci message.OptionalInt32 = 0; 173ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); 174ffe3c632Sopenharmony_ci var json = formatter.Format(message); 175ffe3c632Sopenharmony_ci // The non-optional proto3 fields are formatted, as is the optional-but-specified field. 176ffe3c632Sopenharmony_ci AssertJson("{ 'optionalInt32': 0, 'singularInt32': 0, 'singularInt64': '0' }", json); 177ffe3c632Sopenharmony_ci } 178ffe3c632Sopenharmony_ci 179ffe3c632Sopenharmony_ci [Test] 180ffe3c632Sopenharmony_ci public void WithFormatDefaultValues_DoesNotAffectProto2Fields() 181ffe3c632Sopenharmony_ci { 182ffe3c632Sopenharmony_ci var message = new TestProtos.Proto2.ForeignMessage(); 183ffe3c632Sopenharmony_ci message.C = 0; 184ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); 185ffe3c632Sopenharmony_ci var json = formatter.Format(message); 186ffe3c632Sopenharmony_ci // The specified field is formatted, but the non-specified field (d) is not. 187ffe3c632Sopenharmony_ci AssertJson("{ 'c': 0 }", json); 188ffe3c632Sopenharmony_ci } 189ffe3c632Sopenharmony_ci 190ffe3c632Sopenharmony_ci [Test] 191ffe3c632Sopenharmony_ci public void WithFormatDefaultValues_DoesNotAffectOneofFields() 192ffe3c632Sopenharmony_ci { 193ffe3c632Sopenharmony_ci var message = new TestOneof(); 194ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); 195ffe3c632Sopenharmony_ci var json = formatter.Format(message); 196ffe3c632Sopenharmony_ci AssertJson("{ }", json); 197ffe3c632Sopenharmony_ci } 198ffe3c632Sopenharmony_ci 199ffe3c632Sopenharmony_ci [Test] 200ffe3c632Sopenharmony_ci public void RepeatedField() 201ffe3c632Sopenharmony_ci { 202ffe3c632Sopenharmony_ci AssertJson("{ 'repeatedInt32': [ 1, 2, 3, 4, 5 ] }", 203ffe3c632Sopenharmony_ci JsonFormatter.Default.Format(new TestAllTypes { RepeatedInt32 = { 1, 2, 3, 4, 5 } })); 204ffe3c632Sopenharmony_ci } 205ffe3c632Sopenharmony_ci 206ffe3c632Sopenharmony_ci [Test] 207ffe3c632Sopenharmony_ci public void MapField_StringString() 208ffe3c632Sopenharmony_ci { 209ffe3c632Sopenharmony_ci AssertJson("{ 'mapStringString': { 'with spaces': 'bar', 'a': 'b' } }", 210ffe3c632Sopenharmony_ci JsonFormatter.Default.Format(new TestMap { MapStringString = { { "with spaces", "bar" }, { "a", "b" } } })); 211ffe3c632Sopenharmony_ci } 212ffe3c632Sopenharmony_ci 213ffe3c632Sopenharmony_ci [Test] 214ffe3c632Sopenharmony_ci public void MapField_Int32Int32() 215ffe3c632Sopenharmony_ci { 216ffe3c632Sopenharmony_ci // The keys are quoted, but the values aren't. 217ffe3c632Sopenharmony_ci AssertJson("{ 'mapInt32Int32': { '0': 1, '2': 3 } }", 218ffe3c632Sopenharmony_ci JsonFormatter.Default.Format(new TestMap { MapInt32Int32 = { { 0, 1 }, { 2, 3 } } })); 219ffe3c632Sopenharmony_ci } 220ffe3c632Sopenharmony_ci 221ffe3c632Sopenharmony_ci [Test] 222ffe3c632Sopenharmony_ci public void MapField_BoolBool() 223ffe3c632Sopenharmony_ci { 224ffe3c632Sopenharmony_ci // The keys are quoted, but the values aren't. 225ffe3c632Sopenharmony_ci AssertJson("{ 'mapBoolBool': { 'false': true, 'true': false } }", 226ffe3c632Sopenharmony_ci JsonFormatter.Default.Format(new TestMap { MapBoolBool = { { false, true }, { true, false } } })); 227ffe3c632Sopenharmony_ci } 228ffe3c632Sopenharmony_ci 229ffe3c632Sopenharmony_ci [Test] 230ffe3c632Sopenharmony_ci public void NullValueOutsideStruct() 231ffe3c632Sopenharmony_ci { 232ffe3c632Sopenharmony_ci var message = new NullValueOutsideStruct { NullValue = NullValue.NullValue }; 233ffe3c632Sopenharmony_ci AssertJson("{ 'nullValue': null }", JsonFormatter.Default.Format(message)); 234ffe3c632Sopenharmony_ci } 235ffe3c632Sopenharmony_ci 236ffe3c632Sopenharmony_ci [Test] 237ffe3c632Sopenharmony_ci public void NullValueNotInOneof() 238ffe3c632Sopenharmony_ci { 239ffe3c632Sopenharmony_ci var message = new NullValueNotInOneof(); 240ffe3c632Sopenharmony_ci AssertJson("{ }", JsonFormatter.Default.Format(message)); 241ffe3c632Sopenharmony_ci } 242ffe3c632Sopenharmony_ci 243ffe3c632Sopenharmony_ci [Test] 244ffe3c632Sopenharmony_ci public void NullValueNotInOneof_FormatDefaults() 245ffe3c632Sopenharmony_ci { 246ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); 247ffe3c632Sopenharmony_ci var message = new NullValueNotInOneof(); 248ffe3c632Sopenharmony_ci AssertJson("{ 'nullValue': null }", formatter.Format(message)); 249ffe3c632Sopenharmony_ci } 250ffe3c632Sopenharmony_ci 251ffe3c632Sopenharmony_ci [TestCase(1.0, "1")] 252ffe3c632Sopenharmony_ci [TestCase(double.NaN, "'NaN'")] 253ffe3c632Sopenharmony_ci [TestCase(double.PositiveInfinity, "'Infinity'")] 254ffe3c632Sopenharmony_ci [TestCase(double.NegativeInfinity, "'-Infinity'")] 255ffe3c632Sopenharmony_ci public void DoubleRepresentations(double value, string expectedValueText) 256ffe3c632Sopenharmony_ci { 257ffe3c632Sopenharmony_ci var message = new TestAllTypes { SingleDouble = value }; 258ffe3c632Sopenharmony_ci string actualText = JsonFormatter.Default.Format(message); 259ffe3c632Sopenharmony_ci string expectedText = "{ 'singleDouble': " + expectedValueText + " }"; 260ffe3c632Sopenharmony_ci AssertJson(expectedText, actualText); 261ffe3c632Sopenharmony_ci } 262ffe3c632Sopenharmony_ci 263ffe3c632Sopenharmony_ci [Test] 264ffe3c632Sopenharmony_ci public void UnknownEnumValueNumeric_SingleField() 265ffe3c632Sopenharmony_ci { 266ffe3c632Sopenharmony_ci var message = new TestAllTypes { SingleForeignEnum = (ForeignEnum) 100 }; 267ffe3c632Sopenharmony_ci AssertJson("{ 'singleForeignEnum': 100 }", JsonFormatter.Default.Format(message)); 268ffe3c632Sopenharmony_ci } 269ffe3c632Sopenharmony_ci 270ffe3c632Sopenharmony_ci [Test] 271ffe3c632Sopenharmony_ci public void UnknownEnumValueNumeric_RepeatedField() 272ffe3c632Sopenharmony_ci { 273ffe3c632Sopenharmony_ci var message = new TestAllTypes { RepeatedForeignEnum = { ForeignEnum.ForeignBaz, (ForeignEnum) 100, ForeignEnum.ForeignFoo } }; 274ffe3c632Sopenharmony_ci AssertJson("{ 'repeatedForeignEnum': [ 'FOREIGN_BAZ', 100, 'FOREIGN_FOO' ] }", JsonFormatter.Default.Format(message)); 275ffe3c632Sopenharmony_ci } 276ffe3c632Sopenharmony_ci 277ffe3c632Sopenharmony_ci [Test] 278ffe3c632Sopenharmony_ci public void UnknownEnumValueNumeric_MapField() 279ffe3c632Sopenharmony_ci { 280ffe3c632Sopenharmony_ci var message = new TestMap { MapInt32Enum = { { 1, MapEnum.Foo }, { 2, (MapEnum) 100 }, { 3, MapEnum.Bar } } }; 281ffe3c632Sopenharmony_ci AssertJson("{ 'mapInt32Enum': { '1': 'MAP_ENUM_FOO', '2': 100, '3': 'MAP_ENUM_BAR' } }", JsonFormatter.Default.Format(message)); 282ffe3c632Sopenharmony_ci } 283ffe3c632Sopenharmony_ci 284ffe3c632Sopenharmony_ci [Test] 285ffe3c632Sopenharmony_ci public void UnknownEnumValue_RepeatedField_AllEntriesUnknown() 286ffe3c632Sopenharmony_ci { 287ffe3c632Sopenharmony_ci var message = new TestAllTypes { RepeatedForeignEnum = { (ForeignEnum) 200, (ForeignEnum) 100 } }; 288ffe3c632Sopenharmony_ci AssertJson("{ 'repeatedForeignEnum': [ 200, 100 ] }", JsonFormatter.Default.Format(message)); 289ffe3c632Sopenharmony_ci } 290ffe3c632Sopenharmony_ci 291ffe3c632Sopenharmony_ci [Test] 292ffe3c632Sopenharmony_ci [TestCase("a\u17b4b", "a\\u17b4b")] // Explicit 293ffe3c632Sopenharmony_ci [TestCase("a\u0601b", "a\\u0601b")] // Ranged 294ffe3c632Sopenharmony_ci [TestCase("a\u0605b", "a\u0605b")] // Passthrough (note lack of double backslash...) 295ffe3c632Sopenharmony_ci public void SimpleNonAscii(string text, string encoded) 296ffe3c632Sopenharmony_ci { 297ffe3c632Sopenharmony_ci var message = new TestAllTypes { SingleString = text }; 298ffe3c632Sopenharmony_ci AssertJson("{ 'singleString': '" + encoded + "' }", JsonFormatter.Default.Format(message)); 299ffe3c632Sopenharmony_ci } 300ffe3c632Sopenharmony_ci 301ffe3c632Sopenharmony_ci [Test] 302ffe3c632Sopenharmony_ci public void SurrogatePairEscaping() 303ffe3c632Sopenharmony_ci { 304ffe3c632Sopenharmony_ci var message = new TestAllTypes { SingleString = "a\uD801\uDC01b" }; 305ffe3c632Sopenharmony_ci AssertJson("{ 'singleString': 'a\\ud801\\udc01b' }", JsonFormatter.Default.Format(message)); 306ffe3c632Sopenharmony_ci } 307ffe3c632Sopenharmony_ci 308ffe3c632Sopenharmony_ci [Test] 309ffe3c632Sopenharmony_ci public void InvalidSurrogatePairsFail() 310ffe3c632Sopenharmony_ci { 311ffe3c632Sopenharmony_ci // Note: don't use TestCase for these, as the strings can't be reliably represented 312ffe3c632Sopenharmony_ci // See http://codeblog.jonskeet.uk/2014/11/07/when-is-a-string-not-a-string/ 313ffe3c632Sopenharmony_ci 314ffe3c632Sopenharmony_ci // Lone low surrogate 315ffe3c632Sopenharmony_ci var message = new TestAllTypes { SingleString = "a\uDC01b" }; 316ffe3c632Sopenharmony_ci Assert.Throws<ArgumentException>(() => JsonFormatter.Default.Format(message)); 317ffe3c632Sopenharmony_ci 318ffe3c632Sopenharmony_ci // Lone high surrogate 319ffe3c632Sopenharmony_ci message = new TestAllTypes { SingleString = "a\uD801b" }; 320ffe3c632Sopenharmony_ci Assert.Throws<ArgumentException>(() => JsonFormatter.Default.Format(message)); 321ffe3c632Sopenharmony_ci } 322ffe3c632Sopenharmony_ci 323ffe3c632Sopenharmony_ci [Test] 324ffe3c632Sopenharmony_ci [TestCase("foo_bar", "fooBar")] 325ffe3c632Sopenharmony_ci [TestCase("bananaBanana", "bananaBanana")] 326ffe3c632Sopenharmony_ci [TestCase("BANANABanana", "BANANABanana")] 327ffe3c632Sopenharmony_ci [TestCase("simple", "simple")] 328ffe3c632Sopenharmony_ci [TestCase("ACTION_AND_ADVENTURE", "ACTIONANDADVENTURE")] 329ffe3c632Sopenharmony_ci [TestCase("action_and_adventure", "actionAndAdventure")] 330ffe3c632Sopenharmony_ci [TestCase("kFoo", "kFoo")] 331ffe3c632Sopenharmony_ci [TestCase("HTTPServer", "HTTPServer")] 332ffe3c632Sopenharmony_ci [TestCase("CLIENT", "CLIENT")] 333ffe3c632Sopenharmony_ci public void ToJsonName(string original, string expected) 334ffe3c632Sopenharmony_ci { 335ffe3c632Sopenharmony_ci Assert.AreEqual(expected, JsonFormatter.ToJsonName(original)); 336ffe3c632Sopenharmony_ci } 337ffe3c632Sopenharmony_ci 338ffe3c632Sopenharmony_ci [Test] 339ffe3c632Sopenharmony_ci [TestCase(null, "{ }")] 340ffe3c632Sopenharmony_ci [TestCase("x", "{ 'fooString': 'x' }")] 341ffe3c632Sopenharmony_ci [TestCase("", "{ 'fooString': '' }")] 342ffe3c632Sopenharmony_ci public void Oneof(string fooStringValue, string expectedJson) 343ffe3c632Sopenharmony_ci { 344ffe3c632Sopenharmony_ci var message = new TestOneof(); 345ffe3c632Sopenharmony_ci if (fooStringValue != null) 346ffe3c632Sopenharmony_ci { 347ffe3c632Sopenharmony_ci message.FooString = fooStringValue; 348ffe3c632Sopenharmony_ci } 349ffe3c632Sopenharmony_ci 350ffe3c632Sopenharmony_ci // We should get the same result both with and without "format default values". 351ffe3c632Sopenharmony_ci var formatter = JsonFormatter.Default; 352ffe3c632Sopenharmony_ci AssertJson(expectedJson, formatter.Format(message)); 353ffe3c632Sopenharmony_ci formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); 354ffe3c632Sopenharmony_ci AssertJson(expectedJson, formatter.Format(message)); 355ffe3c632Sopenharmony_ci } 356ffe3c632Sopenharmony_ci 357ffe3c632Sopenharmony_ci [Test] 358ffe3c632Sopenharmony_ci public void WrapperFormatting_Single() 359ffe3c632Sopenharmony_ci { 360ffe3c632Sopenharmony_ci // Just a few examples, handling both classes and value types, and 361ffe3c632Sopenharmony_ci // default vs non-default values 362ffe3c632Sopenharmony_ci var message = new TestWellKnownTypes 363ffe3c632Sopenharmony_ci { 364ffe3c632Sopenharmony_ci Int64Field = 10, 365ffe3c632Sopenharmony_ci Int32Field = 0, 366ffe3c632Sopenharmony_ci BytesField = ByteString.FromBase64("ABCD"), 367ffe3c632Sopenharmony_ci StringField = "" 368ffe3c632Sopenharmony_ci }; 369ffe3c632Sopenharmony_ci var expectedJson = "{ 'int64Field': '10', 'int32Field': 0, 'stringField': '', 'bytesField': 'ABCD' }"; 370ffe3c632Sopenharmony_ci AssertJson(expectedJson, JsonFormatter.Default.Format(message)); 371ffe3c632Sopenharmony_ci } 372ffe3c632Sopenharmony_ci 373ffe3c632Sopenharmony_ci [Test] 374ffe3c632Sopenharmony_ci public void WrapperFormatting_Message() 375ffe3c632Sopenharmony_ci { 376ffe3c632Sopenharmony_ci Assert.AreEqual("\"\"", JsonFormatter.Default.Format(new StringValue())); 377ffe3c632Sopenharmony_ci Assert.AreEqual("0", JsonFormatter.Default.Format(new Int32Value())); 378ffe3c632Sopenharmony_ci } 379ffe3c632Sopenharmony_ci 380ffe3c632Sopenharmony_ci [Test] 381ffe3c632Sopenharmony_ci public void WrapperFormatting_FormatDefaultValuesDoesNotFormatNull() 382ffe3c632Sopenharmony_ci { 383ffe3c632Sopenharmony_ci // The actual JSON here is very large because there are lots of fields. Just test a couple of them. 384ffe3c632Sopenharmony_ci var message = new TestWellKnownTypes { Int32Field = 10 }; 385ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); 386ffe3c632Sopenharmony_ci var actualJson = formatter.Format(message); 387ffe3c632Sopenharmony_ci // This *used* to include "int64Field": null, but that was a bug. 388ffe3c632Sopenharmony_ci // WithDefaultValues should not affect message fields, including wrapper types. 389ffe3c632Sopenharmony_ci Assert.IsFalse(actualJson.Contains("\"int64Field\": null")); 390ffe3c632Sopenharmony_ci Assert.IsTrue(actualJson.Contains("\"int32Field\": 10")); 391ffe3c632Sopenharmony_ci } 392ffe3c632Sopenharmony_ci 393ffe3c632Sopenharmony_ci [Test] 394ffe3c632Sopenharmony_ci public void OutputIsInNumericFieldOrder_NoDefaults() 395ffe3c632Sopenharmony_ci { 396ffe3c632Sopenharmony_ci var formatter = JsonFormatter.Default; 397ffe3c632Sopenharmony_ci var message = new TestJsonFieldOrdering { PlainString = "p1", PlainInt32 = 2 }; 398ffe3c632Sopenharmony_ci AssertJson("{ 'plainString': 'p1', 'plainInt32': 2 }", formatter.Format(message)); 399ffe3c632Sopenharmony_ci message = new TestJsonFieldOrdering { O1Int32 = 5, O2String = "o2", PlainInt32 = 10, PlainString = "plain" }; 400ffe3c632Sopenharmony_ci AssertJson("{ 'plainString': 'plain', 'o2String': 'o2', 'plainInt32': 10, 'o1Int32': 5 }", formatter.Format(message)); 401ffe3c632Sopenharmony_ci message = new TestJsonFieldOrdering { O1String = "", O2Int32 = 0, PlainInt32 = 10, PlainString = "plain" }; 402ffe3c632Sopenharmony_ci AssertJson("{ 'plainString': 'plain', 'o1String': '', 'plainInt32': 10, 'o2Int32': 0 }", formatter.Format(message)); 403ffe3c632Sopenharmony_ci } 404ffe3c632Sopenharmony_ci 405ffe3c632Sopenharmony_ci [Test] 406ffe3c632Sopenharmony_ci public void OutputIsInNumericFieldOrder_WithDefaults() 407ffe3c632Sopenharmony_ci { 408ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); 409ffe3c632Sopenharmony_ci var message = new TestJsonFieldOrdering(); 410ffe3c632Sopenharmony_ci AssertJson("{ 'plainString': '', 'plainInt32': 0 }", formatter.Format(message)); 411ffe3c632Sopenharmony_ci message = new TestJsonFieldOrdering { O1Int32 = 5, O2String = "o2", PlainInt32 = 10, PlainString = "plain" }; 412ffe3c632Sopenharmony_ci AssertJson("{ 'plainString': 'plain', 'o2String': 'o2', 'plainInt32': 10, 'o1Int32': 5 }", formatter.Format(message)); 413ffe3c632Sopenharmony_ci message = new TestJsonFieldOrdering { O1String = "", O2Int32 = 0, PlainInt32 = 10, PlainString = "plain" }; 414ffe3c632Sopenharmony_ci AssertJson("{ 'plainString': 'plain', 'o1String': '', 'plainInt32': 10, 'o2Int32': 0 }", formatter.Format(message)); 415ffe3c632Sopenharmony_ci } 416ffe3c632Sopenharmony_ci 417ffe3c632Sopenharmony_ci [Test] 418ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00Z", 0)] 419ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.000000001Z", 1)] 420ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.000000010Z", 10)] 421ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.000000100Z", 100)] 422ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.000001Z", 1000)] 423ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.000010Z", 10000)] 424ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.000100Z", 100000)] 425ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.001Z", 1000000)] 426ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.010Z", 10000000)] 427ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.100Z", 100000000)] 428ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.120Z", 120000000)] 429ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.123Z", 123000000)] 430ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.123400Z", 123400000)] 431ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.123450Z", 123450000)] 432ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.123456Z", 123456000)] 433ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.123456700Z", 123456700)] 434ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.123456780Z", 123456780)] 435ffe3c632Sopenharmony_ci [TestCase("1970-01-01T00:00:00.123456789Z", 123456789)] 436ffe3c632Sopenharmony_ci public void TimestampStandalone(string expected, int nanos) 437ffe3c632Sopenharmony_ci { 438ffe3c632Sopenharmony_ci Assert.AreEqual(WrapInQuotes(expected), new Timestamp { Nanos = nanos }.ToString()); 439ffe3c632Sopenharmony_ci } 440ffe3c632Sopenharmony_ci 441ffe3c632Sopenharmony_ci [Test] 442ffe3c632Sopenharmony_ci public void TimestampStandalone_FromDateTime() 443ffe3c632Sopenharmony_ci { 444ffe3c632Sopenharmony_ci // One before and one after the Unix epoch, more easily represented via DateTime. 445ffe3c632Sopenharmony_ci Assert.AreEqual("\"1673-06-19T12:34:56Z\"", 446ffe3c632Sopenharmony_ci new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp().ToString()); 447ffe3c632Sopenharmony_ci Assert.AreEqual("\"2015-07-31T10:29:34Z\"", 448ffe3c632Sopenharmony_ci new DateTime(2015, 7, 31, 10, 29, 34, DateTimeKind.Utc).ToTimestamp().ToString()); 449ffe3c632Sopenharmony_ci } 450ffe3c632Sopenharmony_ci 451ffe3c632Sopenharmony_ci [Test] 452ffe3c632Sopenharmony_ci [TestCase(-1, -1)] // Would be valid as duration 453ffe3c632Sopenharmony_ci [TestCase(1, Timestamp.MaxNanos + 1)] 454ffe3c632Sopenharmony_ci [TestCase(Timestamp.UnixSecondsAtBclMaxValue + 1, 0)] 455ffe3c632Sopenharmony_ci [TestCase(Timestamp.UnixSecondsAtBclMinValue - 1, 0)] 456ffe3c632Sopenharmony_ci public void TimestampStandalone_NonNormalized(long seconds, int nanoseconds) 457ffe3c632Sopenharmony_ci { 458ffe3c632Sopenharmony_ci var timestamp = new Timestamp { Seconds = seconds, Nanos = nanoseconds }; 459ffe3c632Sopenharmony_ci Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(timestamp)); 460ffe3c632Sopenharmony_ci } 461ffe3c632Sopenharmony_ci 462ffe3c632Sopenharmony_ci [Test] 463ffe3c632Sopenharmony_ci public void TimestampField() 464ffe3c632Sopenharmony_ci { 465ffe3c632Sopenharmony_ci var message = new TestWellKnownTypes { TimestampField = new Timestamp() }; 466ffe3c632Sopenharmony_ci AssertJson("{ 'timestampField': '1970-01-01T00:00:00Z' }", JsonFormatter.Default.Format(message)); 467ffe3c632Sopenharmony_ci } 468ffe3c632Sopenharmony_ci 469ffe3c632Sopenharmony_ci [Test] 470ffe3c632Sopenharmony_ci [TestCase(0, 0, "0s")] 471ffe3c632Sopenharmony_ci [TestCase(1, 0, "1s")] 472ffe3c632Sopenharmony_ci [TestCase(-1, 0, "-1s")] 473ffe3c632Sopenharmony_ci [TestCase(0, 1, "0.000000001s")] 474ffe3c632Sopenharmony_ci [TestCase(0, 10, "0.000000010s")] 475ffe3c632Sopenharmony_ci [TestCase(0, 100, "0.000000100s")] 476ffe3c632Sopenharmony_ci [TestCase(0, 1000, "0.000001s")] 477ffe3c632Sopenharmony_ci [TestCase(0, 10000, "0.000010s")] 478ffe3c632Sopenharmony_ci [TestCase(0, 100000, "0.000100s")] 479ffe3c632Sopenharmony_ci [TestCase(0, 1000000, "0.001s")] 480ffe3c632Sopenharmony_ci [TestCase(0, 10000000, "0.010s")] 481ffe3c632Sopenharmony_ci [TestCase(0, 100000000, "0.100s")] 482ffe3c632Sopenharmony_ci [TestCase(0, 120000000, "0.120s")] 483ffe3c632Sopenharmony_ci [TestCase(0, 123000000, "0.123s")] 484ffe3c632Sopenharmony_ci [TestCase(0, 123400000, "0.123400s")] 485ffe3c632Sopenharmony_ci [TestCase(0, 123450000, "0.123450s")] 486ffe3c632Sopenharmony_ci [TestCase(0, 123456000, "0.123456s")] 487ffe3c632Sopenharmony_ci [TestCase(0, 123456700, "0.123456700s")] 488ffe3c632Sopenharmony_ci [TestCase(0, 123456780, "0.123456780s")] 489ffe3c632Sopenharmony_ci [TestCase(0, 123456789, "0.123456789s")] 490ffe3c632Sopenharmony_ci [TestCase(0, -100000000, "-0.100s")] 491ffe3c632Sopenharmony_ci [TestCase(1, 100000000, "1.100s")] 492ffe3c632Sopenharmony_ci [TestCase(-1, -100000000, "-1.100s")] 493ffe3c632Sopenharmony_ci public void DurationStandalone(long seconds, int nanoseconds, string expected) 494ffe3c632Sopenharmony_ci { 495ffe3c632Sopenharmony_ci var json = JsonFormatter.Default.Format(new Duration { Seconds = seconds, Nanos = nanoseconds }); 496ffe3c632Sopenharmony_ci Assert.AreEqual(WrapInQuotes(expected), json); 497ffe3c632Sopenharmony_ci } 498ffe3c632Sopenharmony_ci 499ffe3c632Sopenharmony_ci [Test] 500ffe3c632Sopenharmony_ci [TestCase(1, 2123456789)] 501ffe3c632Sopenharmony_ci [TestCase(1, -100000000)] 502ffe3c632Sopenharmony_ci public void DurationStandalone_NonNormalized(long seconds, int nanoseconds) 503ffe3c632Sopenharmony_ci { 504ffe3c632Sopenharmony_ci var duration = new Duration { Seconds = seconds, Nanos = nanoseconds }; 505ffe3c632Sopenharmony_ci Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(duration)); 506ffe3c632Sopenharmony_ci } 507ffe3c632Sopenharmony_ci 508ffe3c632Sopenharmony_ci [Test] 509ffe3c632Sopenharmony_ci public void DurationField() 510ffe3c632Sopenharmony_ci { 511ffe3c632Sopenharmony_ci var message = new TestWellKnownTypes { DurationField = new Duration() }; 512ffe3c632Sopenharmony_ci AssertJson("{ 'durationField': '0s' }", JsonFormatter.Default.Format(message)); 513ffe3c632Sopenharmony_ci } 514ffe3c632Sopenharmony_ci 515ffe3c632Sopenharmony_ci [Test] 516ffe3c632Sopenharmony_ci public void StructSample() 517ffe3c632Sopenharmony_ci { 518ffe3c632Sopenharmony_ci var message = new Struct 519ffe3c632Sopenharmony_ci { 520ffe3c632Sopenharmony_ci Fields = 521ffe3c632Sopenharmony_ci { 522ffe3c632Sopenharmony_ci { "a", Value.ForNull() }, 523ffe3c632Sopenharmony_ci { "b", Value.ForBool(false) }, 524ffe3c632Sopenharmony_ci { "c", Value.ForNumber(10.5) }, 525ffe3c632Sopenharmony_ci { "d", Value.ForString("text") }, 526ffe3c632Sopenharmony_ci { "e", Value.ForList(Value.ForString("t1"), Value.ForNumber(5)) }, 527ffe3c632Sopenharmony_ci { "f", Value.ForStruct(new Struct { Fields = { { "nested", Value.ForString("value") } } }) } 528ffe3c632Sopenharmony_ci } 529ffe3c632Sopenharmony_ci }; 530ffe3c632Sopenharmony_ci AssertJson("{ 'a': null, 'b': false, 'c': 10.5, 'd': 'text', 'e': [ 't1', 5 ], 'f': { 'nested': 'value' } }", message.ToString()); 531ffe3c632Sopenharmony_ci } 532ffe3c632Sopenharmony_ci 533ffe3c632Sopenharmony_ci [Test] 534ffe3c632Sopenharmony_ci [TestCase("foo__bar")] 535ffe3c632Sopenharmony_ci [TestCase("foo_3_ar")] 536ffe3c632Sopenharmony_ci [TestCase("fooBar")] 537ffe3c632Sopenharmony_ci public void FieldMaskInvalid(string input) 538ffe3c632Sopenharmony_ci { 539ffe3c632Sopenharmony_ci var mask = new FieldMask { Paths = { input } }; 540ffe3c632Sopenharmony_ci Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(mask)); 541ffe3c632Sopenharmony_ci } 542ffe3c632Sopenharmony_ci 543ffe3c632Sopenharmony_ci [Test] 544ffe3c632Sopenharmony_ci public void FieldMaskStandalone() 545ffe3c632Sopenharmony_ci { 546ffe3c632Sopenharmony_ci var fieldMask = new FieldMask { Paths = { "", "single", "with_underscore", "nested.field.name", "nested..double_dot" } }; 547ffe3c632Sopenharmony_ci Assert.AreEqual("\",single,withUnderscore,nested.field.name,nested..doubleDot\"", fieldMask.ToString()); 548ffe3c632Sopenharmony_ci 549ffe3c632Sopenharmony_ci // Invalid, but we shouldn't create broken JSON... 550ffe3c632Sopenharmony_ci fieldMask = new FieldMask { Paths = { "x\\y" } }; 551ffe3c632Sopenharmony_ci Assert.AreEqual(@"""x\\y""", fieldMask.ToString()); 552ffe3c632Sopenharmony_ci } 553ffe3c632Sopenharmony_ci 554ffe3c632Sopenharmony_ci [Test] 555ffe3c632Sopenharmony_ci public void FieldMaskField() 556ffe3c632Sopenharmony_ci { 557ffe3c632Sopenharmony_ci var message = new TestWellKnownTypes { FieldMaskField = new FieldMask { Paths = { "user.display_name", "photo" } } }; 558ffe3c632Sopenharmony_ci AssertJson("{ 'fieldMaskField': 'user.displayName,photo' }", JsonFormatter.Default.Format(message)); 559ffe3c632Sopenharmony_ci } 560ffe3c632Sopenharmony_ci 561ffe3c632Sopenharmony_ci // SourceContext is an example of a well-known type with no special JSON handling 562ffe3c632Sopenharmony_ci [Test] 563ffe3c632Sopenharmony_ci public void SourceContextStandalone() 564ffe3c632Sopenharmony_ci { 565ffe3c632Sopenharmony_ci var message = new SourceContext { FileName = "foo.proto" }; 566ffe3c632Sopenharmony_ci AssertJson("{ 'fileName': 'foo.proto' }", JsonFormatter.Default.Format(message)); 567ffe3c632Sopenharmony_ci } 568ffe3c632Sopenharmony_ci 569ffe3c632Sopenharmony_ci [Test] 570ffe3c632Sopenharmony_ci public void AnyWellKnownType() 571ffe3c632Sopenharmony_ci { 572ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithTypeRegistry(TypeRegistry.FromMessages(Timestamp.Descriptor))); 573ffe3c632Sopenharmony_ci var timestamp = new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp(); 574ffe3c632Sopenharmony_ci var any = Any.Pack(timestamp); 575ffe3c632Sopenharmony_ci AssertJson("{ '@type': 'type.googleapis.com/google.protobuf.Timestamp', 'value': '1673-06-19T12:34:56Z' }", formatter.Format(any)); 576ffe3c632Sopenharmony_ci } 577ffe3c632Sopenharmony_ci 578ffe3c632Sopenharmony_ci [Test] 579ffe3c632Sopenharmony_ci public void AnyMessageType() 580ffe3c632Sopenharmony_ci { 581ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithTypeRegistry(TypeRegistry.FromMessages(TestAllTypes.Descriptor))); 582ffe3c632Sopenharmony_ci var message = new TestAllTypes { SingleInt32 = 10, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 } }; 583ffe3c632Sopenharmony_ci var any = Any.Pack(message); 584ffe3c632Sopenharmony_ci AssertJson("{ '@type': 'type.googleapis.com/protobuf_unittest3.TestAllTypes', 'singleInt32': 10, 'singleNestedMessage': { 'bb': 20 } }", formatter.Format(any)); 585ffe3c632Sopenharmony_ci } 586ffe3c632Sopenharmony_ci 587ffe3c632Sopenharmony_ci [Test] 588ffe3c632Sopenharmony_ci public void AnyMessageType_CustomPrefix() 589ffe3c632Sopenharmony_ci { 590ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithTypeRegistry(TypeRegistry.FromMessages(TestAllTypes.Descriptor))); 591ffe3c632Sopenharmony_ci var message = new TestAllTypes { SingleInt32 = 10 }; 592ffe3c632Sopenharmony_ci var any = Any.Pack(message, "foo.bar/baz"); 593ffe3c632Sopenharmony_ci AssertJson("{ '@type': 'foo.bar/baz/protobuf_unittest3.TestAllTypes', 'singleInt32': 10 }", formatter.Format(any)); 594ffe3c632Sopenharmony_ci } 595ffe3c632Sopenharmony_ci 596ffe3c632Sopenharmony_ci [Test] 597ffe3c632Sopenharmony_ci public void AnyNested() 598ffe3c632Sopenharmony_ci { 599ffe3c632Sopenharmony_ci var registry = TypeRegistry.FromMessages(TestWellKnownTypes.Descriptor, TestAllTypes.Descriptor); 600ffe3c632Sopenharmony_ci var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithTypeRegistry(registry)); 601ffe3c632Sopenharmony_ci 602ffe3c632Sopenharmony_ci // Nest an Any as the value of an Any. 603ffe3c632Sopenharmony_ci var doubleNestedMessage = new TestAllTypes { SingleInt32 = 20 }; 604ffe3c632Sopenharmony_ci var nestedMessage = Any.Pack(doubleNestedMessage); 605ffe3c632Sopenharmony_ci var message = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) }; 606ffe3c632Sopenharmony_ci AssertJson("{ 'anyField': { '@type': 'type.googleapis.com/google.protobuf.Any', 'value': { '@type': 'type.googleapis.com/protobuf_unittest3.TestAllTypes', 'singleInt32': 20 } } }", 607ffe3c632Sopenharmony_ci formatter.Format(message)); 608ffe3c632Sopenharmony_ci } 609ffe3c632Sopenharmony_ci 610ffe3c632Sopenharmony_ci [Test] 611ffe3c632Sopenharmony_ci public void AnyUnknownType() 612ffe3c632Sopenharmony_ci { 613ffe3c632Sopenharmony_ci // The default type registry doesn't have any types in it. 614ffe3c632Sopenharmony_ci var message = new TestAllTypes(); 615ffe3c632Sopenharmony_ci var any = Any.Pack(message); 616ffe3c632Sopenharmony_ci Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(any)); 617ffe3c632Sopenharmony_ci } 618ffe3c632Sopenharmony_ci 619ffe3c632Sopenharmony_ci [Test] 620ffe3c632Sopenharmony_ci [TestCase(typeof(BoolValue), true, "true")] 621ffe3c632Sopenharmony_ci [TestCase(typeof(Int32Value), 32, "32")] 622ffe3c632Sopenharmony_ci [TestCase(typeof(Int64Value), 32L, "\"32\"")] 623ffe3c632Sopenharmony_ci [TestCase(typeof(UInt32Value), 32U, "32")] 624ffe3c632Sopenharmony_ci [TestCase(typeof(UInt64Value), 32UL, "\"32\"")] 625ffe3c632Sopenharmony_ci [TestCase(typeof(StringValue), "foo", "\"foo\"")] 626ffe3c632Sopenharmony_ci [TestCase(typeof(FloatValue), 1.5f, "1.5")] 627ffe3c632Sopenharmony_ci [TestCase(typeof(DoubleValue), 1.5d, "1.5")] 628ffe3c632Sopenharmony_ci public void Wrappers_Standalone(System.Type wrapperType, object value, string expectedJson) 629ffe3c632Sopenharmony_ci { 630ffe3c632Sopenharmony_ci IMessage populated = (IMessage)Activator.CreateInstance(wrapperType); 631ffe3c632Sopenharmony_ci populated.Descriptor.Fields[WrappersReflection.WrapperValueFieldNumber].Accessor.SetValue(populated, value); 632ffe3c632Sopenharmony_ci Assert.AreEqual(expectedJson, JsonFormatter.Default.Format(populated)); 633ffe3c632Sopenharmony_ci } 634ffe3c632Sopenharmony_ci 635ffe3c632Sopenharmony_ci // Sanity tests for WriteValue. Not particularly comprehensive, as it's all covered above already, 636ffe3c632Sopenharmony_ci // as FormatMessage uses WriteValue. 637ffe3c632Sopenharmony_ci 638ffe3c632Sopenharmony_ci [TestCase(null, "null")] 639ffe3c632Sopenharmony_ci [TestCase(1, "1")] 640ffe3c632Sopenharmony_ci [TestCase(1L, "'1'")] 641ffe3c632Sopenharmony_ci [TestCase(0.5f, "0.5")] 642ffe3c632Sopenharmony_ci [TestCase(0.5d, "0.5")] 643ffe3c632Sopenharmony_ci [TestCase("text", "'text'")] 644ffe3c632Sopenharmony_ci [TestCase("x\ny", @"'x\ny'")] 645ffe3c632Sopenharmony_ci [TestCase(ForeignEnum.ForeignBar, "'FOREIGN_BAR'")] 646ffe3c632Sopenharmony_ci public void WriteValue_Constant(object value, string expectedJson) 647ffe3c632Sopenharmony_ci { 648ffe3c632Sopenharmony_ci AssertWriteValue(value, expectedJson); 649ffe3c632Sopenharmony_ci } 650ffe3c632Sopenharmony_ci 651ffe3c632Sopenharmony_ci [Test] 652ffe3c632Sopenharmony_ci public void WriteValue_Timestamp() 653ffe3c632Sopenharmony_ci { 654ffe3c632Sopenharmony_ci var value = new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp(); 655ffe3c632Sopenharmony_ci AssertWriteValue(value, "'1673-06-19T12:34:56Z'"); 656ffe3c632Sopenharmony_ci } 657ffe3c632Sopenharmony_ci 658ffe3c632Sopenharmony_ci [Test] 659ffe3c632Sopenharmony_ci public void WriteValue_Message() 660ffe3c632Sopenharmony_ci { 661ffe3c632Sopenharmony_ci var value = new TestAllTypes { SingleInt32 = 100, SingleInt64 = 3210987654321L }; 662ffe3c632Sopenharmony_ci AssertWriteValue(value, "{ 'singleInt32': 100, 'singleInt64': '3210987654321' }"); 663ffe3c632Sopenharmony_ci } 664ffe3c632Sopenharmony_ci 665ffe3c632Sopenharmony_ci [Test] 666ffe3c632Sopenharmony_ci public void WriteValue_List() 667ffe3c632Sopenharmony_ci { 668ffe3c632Sopenharmony_ci var value = new RepeatedField<int> { 1, 2, 3 }; 669ffe3c632Sopenharmony_ci AssertWriteValue(value, "[ 1, 2, 3 ]"); 670ffe3c632Sopenharmony_ci } 671ffe3c632Sopenharmony_ci 672ffe3c632Sopenharmony_ci [Test] 673ffe3c632Sopenharmony_ci public void Proto2_DefaultValuesWritten() 674ffe3c632Sopenharmony_ci { 675ffe3c632Sopenharmony_ci var value = new ProtobufTestMessages.Proto2.TestAllTypesProto2() { FieldName13 = 0 }; 676ffe3c632Sopenharmony_ci AssertWriteValue(value, "{ 'FieldName13': 0 }"); 677ffe3c632Sopenharmony_ci } 678ffe3c632Sopenharmony_ci 679ffe3c632Sopenharmony_ci private static void AssertWriteValue(object value, string expectedJson) 680ffe3c632Sopenharmony_ci { 681ffe3c632Sopenharmony_ci var writer = new StringWriter(); 682ffe3c632Sopenharmony_ci JsonFormatter.Default.WriteValue(writer, value); 683ffe3c632Sopenharmony_ci string actual = writer.ToString(); 684ffe3c632Sopenharmony_ci AssertJson(expectedJson, actual); 685ffe3c632Sopenharmony_ci } 686ffe3c632Sopenharmony_ci 687ffe3c632Sopenharmony_ci /// <summary> 688ffe3c632Sopenharmony_ci /// Checks that the actual JSON is the same as the expected JSON - but after replacing 689ffe3c632Sopenharmony_ci /// all apostrophes in the expected JSON with double quotes. This basically makes the tests easier 690ffe3c632Sopenharmony_ci /// to read. 691ffe3c632Sopenharmony_ci /// </summary> 692ffe3c632Sopenharmony_ci private static void AssertJson(string expectedJsonWithApostrophes, string actualJson) 693ffe3c632Sopenharmony_ci { 694ffe3c632Sopenharmony_ci var expectedJson = expectedJsonWithApostrophes.Replace("'", "\""); 695ffe3c632Sopenharmony_ci Assert.AreEqual(expectedJson, actualJson); 696ffe3c632Sopenharmony_ci } 697ffe3c632Sopenharmony_ci } 698ffe3c632Sopenharmony_ci} 699