Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
feb9385b
Commit
feb9385b
authored
Aug 14, 2008
by
Jon Skeet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Lots of text formatting tests, but ignored the parsing ones for the moment.
parent
ca4cbda9
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
514 additions
and
36 deletions
+514
-36
CodedOutputStreamTest.cs
csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs
+12
-25
TestUtil.cs
csharp/ProtocolBuffers.Test/TestUtil.cs
+14
-0
TextFormatTest.cs
csharp/ProtocolBuffers.Test/TextFormatTest.cs
+439
-1
TextFormat.cs
csharp/ProtocolBuffers/TextFormat.cs
+49
-10
No files found.
csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs
View file @
feb9385b
...
...
@@ -21,19 +21,6 @@ namespace Google.ProtocolBuffers {
[
TestFixture
]
public
class
CodedOutputStreamTest
{
/// <summary>
/// Helper to construct a byte array from a bunch of bytes. The inputs are
/// actually ints so that I can use hex notation and not get stupid errors
/// about precision.
/// </summary>
private
static
byte
[]
Bytes
(
params
int
[]
bytesAsInts
)
{
byte
[]
bytes
=
new
byte
[
bytesAsInts
.
Length
];
for
(
int
i
=
0
;
i
<
bytesAsInts
.
Length
;
i
++)
{
bytes
[
i
]
=
(
byte
)
bytesAsInts
[
i
];
}
return
bytes
;
}
private
static
void
AssertEqualBytes
(
byte
[]
a
,
byte
[]
b
)
{
Assert
.
AreEqual
(
ByteString
.
CopyFrom
(
a
),
ByteString
.
CopyFrom
(
b
));
}
...
...
@@ -92,29 +79,29 @@ namespace Google.ProtocolBuffers {
/// </summary>
[
Test
]
public
void
WriteVarint
()
{
AssertWriteVarint
(
Bytes
(
0x00
)
,
0
);
AssertWriteVarint
(
Bytes
(
0x01
)
,
1
);
AssertWriteVarint
(
Bytes
(
0x7f
)
,
127
);
AssertWriteVarint
(
new
byte
[]
{
0x00
}
,
0
);
AssertWriteVarint
(
new
byte
[]
{
0x01
}
,
1
);
AssertWriteVarint
(
new
byte
[]
{
0x7f
}
,
127
);
// 14882
AssertWriteVarint
(
Bytes
(
0xa2
,
0x74
)
,
(
0x22
<<
0
)
|
(
0x74
<<
7
));
AssertWriteVarint
(
new
byte
[]
{
0xa2
,
0x74
}
,
(
0x22
<<
0
)
|
(
0x74
<<
7
));
// 2961488830
AssertWriteVarint
(
Bytes
(
0xbe
,
0xf7
,
0x92
,
0x84
,
0x0b
)
,
AssertWriteVarint
(
new
byte
[]
{
0xbe
,
0xf7
,
0x92
,
0x84
,
0x0b
}
,
(
0x3e
<<
0
)
|
(
0x77
<<
7
)
|
(
0x12
<<
14
)
|
(
0x04
<<
21
)
|
(
0x0bL
<<
28
));
// 64-bit
// 7256456126
AssertWriteVarint
(
Bytes
(
0xbe
,
0xf7
,
0x92
,
0x84
,
0x1b
)
,
AssertWriteVarint
(
new
byte
[]
{
0xbe
,
0xf7
,
0x92
,
0x84
,
0x1b
}
,
(
0x3e
<<
0
)
|
(
0x77
<<
7
)
|
(
0x12
<<
14
)
|
(
0x04
<<
21
)
|
(
0x1bL
<<
28
));
// 41256202580718336
AssertWriteVarint
(
Bytes
(
0x80
,
0xe6
,
0xeb
,
0x9c
,
0xc3
,
0xc9
,
0xa4
,
0x49
)
,
new
byte
[]
{
0x80
,
0xe6
,
0xeb
,
0x9c
,
0xc3
,
0xc9
,
0xa4
,
0x49
}
,
(
0x00
<<
0
)
|
(
0x66
<<
7
)
|
(
0x6b
<<
14
)
|
(
0x1c
<<
21
)
|
(
0x43U
L
<<
28
)
|
(
0x49L
<<
35
)
|
(
0x24U
L
<<
42
)
|
(
0x49U
L
<<
49
));
// 11964378330978735131
AssertWriteVarint
(
Bytes
(
0x9b
,
0xa8
,
0xf9
,
0xc2
,
0xbb
,
0xd6
,
0x80
,
0x85
,
0xa6
,
0x01
)
,
new
byte
[]
{
0x9b
,
0xa8
,
0xf9
,
0xc2
,
0xbb
,
0xd6
,
0x80
,
0x85
,
0xa6
,
0x01
}
,
unchecked
((
ulong
)
((
0x1b
<<
0
)
|
(
0x28
<<
7
)
|
(
0x79
<<
14
)
|
(
0x42
<<
21
)
|
(
0x3bL
<<
28
)
|
(
0x56L
<<
35
)
|
(
0x00L
<<
42
)
|
...
...
@@ -168,14 +155,14 @@ namespace Google.ProtocolBuffers {
/// </summary>
[
Test
]
public
void
WriteLittleEndian
()
{
AssertWriteLittleEndian32
(
Bytes
(
0x78
,
0x56
,
0x34
,
0x12
)
,
0x12345678
);
AssertWriteLittleEndian32
(
Bytes
(
0xf0
,
0xde
,
0xbc
,
0x9a
)
,
0x9abcdef0
);
AssertWriteLittleEndian32
(
new
byte
[]
{
0x78
,
0x56
,
0x34
,
0x12
}
,
0x12345678
);
AssertWriteLittleEndian32
(
new
byte
[]
{
0xf0
,
0xde
,
0xbc
,
0x9a
}
,
0x9abcdef0
);
AssertWriteLittleEndian64
(
Bytes
(
0xf0
,
0xde
,
0xbc
,
0x9a
,
0x78
,
0x56
,
0x34
,
0x12
)
,
new
byte
[]{
0xf0
,
0xde
,
0xbc
,
0x9a
,
0x78
,
0x56
,
0x34
,
0x12
}
,
0x123456789abcdef0L
);
AssertWriteLittleEndian64
(
Bytes
(
0x78
,
0x56
,
0x34
,
0x12
,
0xf0
,
0xde
,
0xbc
,
0x9a
)
,
new
byte
[]{
0x78
,
0x56
,
0x34
,
0x12
,
0xf0
,
0xde
,
0xbc
,
0x9a
}
,
0x9abcdef012345678U
L
);
}
...
...
csharp/ProtocolBuffers.Test/TestUtil.cs
View file @
feb9385b
...
...
@@ -129,6 +129,9 @@ namespace Google.ProtocolBuffers {
registry
.
Add
(
UnitTestProtoFile
.
DefaultCordExtension
);
}
internal
static
string
ReadTextFromFile
(
string
filePath
)
{
return
ReadBytesFromFile
(
filePath
).
ToStringUtf8
();
}
internal
static
ByteString
ReadBytesFromFile
(
String
filename
)
{
byte
[]
data
=
File
.
ReadAllBytes
(
Path
.
Combine
(
TestDataDirectory
,
filename
));
...
...
@@ -1334,5 +1337,16 @@ namespace Google.ProtocolBuffers {
Assert
.
AreEqual
(
"abc"
,
message
.
GetExtension
(
UnitTestProtoFile
.
DefaultStringPieceExtension
));
Assert
.
AreEqual
(
"123"
,
message
.
GetExtension
(
UnitTestProtoFile
.
DefaultCordExtension
));
}
/// <summary>
/// Helper to construct a byte array from a bunch of bytes.
/// </summary>
internal
static
byte
[]
Bytes
(
params
byte
[]
bytesAsInts
)
{
byte
[]
bytes
=
new
byte
[
bytesAsInts
.
Length
];
for
(
int
i
=
0
;
i
<
bytesAsInts
.
Length
;
i
++)
{
bytes
[
i
]
=
(
byte
)
bytesAsInts
[
i
];
}
return
bytes
;
}
}
}
csharp/ProtocolBuffers.Test/TextFormatTest.cs
View file @
feb9385b
using
System
;
using
System.
Collections.Generic
;
using
System.
IO
;
using
System.Text
;
using
Google.ProtocolBuffers.TestProtos
;
using
NUnit.Framework
;
namespace
Google.ProtocolBuffers
{
[
TestFixture
]
public
class
TextFormatTest
{
/// <summary>
/// A basic string with different escapable characters for testing.
/// </summary>
private
const
string
EscapeTestString
=
"\"A string with ' characters \n and \r newlines and \t tabs and \001 "
+
"slashes \\"
;
/// <summary>
/// A representation of the above string with all the characters escaped.
/// </summary>
private
const
string
EscapeTestStringEscaped
=
"\"\\\"A string with \\' characters \\n and \\r newlines "
+
"and \\t tabs and \\001 slashes \\\\\""
;
private
static
readonly
string
AllFieldsSetText
=
TestUtil
.
ReadTextFromFile
(
"text_format_unittest_data.txt"
);
private
static
readonly
string
AllExtensionsSetText
=
TestUtil
.
ReadTextFromFile
(
"text_format_unittest_extensions_data.txt"
);
/// <summary>
/// Note that this is slightly different to the Java - 123.0 becomes 123, and 1.23E17 becomes 1.23E+17.
/// Both of these differences can be parsed by the Java and the C++, and we can parse their output too.
/// </summary>
private
const
string
ExoticText
=
"repeated_int32: -1\n"
+
"repeated_int32: -2147483648\n"
+
"repeated_int64: -1\n"
+
"repeated_int64: -9223372036854775808\n"
+
"repeated_uint32: 4294967295\n"
+
"repeated_uint32: 2147483648\n"
+
"repeated_uint64: 18446744073709551615\n"
+
"repeated_uint64: 9223372036854775808\n"
+
"repeated_double: 123\n"
+
"repeated_double: 123.5\n"
+
"repeated_double: 0.125\n"
+
"repeated_double: 1.23E+17\n"
+
"repeated_double: 1.235E+22\n"
+
"repeated_double: 1.235E-18\n"
+
"repeated_double: 123.456789\n"
+
"repeated_double: Infinity\n"
+
"repeated_double: -Infinity\n"
+
"repeated_double: NaN\n"
+
"repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""
+
"\\341\\210\\264\"\n"
+
"repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n"
;
private
const
string
MessageSetText
=
"[protobuf_unittest.TestMessageSetExtension1] {\n"
+
" i: 123\n"
+
"}\n"
+
"[protobuf_unittest.TestMessageSetExtension2] {\n"
+
" str: \"foo\"\n"
+
"}\n"
;
/// <summary>
/// Print TestAllTypes and compare with golden file.
/// </summary>
[
Test
]
public
void
PrintMessage
()
{
string
text
=
TextFormat
.
PrintToString
(
TestUtil
.
GetAllSet
());
Assert
.
AreEqual
(
AllFieldsSetText
.
Replace
(
"\r\n"
,
"\n"
),
text
.
Replace
(
"\r\n"
,
"\n"
));
}
/// <summary>
/// Print TestAllExtensions and compare with golden file.
/// </summary>
[
Test
]
public
void
PrintExtensions
()
{
string
text
=
TextFormat
.
PrintToString
(
TestUtil
.
GetAllExtensionsSet
());
Assert
.
AreEqual
(
AllExtensionsSetText
.
Replace
(
"\r\n"
,
"\n"
),
text
.
Replace
(
"\r\n"
,
"\n"
));
}
/// <summary>
/// Test printing of unknown fields in a message.
/// </summary>
[
Test
]
public
void
PrintUnknownFields
()
{
TestEmptyMessage
message
=
TestEmptyMessage
.
CreateBuilder
()
.
SetUnknownFields
(
UnknownFieldSet
.
CreateBuilder
()
.
AddField
(
5
,
UnknownField
.
CreateBuilder
()
.
AddVarint
(
1
)
.
AddFixed32
(
2
)
.
AddFixed64
(
3
)
.
AddLengthDelimited
(
ByteString
.
CopyFromUtf8
(
"4"
))
.
AddGroup
(
UnknownFieldSet
.
CreateBuilder
()
.
AddField
(
10
,
UnknownField
.
CreateBuilder
()
.
AddVarint
(
5
)
.
Build
())
.
Build
())
.
Build
())
.
AddField
(
8
,
UnknownField
.
CreateBuilder
()
.
AddVarint
(
1
)
.
AddVarint
(
2
)
.
AddVarint
(
3
)
.
Build
())
.
AddField
(
15
,
UnknownField
.
CreateBuilder
()
.
AddVarint
(
0xABCDEF1234567890L
)
.
AddFixed32
(
0xABCD1234
)
.
AddFixed64
(
0xABCDEF1234567890L
)
.
Build
())
.
Build
())
.
Build
();
Assert
.
AreEqual
(
"5: 1\n"
+
"5: 0x00000002\n"
+
"5: 0x0000000000000003\n"
+
"5: \"4\"\n"
+
"5 {\n"
+
" 10: 5\n"
+
"}\n"
+
"8: 1\n"
+
"8: 2\n"
+
"8: 3\n"
+
"15: 12379813812177893520\n"
+
"15: 0xabcd1234\n"
+
"15: 0xabcdef1234567890\n"
,
TextFormat
.
PrintToString
(
message
));
}
/// <summary>
/// Helper to construct a ByteString from a string containing only 8-bit
/// characters. The characters are converted directly to bytes, *not*
/// encoded using UTF-8.
/// </summary>
private
static
ByteString
Bytes
(
string
str
)
{
return
ByteString
.
CopyFrom
(
Encoding
.
GetEncoding
(
28591
).
GetBytes
(
str
));
}
[
Test
]
public
void
PrintExotic
()
{
IMessage
message
=
TestAllTypes
.
CreateBuilder
()
// Signed vs. unsigned numbers.
.
AddRepeatedInt32
(-
1
)
.
AddRepeatedUint32
(
uint
.
MaxValue
)
.
AddRepeatedInt64
(-
1
)
.
AddRepeatedUint64
(
ulong
.
MaxValue
)
.
AddRepeatedInt32
(
1
<<
31
)
.
AddRepeatedUint32
(
1U
<<
31
)
.
AddRepeatedInt64
(
1L
<<
63
)
.
AddRepeatedUint64
(
1U
L
<<
63
)
// Floats of various precisions and exponents.
.
AddRepeatedDouble
(
123
)
.
AddRepeatedDouble
(
123.5
)
.
AddRepeatedDouble
(
0.125
)
.
AddRepeatedDouble
(
123
e15
)
.
AddRepeatedDouble
(
123.5
e20
)
.
AddRepeatedDouble
(
123.5e-20
)
.
AddRepeatedDouble
(
123.456789
)
.
AddRepeatedDouble
(
Double
.
PositiveInfinity
)
.
AddRepeatedDouble
(
Double
.
NegativeInfinity
)
.
AddRepeatedDouble
(
Double
.
NaN
)
// Strings and bytes that needing escaping.
.
AddRepeatedString
(
"\0\u0001\u0007\b\f\n\r\t\v\\\'\"\u1234"
)
.
AddRepeatedBytes
(
Bytes
(
"\0\u0001\u0007\b\f\n\r\t\v\\\'\"\u00fe"
))
.
Build
();
Assert
.
AreEqual
(
ExoticText
,
message
.
ToString
());
}
[
Test
]
public
void
PrintMessageSet
()
{
TestMessageSet
messageSet
=
TestMessageSet
.
CreateBuilder
()
.
SetExtension
(
TestMessageSetExtension1
.
MessageSetExtension
,
TestMessageSetExtension1
.
CreateBuilder
().
SetI
(
123
).
Build
())
.
SetExtension
(
TestMessageSetExtension2
.
MessageSetExtension
,
TestMessageSetExtension2
.
CreateBuilder
().
SetStr
(
"foo"
).
Build
())
.
Build
();
Assert
.
AreEqual
(
MessageSetText
,
messageSet
.
ToString
());
}
// =================================================================
[
Test
]
[
Ignore
(
"Parsing not implemented"
)]
public
void
Parse
()
{
TestAllTypes
.
Builder
builder
=
TestAllTypes
.
CreateBuilder
();
TextFormat
.
Merge
(
AllFieldsSetText
,
builder
);
TestUtil
.
AssertAllFieldsSet
(
builder
.
Build
());
}
[
Test
]
[
Ignore
(
"Parsing not implemented"
)]
public
void
ParseReader
()
{
TestAllTypes
.
Builder
builder
=
TestAllTypes
.
CreateBuilder
();
TextFormat
.
Merge
(
new
StringReader
(
AllFieldsSetText
),
builder
);
TestUtil
.
AssertAllFieldsSet
(
builder
.
Build
());
}
[
Test
]
[
Ignore
(
"Parsing not implemented"
)]
public
void
ParseExtensions
()
{
TestAllExtensions
.
Builder
builder
=
TestAllExtensions
.
CreateBuilder
();
TextFormat
.
Merge
(
AllExtensionsSetText
,
TestUtil
.
CreateExtensionRegistry
(),
builder
);
TestUtil
.
AssertAllExtensionsSet
(
builder
.
Build
());
}
[
Test
]
[
Ignore
(
"Parsing not implemented"
)]
public
void
ParseExotic
()
{
TestAllTypes
.
Builder
builder
=
TestAllTypes
.
CreateBuilder
();
TextFormat
.
Merge
(
ExoticText
,
builder
);
// Too lazy to check things individually. Don't try to debug this
// if testPrintExotic() is Assert.Failing.
Assert
.
AreEqual
(
ExoticText
,
builder
.
Build
().
ToString
());
}
[
Test
]
[
Ignore
(
"Parsing not implemented"
)]
public
void
ParseMessageSet
()
{
ExtensionRegistry
extensionRegistry
=
ExtensionRegistry
.
CreateInstance
();
extensionRegistry
.
Add
(
TestMessageSetExtension1
.
MessageSetExtension
);
extensionRegistry
.
Add
(
TestMessageSetExtension2
.
MessageSetExtension
);
TestMessageSet
.
Builder
builder
=
TestMessageSet
.
CreateBuilder
();
TextFormat
.
Merge
(
MessageSetText
,
extensionRegistry
,
builder
);
TestMessageSet
messageSet
=
builder
.
Build
();
Assert
.
IsTrue
(
messageSet
.
HasExtension
(
TestMessageSetExtension1
.
MessageSetExtension
));
Assert
.
AreEqual
(
123
,
messageSet
.
GetExtension
(
TestMessageSetExtension1
.
MessageSetExtension
).
I
);
Assert
.
IsTrue
(
messageSet
.
HasExtension
(
TestMessageSetExtension2
.
MessageSetExtension
));
Assert
.
AreEqual
(
"foo"
,
messageSet
.
GetExtension
(
TestMessageSetExtension2
.
MessageSetExtension
).
Str
);
}
[
Test
]
[
Ignore
(
"Parsing not implemented"
)]
public
void
ParseNumericEnum
()
{
TestAllTypes
.
Builder
builder
=
TestAllTypes
.
CreateBuilder
();
TextFormat
.
Merge
(
"optional_nested_enum: 2"
,
builder
);
Assert
.
AreEqual
(
TestAllTypes
.
Types
.
NestedEnum
.
BAR
,
builder
.
OptionalNestedEnum
);
}
[
Test
]
[
Ignore
(
"Parsing not implemented"
)]
public
void
ParseAngleBrackets
()
{
TestAllTypes
.
Builder
builder
=
TestAllTypes
.
CreateBuilder
();
TextFormat
.
Merge
(
"OptionalGroup: < a: 1 >"
,
builder
);
Assert
.
IsTrue
(
builder
.
HasOptionalGroup
);
Assert
.
AreEqual
(
1
,
builder
.
OptionalGroup
.
A
);
}
private
static
void
AssertParseError
(
string
error
,
string
text
)
{
TestAllTypes
.
Builder
builder
=
TestAllTypes
.
CreateBuilder
();
try
{
TextFormat
.
Merge
(
text
,
TestUtil
.
CreateExtensionRegistry
(),
builder
);
Assert
.
Fail
(
"Expected parse exception."
);
}
catch
(
FormatException
e
)
{
Assert
.
AreEqual
(
error
,
e
.
Message
);
}
}
[
Test
]
[
Ignore
(
"Parsing not implemented"
)]
public
void
ParseErrors
()
{
AssertParseError
(
"1:16: Expected \":\"."
,
"optional_int32 123"
);
AssertParseError
(
"1:23: Expected identifier."
,
"optional_nested_enum: ?"
);
AssertParseError
(
"1:18: Couldn't parse integer: Number must be positive: -1"
,
"optional_uint32: -1"
);
AssertParseError
(
"1:17: Couldn't parse integer: Number out of range for 32-bit signed "
+
"integer: 82301481290849012385230157"
,
"optional_int32: 82301481290849012385230157"
);
AssertParseError
(
"1:16: Expected \"true\" or \"false\"."
,
"optional_bool: maybe"
);
AssertParseError
(
"1:18: Expected string."
,
"optional_string: 123"
);
AssertParseError
(
"1:18: string missing ending quote."
,
"optional_string: \"ueoauaoe"
);
AssertParseError
(
"1:18: string missing ending quote."
,
"optional_string: \"ueoauaoe\n"
+
"optional_int32: 123"
);
AssertParseError
(
"1:18: Invalid escape sequence: '\\z'"
,
"optional_string: \"\\z\""
);
AssertParseError
(
"1:18: string missing ending quote."
,
"optional_string: \"ueoauaoe\n"
+
"optional_int32: 123"
);
AssertParseError
(
"1:2: Extension \"nosuchext\" not found in the ExtensionRegistry."
,
"[nosuchext]: 123"
);
AssertParseError
(
"1:20: Extension \"protobuf_unittest.optional_int32_extension\" does "
+
"not extend message type \"protobuf_unittest.TestAllTypes\"."
,
"[protobuf_unittest.optional_int32_extension]: 123"
);
AssertParseError
(
"1:1: Message type \"protobuf_unittest.TestAllTypes\" has no field "
+
"named \"nosuchfield\"."
,
"nosuchfield: 123"
);
AssertParseError
(
"1:21: Expected \">\"."
,
"OptionalGroup < a: 1"
);
AssertParseError
(
"1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no "
+
"value named \"NO_SUCH_VALUE\"."
,
"optional_nested_enum: NO_SUCH_VALUE"
);
AssertParseError
(
"1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no "
+
"value with number 123."
,
"optional_nested_enum: 123"
);
// Delimiters must match.
AssertParseError
(
"1:22: Expected identifier."
,
"OptionalGroup < a: 1 }"
);
AssertParseError
(
"1:22: Expected identifier."
,
"OptionalGroup { a: 1 >"
);
}
// =================================================================
private
static
ByteString
Bytes
(
params
byte
[]
bytes
)
{
return
ByteString
.
CopyFrom
(
bytes
);
}
private
delegate
void
FormattingAction
();
private
static
void
AssertFormatException
(
FormattingAction
action
)
{
try
{
action
();
Assert
.
Fail
(
"Should have thrown an exception."
);
}
catch
(
FormatException
)
{
// success
}
}
[
Test
]
public
void
Escape
()
{
// Escape sequences.
Assert
.
AreEqual
(
"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""
,
TextFormat
.
EscapeBytes
(
Bytes
(
"\0\u0001\u0007\b\f\n\r\t\v\\\'\""
)));
Assert
.
AreEqual
(
"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""
,
TextFormat
.
EscapeText
(
"\0\u0001\u0007\b\f\n\r\t\v\\\'\""
));
Assert
.
AreEqual
(
Bytes
(
"\0\u0001\u0007\b\f\n\r\t\v\\\'\""
),
TextFormat
.
UnescapeBytes
(
"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""
));
Assert
.
AreEqual
(
"\0\u0001\u0007\b\f\n\r\t\v\\\'\""
,
TextFormat
.
UnescapeText
(
"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""
));
// Unicode handling.
Assert
.
AreEqual
(
"\\341\\210\\264"
,
TextFormat
.
EscapeText
(
"\u1234"
));
Assert
.
AreEqual
(
"\\341\\210\\264"
,
TextFormat
.
EscapeBytes
(
Bytes
(
0xe1
,
0x88
,
0xb4
)));
Assert
.
AreEqual
(
"\u1234"
,
TextFormat
.
UnescapeText
(
"\\341\\210\\264"
));
Assert
.
AreEqual
(
Bytes
(
0xe1
,
0x88
,
0xb4
),
TextFormat
.
UnescapeBytes
(
"\\341\\210\\264"
));
Assert
.
AreEqual
(
"\u1234"
,
TextFormat
.
UnescapeText
(
"\\xe1\\x88\\xb4"
));
Assert
.
AreEqual
(
Bytes
(
0xe1
,
0x88
,
0xb4
),
TextFormat
.
UnescapeBytes
(
"\\xe1\\x88\\xb4"
));
// Errors.
AssertFormatException
(()
=>
TextFormat
.
UnescapeText
(
"\\x"
));
AssertFormatException
(()
=>
TextFormat
.
UnescapeText
(
"\\z"
));
AssertFormatException
(()
=>
TextFormat
.
UnescapeText
(
"\\"
));
}
[
Test
]
public
void
ParseInteger
()
{
Assert
.
AreEqual
(
0
,
TextFormat
.
ParseInt32
(
"0"
));
Assert
.
AreEqual
(
1
,
TextFormat
.
ParseInt32
(
"1"
));
Assert
.
AreEqual
(
-
1
,
TextFormat
.
ParseInt32
(
"-1"
));
Assert
.
AreEqual
(
12345
,
TextFormat
.
ParseInt32
(
"12345"
));
Assert
.
AreEqual
(
-
12345
,
TextFormat
.
ParseInt32
(
"-12345"
));
Assert
.
AreEqual
(
2147483647
,
TextFormat
.
ParseInt32
(
"2147483647"
));
Assert
.
AreEqual
(-
2147483648
,
TextFormat
.
ParseInt32
(
"-2147483648"
));
Assert
.
AreEqual
(
0
,
TextFormat
.
ParseUInt32
(
"0"
));
Assert
.
AreEqual
(
1
,
TextFormat
.
ParseUInt32
(
"1"
));
Assert
.
AreEqual
(
12345
,
TextFormat
.
ParseUInt32
(
"12345"
));
Assert
.
AreEqual
(
2147483647
,
TextFormat
.
ParseUInt32
(
"2147483647"
));
Assert
.
AreEqual
(
2147483648U
,
TextFormat
.
ParseUInt32
(
"2147483648"
));
Assert
.
AreEqual
(
4294967295U
,
TextFormat
.
ParseUInt32
(
"4294967295"
));
Assert
.
AreEqual
(
0L
,
TextFormat
.
ParseInt64
(
"0"
));
Assert
.
AreEqual
(
1L
,
TextFormat
.
ParseInt64
(
"1"
));
Assert
.
AreEqual
(
-
1L
,
TextFormat
.
ParseInt64
(
"-1"
));
Assert
.
AreEqual
(
12345L
,
TextFormat
.
ParseInt64
(
"12345"
));
Assert
.
AreEqual
(
-
12345L
,
TextFormat
.
ParseInt64
(
"-12345"
));
Assert
.
AreEqual
(
2147483647L
,
TextFormat
.
ParseInt64
(
"2147483647"
));
Assert
.
AreEqual
(-
2147483648L
,
TextFormat
.
ParseInt64
(
"-2147483648"
));
Assert
.
AreEqual
(
4294967295L
,
TextFormat
.
ParseInt64
(
"4294967295"
));
Assert
.
AreEqual
(
4294967296L
,
TextFormat
.
ParseInt64
(
"4294967296"
));
Assert
.
AreEqual
(
9223372036854775807L
,
TextFormat
.
ParseInt64
(
"9223372036854775807"
));
Assert
.
AreEqual
(-
9223372036854775808L
,
TextFormat
.
ParseInt64
(
"-9223372036854775808"
));
Assert
.
AreEqual
(
0L
,
TextFormat
.
ParseUInt64
(
"0"
));
Assert
.
AreEqual
(
1L
,
TextFormat
.
ParseUInt64
(
"1"
));
Assert
.
AreEqual
(
12345L
,
TextFormat
.
ParseUInt64
(
"12345"
));
Assert
.
AreEqual
(
2147483647L
,
TextFormat
.
ParseUInt64
(
"2147483647"
));
Assert
.
AreEqual
(
4294967295L
,
TextFormat
.
ParseUInt64
(
"4294967295"
));
Assert
.
AreEqual
(
4294967296L
,
TextFormat
.
ParseUInt64
(
"4294967296"
));
Assert
.
AreEqual
(
9223372036854775807U
L
,
TextFormat
.
ParseUInt64
(
"9223372036854775807"
));
Assert
.
AreEqual
(
9223372036854775808U
L
,
TextFormat
.
ParseUInt64
(
"9223372036854775808"
));
Assert
.
AreEqual
(
18446744073709551615U
L
,
TextFormat
.
ParseUInt64
(
"18446744073709551615"
));
// Hex
Assert
.
AreEqual
(
0x1234abcd
,
TextFormat
.
ParseInt32
(
"0x1234abcd"
));
Assert
.
AreEqual
(-
0x1234abcd
,
TextFormat
.
ParseInt32
(
"-0x1234abcd"
));
Assert
.
AreEqual
(
0xffffffffffffffffU
L
,
TextFormat
.
ParseUInt64
(
"0xffffffffffffffff"
));
Assert
.
AreEqual
(
0x7fffffffffffffffL
,
TextFormat
.
ParseInt64
(
"0x7fffffffffffffff"
));
// Octal
Assert
.
AreEqual
(
342391
,
TextFormat
.
ParseInt32
(
"01234567"
));
// Out-of-range
AssertFormatException
(()
=>
TextFormat
.
ParseInt32
(
"2147483648"
));
AssertFormatException
(()
=>
TextFormat
.
ParseInt32
(
"-2147483649"
));
AssertFormatException
(()
=>
TextFormat
.
ParseUInt32
(
"4294967296"
));
AssertFormatException
(()
=>
TextFormat
.
ParseUInt32
(
"-1"
));
AssertFormatException
(()
=>
TextFormat
.
ParseInt64
(
"9223372036854775808"
));
AssertFormatException
(()
=>
TextFormat
.
ParseInt64
(
"-9223372036854775809"
));
AssertFormatException
(()
=>
TextFormat
.
ParseUInt64
(
"18446744073709551616"
));
AssertFormatException
(()
=>
TextFormat
.
ParseUInt64
(
"-1"
));
AssertFormatException
(()
=>
TextFormat
.
ParseInt32
(
"abcd"
));
}
}
}
csharp/ProtocolBuffers/TextFormat.cs
View file @
feb9385b
...
...
@@ -187,19 +187,23 @@ namespace Google.ProtocolBuffers {
}
}
internal
static
ulong
ParseUInt64
(
string
text
)
{
// TODO(jonskeet): InternalsVisibleTo
public
static
ulong
ParseUInt64
(
string
text
)
{
return
(
ulong
)
ParseInteger
(
text
,
false
,
true
);
}
internal
static
long
ParseInt64
(
string
text
)
{
// TODO(jonskeet): InternalsVisibleTo
public
static
long
ParseInt64
(
string
text
)
{
return
ParseInteger
(
text
,
true
,
true
);
}
internal
static
uint
ParseUInt32
(
string
text
)
{
// TODO(jonskeet): InternalsVisibleTo
public
static
uint
ParseUInt32
(
string
text
)
{
return
(
uint
)
ParseInteger
(
text
,
false
,
false
);
}
internal
static
int
ParseInt32
(
string
text
)
{
// TODO(jonskeet): InternalsVisibleTo
public
static
int
ParseInt32
(
string
text
)
{
return
(
int
)
ParseInteger
(
text
,
true
,
false
);
}
...
...
@@ -224,10 +228,17 @@ namespace Google.ProtocolBuffers {
text
=
text
.
Substring
(
2
);
}
else
if
(
text
.
StartsWith
(
"0"
))
{
radix
=
8
;
text
=
text
.
Substring
(
1
);
}
ulong
result
=
Convert
.
ToUInt64
(
text
,
radix
);
ulong
result
;
try
{
// Workaround for https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448
// We should be able to use Convert.ToUInt64 for all cases.
result
=
radix
==
10
?
ulong
.
Parse
(
text
)
:
Convert
.
ToUInt64
(
text
,
radix
);
}
catch
(
OverflowException
)
{
// Convert OverflowException to FormatException so there's a single exception type this method can throw.
throw
new
FormatException
(
"Number of out range: "
+
original
);
}
if
(
negative
)
{
ulong
max
=
isLong
?
0x8000000000000000U
L
:
0x80000000L
;
...
...
@@ -276,12 +287,22 @@ namespace Google.ProtocolBuffers {
}
}
/// <summary>
/// Unescapes a text string as escaped using <see cref="EscapeText(string)" />.
/// Two-digit hex escapes (starting with "\x" are also recognised.
/// TODO(jonskeet): InternalsVisibleTo
/// </summary>
public
static
string
UnescapeText
(
string
input
)
{
return
UnescapeBytes
(
input
).
ToStringUtf8
();
}
/// <summary>
/// Like <see cref="EscapeBytes" /> but escapes a text string.
/// The string is first encoded as UTF-8, then each byte escaped individually.
/// The returned value is guaranteed to be entirely ASCII.
/// TODO(jonskeet): InternalsVisibleTo
/// </summary>
static
S
tring
EscapeText
(
string
input
)
{
public
static
s
tring
EscapeText
(
string
input
)
{
return
EscapeBytes
(
ByteString
.
CopyFromUtf8
(
input
));
}
/// <summary>
...
...
@@ -292,8 +313,9 @@ namespace Google.ProtocolBuffers {
/// which no defined short-hand escape sequence is defined will be escaped
/// using 3-digit octal sequences.
/// The returned value is guaranteed to be entirely ASCII.
/// TODO(jonskeet): InternalsVisibleTo
/// </summary>
p
rivate
static
String
EscapeBytes
(
ByteString
input
)
{
p
ublic
static
String
EscapeBytes
(
ByteString
input
)
{
StringBuilder
builder
=
new
StringBuilder
(
input
.
Length
);
foreach
(
byte
b
in
input
)
{
switch
(
b
)
{
...
...
@@ -309,7 +331,7 @@ namespace Google.ProtocolBuffers {
case
(
byte
)
'\''
:
builder
.
Append
(
"\\\'"
);
break
;
case
(
byte
)
'"'
:
builder
.
Append
(
"\\\""
);
break
;
default
:
if
(
b
>=
0x20
)
{
if
(
b
>=
0x20
&&
b
<
128
)
{
builder
.
Append
((
char
)
b
);
}
else
{
builder
.
Append
(
'\\'
);
...
...
@@ -325,8 +347,9 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Performs string unescaping from C style (octal, hex, form feeds, tab etc) into a byte string.
/// TODO(jonskeet): Make this internal again, and use InternalsVisibleTo.
/// </summary>
internal
static
ByteString
UnescapeBytes
(
string
input
)
{
public
static
ByteString
UnescapeBytes
(
string
input
)
{
byte
[]
result
=
new
byte
[
input
.
Length
];
int
pos
=
0
;
for
(
int
i
=
0
;
i
<
input
.
Length
;
i
++)
{
...
...
@@ -393,5 +416,21 @@ namespace Google.ProtocolBuffers {
return
ByteString
.
CopyFrom
(
result
,
0
,
pos
);
}
public
static
void
Merge
(
string
text
,
IBuilder
builder
)
{
throw
new
NotImplementedException
();
}
public
static
void
Merge
(
TextReader
reader
,
IBuilder
builder
)
{
throw
new
NotImplementedException
();
}
public
static
void
Merge
(
string
text
,
ExtensionRegistry
registry
,
IBuilder
builder
)
{
throw
new
NotImplementedException
();
}
public
static
void
Merge
(
TextReader
reader
,
ExtensionRegistry
registry
,
IBuilder
builder
)
{
throw
new
NotImplementedException
();
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment