csharptest | 71f662c | 2011-05-20 15:15:34 -0500 | [diff] [blame] | 1 | #region Copyright notice and license
|
| 2 |
|
| 3 | // Protocol Buffers - Google's data interchange format
|
| 4 | // Copyright 2008 Google Inc. All rights reserved.
|
| 5 | // http://github.com/jskeet/dotnet-protobufs/
|
| 6 | // Original C++/Java/Python code:
|
| 7 | // http://code.google.com/p/protobuf/
|
| 8 | //
|
| 9 | // Redistribution and use in source and binary forms, with or without
|
| 10 | // modification, are permitted provided that the following conditions are
|
| 11 | // met:
|
| 12 | //
|
| 13 | // * Redistributions of source code must retain the above copyright
|
| 14 | // notice, this list of conditions and the following disclaimer.
|
| 15 | // * Redistributions in binary form must reproduce the above
|
| 16 | // copyright notice, this list of conditions and the following disclaimer
|
| 17 | // in the documentation and/or other materials provided with the
|
| 18 | // distribution.
|
| 19 | // * Neither the name of Google Inc. nor the names of its
|
| 20 | // contributors may be used to endorse or promote products derived from
|
| 21 | // this software without specific prior written permission.
|
| 22 | //
|
| 23 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| 24 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| 25 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| 26 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| 27 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| 28 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| 29 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| 30 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| 31 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| 32 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| 33 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| 34 |
|
| 35 | #endregion
|
| 36 |
|
| 37 | using System;
|
| 38 | using System.IO;
|
| 39 | using System.Text;
|
| 40 | using Google.ProtocolBuffers.TestProtos;
|
| 41 | using NUnit.Framework;
|
| 42 | using System.Globalization;
|
| 43 | using System.Threading;
|
| 44 |
|
| 45 | namespace Google.ProtocolBuffers
|
| 46 | {
|
| 47 | [TestFixture]
|
| 48 | public class TextFormatTest
|
| 49 | {
|
| 50 | private static readonly string AllFieldsSetText = TestUtil.ReadTextFromFile("text_format_unittest_data.txt");
|
| 51 |
|
| 52 | private static readonly string AllExtensionsSetText =
|
| 53 | TestUtil.ReadTextFromFile("text_format_unittest_extensions_data.txt");
|
| 54 |
|
| 55 | /// <summary>
|
| 56 | /// Note that this is slightly different to the Java - 123.0 becomes 123, and 1.23E17 becomes 1.23E+17.
|
| 57 | /// Both of these differences can be parsed by the Java and the C++, and we can parse their output too.
|
| 58 | /// </summary>
|
| 59 | private const string ExoticText =
|
| 60 | "repeated_int32: -1\n" +
|
| 61 | "repeated_int32: -2147483648\n" +
|
| 62 | "repeated_int64: -1\n" +
|
| 63 | "repeated_int64: -9223372036854775808\n" +
|
| 64 | "repeated_uint32: 4294967295\n" +
|
| 65 | "repeated_uint32: 2147483648\n" +
|
| 66 | "repeated_uint64: 18446744073709551615\n" +
|
| 67 | "repeated_uint64: 9223372036854775808\n" +
|
| 68 | "repeated_double: 123\n" +
|
| 69 | "repeated_double: 123.5\n" +
|
| 70 | "repeated_double: 0.125\n" +
|
| 71 | "repeated_double: 1.23E+17\n" +
|
| 72 | "repeated_double: 1.235E+22\n" +
|
| 73 | "repeated_double: 1.235E-18\n" +
|
| 74 | "repeated_double: 123.456789\n" +
|
| 75 | "repeated_double: Infinity\n" +
|
| 76 | "repeated_double: -Infinity\n" +
|
| 77 | "repeated_double: NaN\n" +
|
| 78 | "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"" +
|
| 79 | "\\341\\210\\264\"\n" +
|
| 80 | "repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n";
|
| 81 |
|
| 82 | private const string MessageSetText =
|
| 83 | "[protobuf_unittest.TestMessageSetExtension1] {\n" +
|
| 84 | " i: 123\n" +
|
| 85 | "}\n" +
|
| 86 | "[protobuf_unittest.TestMessageSetExtension2] {\n" +
|
| 87 | " str: \"foo\"\n" +
|
| 88 | "}\n";
|
| 89 |
|
| 90 | /// <summary>
|
| 91 | /// Print TestAllTypes and compare with golden file.
|
| 92 | /// </summary>
|
| 93 | [Test]
|
| 94 | public void PrintMessage()
|
| 95 | {
|
| 96 | TestUtil.TestInMultipleCultures(() =>
|
| 97 | {
|
| 98 | string text = TextFormat.PrintToString(TestUtil.GetAllSet());
|
| 99 | Assert.AreEqual(AllFieldsSetText.Replace("\r\n", "\n"),
|
| 100 | text.Replace("\r\n", "\n"));
|
| 101 | });
|
| 102 | }
|
| 103 |
|
| 104 | /// <summary>
|
| 105 | /// Print TestAllExtensions and compare with golden file.
|
| 106 | /// </summary>
|
| 107 | [Test]
|
| 108 | public void PrintExtensions()
|
| 109 | {
|
| 110 | string text = TextFormat.PrintToString(TestUtil.GetAllExtensionsSet());
|
| 111 |
|
| 112 | Assert.AreEqual(AllExtensionsSetText.Replace("\r\n", "\n"), text.Replace("\r\n", "\n"));
|
| 113 | }
|
| 114 |
|
| 115 | /// <summary>
|
| 116 | /// Test printing of unknown fields in a message.
|
| 117 | /// </summary>
|
| 118 | [Test]
|
| 119 | public void PrintUnknownFields()
|
| 120 | {
|
| 121 | TestEmptyMessage message =
|
| 122 | TestEmptyMessage.CreateBuilder()
|
| 123 | .SetUnknownFields(
|
| 124 | UnknownFieldSet.CreateBuilder()
|
| 125 | .AddField(5,
|
| 126 | UnknownField.CreateBuilder()
|
| 127 | .AddVarint(1)
|
| 128 | .AddFixed32(2)
|
| 129 | .AddFixed64(3)
|
| 130 | .AddLengthDelimited(ByteString.CopyFromUtf8("4"))
|
| 131 | .AddGroup(
|
| 132 | UnknownFieldSet.CreateBuilder()
|
| 133 | .AddField(10,
|
| 134 | UnknownField.CreateBuilder()
|
| 135 | .AddVarint(5)
|
| 136 | .Build())
|
| 137 | .Build())
|
| 138 | .Build())
|
| 139 | .AddField(8,
|
| 140 | UnknownField.CreateBuilder()
|
| 141 | .AddVarint(1)
|
| 142 | .AddVarint(2)
|
| 143 | .AddVarint(3)
|
| 144 | .Build())
|
| 145 | .AddField(15,
|
| 146 | UnknownField.CreateBuilder()
|
| 147 | .AddVarint(0xABCDEF1234567890L)
|
| 148 | .AddFixed32(0xABCD1234)
|
| 149 | .AddFixed64(0xABCDEF1234567890L)
|
| 150 | .Build())
|
| 151 | .Build())
|
| 152 | .Build();
|
| 153 |
|
| 154 | Assert.AreEqual(
|
| 155 | "5: 1\n" +
|
| 156 | "5: 0x00000002\n" +
|
| 157 | "5: 0x0000000000000003\n" +
|
| 158 | "5: \"4\"\n" +
|
| 159 | "5 {\n" +
|
| 160 | " 10: 5\n" +
|
| 161 | "}\n" +
|
| 162 | "8: 1\n" +
|
| 163 | "8: 2\n" +
|
| 164 | "8: 3\n" +
|
| 165 | "15: 12379813812177893520\n" +
|
| 166 | "15: 0xabcd1234\n" +
|
| 167 | "15: 0xabcdef1234567890\n",
|
| 168 | TextFormat.PrintToString(message));
|
| 169 | }
|
| 170 |
|
| 171 | /// <summary>
|
| 172 | /// Helper to construct a ByteString from a string containing only 8-bit
|
| 173 | /// characters. The characters are converted directly to bytes, *not*
|
| 174 | /// encoded using UTF-8.
|
| 175 | /// </summary>
|
| 176 | private static ByteString Bytes(string str)
|
| 177 | {
|
| 178 | return ByteString.CopyFrom(Encoding.GetEncoding(28591).GetBytes(str));
|
| 179 | }
|
| 180 |
|
| 181 | [Test]
|
| 182 | public void PrintExotic()
|
| 183 | {
|
| 184 | IMessage message = TestAllTypes.CreateBuilder()
|
| 185 | // Signed vs. unsigned numbers.
|
| 186 | .AddRepeatedInt32(-1)
|
| 187 | .AddRepeatedUint32(uint.MaxValue)
|
| 188 | .AddRepeatedInt64(-1)
|
| 189 | .AddRepeatedUint64(ulong.MaxValue)
|
| 190 | .AddRepeatedInt32(1 << 31)
|
| 191 | .AddRepeatedUint32(1U << 31)
|
| 192 | .AddRepeatedInt64(1L << 63)
|
| 193 | .AddRepeatedUint64(1UL << 63)
|
| 194 |
|
| 195 | // Floats of various precisions and exponents.
|
| 196 | .AddRepeatedDouble(123)
|
| 197 | .AddRepeatedDouble(123.5)
|
| 198 | .AddRepeatedDouble(0.125)
|
| 199 | .AddRepeatedDouble(123e15)
|
| 200 | .AddRepeatedDouble(123.5e20)
|
| 201 | .AddRepeatedDouble(123.5e-20)
|
| 202 | .AddRepeatedDouble(123.456789)
|
| 203 | .AddRepeatedDouble(Double.PositiveInfinity)
|
| 204 | .AddRepeatedDouble(Double.NegativeInfinity)
|
| 205 | .AddRepeatedDouble(Double.NaN)
|
| 206 |
|
| 207 | // Strings and bytes that needing escaping.
|
| 208 | .AddRepeatedString("\0\u0001\u0007\b\f\n\r\t\v\\\'\"\u1234")
|
| 209 | .AddRepeatedBytes(Bytes("\0\u0001\u0007\b\f\n\r\t\v\\\'\"\u00fe"))
|
| 210 | .Build();
|
| 211 |
|
| 212 | Assert.AreEqual(ExoticText, message.ToString());
|
| 213 | }
|
| 214 |
|
| 215 | [Test]
|
| 216 | public void PrintMessageSet()
|
| 217 | {
|
| 218 | TestMessageSet messageSet =
|
| 219 | TestMessageSet.CreateBuilder()
|
| 220 | .SetExtension(
|
| 221 | TestMessageSetExtension1.MessageSetExtension,
|
| 222 | TestMessageSetExtension1.CreateBuilder().SetI(123).Build())
|
| 223 | .SetExtension(
|
| 224 | TestMessageSetExtension2.MessageSetExtension,
|
| 225 | TestMessageSetExtension2.CreateBuilder().SetStr("foo").Build())
|
| 226 | .Build();
|
| 227 |
|
| 228 | Assert.AreEqual(MessageSetText, messageSet.ToString());
|
| 229 | }
|
| 230 |
|
| 231 | // =================================================================
|
| 232 |
|
| 233 | [Test]
|
| 234 | public void Parse()
|
| 235 | {
|
| 236 | TestUtil.TestInMultipleCultures(() =>
|
| 237 | {
|
| 238 | TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
|
| 239 | TextFormat.Merge(AllFieldsSetText, builder);
|
| 240 | TestUtil.AssertAllFieldsSet(builder.Build());
|
| 241 | });
|
| 242 | }
|
| 243 |
|
| 244 | [Test]
|
| 245 | public void ParseReader()
|
| 246 | {
|
| 247 | TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
|
| 248 | TextFormat.Merge(new StringReader(AllFieldsSetText), builder);
|
| 249 | TestUtil.AssertAllFieldsSet(builder.Build());
|
| 250 | }
|
| 251 |
|
| 252 | [Test]
|
| 253 | public void ParseExtensions()
|
| 254 | {
|
| 255 | TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder();
|
| 256 | TextFormat.Merge(AllExtensionsSetText,
|
| 257 | TestUtil.CreateExtensionRegistry(),
|
| 258 | builder);
|
| 259 | TestUtil.AssertAllExtensionsSet(builder.Build());
|
| 260 | }
|
| 261 |
|
| 262 | [Test]
|
| 263 | public void ParseCompatibility()
|
| 264 | {
|
| 265 | string original = "repeated_float: inf\n" +
|
| 266 | "repeated_float: -inf\n" +
|
| 267 | "repeated_float: nan\n" +
|
| 268 | "repeated_float: inff\n" +
|
| 269 | "repeated_float: -inff\n" +
|
| 270 | "repeated_float: nanf\n" +
|
| 271 | "repeated_float: 1.0f\n" +
|
| 272 | "repeated_float: infinityf\n" +
|
| 273 | "repeated_float: -Infinityf\n" +
|
| 274 | "repeated_double: infinity\n" +
|
| 275 | "repeated_double: -infinity\n" +
|
| 276 | "repeated_double: nan\n";
|
| 277 | string canonical = "repeated_float: Infinity\n" +
|
| 278 | "repeated_float: -Infinity\n" +
|
| 279 | "repeated_float: NaN\n" +
|
| 280 | "repeated_float: Infinity\n" +
|
| 281 | "repeated_float: -Infinity\n" +
|
| 282 | "repeated_float: NaN\n" +
|
| 283 | "repeated_float: 1\n" + // Java has 1.0; this is fine
|
| 284 | "repeated_float: Infinity\n" +
|
| 285 | "repeated_float: -Infinity\n" +
|
| 286 | "repeated_double: Infinity\n" +
|
| 287 | "repeated_double: -Infinity\n" +
|
| 288 | "repeated_double: NaN\n";
|
| 289 | TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
|
| 290 | TextFormat.Merge(original, builder);
|
| 291 | Assert.AreEqual(canonical, builder.Build().ToString());
|
| 292 | }
|
| 293 |
|
| 294 | [Test]
|
| 295 | public void ParseExotic()
|
| 296 | {
|
| 297 | TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
|
| 298 | TextFormat.Merge(ExoticText, builder);
|
| 299 |
|
| 300 | // Too lazy to check things individually. Don't try to debug this
|
| 301 | // if testPrintExotic() is Assert.Failing.
|
| 302 | Assert.AreEqual(ExoticText, builder.Build().ToString());
|
| 303 | }
|
| 304 |
|
| 305 | [Test]
|
| 306 | public void ParseMessageSet()
|
| 307 | {
|
| 308 | ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
|
| 309 | extensionRegistry.Add(TestMessageSetExtension1.MessageSetExtension);
|
| 310 | extensionRegistry.Add(TestMessageSetExtension2.MessageSetExtension);
|
| 311 |
|
| 312 | TestMessageSet.Builder builder = TestMessageSet.CreateBuilder();
|
| 313 | TextFormat.Merge(MessageSetText, extensionRegistry, builder);
|
| 314 | TestMessageSet messageSet = builder.Build();
|
| 315 |
|
| 316 | Assert.IsTrue(messageSet.HasExtension(TestMessageSetExtension1.MessageSetExtension));
|
| 317 | Assert.AreEqual(123, messageSet.GetExtension(TestMessageSetExtension1.MessageSetExtension).I);
|
| 318 | Assert.IsTrue(messageSet.HasExtension(TestMessageSetExtension2.MessageSetExtension));
|
| 319 | Assert.AreEqual("foo", messageSet.GetExtension(TestMessageSetExtension2.MessageSetExtension).Str);
|
| 320 | }
|
| 321 |
|
| 322 | [Test]
|
| 323 | public void ParseNumericEnum()
|
| 324 | {
|
| 325 | TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
|
| 326 | TextFormat.Merge("optional_nested_enum: 2", builder);
|
| 327 | Assert.AreEqual(TestAllTypes.Types.NestedEnum.BAR, builder.OptionalNestedEnum);
|
| 328 | }
|
| 329 |
|
| 330 | [Test]
|
| 331 | public void ParseAngleBrackets()
|
| 332 | {
|
| 333 | TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
|
| 334 | TextFormat.Merge("OptionalGroup: < a: 1 >", builder);
|
| 335 | Assert.IsTrue(builder.HasOptionalGroup);
|
| 336 | Assert.AreEqual(1, builder.OptionalGroup.A);
|
| 337 | }
|
| 338 |
|
| 339 | [Test]
|
| 340 | public void ParseComment()
|
| 341 | {
|
| 342 | TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
|
| 343 | TextFormat.Merge(
|
| 344 | "# this is a comment\n" +
|
| 345 | "optional_int32: 1 # another comment\n" +
|
| 346 | "optional_int64: 2\n" +
|
| 347 | "# EOF comment", builder);
|
| 348 | Assert.AreEqual(1, builder.OptionalInt32);
|
| 349 | Assert.AreEqual(2, builder.OptionalInt64);
|
| 350 | }
|
| 351 |
|
| 352 |
|
| 353 | private static void AssertParseError(string error, string text)
|
| 354 | {
|
| 355 | TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
|
| 356 | try
|
| 357 | {
|
| 358 | TextFormat.Merge(text, TestUtil.CreateExtensionRegistry(), builder);
|
| 359 | Assert.Fail("Expected parse exception.");
|
| 360 | }
|
| 361 | catch (FormatException e)
|
| 362 | {
|
| 363 | Assert.AreEqual(error, e.Message);
|
| 364 | }
|
| 365 | }
|
| 366 |
|
| 367 | [Test]
|
| 368 | public void ParseErrors()
|
| 369 | {
|
| 370 | AssertParseError(
|
| 371 | "1:16: Expected \":\".",
|
| 372 | "optional_int32 123");
|
| 373 | AssertParseError(
|
| 374 | "1:23: Expected identifier.",
|
| 375 | "optional_nested_enum: ?");
|
| 376 | AssertParseError(
|
| 377 | "1:18: Couldn't parse integer: Number must be positive: -1",
|
| 378 | "optional_uint32: -1");
|
| 379 | AssertParseError(
|
| 380 | "1:17: Couldn't parse integer: Number out of range for 32-bit signed " +
|
| 381 | "integer: 82301481290849012385230157",
|
| 382 | "optional_int32: 82301481290849012385230157");
|
| 383 | AssertParseError(
|
| 384 | "1:16: Expected \"true\" or \"false\".",
|
| 385 | "optional_bool: maybe");
|
| 386 | AssertParseError(
|
| 387 | "1:18: Expected string.",
|
| 388 | "optional_string: 123");
|
| 389 | AssertParseError(
|
| 390 | "1:18: String missing ending quote.",
|
| 391 | "optional_string: \"ueoauaoe");
|
| 392 | AssertParseError(
|
| 393 | "1:18: String missing ending quote.",
|
| 394 | "optional_string: \"ueoauaoe\n" +
|
| 395 | "optional_int32: 123");
|
| 396 | AssertParseError(
|
| 397 | "1:18: Invalid escape sequence: '\\z'",
|
| 398 | "optional_string: \"\\z\"");
|
| 399 | AssertParseError(
|
| 400 | "1:18: String missing ending quote.",
|
| 401 | "optional_string: \"ueoauaoe\n" +
|
| 402 | "optional_int32: 123");
|
| 403 | AssertParseError(
|
| 404 | "1:2: Extension \"nosuchext\" not found in the ExtensionRegistry.",
|
| 405 | "[nosuchext]: 123");
|
| 406 | AssertParseError(
|
csharptest | 27bfcc5 | 2011-06-02 12:04:06 -0500 | [diff] [blame^] | 407 | "1:20: Extension \"protobuf_unittest.optional_int32_extension\" " +
|
| 408 | "not found in the ExtensionRegistry.",
|
csharptest | 71f662c | 2011-05-20 15:15:34 -0500 | [diff] [blame] | 409 | "[protobuf_unittest.optional_int32_extension]: 123");
|
| 410 | AssertParseError(
|
| 411 | "1:1: Message type \"protobuf_unittest.TestAllTypes\" has no field " +
|
| 412 | "named \"nosuchfield\".",
|
| 413 | "nosuchfield: 123");
|
| 414 | AssertParseError(
|
| 415 | "1:21: Expected \">\".",
|
| 416 | "OptionalGroup < a: 1");
|
| 417 | AssertParseError(
|
| 418 | "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
|
| 419 | "value named \"NO_SUCH_VALUE\".",
|
| 420 | "optional_nested_enum: NO_SUCH_VALUE");
|
| 421 | AssertParseError(
|
| 422 | "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
|
| 423 | "value with number 123.",
|
| 424 | "optional_nested_enum: 123");
|
| 425 |
|
| 426 | // Delimiters must match.
|
| 427 | AssertParseError(
|
| 428 | "1:22: Expected identifier.",
|
| 429 | "OptionalGroup < a: 1 }");
|
| 430 | AssertParseError(
|
| 431 | "1:22: Expected identifier.",
|
| 432 | "OptionalGroup { a: 1 >");
|
| 433 | }
|
| 434 |
|
| 435 | // =================================================================
|
| 436 |
|
| 437 | private static ByteString Bytes(params byte[] bytes)
|
| 438 | {
|
| 439 | return ByteString.CopyFrom(bytes);
|
| 440 | }
|
| 441 |
|
| 442 | private delegate void FormattingAction();
|
| 443 |
|
| 444 | private static void AssertFormatException(FormattingAction action)
|
| 445 | {
|
| 446 | try
|
| 447 | {
|
| 448 | action();
|
| 449 | Assert.Fail("Should have thrown an exception.");
|
| 450 | }
|
| 451 | catch (FormatException)
|
| 452 | {
|
| 453 | // success
|
| 454 | }
|
| 455 | }
|
| 456 |
|
| 457 | [Test]
|
| 458 | public void Escape()
|
| 459 | {
|
| 460 | // Escape sequences.
|
| 461 | Assert.AreEqual("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"",
|
| 462 | TextFormat.EscapeBytes(Bytes("\0\u0001\u0007\b\f\n\r\t\v\\\'\"")));
|
| 463 | Assert.AreEqual("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"",
|
| 464 | TextFormat.EscapeText("\0\u0001\u0007\b\f\n\r\t\v\\\'\""));
|
| 465 | Assert.AreEqual(Bytes("\0\u0001\u0007\b\f\n\r\t\v\\\'\""),
|
| 466 | TextFormat.UnescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
|
| 467 | Assert.AreEqual("\0\u0001\u0007\b\f\n\r\t\v\\\'\"",
|
| 468 | TextFormat.UnescapeText("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
|
| 469 |
|
| 470 | // Unicode handling.
|
| 471 | Assert.AreEqual("\\341\\210\\264", TextFormat.EscapeText("\u1234"));
|
| 472 | Assert.AreEqual("\\341\\210\\264", TextFormat.EscapeBytes(Bytes(0xe1, 0x88, 0xb4)));
|
| 473 | Assert.AreEqual("\u1234", TextFormat.UnescapeText("\\341\\210\\264"));
|
| 474 | Assert.AreEqual(Bytes(0xe1, 0x88, 0xb4), TextFormat.UnescapeBytes("\\341\\210\\264"));
|
| 475 | Assert.AreEqual("\u1234", TextFormat.UnescapeText("\\xe1\\x88\\xb4"));
|
| 476 | Assert.AreEqual(Bytes(0xe1, 0x88, 0xb4), TextFormat.UnescapeBytes("\\xe1\\x88\\xb4"));
|
| 477 |
|
| 478 | // Errors.
|
| 479 | AssertFormatException(() => TextFormat.UnescapeText("\\x"));
|
| 480 | AssertFormatException(() => TextFormat.UnescapeText("\\z"));
|
| 481 | AssertFormatException(() => TextFormat.UnescapeText("\\"));
|
| 482 | }
|
| 483 |
|
| 484 | [Test]
|
| 485 | public void ParseInteger()
|
| 486 | {
|
| 487 | Assert.AreEqual(0, TextFormat.ParseInt32("0"));
|
| 488 | Assert.AreEqual(1, TextFormat.ParseInt32("1"));
|
| 489 | Assert.AreEqual(-1, TextFormat.ParseInt32("-1"));
|
| 490 | Assert.AreEqual(12345, TextFormat.ParseInt32("12345"));
|
| 491 | Assert.AreEqual(-12345, TextFormat.ParseInt32("-12345"));
|
| 492 | Assert.AreEqual(2147483647, TextFormat.ParseInt32("2147483647"));
|
| 493 | Assert.AreEqual(-2147483648, TextFormat.ParseInt32("-2147483648"));
|
| 494 |
|
| 495 | Assert.AreEqual(0, TextFormat.ParseUInt32("0"));
|
| 496 | Assert.AreEqual(1, TextFormat.ParseUInt32("1"));
|
| 497 | Assert.AreEqual(12345, TextFormat.ParseUInt32("12345"));
|
| 498 | Assert.AreEqual(2147483647, TextFormat.ParseUInt32("2147483647"));
|
| 499 | Assert.AreEqual(2147483648U, TextFormat.ParseUInt32("2147483648"));
|
| 500 | Assert.AreEqual(4294967295U, TextFormat.ParseUInt32("4294967295"));
|
| 501 |
|
| 502 | Assert.AreEqual(0L, TextFormat.ParseInt64("0"));
|
| 503 | Assert.AreEqual(1L, TextFormat.ParseInt64("1"));
|
| 504 | Assert.AreEqual(-1L, TextFormat.ParseInt64("-1"));
|
| 505 | Assert.AreEqual(12345L, TextFormat.ParseInt64("12345"));
|
| 506 | Assert.AreEqual(-12345L, TextFormat.ParseInt64("-12345"));
|
| 507 | Assert.AreEqual(2147483647L, TextFormat.ParseInt64("2147483647"));
|
| 508 | Assert.AreEqual(-2147483648L, TextFormat.ParseInt64("-2147483648"));
|
| 509 | Assert.AreEqual(4294967295L, TextFormat.ParseInt64("4294967295"));
|
| 510 | Assert.AreEqual(4294967296L, TextFormat.ParseInt64("4294967296"));
|
| 511 | Assert.AreEqual(9223372036854775807L, TextFormat.ParseInt64("9223372036854775807"));
|
| 512 | Assert.AreEqual(-9223372036854775808L, TextFormat.ParseInt64("-9223372036854775808"));
|
| 513 |
|
| 514 | Assert.AreEqual(0L, TextFormat.ParseUInt64("0"));
|
| 515 | Assert.AreEqual(1L, TextFormat.ParseUInt64("1"));
|
| 516 | Assert.AreEqual(12345L, TextFormat.ParseUInt64("12345"));
|
| 517 | Assert.AreEqual(2147483647L, TextFormat.ParseUInt64("2147483647"));
|
| 518 | Assert.AreEqual(4294967295L, TextFormat.ParseUInt64("4294967295"));
|
| 519 | Assert.AreEqual(4294967296L, TextFormat.ParseUInt64("4294967296"));
|
| 520 | Assert.AreEqual(9223372036854775807UL, TextFormat.ParseUInt64("9223372036854775807"));
|
| 521 | Assert.AreEqual(9223372036854775808UL, TextFormat.ParseUInt64("9223372036854775808"));
|
| 522 | Assert.AreEqual(18446744073709551615UL, TextFormat.ParseUInt64("18446744073709551615"));
|
| 523 |
|
| 524 | // Hex
|
| 525 | Assert.AreEqual(0x1234abcd, TextFormat.ParseInt32("0x1234abcd"));
|
| 526 | Assert.AreEqual(-0x1234abcd, TextFormat.ParseInt32("-0x1234abcd"));
|
| 527 | Assert.AreEqual(0xffffffffffffffffUL, TextFormat.ParseUInt64("0xffffffffffffffff"));
|
| 528 | Assert.AreEqual(0x7fffffffffffffffL,
|
| 529 | TextFormat.ParseInt64("0x7fffffffffffffff"));
|
| 530 |
|
| 531 | // Octal
|
| 532 | Assert.AreEqual(342391, TextFormat.ParseInt32("01234567"));
|
| 533 |
|
| 534 | // Out-of-range
|
| 535 | AssertFormatException(() => TextFormat.ParseInt32("2147483648"));
|
| 536 | AssertFormatException(() => TextFormat.ParseInt32("-2147483649"));
|
| 537 | AssertFormatException(() => TextFormat.ParseUInt32("4294967296"));
|
| 538 | AssertFormatException(() => TextFormat.ParseUInt32("-1"));
|
| 539 | AssertFormatException(() => TextFormat.ParseInt64("9223372036854775808"));
|
| 540 | AssertFormatException(() => TextFormat.ParseInt64("-9223372036854775809"));
|
| 541 | AssertFormatException(() => TextFormat.ParseUInt64("18446744073709551616"));
|
| 542 | AssertFormatException(() => TextFormat.ParseUInt64("-1"));
|
| 543 | AssertFormatException(() => TextFormat.ParseInt32("abcd"));
|
| 544 | }
|
| 545 |
|
| 546 | [Test]
|
| 547 | public void ParseLongString()
|
| 548 | {
|
| 549 | string longText =
|
| 550 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 551 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 552 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 553 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 554 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 555 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 556 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 557 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 558 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 559 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 560 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 561 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 562 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 563 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 564 | "123456789012345678901234567890123456789012345678901234567890" +
|
| 565 | "123456789012345678901234567890123456789012345678901234567890";
|
| 566 | TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
|
| 567 | TextFormat.Merge("optional_string: \"" + longText + "\"", builder);
|
| 568 | Assert.AreEqual(longText, builder.OptionalString);
|
| 569 | }
|
| 570 | }
|
| 571 | } |