Merge pull request #2701 from anandolee/master
Add csharp compatibility tests against v3.0.0pull/2814/head
commit
3f6f73b796
37 changed files with 7893 additions and 1 deletions
@ -0,0 +1,126 @@ |
|||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
// These proto descriptors have at one time been reported as an issue or defect. |
||||||
|
// They are kept here to replicate the issue, and continue to verify the fix. |
||||||
|
|
||||||
|
// Issue: Non-"Google.Protobuffers" namespace will ensure that protobuffer library types are qualified |
||||||
|
option csharp_namespace = "UnitTest.Issues.TestProtos"; |
||||||
|
|
||||||
|
package unittest_issues; |
||||||
|
option optimize_for = SPEED; |
||||||
|
|
||||||
|
// Issue 307: when generating doubly-nested types, any references |
||||||
|
// should be of the form A.Types.B.Types.C. |
||||||
|
message Issue307 { |
||||||
|
message NestedOnce { |
||||||
|
message NestedTwice { |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Old issue 13: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=13 |
||||||
|
// New issue 309: https://github.com/google/protobuf/issues/309 |
||||||
|
|
||||||
|
// message A { |
||||||
|
// optional int32 _A = 1; |
||||||
|
// } |
||||||
|
|
||||||
|
// message B { |
||||||
|
// optional int32 B_ = 1; |
||||||
|
// } |
||||||
|
|
||||||
|
//message AB { |
||||||
|
// optional int32 a_b = 1; |
||||||
|
//} |
||||||
|
|
||||||
|
// Similar issue with numeric names |
||||||
|
// Java code failed too, so probably best for this to be a restriction. |
||||||
|
// See https://github.com/google/protobuf/issues/308 |
||||||
|
// message NumberField { |
||||||
|
// optional int32 _01 = 1; |
||||||
|
// } |
||||||
|
|
||||||
|
// issue 19 - negative enum values |
||||||
|
|
||||||
|
enum NegativeEnum { |
||||||
|
NEGATIVE_ENUM_ZERO = 0; |
||||||
|
FiveBelow = -5; |
||||||
|
MinusOne = -1; |
||||||
|
} |
||||||
|
|
||||||
|
message NegativeEnumMessage { |
||||||
|
NegativeEnum value = 1; |
||||||
|
repeated NegativeEnum values = 2 [packed = false]; |
||||||
|
repeated NegativeEnum packed_values = 3 [packed=true]; |
||||||
|
} |
||||||
|
|
||||||
|
// Issue 21: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=21 |
||||||
|
// Decorate fields with [deprecated=true] as [System.Obsolete] |
||||||
|
|
||||||
|
message DeprecatedChild { |
||||||
|
} |
||||||
|
|
||||||
|
enum DeprecatedEnum { |
||||||
|
DEPRECATED_ZERO = 0; |
||||||
|
one = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message DeprecatedFieldsMessage { |
||||||
|
int32 PrimitiveValue = 1 [deprecated = true]; |
||||||
|
repeated int32 PrimitiveArray = 2 [deprecated = true]; |
||||||
|
|
||||||
|
DeprecatedChild MessageValue = 3 [deprecated = true]; |
||||||
|
repeated DeprecatedChild MessageArray = 4 [deprecated = true]; |
||||||
|
|
||||||
|
DeprecatedEnum EnumValue = 5 [deprecated = true]; |
||||||
|
repeated DeprecatedEnum EnumArray = 6 [deprecated = true]; |
||||||
|
} |
||||||
|
|
||||||
|
// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45 |
||||||
|
message ItemField { |
||||||
|
int32 item = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message ReservedNames { |
||||||
|
// Force a nested type called Types |
||||||
|
message SomeNestedType { |
||||||
|
} |
||||||
|
|
||||||
|
int32 types = 1; |
||||||
|
int32 descriptor = 2; |
||||||
|
} |
||||||
|
|
||||||
|
message TestJsonFieldOrdering { |
||||||
|
// These fields are deliberately not declared in numeric |
||||||
|
// order, and the oneof fields aren't contiguous either. |
||||||
|
// This allows for reasonably robust tests of JSON output |
||||||
|
// ordering. |
||||||
|
// TestFieldOrderings in unittest_proto3.proto is similar, |
||||||
|
// but doesn't include oneofs. |
||||||
|
// TODO: Consider adding oneofs to TestFieldOrderings, although |
||||||
|
// that will require fixing other tests in multiple platforms. |
||||||
|
// Alternatively, consider just adding this to |
||||||
|
// unittest_proto3.proto if multiple platforms want it. |
||||||
|
|
||||||
|
int32 plain_int32 = 4; |
||||||
|
|
||||||
|
oneof o1 { |
||||||
|
string o1_string = 2; |
||||||
|
int32 o1_int32 = 5; |
||||||
|
} |
||||||
|
|
||||||
|
string plain_string = 1; |
||||||
|
|
||||||
|
oneof o2 { |
||||||
|
int32 o2_int32 = 6; |
||||||
|
string o2_string = 3; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
message TestJsonName { |
||||||
|
// Message for testing the effects for of the json_name option |
||||||
|
string name = 1; |
||||||
|
string description = 2 [json_name = "desc"]; |
||||||
|
string guid = 3 [json_name = "exid"]; |
||||||
|
} |
@ -0,0 +1,120 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// https://developers.google.com/protocol-buffers/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
// This file is mostly equivalent to map_unittest.proto, but imports |
||||||
|
// unittest_proto3.proto instead of unittest.proto, so that it only |
||||||
|
// uses proto3 messages. This makes it suitable for testing |
||||||
|
// implementations which only support proto3. |
||||||
|
// The TestRequiredMessageMap message has been removed as there are no |
||||||
|
// required fields in proto3. |
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
option cc_enable_arenas = true; |
||||||
|
option csharp_namespace = "Google.Protobuf.TestProtos"; |
||||||
|
|
||||||
|
import "google/protobuf/unittest_proto3.proto"; |
||||||
|
|
||||||
|
// We don't put this in a package within proto2 because we need to make sure |
||||||
|
// that the generated code doesn't depend on being in the proto2 namespace. |
||||||
|
// In map_test_util.h we do "using namespace unittest = protobuf_unittest". |
||||||
|
package protobuf_unittest; |
||||||
|
|
||||||
|
// Tests maps. |
||||||
|
message TestMap { |
||||||
|
map<int32 , int32 > map_int32_int32 = 1; |
||||||
|
map<int64 , int64 > map_int64_int64 = 2; |
||||||
|
map<uint32 , uint32 > map_uint32_uint32 = 3; |
||||||
|
map<uint64 , uint64 > map_uint64_uint64 = 4; |
||||||
|
map<sint32 , sint32 > map_sint32_sint32 = 5; |
||||||
|
map<sint64 , sint64 > map_sint64_sint64 = 6; |
||||||
|
map<fixed32 , fixed32 > map_fixed32_fixed32 = 7; |
||||||
|
map<fixed64 , fixed64 > map_fixed64_fixed64 = 8; |
||||||
|
map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9; |
||||||
|
map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10; |
||||||
|
map<int32 , float > map_int32_float = 11; |
||||||
|
map<int32 , double > map_int32_double = 12; |
||||||
|
map<bool , bool > map_bool_bool = 13; |
||||||
|
map<string , string > map_string_string = 14; |
||||||
|
map<int32 , bytes > map_int32_bytes = 15; |
||||||
|
map<int32 , MapEnum > map_int32_enum = 16; |
||||||
|
map<int32 , ForeignMessage> map_int32_foreign_message = 17; |
||||||
|
} |
||||||
|
|
||||||
|
message TestMapSubmessage { |
||||||
|
TestMap test_map = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message TestMessageMap { |
||||||
|
map<int32, TestAllTypes> map_int32_message = 1; |
||||||
|
} |
||||||
|
|
||||||
|
// Two map fields share the same entry default instance. |
||||||
|
message TestSameTypeMap { |
||||||
|
map<int32, int32> map1 = 1; |
||||||
|
map<int32, int32> map2 = 2; |
||||||
|
} |
||||||
|
|
||||||
|
enum MapEnum { |
||||||
|
MAP_ENUM_FOO = 0; |
||||||
|
MAP_ENUM_BAR = 1; |
||||||
|
MAP_ENUM_BAZ = 2; |
||||||
|
} |
||||||
|
|
||||||
|
message TestArenaMap { |
||||||
|
map<int32 , int32 > map_int32_int32 = 1; |
||||||
|
map<int64 , int64 > map_int64_int64 = 2; |
||||||
|
map<uint32 , uint32 > map_uint32_uint32 = 3; |
||||||
|
map<uint64 , uint64 > map_uint64_uint64 = 4; |
||||||
|
map<sint32 , sint32 > map_sint32_sint32 = 5; |
||||||
|
map<sint64 , sint64 > map_sint64_sint64 = 6; |
||||||
|
map<fixed32 , fixed32 > map_fixed32_fixed32 = 7; |
||||||
|
map<fixed64 , fixed64 > map_fixed64_fixed64 = 8; |
||||||
|
map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9; |
||||||
|
map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10; |
||||||
|
map<int32 , float > map_int32_float = 11; |
||||||
|
map<int32 , double > map_int32_double = 12; |
||||||
|
map<bool , bool > map_bool_bool = 13; |
||||||
|
map<int32 , MapEnum > map_int32_enum = 14; |
||||||
|
map<int32 , ForeignMessage> map_int32_foreign_message = 15; |
||||||
|
} |
||||||
|
|
||||||
|
// Previously, message containing enum called Type cannot be used as value of |
||||||
|
// map field. |
||||||
|
message MessageContainingEnumCalledType { |
||||||
|
enum Type { |
||||||
|
TYPE_FOO = 0; |
||||||
|
} |
||||||
|
map<int32, MessageContainingEnumCalledType> type = 1; |
||||||
|
} |
||||||
|
|
||||||
|
// Previously, message cannot contain map field called "entry". |
||||||
|
message MessageContainingMapCalledEntry { |
||||||
|
map<int32, int32> entry = 1; |
||||||
|
} |
@ -0,0 +1,68 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// https://developers.google.com/protocol-buffers/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda) |
||||||
|
// Based on original Protocol Buffers design by |
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others. |
||||||
|
// |
||||||
|
// A proto file which is imported by unittest_proto3.proto to test importing. |
||||||
|
|
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
// We don't put this in a package within proto2 because we need to make sure |
||||||
|
// that the generated code doesn't depend on being in the proto2 namespace. |
||||||
|
// In test_util.h we do |
||||||
|
// "using namespace unittest_import = protobuf_unittest_import". |
||||||
|
package protobuf_unittest_import; |
||||||
|
|
||||||
|
option optimize_for = SPEED; |
||||||
|
option cc_enable_arenas = true; |
||||||
|
|
||||||
|
// Exercise the java_package option. |
||||||
|
option java_package = "com.google.protobuf.test"; |
||||||
|
option csharp_namespace = "Google.Protobuf.TestProtos"; |
||||||
|
|
||||||
|
// Do not set a java_outer_classname here to verify that Proto2 works without |
||||||
|
// one. |
||||||
|
|
||||||
|
// Test public import |
||||||
|
import public "google/protobuf/unittest_import_public_proto3.proto"; |
||||||
|
|
||||||
|
message ImportMessage { |
||||||
|
int32 d = 1; |
||||||
|
} |
||||||
|
|
||||||
|
enum ImportEnum { |
||||||
|
IMPORT_ENUM_UNSPECIFIED = 0; |
||||||
|
IMPORT_FOO = 7; |
||||||
|
IMPORT_BAR = 8; |
||||||
|
IMPORT_BAZ = 9; |
||||||
|
} |
||||||
|
|
@ -0,0 +1,42 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// https://developers.google.com/protocol-buffers/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
// Author: liujisi@google.com (Pherl Liu) |
||||||
|
|
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package protobuf_unittest_import; |
||||||
|
|
||||||
|
option java_package = "com.google.protobuf.test"; |
||||||
|
option csharp_namespace = "Google.Protobuf.TestProtos"; |
||||||
|
|
||||||
|
message PublicImportMessage { |
||||||
|
int32 e = 1; |
||||||
|
} |
@ -0,0 +1,388 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// https://developers.google.com/protocol-buffers/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda) |
||||||
|
// Based on original Protocol Buffers design by |
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others. |
||||||
|
// |
||||||
|
// A proto file we will use for unit testing. |
||||||
|
|
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
// Some generic_services option(s) added automatically. |
||||||
|
// See: http://go/proto2-generic-services-default |
||||||
|
option cc_generic_services = true; // auto-added |
||||||
|
option java_generic_services = true; // auto-added |
||||||
|
option py_generic_services = true; // auto-added |
||||||
|
option cc_enable_arenas = true; |
||||||
|
option csharp_namespace = "Google.Protobuf.TestProtos"; |
||||||
|
|
||||||
|
import "google/protobuf/unittest_import_proto3.proto"; |
||||||
|
|
||||||
|
// We don't put this in a package within proto2 because we need to make sure |
||||||
|
// that the generated code doesn't depend on being in the proto2 namespace. |
||||||
|
// In test_util.h we do "using namespace unittest = protobuf_unittest". |
||||||
|
package protobuf_unittest; |
||||||
|
|
||||||
|
// Protos optimized for SPEED use a strict superset of the generated code |
||||||
|
// of equivalent ones optimized for CODE_SIZE, so we should optimize all our |
||||||
|
// tests for speed unless explicitly testing code size optimization. |
||||||
|
option optimize_for = SPEED; |
||||||
|
|
||||||
|
option java_outer_classname = "UnittestProto"; |
||||||
|
|
||||||
|
// This proto includes every type of field in both singular and repeated |
||||||
|
// forms. |
||||||
|
message TestAllTypes { |
||||||
|
message NestedMessage { |
||||||
|
// The field name "b" fails to compile in proto1 because it conflicts with |
||||||
|
// a local variable named "b" in one of the generated methods. Doh. |
||||||
|
// This file needs to compile in proto1 to test backwards-compatibility. |
||||||
|
int32 bb = 1; |
||||||
|
} |
||||||
|
|
||||||
|
enum NestedEnum { |
||||||
|
NESTED_ENUM_UNSPECIFIED = 0; |
||||||
|
FOO = 1; |
||||||
|
BAR = 2; |
||||||
|
BAZ = 3; |
||||||
|
NEG = -1; // Intentionally negative. |
||||||
|
} |
||||||
|
|
||||||
|
// Singular |
||||||
|
int32 single_int32 = 1; |
||||||
|
int64 single_int64 = 2; |
||||||
|
uint32 single_uint32 = 3; |
||||||
|
uint64 single_uint64 = 4; |
||||||
|
sint32 single_sint32 = 5; |
||||||
|
sint64 single_sint64 = 6; |
||||||
|
fixed32 single_fixed32 = 7; |
||||||
|
fixed64 single_fixed64 = 8; |
||||||
|
sfixed32 single_sfixed32 = 9; |
||||||
|
sfixed64 single_sfixed64 = 10; |
||||||
|
float single_float = 11; |
||||||
|
double single_double = 12; |
||||||
|
bool single_bool = 13; |
||||||
|
string single_string = 14; |
||||||
|
bytes single_bytes = 15; |
||||||
|
|
||||||
|
NestedMessage single_nested_message = 18; |
||||||
|
ForeignMessage single_foreign_message = 19; |
||||||
|
protobuf_unittest_import.ImportMessage single_import_message = 20; |
||||||
|
|
||||||
|
NestedEnum single_nested_enum = 21; |
||||||
|
ForeignEnum single_foreign_enum = 22; |
||||||
|
protobuf_unittest_import.ImportEnum single_import_enum = 23; |
||||||
|
|
||||||
|
// Defined in unittest_import_public.proto |
||||||
|
protobuf_unittest_import.PublicImportMessage |
||||||
|
single_public_import_message = 26; |
||||||
|
|
||||||
|
// Repeated |
||||||
|
repeated int32 repeated_int32 = 31; |
||||||
|
repeated int64 repeated_int64 = 32; |
||||||
|
repeated uint32 repeated_uint32 = 33; |
||||||
|
repeated uint64 repeated_uint64 = 34; |
||||||
|
repeated sint32 repeated_sint32 = 35; |
||||||
|
repeated sint64 repeated_sint64 = 36; |
||||||
|
repeated fixed32 repeated_fixed32 = 37; |
||||||
|
repeated fixed64 repeated_fixed64 = 38; |
||||||
|
repeated sfixed32 repeated_sfixed32 = 39; |
||||||
|
repeated sfixed64 repeated_sfixed64 = 40; |
||||||
|
repeated float repeated_float = 41; |
||||||
|
repeated double repeated_double = 42; |
||||||
|
repeated bool repeated_bool = 43; |
||||||
|
repeated string repeated_string = 44; |
||||||
|
repeated bytes repeated_bytes = 45; |
||||||
|
|
||||||
|
repeated NestedMessage repeated_nested_message = 48; |
||||||
|
repeated ForeignMessage repeated_foreign_message = 49; |
||||||
|
repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; |
||||||
|
|
||||||
|
repeated NestedEnum repeated_nested_enum = 51; |
||||||
|
repeated ForeignEnum repeated_foreign_enum = 52; |
||||||
|
repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; |
||||||
|
// Defined in unittest_import_public.proto |
||||||
|
repeated protobuf_unittest_import.PublicImportMessage |
||||||
|
repeated_public_import_message = 54; |
||||||
|
|
||||||
|
// For oneof test |
||||||
|
oneof oneof_field { |
||||||
|
uint32 oneof_uint32 = 111; |
||||||
|
NestedMessage oneof_nested_message = 112; |
||||||
|
string oneof_string = 113; |
||||||
|
bytes oneof_bytes = 114; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// This proto includes a recusively nested message. |
||||||
|
message NestedTestAllTypes { |
||||||
|
NestedTestAllTypes child = 1; |
||||||
|
TestAllTypes payload = 2; |
||||||
|
repeated NestedTestAllTypes repeated_child = 3; |
||||||
|
} |
||||||
|
|
||||||
|
message TestDeprecatedFields { |
||||||
|
int32 deprecated_int32 = 1 [deprecated=true]; |
||||||
|
} |
||||||
|
|
||||||
|
// Define these after TestAllTypes to make sure the compiler can handle |
||||||
|
// that. |
||||||
|
message ForeignMessage { |
||||||
|
int32 c = 1; |
||||||
|
} |
||||||
|
|
||||||
|
enum ForeignEnum { |
||||||
|
FOREIGN_UNSPECIFIED = 0; |
||||||
|
FOREIGN_FOO = 4; |
||||||
|
FOREIGN_BAR = 5; |
||||||
|
FOREIGN_BAZ = 6; |
||||||
|
} |
||||||
|
|
||||||
|
message TestReservedFields { |
||||||
|
reserved 2, 15, 9 to 11; |
||||||
|
reserved "bar", "baz"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Test that we can use NestedMessage from outside TestAllTypes. |
||||||
|
message TestForeignNested { |
||||||
|
TestAllTypes.NestedMessage foreign_nested = 1; |
||||||
|
} |
||||||
|
|
||||||
|
// Test that really large tag numbers don't break anything. |
||||||
|
message TestReallyLargeTagNumber { |
||||||
|
// The largest possible tag number is 2^28 - 1, since the wire format uses |
||||||
|
// three bits to communicate wire type. |
||||||
|
int32 a = 1; |
||||||
|
int32 bb = 268435455; |
||||||
|
} |
||||||
|
|
||||||
|
message TestRecursiveMessage { |
||||||
|
TestRecursiveMessage a = 1; |
||||||
|
int32 i = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// Test that mutual recursion works. |
||||||
|
message TestMutualRecursionA { |
||||||
|
TestMutualRecursionB bb = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message TestMutualRecursionB { |
||||||
|
TestMutualRecursionA a = 1; |
||||||
|
int32 optional_int32 = 2; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Test an enum that has multiple values with the same number. |
||||||
|
enum TestEnumWithDupValue { |
||||||
|
TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0; |
||||||
|
option allow_alias = true; |
||||||
|
|
||||||
|
FOO1 = 1; |
||||||
|
BAR1 = 2; |
||||||
|
BAZ = 3; |
||||||
|
FOO2 = 1; |
||||||
|
BAR2 = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// Test an enum with large, unordered values. |
||||||
|
enum TestSparseEnum { |
||||||
|
TEST_SPARSE_ENUM_UNSPECIFIED = 0; |
||||||
|
SPARSE_A = 123; |
||||||
|
SPARSE_B = 62374; |
||||||
|
SPARSE_C = 12589234; |
||||||
|
SPARSE_D = -15; |
||||||
|
SPARSE_E = -53452; |
||||||
|
// In proto3, value 0 must be the first one specified |
||||||
|
// SPARSE_F = 0; |
||||||
|
SPARSE_G = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// Test message with CamelCase field names. This violates Protocol Buffer |
||||||
|
// standard style. |
||||||
|
message TestCamelCaseFieldNames { |
||||||
|
int32 PrimitiveField = 1; |
||||||
|
string StringField = 2; |
||||||
|
ForeignEnum EnumField = 3; |
||||||
|
ForeignMessage MessageField = 4; |
||||||
|
|
||||||
|
repeated int32 RepeatedPrimitiveField = 7; |
||||||
|
repeated string RepeatedStringField = 8; |
||||||
|
repeated ForeignEnum RepeatedEnumField = 9; |
||||||
|
repeated ForeignMessage RepeatedMessageField = 10; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// We list fields out of order, to ensure that we're using field number and not |
||||||
|
// field index to determine serialization order. |
||||||
|
message TestFieldOrderings { |
||||||
|
string my_string = 11; |
||||||
|
int64 my_int = 1; |
||||||
|
float my_float = 101; |
||||||
|
message NestedMessage { |
||||||
|
int64 oo = 2; |
||||||
|
// The field name "b" fails to compile in proto1 because it conflicts with |
||||||
|
// a local variable named "b" in one of the generated methods. Doh. |
||||||
|
// This file needs to compile in proto1 to test backwards-compatibility. |
||||||
|
int32 bb = 1; |
||||||
|
} |
||||||
|
|
||||||
|
NestedMessage single_nested_message = 200; |
||||||
|
} |
||||||
|
|
||||||
|
message SparseEnumMessage { |
||||||
|
TestSparseEnum sparse_enum = 1; |
||||||
|
} |
||||||
|
|
||||||
|
// Test String and Bytes: string is for valid UTF-8 strings |
||||||
|
message OneString { |
||||||
|
string data = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message MoreString { |
||||||
|
repeated string data = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message OneBytes { |
||||||
|
bytes data = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message MoreBytes { |
||||||
|
bytes data = 1; |
||||||
|
} |
||||||
|
|
||||||
|
// Test int32, uint32, int64, uint64, and bool are all compatible |
||||||
|
message Int32Message { |
||||||
|
int32 data = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message Uint32Message { |
||||||
|
uint32 data = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message Int64Message { |
||||||
|
int64 data = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message Uint64Message { |
||||||
|
uint64 data = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message BoolMessage { |
||||||
|
bool data = 1; |
||||||
|
} |
||||||
|
|
||||||
|
// Test oneofs. |
||||||
|
message TestOneof { |
||||||
|
oneof foo { |
||||||
|
int32 foo_int = 1; |
||||||
|
string foo_string = 2; |
||||||
|
TestAllTypes foo_message = 3; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Test messages for packed fields |
||||||
|
|
||||||
|
message TestPackedTypes { |
||||||
|
repeated int32 packed_int32 = 90 [packed = true]; |
||||||
|
repeated int64 packed_int64 = 91 [packed = true]; |
||||||
|
repeated uint32 packed_uint32 = 92 [packed = true]; |
||||||
|
repeated uint64 packed_uint64 = 93 [packed = true]; |
||||||
|
repeated sint32 packed_sint32 = 94 [packed = true]; |
||||||
|
repeated sint64 packed_sint64 = 95 [packed = true]; |
||||||
|
repeated fixed32 packed_fixed32 = 96 [packed = true]; |
||||||
|
repeated fixed64 packed_fixed64 = 97 [packed = true]; |
||||||
|
repeated sfixed32 packed_sfixed32 = 98 [packed = true]; |
||||||
|
repeated sfixed64 packed_sfixed64 = 99 [packed = true]; |
||||||
|
repeated float packed_float = 100 [packed = true]; |
||||||
|
repeated double packed_double = 101 [packed = true]; |
||||||
|
repeated bool packed_bool = 102 [packed = true]; |
||||||
|
repeated ForeignEnum packed_enum = 103 [packed = true]; |
||||||
|
} |
||||||
|
|
||||||
|
// A message with the same fields as TestPackedTypes, but without packing. Used |
||||||
|
// to test packed <-> unpacked wire compatibility. |
||||||
|
message TestUnpackedTypes { |
||||||
|
repeated int32 unpacked_int32 = 90 [packed = false]; |
||||||
|
repeated int64 unpacked_int64 = 91 [packed = false]; |
||||||
|
repeated uint32 unpacked_uint32 = 92 [packed = false]; |
||||||
|
repeated uint64 unpacked_uint64 = 93 [packed = false]; |
||||||
|
repeated sint32 unpacked_sint32 = 94 [packed = false]; |
||||||
|
repeated sint64 unpacked_sint64 = 95 [packed = false]; |
||||||
|
repeated fixed32 unpacked_fixed32 = 96 [packed = false]; |
||||||
|
repeated fixed64 unpacked_fixed64 = 97 [packed = false]; |
||||||
|
repeated sfixed32 unpacked_sfixed32 = 98 [packed = false]; |
||||||
|
repeated sfixed64 unpacked_sfixed64 = 99 [packed = false]; |
||||||
|
repeated float unpacked_float = 100 [packed = false]; |
||||||
|
repeated double unpacked_double = 101 [packed = false]; |
||||||
|
repeated bool unpacked_bool = 102 [packed = false]; |
||||||
|
repeated ForeignEnum unpacked_enum = 103 [packed = false]; |
||||||
|
} |
||||||
|
|
||||||
|
message TestRepeatedScalarDifferentTagSizes { |
||||||
|
// Parsing repeated fixed size values used to fail. This message needs to be |
||||||
|
// used in order to get a tag of the right size; all of the repeated fields |
||||||
|
// in TestAllTypes didn't trigger the check. |
||||||
|
repeated fixed32 repeated_fixed32 = 12; |
||||||
|
// Check for a varint type, just for good measure. |
||||||
|
repeated int32 repeated_int32 = 13; |
||||||
|
|
||||||
|
// These have two-byte tags. |
||||||
|
repeated fixed64 repeated_fixed64 = 2046; |
||||||
|
repeated int64 repeated_int64 = 2047; |
||||||
|
|
||||||
|
// Three byte tags. |
||||||
|
repeated float repeated_float = 262142; |
||||||
|
repeated uint64 repeated_uint64 = 262143; |
||||||
|
} |
||||||
|
|
||||||
|
message TestCommentInjectionMessage { |
||||||
|
// */ <- This should not close the generated doc comment |
||||||
|
string a = 1; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Test that RPC services work. |
||||||
|
message FooRequest {} |
||||||
|
message FooResponse {} |
||||||
|
|
||||||
|
message FooClientMessage {} |
||||||
|
message FooServerMessage{} |
||||||
|
|
||||||
|
service TestService { |
||||||
|
rpc Foo(FooRequest) returns (FooResponse); |
||||||
|
rpc Bar(BarRequest) returns (BarResponse); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
message BarRequest {} |
||||||
|
message BarResponse {} |
||||||
|
|
@ -0,0 +1,114 @@ |
|||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package protobuf_unittest; |
||||||
|
|
||||||
|
option csharp_namespace = "Google.Protobuf.TestProtos"; |
||||||
|
option java_multiple_files = true; |
||||||
|
option java_package = "com.google.protobuf.test"; |
||||||
|
|
||||||
|
import "google/protobuf/any.proto"; |
||||||
|
import "google/protobuf/api.proto"; |
||||||
|
import "google/protobuf/duration.proto"; |
||||||
|
import "google/protobuf/empty.proto"; |
||||||
|
import "google/protobuf/field_mask.proto"; |
||||||
|
import "google/protobuf/source_context.proto"; |
||||||
|
import "google/protobuf/struct.proto"; |
||||||
|
import "google/protobuf/timestamp.proto"; |
||||||
|
import "google/protobuf/type.proto"; |
||||||
|
import "google/protobuf/wrappers.proto"; |
||||||
|
|
||||||
|
// Test that we can include all well-known types. |
||||||
|
// Each wrapper type is included separately, as languages |
||||||
|
// map handle different wrappers in different ways. |
||||||
|
message TestWellKnownTypes { |
||||||
|
google.protobuf.Any any_field = 1; |
||||||
|
google.protobuf.Api api_field = 2; |
||||||
|
google.protobuf.Duration duration_field = 3; |
||||||
|
google.protobuf.Empty empty_field = 4; |
||||||
|
google.protobuf.FieldMask field_mask_field = 5; |
||||||
|
google.protobuf.SourceContext source_context_field = 6; |
||||||
|
google.protobuf.Struct struct_field = 7; |
||||||
|
google.protobuf.Timestamp timestamp_field = 8; |
||||||
|
google.protobuf.Type type_field = 9; |
||||||
|
google.protobuf.DoubleValue double_field = 10; |
||||||
|
google.protobuf.FloatValue float_field = 11; |
||||||
|
google.protobuf.Int64Value int64_field = 12; |
||||||
|
google.protobuf.UInt64Value uint64_field = 13; |
||||||
|
google.protobuf.Int32Value int32_field = 14; |
||||||
|
google.protobuf.UInt32Value uint32_field = 15; |
||||||
|
google.protobuf.BoolValue bool_field = 16; |
||||||
|
google.protobuf.StringValue string_field = 17; |
||||||
|
google.protobuf.BytesValue bytes_field = 18; |
||||||
|
// Part of struct, but useful to be able to test separately |
||||||
|
google.protobuf.Value value_field = 19; |
||||||
|
} |
||||||
|
|
||||||
|
// A repeated field for each well-known type. |
||||||
|
message RepeatedWellKnownTypes { |
||||||
|
repeated google.protobuf.Any any_field = 1; |
||||||
|
repeated google.protobuf.Api api_field = 2; |
||||||
|
repeated google.protobuf.Duration duration_field = 3; |
||||||
|
repeated google.protobuf.Empty empty_field = 4; |
||||||
|
repeated google.protobuf.FieldMask field_mask_field = 5; |
||||||
|
repeated google.protobuf.SourceContext source_context_field = 6; |
||||||
|
repeated google.protobuf.Struct struct_field = 7; |
||||||
|
repeated google.protobuf.Timestamp timestamp_field = 8; |
||||||
|
repeated google.protobuf.Type type_field = 9; |
||||||
|
// These don't actually make a lot of sense, but they're not prohibited... |
||||||
|
repeated google.protobuf.DoubleValue double_field = 10; |
||||||
|
repeated google.protobuf.FloatValue float_field = 11; |
||||||
|
repeated google.protobuf.Int64Value int64_field = 12; |
||||||
|
repeated google.protobuf.UInt64Value uint64_field = 13; |
||||||
|
repeated google.protobuf.Int32Value int32_field = 14; |
||||||
|
repeated google.protobuf.UInt32Value uint32_field = 15; |
||||||
|
repeated google.protobuf.BoolValue bool_field = 16; |
||||||
|
repeated google.protobuf.StringValue string_field = 17; |
||||||
|
repeated google.protobuf.BytesValue bytes_field = 18; |
||||||
|
} |
||||||
|
|
||||||
|
message OneofWellKnownTypes { |
||||||
|
oneof oneof_field { |
||||||
|
google.protobuf.Any any_field = 1; |
||||||
|
google.protobuf.Api api_field = 2; |
||||||
|
google.protobuf.Duration duration_field = 3; |
||||||
|
google.protobuf.Empty empty_field = 4; |
||||||
|
google.protobuf.FieldMask field_mask_field = 5; |
||||||
|
google.protobuf.SourceContext source_context_field = 6; |
||||||
|
google.protobuf.Struct struct_field = 7; |
||||||
|
google.protobuf.Timestamp timestamp_field = 8; |
||||||
|
google.protobuf.Type type_field = 9; |
||||||
|
google.protobuf.DoubleValue double_field = 10; |
||||||
|
google.protobuf.FloatValue float_field = 11; |
||||||
|
google.protobuf.Int64Value int64_field = 12; |
||||||
|
google.protobuf.UInt64Value uint64_field = 13; |
||||||
|
google.protobuf.Int32Value int32_field = 14; |
||||||
|
google.protobuf.UInt32Value uint32_field = 15; |
||||||
|
google.protobuf.BoolValue bool_field = 16; |
||||||
|
google.protobuf.StringValue string_field = 17; |
||||||
|
google.protobuf.BytesValue bytes_field = 18; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// A map field for each well-known type. We only |
||||||
|
// need to worry about the value part of the map being the |
||||||
|
// well-known types, as messages can't be map keys. |
||||||
|
message MapWellKnownTypes { |
||||||
|
map<int32,google.protobuf.Any> any_field = 1; |
||||||
|
map<int32,google.protobuf.Api> api_field = 2; |
||||||
|
map<int32,google.protobuf.Duration> duration_field = 3; |
||||||
|
map<int32,google.protobuf.Empty> empty_field = 4; |
||||||
|
map<int32,google.protobuf.FieldMask> field_mask_field = 5; |
||||||
|
map<int32,google.protobuf.SourceContext> source_context_field = 6; |
||||||
|
map<int32,google.protobuf.Struct> struct_field = 7; |
||||||
|
map<int32,google.protobuf.Timestamp> timestamp_field = 8; |
||||||
|
map<int32,google.protobuf.Type> type_field = 9; |
||||||
|
map<int32,google.protobuf.DoubleValue> double_field = 10; |
||||||
|
map<int32,google.protobuf.FloatValue> float_field = 11; |
||||||
|
map<int32,google.protobuf.Int64Value> int64_field = 12; |
||||||
|
map<int32,google.protobuf.UInt64Value> uint64_field = 13; |
||||||
|
map<int32,google.protobuf.Int32Value> int32_field = 14; |
||||||
|
map<int32,google.protobuf.UInt32Value> uint32_field = 15; |
||||||
|
map<int32,google.protobuf.BoolValue> bool_field = 16; |
||||||
|
map<int32,google.protobuf.StringValue> string_field = 17; |
||||||
|
map<int32,google.protobuf.BytesValue> bytes_field = 18; |
||||||
|
} |
@ -0,0 +1,171 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// https://developers.google.com/protocol-buffers/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
#endregion |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Text; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace Google.Protobuf |
||||||
|
{ |
||||||
|
public class ByteStringTest |
||||||
|
{ |
||||||
|
[Test] |
||||||
|
public void Equality() |
||||||
|
{ |
||||||
|
ByteString b1 = ByteString.CopyFrom(1, 2, 3); |
||||||
|
ByteString b2 = ByteString.CopyFrom(1, 2, 3); |
||||||
|
ByteString b3 = ByteString.CopyFrom(1, 2, 4); |
||||||
|
ByteString b4 = ByteString.CopyFrom(1, 2, 3, 4); |
||||||
|
EqualityTester.AssertEquality(b1, b1); |
||||||
|
EqualityTester.AssertEquality(b1, b2); |
||||||
|
EqualityTester.AssertInequality(b1, b3); |
||||||
|
EqualityTester.AssertInequality(b1, b4); |
||||||
|
EqualityTester.AssertInequality(b1, null); |
||||||
|
#pragma warning disable 1718 // Deliberately calling ==(b1, b1) and !=(b1, b1) |
||||||
|
Assert.IsTrue(b1 == b1); |
||||||
|
Assert.IsTrue(b1 == b2); |
||||||
|
Assert.IsFalse(b1 == b3); |
||||||
|
Assert.IsFalse(b1 == b4); |
||||||
|
Assert.IsFalse(b1 == null); |
||||||
|
Assert.IsTrue((ByteString) null == null); |
||||||
|
Assert.IsFalse(b1 != b1); |
||||||
|
Assert.IsFalse(b1 != b2); |
||||||
|
#pragma warning disable 1718 |
||||||
|
Assert.IsTrue(b1 != b3); |
||||||
|
Assert.IsTrue(b1 != b4); |
||||||
|
Assert.IsTrue(b1 != null); |
||||||
|
Assert.IsFalse((ByteString) null != null); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void EmptyByteStringHasZeroSize() |
||||||
|
{ |
||||||
|
Assert.AreEqual(0, ByteString.Empty.Length); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CopyFromStringWithExplicitEncoding() |
||||||
|
{ |
||||||
|
ByteString bs = ByteString.CopyFrom("AB", Encoding.Unicode); |
||||||
|
Assert.AreEqual(4, bs.Length); |
||||||
|
Assert.AreEqual(65, bs[0]); |
||||||
|
Assert.AreEqual(0, bs[1]); |
||||||
|
Assert.AreEqual(66, bs[2]); |
||||||
|
Assert.AreEqual(0, bs[3]); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void IsEmptyWhenEmpty() |
||||||
|
{ |
||||||
|
Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void IsEmptyWhenNotEmpty() |
||||||
|
{ |
||||||
|
Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CopyFromByteArrayCopiesContents() |
||||||
|
{ |
||||||
|
byte[] data = new byte[1]; |
||||||
|
data[0] = 10; |
||||||
|
ByteString bs = ByteString.CopyFrom(data); |
||||||
|
Assert.AreEqual(10, bs[0]); |
||||||
|
data[0] = 5; |
||||||
|
Assert.AreEqual(10, bs[0]); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ToByteArrayCopiesContents() |
||||||
|
{ |
||||||
|
ByteString bs = ByteString.CopyFromUtf8("Hello"); |
||||||
|
byte[] data = bs.ToByteArray(); |
||||||
|
Assert.AreEqual((byte)'H', data[0]); |
||||||
|
Assert.AreEqual((byte)'H', bs[0]); |
||||||
|
data[0] = 0; |
||||||
|
Assert.AreEqual(0, data[0]); |
||||||
|
Assert.AreEqual((byte)'H', bs[0]); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CopyFromUtf8UsesUtf8() |
||||||
|
{ |
||||||
|
ByteString bs = ByteString.CopyFromUtf8("\u20ac"); |
||||||
|
Assert.AreEqual(3, bs.Length); |
||||||
|
Assert.AreEqual(0xe2, bs[0]); |
||||||
|
Assert.AreEqual(0x82, bs[1]); |
||||||
|
Assert.AreEqual(0xac, bs[2]); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CopyFromPortion() |
||||||
|
{ |
||||||
|
byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6}; |
||||||
|
ByteString bs = ByteString.CopyFrom(data, 2, 3); |
||||||
|
Assert.AreEqual(3, bs.Length); |
||||||
|
Assert.AreEqual(2, bs[0]); |
||||||
|
Assert.AreEqual(3, bs[1]); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ToStringUtf8() |
||||||
|
{ |
||||||
|
ByteString bs = ByteString.CopyFromUtf8("\u20ac"); |
||||||
|
Assert.AreEqual("\u20ac", bs.ToStringUtf8()); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ToStringWithExplicitEncoding() |
||||||
|
{ |
||||||
|
ByteString bs = ByteString.CopyFrom("\u20ac", Encoding.Unicode); |
||||||
|
Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void FromBase64_WithText() |
||||||
|
{ |
||||||
|
byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6}; |
||||||
|
string base64 = Convert.ToBase64String(data); |
||||||
|
ByteString bs = ByteString.FromBase64(base64); |
||||||
|
Assert.AreEqual(data, bs.ToByteArray()); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void FromBase64_Empty() |
||||||
|
{ |
||||||
|
// Optimization which also fixes issue 61. |
||||||
|
Assert.AreSame(ByteString.Empty, ByteString.FromBase64("")); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,598 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// https://developers.google.com/protocol-buffers/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
#endregion |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
using Google.Protobuf.TestProtos; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace Google.Protobuf |
||||||
|
{ |
||||||
|
public class CodedInputStreamTest |
||||||
|
{ |
||||||
|
/// <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; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() |
||||||
|
/// </summary> |
||||||
|
private static void AssertReadVarint(byte[] data, ulong value) |
||||||
|
{ |
||||||
|
CodedInputStream input = new CodedInputStream(data); |
||||||
|
Assert.AreEqual((uint) value, input.ReadRawVarint32()); |
||||||
|
|
||||||
|
input = new CodedInputStream(data); |
||||||
|
Assert.AreEqual(value, input.ReadRawVarint64()); |
||||||
|
Assert.IsTrue(input.IsAtEnd); |
||||||
|
|
||||||
|
// Try different block sizes. |
||||||
|
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) |
||||||
|
{ |
||||||
|
input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize)); |
||||||
|
Assert.AreEqual((uint) value, input.ReadRawVarint32()); |
||||||
|
|
||||||
|
input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize)); |
||||||
|
Assert.AreEqual(value, input.ReadRawVarint64()); |
||||||
|
Assert.IsTrue(input.IsAtEnd); |
||||||
|
} |
||||||
|
|
||||||
|
// Try reading directly from a MemoryStream. We want to verify that it |
||||||
|
// doesn't read past the end of the input, so write an extra byte - this |
||||||
|
// lets us test the position at the end. |
||||||
|
MemoryStream memoryStream = new MemoryStream(); |
||||||
|
memoryStream.Write(data, 0, data.Length); |
||||||
|
memoryStream.WriteByte(0); |
||||||
|
memoryStream.Position = 0; |
||||||
|
Assert.AreEqual((uint) value, CodedInputStream.ReadRawVarint32(memoryStream)); |
||||||
|
Assert.AreEqual(data.Length, memoryStream.Position); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and |
||||||
|
/// expects them to fail with an InvalidProtocolBufferException whose |
||||||
|
/// description matches the given one. |
||||||
|
/// </summary> |
||||||
|
private static void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data) |
||||||
|
{ |
||||||
|
CodedInputStream input = new CodedInputStream(data); |
||||||
|
var exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint32()); |
||||||
|
Assert.AreEqual(expected.Message, exception.Message); |
||||||
|
|
||||||
|
input = new CodedInputStream(data); |
||||||
|
exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint64()); |
||||||
|
Assert.AreEqual(expected.Message, exception.Message); |
||||||
|
|
||||||
|
// Make sure we get the same error when reading directly from a Stream. |
||||||
|
exception = Assert.Throws<InvalidProtocolBufferException>(() => CodedInputStream.ReadRawVarint32(new MemoryStream(data))); |
||||||
|
Assert.AreEqual(expected.Message, exception.Message); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ReadVarint() |
||||||
|
{ |
||||||
|
AssertReadVarint(Bytes(0x00), 0); |
||||||
|
AssertReadVarint(Bytes(0x01), 1); |
||||||
|
AssertReadVarint(Bytes(0x7f), 127); |
||||||
|
// 14882 |
||||||
|
AssertReadVarint(Bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7)); |
||||||
|
// 2961488830 |
||||||
|
AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b), |
||||||
|
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | |
||||||
|
(0x0bL << 28)); |
||||||
|
|
||||||
|
// 64-bit |
||||||
|
// 7256456126 |
||||||
|
AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b), |
||||||
|
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | |
||||||
|
(0x1bL << 28)); |
||||||
|
// 41256202580718336 |
||||||
|
AssertReadVarint(Bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49), |
||||||
|
(0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | |
||||||
|
(0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49)); |
||||||
|
// 11964378330978735131 |
||||||
|
AssertReadVarint(Bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01), |
||||||
|
(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | |
||||||
|
(0x3bUL << 28) | (0x56UL << 35) | (0x00UL << 42) | |
||||||
|
(0x05UL << 49) | (0x26UL << 56) | (0x01UL << 63)); |
||||||
|
|
||||||
|
// Failures |
||||||
|
AssertReadVarintFailure( |
||||||
|
InvalidProtocolBufferException.MalformedVarint(), |
||||||
|
Bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
||||||
|
0x00)); |
||||||
|
AssertReadVarintFailure( |
||||||
|
InvalidProtocolBufferException.TruncatedMessage(), |
||||||
|
Bytes(0x80)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Parses the given bytes using ReadRawLittleEndian32() and checks |
||||||
|
/// that the result matches the given value. |
||||||
|
/// </summary> |
||||||
|
private static void AssertReadLittleEndian32(byte[] data, uint value) |
||||||
|
{ |
||||||
|
CodedInputStream input = new CodedInputStream(data); |
||||||
|
Assert.AreEqual(value, input.ReadRawLittleEndian32()); |
||||||
|
Assert.IsTrue(input.IsAtEnd); |
||||||
|
|
||||||
|
// Try different block sizes. |
||||||
|
for (int blockSize = 1; blockSize <= 16; blockSize *= 2) |
||||||
|
{ |
||||||
|
input = new CodedInputStream( |
||||||
|
new SmallBlockInputStream(data, blockSize)); |
||||||
|
Assert.AreEqual(value, input.ReadRawLittleEndian32()); |
||||||
|
Assert.IsTrue(input.IsAtEnd); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Parses the given bytes using ReadRawLittleEndian64() and checks |
||||||
|
/// that the result matches the given value. |
||||||
|
/// </summary> |
||||||
|
private static void AssertReadLittleEndian64(byte[] data, ulong value) |
||||||
|
{ |
||||||
|
CodedInputStream input = new CodedInputStream(data); |
||||||
|
Assert.AreEqual(value, input.ReadRawLittleEndian64()); |
||||||
|
Assert.IsTrue(input.IsAtEnd); |
||||||
|
|
||||||
|
// Try different block sizes. |
||||||
|
for (int blockSize = 1; blockSize <= 16; blockSize *= 2) |
||||||
|
{ |
||||||
|
input = new CodedInputStream( |
||||||
|
new SmallBlockInputStream(data, blockSize)); |
||||||
|
Assert.AreEqual(value, input.ReadRawLittleEndian64()); |
||||||
|
Assert.IsTrue(input.IsAtEnd); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ReadLittleEndian() |
||||||
|
{ |
||||||
|
AssertReadLittleEndian32(Bytes(0x78, 0x56, 0x34, 0x12), 0x12345678); |
||||||
|
AssertReadLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0); |
||||||
|
|
||||||
|
AssertReadLittleEndian64(Bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12), |
||||||
|
0x123456789abcdef0L); |
||||||
|
AssertReadLittleEndian64( |
||||||
|
Bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678UL); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void DecodeZigZag32() |
||||||
|
{ |
||||||
|
Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0)); |
||||||
|
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1)); |
||||||
|
Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2)); |
||||||
|
Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3)); |
||||||
|
Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE)); |
||||||
|
Assert.AreEqual(unchecked((int) 0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF)); |
||||||
|
Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE)); |
||||||
|
Assert.AreEqual(unchecked((int) 0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void DecodeZigZag64() |
||||||
|
{ |
||||||
|
Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0)); |
||||||
|
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1)); |
||||||
|
Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2)); |
||||||
|
Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3)); |
||||||
|
Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL)); |
||||||
|
Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL)); |
||||||
|
Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL)); |
||||||
|
Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL)); |
||||||
|
Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL)); |
||||||
|
Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ReadWholeMessage_VaryingBlockSizes() |
||||||
|
{ |
||||||
|
TestAllTypes message = SampleMessages.CreateFullTestAllTypes(); |
||||||
|
|
||||||
|
byte[] rawBytes = message.ToByteArray(); |
||||||
|
Assert.AreEqual(rawBytes.Length, message.CalculateSize()); |
||||||
|
TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(rawBytes); |
||||||
|
Assert.AreEqual(message, message2); |
||||||
|
|
||||||
|
// Try different block sizes. |
||||||
|
for (int blockSize = 1; blockSize < 256; blockSize *= 2) |
||||||
|
{ |
||||||
|
message2 = TestAllTypes.Parser.ParseFrom(new SmallBlockInputStream(rawBytes, blockSize)); |
||||||
|
Assert.AreEqual(message, message2); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ReadHugeBlob() |
||||||
|
{ |
||||||
|
// Allocate and initialize a 1MB blob. |
||||||
|
byte[] blob = new byte[1 << 20]; |
||||||
|
for (int i = 0; i < blob.Length; i++) |
||||||
|
{ |
||||||
|
blob[i] = (byte) i; |
||||||
|
} |
||||||
|
|
||||||
|
// Make a message containing it. |
||||||
|
var message = new TestAllTypes { SingleBytes = ByteString.CopyFrom(blob) }; |
||||||
|
|
||||||
|
// Serialize and parse it. Make sure to parse from an InputStream, not |
||||||
|
// directly from a ByteString, so that CodedInputStream uses buffered |
||||||
|
// reading. |
||||||
|
TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(message.ToByteString()); |
||||||
|
|
||||||
|
Assert.AreEqual(message, message2); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ReadMaliciouslyLargeBlob() |
||||||
|
{ |
||||||
|
MemoryStream ms = new MemoryStream(); |
||||||
|
CodedOutputStream output = new CodedOutputStream(ms); |
||||||
|
|
||||||
|
uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); |
||||||
|
output.WriteRawVarint32(tag); |
||||||
|
output.WriteRawVarint32(0x7FFFFFFF); |
||||||
|
output.WriteRawBytes(new byte[32]); // Pad with a few random bytes. |
||||||
|
output.Flush(); |
||||||
|
ms.Position = 0; |
||||||
|
|
||||||
|
CodedInputStream input = new CodedInputStream(ms); |
||||||
|
Assert.AreEqual(tag, input.ReadTag()); |
||||||
|
|
||||||
|
Assert.Throws<InvalidProtocolBufferException>(() => input.ReadBytes()); |
||||||
|
} |
||||||
|
|
||||||
|
internal static TestRecursiveMessage MakeRecursiveMessage(int depth) |
||||||
|
{ |
||||||
|
if (depth == 0) |
||||||
|
{ |
||||||
|
return new TestRecursiveMessage { I = 5 }; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return new TestRecursiveMessage { A = MakeRecursiveMessage(depth - 1) }; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal static void AssertMessageDepth(TestRecursiveMessage message, int depth) |
||||||
|
{ |
||||||
|
if (depth == 0) |
||||||
|
{ |
||||||
|
Assert.IsNull(message.A); |
||||||
|
Assert.AreEqual(5, message.I); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
Assert.IsNotNull(message.A); |
||||||
|
AssertMessageDepth(message.A, depth - 1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MaliciousRecursion() |
||||||
|
{ |
||||||
|
ByteString data64 = MakeRecursiveMessage(64).ToByteString(); |
||||||
|
ByteString data65 = MakeRecursiveMessage(65).ToByteString(); |
||||||
|
|
||||||
|
AssertMessageDepth(TestRecursiveMessage.Parser.ParseFrom(data64), 64); |
||||||
|
|
||||||
|
Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(data65)); |
||||||
|
|
||||||
|
CodedInputStream input = CodedInputStream.CreateWithLimits(new MemoryStream(data64.ToByteArray()), 1000000, 63); |
||||||
|
Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(input)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SizeLimit() |
||||||
|
{ |
||||||
|
// Have to use a Stream rather than ByteString.CreateCodedInput as SizeLimit doesn't |
||||||
|
// apply to the latter case. |
||||||
|
MemoryStream ms = new MemoryStream(SampleMessages.CreateFullTestAllTypes().ToByteArray()); |
||||||
|
CodedInputStream input = CodedInputStream.CreateWithLimits(ms, 16, 100); |
||||||
|
Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(input)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Tests that if we read an string that contains invalid UTF-8, no exception |
||||||
|
/// is thrown. Instead, the invalid bytes are replaced with the Unicode |
||||||
|
/// "replacement character" U+FFFD. |
||||||
|
/// </summary> |
||||||
|
[Test] |
||||||
|
public void ReadInvalidUtf8() |
||||||
|
{ |
||||||
|
MemoryStream ms = new MemoryStream(); |
||||||
|
CodedOutputStream output = new CodedOutputStream(ms); |
||||||
|
|
||||||
|
uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); |
||||||
|
output.WriteRawVarint32(tag); |
||||||
|
output.WriteRawVarint32(1); |
||||||
|
output.WriteRawBytes(new byte[] {0x80}); |
||||||
|
output.Flush(); |
||||||
|
ms.Position = 0; |
||||||
|
|
||||||
|
CodedInputStream input = new CodedInputStream(ms); |
||||||
|
|
||||||
|
Assert.AreEqual(tag, input.ReadTag()); |
||||||
|
string text = input.ReadString(); |
||||||
|
Assert.AreEqual('\ufffd', text[0]); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// A stream which limits the number of bytes it reads at a time. |
||||||
|
/// We use this to make sure that CodedInputStream doesn't screw up when |
||||||
|
/// reading in small blocks. |
||||||
|
/// </summary> |
||||||
|
private sealed class SmallBlockInputStream : MemoryStream |
||||||
|
{ |
||||||
|
private readonly int blockSize; |
||||||
|
|
||||||
|
public SmallBlockInputStream(byte[] data, int blockSize) |
||||||
|
: base(data) |
||||||
|
{ |
||||||
|
this.blockSize = blockSize; |
||||||
|
} |
||||||
|
|
||||||
|
public override int Read(byte[] buffer, int offset, int count) |
||||||
|
{ |
||||||
|
return base.Read(buffer, offset, Math.Min(count, blockSize)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void TestNegativeEnum() |
||||||
|
{ |
||||||
|
byte[] bytes = { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 }; |
||||||
|
CodedInputStream input = new CodedInputStream(bytes); |
||||||
|
Assert.AreEqual((int)SampleEnum.NegativeValue, input.ReadEnum()); |
||||||
|
Assert.IsTrue(input.IsAtEnd); |
||||||
|
} |
||||||
|
|
||||||
|
//Issue 71: CodedInputStream.ReadBytes go to slow path unnecessarily |
||||||
|
[Test] |
||||||
|
public void TestSlowPathAvoidance() |
||||||
|
{ |
||||||
|
using (var ms = new MemoryStream()) |
||||||
|
{ |
||||||
|
CodedOutputStream output = new CodedOutputStream(ms); |
||||||
|
output.WriteTag(1, WireFormat.WireType.LengthDelimited); |
||||||
|
output.WriteBytes(ByteString.CopyFrom(new byte[100])); |
||||||
|
output.WriteTag(2, WireFormat.WireType.LengthDelimited); |
||||||
|
output.WriteBytes(ByteString.CopyFrom(new byte[100])); |
||||||
|
output.Flush(); |
||||||
|
|
||||||
|
ms.Position = 0; |
||||||
|
CodedInputStream input = new CodedInputStream(ms, new byte[ms.Length / 2], 0, 0); |
||||||
|
|
||||||
|
uint tag = input.ReadTag(); |
||||||
|
Assert.AreEqual(1, WireFormat.GetTagFieldNumber(tag)); |
||||||
|
Assert.AreEqual(100, input.ReadBytes().Length); |
||||||
|
|
||||||
|
tag = input.ReadTag(); |
||||||
|
Assert.AreEqual(2, WireFormat.GetTagFieldNumber(tag)); |
||||||
|
Assert.AreEqual(100, input.ReadBytes().Length); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Tag0Throws() |
||||||
|
{ |
||||||
|
var input = new CodedInputStream(new byte[] { 0 }); |
||||||
|
Assert.Throws<InvalidProtocolBufferException>(() => input.ReadTag()); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SkipGroup() |
||||||
|
{ |
||||||
|
// Create an output stream with a group in: |
||||||
|
// Field 1: string "field 1" |
||||||
|
// Field 2: group containing: |
||||||
|
// Field 1: fixed int32 value 100 |
||||||
|
// Field 2: string "ignore me" |
||||||
|
// Field 3: nested group containing |
||||||
|
// Field 1: fixed int64 value 1000 |
||||||
|
// Field 3: string "field 3" |
||||||
|
var stream = new MemoryStream(); |
||||||
|
var output = new CodedOutputStream(stream); |
||||||
|
output.WriteTag(1, WireFormat.WireType.LengthDelimited); |
||||||
|
output.WriteString("field 1"); |
||||||
|
|
||||||
|
// The outer group... |
||||||
|
output.WriteTag(2, WireFormat.WireType.StartGroup); |
||||||
|
output.WriteTag(1, WireFormat.WireType.Fixed32); |
||||||
|
output.WriteFixed32(100); |
||||||
|
output.WriteTag(2, WireFormat.WireType.LengthDelimited); |
||||||
|
output.WriteString("ignore me"); |
||||||
|
// The nested group... |
||||||
|
output.WriteTag(3, WireFormat.WireType.StartGroup); |
||||||
|
output.WriteTag(1, WireFormat.WireType.Fixed64); |
||||||
|
output.WriteFixed64(1000); |
||||||
|
// Note: Not sure the field number is relevant for end group... |
||||||
|
output.WriteTag(3, WireFormat.WireType.EndGroup); |
||||||
|
|
||||||
|
// End the outer group |
||||||
|
output.WriteTag(2, WireFormat.WireType.EndGroup); |
||||||
|
|
||||||
|
output.WriteTag(3, WireFormat.WireType.LengthDelimited); |
||||||
|
output.WriteString("field 3"); |
||||||
|
output.Flush(); |
||||||
|
stream.Position = 0; |
||||||
|
|
||||||
|
// Now act like a generated client |
||||||
|
var input = new CodedInputStream(stream); |
||||||
|
Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited), input.ReadTag()); |
||||||
|
Assert.AreEqual("field 1", input.ReadString()); |
||||||
|
Assert.AreEqual(WireFormat.MakeTag(2, WireFormat.WireType.StartGroup), input.ReadTag()); |
||||||
|
input.SkipLastField(); // Should consume the whole group, including the nested one. |
||||||
|
Assert.AreEqual(WireFormat.MakeTag(3, WireFormat.WireType.LengthDelimited), input.ReadTag()); |
||||||
|
Assert.AreEqual("field 3", input.ReadString()); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SkipGroup_WrongEndGroupTag() |
||||||
|
{ |
||||||
|
// Create an output stream with: |
||||||
|
// Field 1: string "field 1" |
||||||
|
// Start group 2 |
||||||
|
// Field 3: fixed int32 |
||||||
|
// End group 4 (should give an error) |
||||||
|
var stream = new MemoryStream(); |
||||||
|
var output = new CodedOutputStream(stream); |
||||||
|
output.WriteTag(1, WireFormat.WireType.LengthDelimited); |
||||||
|
output.WriteString("field 1"); |
||||||
|
|
||||||
|
// The outer group... |
||||||
|
output.WriteTag(2, WireFormat.WireType.StartGroup); |
||||||
|
output.WriteTag(3, WireFormat.WireType.Fixed32); |
||||||
|
output.WriteFixed32(100); |
||||||
|
output.WriteTag(4, WireFormat.WireType.EndGroup); |
||||||
|
output.Flush(); |
||||||
|
stream.Position = 0; |
||||||
|
|
||||||
|
// Now act like a generated client |
||||||
|
var input = new CodedInputStream(stream); |
||||||
|
Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited), input.ReadTag()); |
||||||
|
Assert.AreEqual("field 1", input.ReadString()); |
||||||
|
Assert.AreEqual(WireFormat.MakeTag(2, WireFormat.WireType.StartGroup), input.ReadTag()); |
||||||
|
Assert.Throws<InvalidProtocolBufferException>(input.SkipLastField); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void RogueEndGroupTag() |
||||||
|
{ |
||||||
|
// If we have an end-group tag without a leading start-group tag, generated |
||||||
|
// code will just call SkipLastField... so that should fail. |
||||||
|
|
||||||
|
var stream = new MemoryStream(); |
||||||
|
var output = new CodedOutputStream(stream); |
||||||
|
output.WriteTag(1, WireFormat.WireType.EndGroup); |
||||||
|
output.Flush(); |
||||||
|
stream.Position = 0; |
||||||
|
|
||||||
|
var input = new CodedInputStream(stream); |
||||||
|
Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.EndGroup), input.ReadTag()); |
||||||
|
Assert.Throws<InvalidProtocolBufferException>(input.SkipLastField); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void EndOfStreamReachedWhileSkippingGroup() |
||||||
|
{ |
||||||
|
var stream = new MemoryStream(); |
||||||
|
var output = new CodedOutputStream(stream); |
||||||
|
output.WriteTag(1, WireFormat.WireType.StartGroup); |
||||||
|
output.WriteTag(2, WireFormat.WireType.StartGroup); |
||||||
|
output.WriteTag(2, WireFormat.WireType.EndGroup); |
||||||
|
|
||||||
|
output.Flush(); |
||||||
|
stream.Position = 0; |
||||||
|
|
||||||
|
// Now act like a generated client |
||||||
|
var input = new CodedInputStream(stream); |
||||||
|
input.ReadTag(); |
||||||
|
Assert.Throws<InvalidProtocolBufferException>(input.SkipLastField); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void RecursionLimitAppliedWhileSkippingGroup() |
||||||
|
{ |
||||||
|
var stream = new MemoryStream(); |
||||||
|
var output = new CodedOutputStream(stream); |
||||||
|
for (int i = 0; i < CodedInputStream.DefaultRecursionLimit + 1; i++) |
||||||
|
{ |
||||||
|
output.WriteTag(1, WireFormat.WireType.StartGroup); |
||||||
|
} |
||||||
|
for (int i = 0; i < CodedInputStream.DefaultRecursionLimit + 1; i++) |
||||||
|
{ |
||||||
|
output.WriteTag(1, WireFormat.WireType.EndGroup); |
||||||
|
} |
||||||
|
output.Flush(); |
||||||
|
stream.Position = 0; |
||||||
|
|
||||||
|
// Now act like a generated client |
||||||
|
var input = new CodedInputStream(stream); |
||||||
|
Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.StartGroup), input.ReadTag()); |
||||||
|
Assert.Throws<InvalidProtocolBufferException>(input.SkipLastField); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Construction_Invalid() |
||||||
|
{ |
||||||
|
Assert.Throws<ArgumentNullException>(() => new CodedInputStream((byte[]) null)); |
||||||
|
Assert.Throws<ArgumentNullException>(() => new CodedInputStream(null, 0, 0)); |
||||||
|
Assert.Throws<ArgumentNullException>(() => new CodedInputStream((Stream) null)); |
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => new CodedInputStream(new byte[10], 100, 0)); |
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => new CodedInputStream(new byte[10], 5, 10)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CreateWithLimits_InvalidLimits() |
||||||
|
{ |
||||||
|
var stream = new MemoryStream(); |
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => CodedInputStream.CreateWithLimits(stream, 0, 1)); |
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => CodedInputStream.CreateWithLimits(stream, 1, 0)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Dispose_DisposesUnderlyingStream() |
||||||
|
{ |
||||||
|
var memoryStream = new MemoryStream(); |
||||||
|
Assert.IsTrue(memoryStream.CanRead); |
||||||
|
using (var cis = new CodedInputStream(memoryStream)) |
||||||
|
{ |
||||||
|
} |
||||||
|
Assert.IsFalse(memoryStream.CanRead); // Disposed |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Dispose_WithLeaveOpen() |
||||||
|
{ |
||||||
|
var memoryStream = new MemoryStream(); |
||||||
|
Assert.IsTrue(memoryStream.CanRead); |
||||||
|
using (var cis = new CodedInputStream(memoryStream, true)) |
||||||
|
{ |
||||||
|
} |
||||||
|
Assert.IsTrue(memoryStream.CanRead); // We left the stream open |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,419 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// https://developers.google.com/protocol-buffers/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
#endregion |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
using Google.Protobuf.TestProtos; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace Google.Protobuf |
||||||
|
{ |
||||||
|
public class CodedOutputStreamTest |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and |
||||||
|
/// checks that the result matches the given bytes |
||||||
|
/// </summary> |
||||||
|
private static void AssertWriteVarint(byte[] data, ulong value) |
||||||
|
{ |
||||||
|
// Only do 32-bit write if the value fits in 32 bits. |
||||||
|
if ((value >> 32) == 0) |
||||||
|
{ |
||||||
|
MemoryStream rawOutput = new MemoryStream(); |
||||||
|
CodedOutputStream output = new CodedOutputStream(rawOutput); |
||||||
|
output.WriteRawVarint32((uint) value); |
||||||
|
output.Flush(); |
||||||
|
Assert.AreEqual(data, rawOutput.ToArray()); |
||||||
|
// Also try computing size. |
||||||
|
Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value)); |
||||||
|
} |
||||||
|
|
||||||
|
{ |
||||||
|
MemoryStream rawOutput = new MemoryStream(); |
||||||
|
CodedOutputStream output = new CodedOutputStream(rawOutput); |
||||||
|
output.WriteRawVarint64(value); |
||||||
|
output.Flush(); |
||||||
|
Assert.AreEqual(data, rawOutput.ToArray()); |
||||||
|
|
||||||
|
// Also try computing size. |
||||||
|
Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value)); |
||||||
|
} |
||||||
|
|
||||||
|
// Try different buffer sizes. |
||||||
|
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) |
||||||
|
{ |
||||||
|
// Only do 32-bit write if the value fits in 32 bits. |
||||||
|
if ((value >> 32) == 0) |
||||||
|
{ |
||||||
|
MemoryStream rawOutput = new MemoryStream(); |
||||||
|
CodedOutputStream output = |
||||||
|
new CodedOutputStream(rawOutput, bufferSize); |
||||||
|
output.WriteRawVarint32((uint) value); |
||||||
|
output.Flush(); |
||||||
|
Assert.AreEqual(data, rawOutput.ToArray()); |
||||||
|
} |
||||||
|
|
||||||
|
{ |
||||||
|
MemoryStream rawOutput = new MemoryStream(); |
||||||
|
CodedOutputStream output = new CodedOutputStream(rawOutput, bufferSize); |
||||||
|
output.WriteRawVarint64(value); |
||||||
|
output.Flush(); |
||||||
|
Assert.AreEqual(data, rawOutput.ToArray()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Tests WriteRawVarint32() and WriteRawVarint64() |
||||||
|
/// </summary> |
||||||
|
[Test] |
||||||
|
public void WriteVarint() |
||||||
|
{ |
||||||
|
AssertWriteVarint(new byte[] {0x00}, 0); |
||||||
|
AssertWriteVarint(new byte[] {0x01}, 1); |
||||||
|
AssertWriteVarint(new byte[] {0x7f}, 127); |
||||||
|
// 14882 |
||||||
|
AssertWriteVarint(new byte[] {0xa2, 0x74}, (0x22 << 0) | (0x74 << 7)); |
||||||
|
// 2961488830 |
||||||
|
AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x0b}, |
||||||
|
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | |
||||||
|
(0x0bL << 28)); |
||||||
|
|
||||||
|
// 64-bit |
||||||
|
// 7256456126 |
||||||
|
AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x1b}, |
||||||
|
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | |
||||||
|
(0x1bL << 28)); |
||||||
|
// 41256202580718336 |
||||||
|
AssertWriteVarint( |
||||||
|
new byte[] {0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49}, |
||||||
|
(0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | |
||||||
|
(0x43UL << 28) | (0x49L << 35) | (0x24UL << 42) | (0x49UL << 49)); |
||||||
|
// 11964378330978735131 |
||||||
|
AssertWriteVarint( |
||||||
|
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) | |
||||||
|
(0x05L << 49) | (0x26L << 56) | (0x01L << 63)))); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Parses the given bytes using WriteRawLittleEndian32() and checks |
||||||
|
/// that the result matches the given value. |
||||||
|
/// </summary> |
||||||
|
private static void AssertWriteLittleEndian32(byte[] data, uint value) |
||||||
|
{ |
||||||
|
MemoryStream rawOutput = new MemoryStream(); |
||||||
|
CodedOutputStream output = new CodedOutputStream(rawOutput); |
||||||
|
output.WriteRawLittleEndian32(value); |
||||||
|
output.Flush(); |
||||||
|
Assert.AreEqual(data, rawOutput.ToArray()); |
||||||
|
|
||||||
|
// Try different buffer sizes. |
||||||
|
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) |
||||||
|
{ |
||||||
|
rawOutput = new MemoryStream(); |
||||||
|
output = new CodedOutputStream(rawOutput, bufferSize); |
||||||
|
output.WriteRawLittleEndian32(value); |
||||||
|
output.Flush(); |
||||||
|
Assert.AreEqual(data, rawOutput.ToArray()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Parses the given bytes using WriteRawLittleEndian64() and checks |
||||||
|
/// that the result matches the given value. |
||||||
|
/// </summary> |
||||||
|
private static void AssertWriteLittleEndian64(byte[] data, ulong value) |
||||||
|
{ |
||||||
|
MemoryStream rawOutput = new MemoryStream(); |
||||||
|
CodedOutputStream output = new CodedOutputStream(rawOutput); |
||||||
|
output.WriteRawLittleEndian64(value); |
||||||
|
output.Flush(); |
||||||
|
Assert.AreEqual(data, rawOutput.ToArray()); |
||||||
|
|
||||||
|
// Try different block sizes. |
||||||
|
for (int blockSize = 1; blockSize <= 16; blockSize *= 2) |
||||||
|
{ |
||||||
|
rawOutput = new MemoryStream(); |
||||||
|
output = new CodedOutputStream(rawOutput, blockSize); |
||||||
|
output.WriteRawLittleEndian64(value); |
||||||
|
output.Flush(); |
||||||
|
Assert.AreEqual(data, rawOutput.ToArray()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Tests writeRawLittleEndian32() and writeRawLittleEndian64(). |
||||||
|
/// </summary> |
||||||
|
[Test] |
||||||
|
public void WriteLittleEndian() |
||||||
|
{ |
||||||
|
AssertWriteLittleEndian32(new byte[] {0x78, 0x56, 0x34, 0x12}, 0x12345678); |
||||||
|
AssertWriteLittleEndian32(new byte[] {0xf0, 0xde, 0xbc, 0x9a}, 0x9abcdef0); |
||||||
|
|
||||||
|
AssertWriteLittleEndian64( |
||||||
|
new byte[] {0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12}, |
||||||
|
0x123456789abcdef0L); |
||||||
|
AssertWriteLittleEndian64( |
||||||
|
new byte[] {0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a}, |
||||||
|
0x9abcdef012345678UL); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void WriteWholeMessage_VaryingBlockSizes() |
||||||
|
{ |
||||||
|
TestAllTypes message = SampleMessages.CreateFullTestAllTypes(); |
||||||
|
|
||||||
|
byte[] rawBytes = message.ToByteArray(); |
||||||
|
|
||||||
|
// Try different block sizes. |
||||||
|
for (int blockSize = 1; blockSize < 256; blockSize *= 2) |
||||||
|
{ |
||||||
|
MemoryStream rawOutput = new MemoryStream(); |
||||||
|
CodedOutputStream output = new CodedOutputStream(rawOutput, blockSize); |
||||||
|
message.WriteTo(output); |
||||||
|
output.Flush(); |
||||||
|
Assert.AreEqual(rawBytes, rawOutput.ToArray()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void EncodeZigZag32() |
||||||
|
{ |
||||||
|
Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag32(0)); |
||||||
|
Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag32(-1)); |
||||||
|
Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag32(1)); |
||||||
|
Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag32(-2)); |
||||||
|
Assert.AreEqual(0x7FFFFFFEu, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF)); |
||||||
|
Assert.AreEqual(0x7FFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0xC0000000))); |
||||||
|
Assert.AreEqual(0xFFFFFFFEu, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF)); |
||||||
|
Assert.AreEqual(0xFFFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0x80000000))); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void EncodeZigZag64() |
||||||
|
{ |
||||||
|
Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag64(0)); |
||||||
|
Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag64(-1)); |
||||||
|
Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag64(1)); |
||||||
|
Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag64(-2)); |
||||||
|
Assert.AreEqual(0x000000007FFFFFFEuL, |
||||||
|
CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL))); |
||||||
|
Assert.AreEqual(0x000000007FFFFFFFuL, |
||||||
|
CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL))); |
||||||
|
Assert.AreEqual(0x00000000FFFFFFFEuL, |
||||||
|
CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL))); |
||||||
|
Assert.AreEqual(0x00000000FFFFFFFFuL, |
||||||
|
CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL))); |
||||||
|
Assert.AreEqual(0xFFFFFFFFFFFFFFFEL, |
||||||
|
CodedOutputStream.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL))); |
||||||
|
Assert.AreEqual(0xFFFFFFFFFFFFFFFFL, |
||||||
|
CodedOutputStream.EncodeZigZag64(unchecked((long) 0x8000000000000000UL))); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void RoundTripZigZag32() |
||||||
|
{ |
||||||
|
// Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1) |
||||||
|
// were chosen semi-randomly via keyboard bashing. |
||||||
|
Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0))); |
||||||
|
Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1))); |
||||||
|
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1))); |
||||||
|
Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927))); |
||||||
|
Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612))); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void RoundTripZigZag64() |
||||||
|
{ |
||||||
|
Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0))); |
||||||
|
Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1))); |
||||||
|
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1))); |
||||||
|
Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927))); |
||||||
|
Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612))); |
||||||
|
|
||||||
|
Assert.AreEqual(856912304801416L, |
||||||
|
CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L))); |
||||||
|
Assert.AreEqual(-75123905439571256L, |
||||||
|
CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L))); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void TestNegativeEnumNoTag() |
||||||
|
{ |
||||||
|
Assert.AreEqual(10, CodedOutputStream.ComputeInt32Size(-2)); |
||||||
|
Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) SampleEnum.NegativeValue)); |
||||||
|
|
||||||
|
byte[] bytes = new byte[10]; |
||||||
|
CodedOutputStream output = new CodedOutputStream(bytes); |
||||||
|
output.WriteEnum((int) SampleEnum.NegativeValue); |
||||||
|
|
||||||
|
Assert.AreEqual(0, output.SpaceLeft); |
||||||
|
Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void TestCodedInputOutputPosition() |
||||||
|
{ |
||||||
|
byte[] content = new byte[110]; |
||||||
|
for (int i = 0; i < content.Length; i++) |
||||||
|
content[i] = (byte)i; |
||||||
|
|
||||||
|
byte[] child = new byte[120]; |
||||||
|
{ |
||||||
|
MemoryStream ms = new MemoryStream(child); |
||||||
|
CodedOutputStream cout = new CodedOutputStream(ms, 20); |
||||||
|
// Field 11: numeric value: 500 |
||||||
|
cout.WriteTag(11, WireFormat.WireType.Varint); |
||||||
|
Assert.AreEqual(1, cout.Position); |
||||||
|
cout.WriteInt32(500); |
||||||
|
Assert.AreEqual(3, cout.Position); |
||||||
|
//Field 12: length delimited 120 bytes |
||||||
|
cout.WriteTag(12, WireFormat.WireType.LengthDelimited); |
||||||
|
Assert.AreEqual(4, cout.Position); |
||||||
|
cout.WriteBytes(ByteString.CopyFrom(content)); |
||||||
|
Assert.AreEqual(115, cout.Position); |
||||||
|
// Field 13: fixed numeric value: 501 |
||||||
|
cout.WriteTag(13, WireFormat.WireType.Fixed32); |
||||||
|
Assert.AreEqual(116, cout.Position); |
||||||
|
cout.WriteSFixed32(501); |
||||||
|
Assert.AreEqual(120, cout.Position); |
||||||
|
cout.Flush(); |
||||||
|
} |
||||||
|
|
||||||
|
byte[] bytes = new byte[130]; |
||||||
|
{ |
||||||
|
CodedOutputStream cout = new CodedOutputStream(bytes); |
||||||
|
// Field 1: numeric value: 500 |
||||||
|
cout.WriteTag(1, WireFormat.WireType.Varint); |
||||||
|
Assert.AreEqual(1, cout.Position); |
||||||
|
cout.WriteInt32(500); |
||||||
|
Assert.AreEqual(3, cout.Position); |
||||||
|
//Field 2: length delimited 120 bytes |
||||||
|
cout.WriteTag(2, WireFormat.WireType.LengthDelimited); |
||||||
|
Assert.AreEqual(4, cout.Position); |
||||||
|
cout.WriteBytes(ByteString.CopyFrom(child)); |
||||||
|
Assert.AreEqual(125, cout.Position); |
||||||
|
// Field 3: fixed numeric value: 500 |
||||||
|
cout.WriteTag(3, WireFormat.WireType.Fixed32); |
||||||
|
Assert.AreEqual(126, cout.Position); |
||||||
|
cout.WriteSFixed32(501); |
||||||
|
Assert.AreEqual(130, cout.Position); |
||||||
|
cout.Flush(); |
||||||
|
} |
||||||
|
// Now test Input stream: |
||||||
|
{ |
||||||
|
CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50], 0, 0); |
||||||
|
Assert.AreEqual(0, cin.Position); |
||||||
|
// Field 1: |
||||||
|
uint tag = cin.ReadTag(); |
||||||
|
Assert.AreEqual(1, tag >> 3); |
||||||
|
Assert.AreEqual(1, cin.Position); |
||||||
|
Assert.AreEqual(500, cin.ReadInt32()); |
||||||
|
Assert.AreEqual(3, cin.Position); |
||||||
|
//Field 2: |
||||||
|
tag = cin.ReadTag(); |
||||||
|
Assert.AreEqual(2, tag >> 3); |
||||||
|
Assert.AreEqual(4, cin.Position); |
||||||
|
int childlen = cin.ReadLength(); |
||||||
|
Assert.AreEqual(120, childlen); |
||||||
|
Assert.AreEqual(5, cin.Position); |
||||||
|
int oldlimit = cin.PushLimit((int)childlen); |
||||||
|
Assert.AreEqual(5, cin.Position); |
||||||
|
// Now we are reading child message |
||||||
|
{ |
||||||
|
// Field 11: numeric value: 500 |
||||||
|
tag = cin.ReadTag(); |
||||||
|
Assert.AreEqual(11, tag >> 3); |
||||||
|
Assert.AreEqual(6, cin.Position); |
||||||
|
Assert.AreEqual(500, cin.ReadInt32()); |
||||||
|
Assert.AreEqual(8, cin.Position); |
||||||
|
//Field 12: length delimited 120 bytes |
||||||
|
tag = cin.ReadTag(); |
||||||
|
Assert.AreEqual(12, tag >> 3); |
||||||
|
Assert.AreEqual(9, cin.Position); |
||||||
|
ByteString bstr = cin.ReadBytes(); |
||||||
|
Assert.AreEqual(110, bstr.Length); |
||||||
|
Assert.AreEqual((byte) 109, bstr[109]); |
||||||
|
Assert.AreEqual(120, cin.Position); |
||||||
|
// Field 13: fixed numeric value: 501 |
||||||
|
tag = cin.ReadTag(); |
||||||
|
Assert.AreEqual(13, tag >> 3); |
||||||
|
// ROK - Previously broken here, this returned 126 failing to account for bufferSizeAfterLimit |
||||||
|
Assert.AreEqual(121, cin.Position); |
||||||
|
Assert.AreEqual(501, cin.ReadSFixed32()); |
||||||
|
Assert.AreEqual(125, cin.Position); |
||||||
|
Assert.IsTrue(cin.IsAtEnd); |
||||||
|
} |
||||||
|
cin.PopLimit(oldlimit); |
||||||
|
Assert.AreEqual(125, cin.Position); |
||||||
|
// Field 3: fixed numeric value: 501 |
||||||
|
tag = cin.ReadTag(); |
||||||
|
Assert.AreEqual(3, tag >> 3); |
||||||
|
Assert.AreEqual(126, cin.Position); |
||||||
|
Assert.AreEqual(501, cin.ReadSFixed32()); |
||||||
|
Assert.AreEqual(130, cin.Position); |
||||||
|
Assert.IsTrue(cin.IsAtEnd); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Dispose_DisposesUnderlyingStream() |
||||||
|
{ |
||||||
|
var memoryStream = new MemoryStream(); |
||||||
|
Assert.IsTrue(memoryStream.CanWrite); |
||||||
|
using (var cos = new CodedOutputStream(memoryStream)) |
||||||
|
{ |
||||||
|
cos.WriteRawByte(0); |
||||||
|
Assert.AreEqual(0, memoryStream.Position); // Not flushed yet |
||||||
|
} |
||||||
|
Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream |
||||||
|
Assert.IsFalse(memoryStream.CanWrite); // Disposed |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Dispose_WithLeaveOpen() |
||||||
|
{ |
||||||
|
var memoryStream = new MemoryStream(); |
||||||
|
Assert.IsTrue(memoryStream.CanWrite); |
||||||
|
using (var cos = new CodedOutputStream(memoryStream, true)) |
||||||
|
{ |
||||||
|
cos.WriteRawByte(0); |
||||||
|
Assert.AreEqual(0, memoryStream.Position); // Not flushed yet |
||||||
|
} |
||||||
|
Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream |
||||||
|
Assert.IsTrue(memoryStream.CanWrite); // We left the stream open |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,259 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// https://developers.google.com/protocol-buffers/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
#endregion |
||||||
|
|
||||||
|
using System.Linq; |
||||||
|
using Google.Protobuf.TestProtos; |
||||||
|
using NUnit.Framework; |
||||||
|
using UnitTest.Issues.TestProtos; |
||||||
|
|
||||||
|
namespace Google.Protobuf.Reflection |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Tests for descriptors. (Not in its own namespace or broken up into individual classes as the |
||||||
|
/// size doesn't warrant it. On the other hand, this makes me feel a bit dirty...) |
||||||
|
/// </summary> |
||||||
|
public class DescriptorsTest |
||||||
|
{ |
||||||
|
[Test] |
||||||
|
public void FileDescriptor() |
||||||
|
{ |
||||||
|
FileDescriptor file = UnittestProto3Reflection.Descriptor; |
||||||
|
|
||||||
|
Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name); |
||||||
|
Assert.AreEqual("protobuf_unittest", file.Package); |
||||||
|
|
||||||
|
Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname); |
||||||
|
Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Proto.Name); |
||||||
|
|
||||||
|
// unittest.proto doesn't have any public imports, but unittest_import.proto does. |
||||||
|
Assert.AreEqual(0, file.PublicDependencies.Count); |
||||||
|
Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.PublicDependencies.Count); |
||||||
|
Assert.AreEqual(UnittestImportPublicProto3Reflection.Descriptor, UnittestImportProto3Reflection.Descriptor.PublicDependencies[0]); |
||||||
|
|
||||||
|
Assert.AreEqual(1, file.Dependencies.Count); |
||||||
|
Assert.AreEqual(UnittestImportProto3Reflection.Descriptor, file.Dependencies[0]); |
||||||
|
|
||||||
|
MessageDescriptor messageType = TestAllTypes.Descriptor; |
||||||
|
Assert.AreSame(typeof(TestAllTypes), messageType.ClrType); |
||||||
|
Assert.AreSame(TestAllTypes.Parser, messageType.Parser); |
||||||
|
Assert.AreEqual(messageType, file.MessageTypes[0]); |
||||||
|
Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes")); |
||||||
|
Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType")); |
||||||
|
Assert.Null(file.FindTypeByName<MessageDescriptor>("protobuf_unittest.TestAllTypes")); |
||||||
|
for (int i = 0; i < file.MessageTypes.Count; i++) |
||||||
|
{ |
||||||
|
Assert.AreEqual(i, file.MessageTypes[i].Index); |
||||||
|
} |
||||||
|
|
||||||
|
Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName<EnumDescriptor>("ForeignEnum")); |
||||||
|
Assert.Null(file.FindTypeByName<EnumDescriptor>("NoSuchType")); |
||||||
|
Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest.ForeignEnum")); |
||||||
|
Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.EnumTypes.Count); |
||||||
|
Assert.AreEqual("ImportEnum", UnittestImportProto3Reflection.Descriptor.EnumTypes[0].Name); |
||||||
|
for (int i = 0; i < file.EnumTypes.Count; i++) |
||||||
|
{ |
||||||
|
Assert.AreEqual(i, file.EnumTypes[i].Index); |
||||||
|
} |
||||||
|
|
||||||
|
Assert.AreEqual(10, file.SerializedData[0]); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MessageDescriptor() |
||||||
|
{ |
||||||
|
MessageDescriptor messageType = TestAllTypes.Descriptor; |
||||||
|
MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor; |
||||||
|
|
||||||
|
Assert.AreEqual("TestAllTypes", messageType.Name); |
||||||
|
Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName); |
||||||
|
Assert.AreEqual(UnittestProto3Reflection.Descriptor, messageType.File); |
||||||
|
Assert.IsNull(messageType.ContainingType); |
||||||
|
Assert.IsNull(messageType.Proto.Options); |
||||||
|
|
||||||
|
Assert.AreEqual("TestAllTypes", messageType.Name); |
||||||
|
|
||||||
|
Assert.AreEqual("NestedMessage", nestedType.Name); |
||||||
|
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.FullName); |
||||||
|
Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File); |
||||||
|
Assert.AreEqual(messageType, nestedType.ContainingType); |
||||||
|
|
||||||
|
FieldDescriptor field = messageType.Fields.InDeclarationOrder()[0]; |
||||||
|
Assert.AreEqual("single_int32", field.Name); |
||||||
|
Assert.AreEqual(field, messageType.FindDescriptor<FieldDescriptor>("single_int32")); |
||||||
|
Assert.Null(messageType.FindDescriptor<FieldDescriptor>("no_such_field")); |
||||||
|
Assert.AreEqual(field, messageType.FindFieldByNumber(1)); |
||||||
|
Assert.Null(messageType.FindFieldByNumber(571283)); |
||||||
|
var fieldsInDeclarationOrder = messageType.Fields.InDeclarationOrder(); |
||||||
|
for (int i = 0; i < fieldsInDeclarationOrder.Count; i++) |
||||||
|
{ |
||||||
|
Assert.AreEqual(i, fieldsInDeclarationOrder[i].Index); |
||||||
|
} |
||||||
|
|
||||||
|
Assert.AreEqual(nestedType, messageType.NestedTypes[0]); |
||||||
|
Assert.AreEqual(nestedType, messageType.FindDescriptor<MessageDescriptor>("NestedMessage")); |
||||||
|
Assert.Null(messageType.FindDescriptor<MessageDescriptor>("NoSuchType")); |
||||||
|
for (int i = 0; i < messageType.NestedTypes.Count; i++) |
||||||
|
{ |
||||||
|
Assert.AreEqual(i, messageType.NestedTypes[i].Index); |
||||||
|
} |
||||||
|
|
||||||
|
Assert.AreEqual(messageType.EnumTypes[0], messageType.FindDescriptor<EnumDescriptor>("NestedEnum")); |
||||||
|
Assert.Null(messageType.FindDescriptor<EnumDescriptor>("NoSuchType")); |
||||||
|
for (int i = 0; i < messageType.EnumTypes.Count; i++) |
||||||
|
{ |
||||||
|
Assert.AreEqual(i, messageType.EnumTypes[i].Index); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void FieldDescriptor() |
||||||
|
{ |
||||||
|
MessageDescriptor messageType = TestAllTypes.Descriptor; |
||||||
|
FieldDescriptor primitiveField = messageType.FindDescriptor<FieldDescriptor>("single_int32"); |
||||||
|
FieldDescriptor enumField = messageType.FindDescriptor<FieldDescriptor>("single_nested_enum"); |
||||||
|
FieldDescriptor messageField = messageType.FindDescriptor<FieldDescriptor>("single_foreign_message"); |
||||||
|
|
||||||
|
Assert.AreEqual("single_int32", primitiveField.Name); |
||||||
|
Assert.AreEqual("protobuf_unittest.TestAllTypes.single_int32", |
||||||
|
primitiveField.FullName); |
||||||
|
Assert.AreEqual(1, primitiveField.FieldNumber); |
||||||
|
Assert.AreEqual(messageType, primitiveField.ContainingType); |
||||||
|
Assert.AreEqual(UnittestProto3Reflection.Descriptor, primitiveField.File); |
||||||
|
Assert.AreEqual(FieldType.Int32, primitiveField.FieldType); |
||||||
|
Assert.IsNull(primitiveField.Proto.Options); |
||||||
|
|
||||||
|
Assert.AreEqual("single_nested_enum", enumField.Name); |
||||||
|
Assert.AreEqual(FieldType.Enum, enumField.FieldType); |
||||||
|
// Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType); |
||||||
|
|
||||||
|
Assert.AreEqual("single_foreign_message", messageField.Name); |
||||||
|
Assert.AreEqual(FieldType.Message, messageField.FieldType); |
||||||
|
Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void FieldDescriptorLabel() |
||||||
|
{ |
||||||
|
FieldDescriptor singleField = |
||||||
|
TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("single_int32"); |
||||||
|
FieldDescriptor repeatedField = |
||||||
|
TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_int32"); |
||||||
|
|
||||||
|
Assert.IsFalse(singleField.IsRepeated); |
||||||
|
Assert.IsTrue(repeatedField.IsRepeated); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void EnumDescriptor() |
||||||
|
{ |
||||||
|
// Note: this test is a bit different to the Java version because there's no static way of getting to the descriptor |
||||||
|
EnumDescriptor enumType = UnittestProto3Reflection.Descriptor.FindTypeByName<EnumDescriptor>("ForeignEnum"); |
||||||
|
EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor<EnumDescriptor>("NestedEnum"); |
||||||
|
|
||||||
|
Assert.AreEqual("ForeignEnum", enumType.Name); |
||||||
|
Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName); |
||||||
|
Assert.AreEqual(UnittestProto3Reflection.Descriptor, enumType.File); |
||||||
|
Assert.Null(enumType.ContainingType); |
||||||
|
Assert.Null(enumType.Proto.Options); |
||||||
|
|
||||||
|
Assert.AreEqual("NestedEnum", nestedType.Name); |
||||||
|
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum", |
||||||
|
nestedType.FullName); |
||||||
|
Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File); |
||||||
|
Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType); |
||||||
|
|
||||||
|
EnumValueDescriptor value = enumType.FindValueByName("FOREIGN_FOO"); |
||||||
|
Assert.AreEqual(value, enumType.Values[1]); |
||||||
|
Assert.AreEqual("FOREIGN_FOO", value.Name); |
||||||
|
Assert.AreEqual(4, value.Number); |
||||||
|
Assert.AreEqual((int) ForeignEnum.ForeignFoo, value.Number); |
||||||
|
Assert.AreEqual(value, enumType.FindValueByNumber(4)); |
||||||
|
Assert.Null(enumType.FindValueByName("NO_SUCH_VALUE")); |
||||||
|
for (int i = 0; i < enumType.Values.Count; i++) |
||||||
|
{ |
||||||
|
Assert.AreEqual(i, enumType.Values[i].Index); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void OneofDescriptor() |
||||||
|
{ |
||||||
|
OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field"); |
||||||
|
Assert.AreEqual("oneof_field", descriptor.Name); |
||||||
|
Assert.AreEqual("protobuf_unittest.TestAllTypes.oneof_field", descriptor.FullName); |
||||||
|
|
||||||
|
var expectedFields = new[] { |
||||||
|
TestAllTypes.OneofBytesFieldNumber, |
||||||
|
TestAllTypes.OneofNestedMessageFieldNumber, |
||||||
|
TestAllTypes.OneofStringFieldNumber, |
||||||
|
TestAllTypes.OneofUint32FieldNumber } |
||||||
|
.Select(fieldNumber => TestAllTypes.Descriptor.FindFieldByNumber(fieldNumber)) |
||||||
|
.ToList(); |
||||||
|
foreach (var field in expectedFields) |
||||||
|
{ |
||||||
|
Assert.AreSame(descriptor, field.ContainingOneof); |
||||||
|
} |
||||||
|
|
||||||
|
CollectionAssert.AreEquivalent(expectedFields, descriptor.Fields); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MapEntryMessageDescriptor() |
||||||
|
{ |
||||||
|
var descriptor = MapWellKnownTypes.Descriptor.NestedTypes[0]; |
||||||
|
Assert.IsNull(descriptor.Parser); |
||||||
|
Assert.IsNull(descriptor.ClrType); |
||||||
|
Assert.IsNull(descriptor.Fields[1].Accessor); |
||||||
|
} |
||||||
|
|
||||||
|
// From TestFieldOrdering: |
||||||
|
// string my_string = 11; |
||||||
|
// int64 my_int = 1; |
||||||
|
// float my_float = 101; |
||||||
|
// NestedMessage single_nested_message = 200; |
||||||
|
[Test] |
||||||
|
public void FieldListOrderings() |
||||||
|
{ |
||||||
|
var fields = TestFieldOrderings.Descriptor.Fields; |
||||||
|
Assert.AreEqual(new[] { 11, 1, 101, 200 }, fields.InDeclarationOrder().Select(x => x.FieldNumber)); |
||||||
|
Assert.AreEqual(new[] { 1, 11, 101, 200 }, fields.InFieldNumberOrder().Select(x => x.FieldNumber)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[Test] |
||||||
|
public void DescriptorProtoFileDescriptor() |
||||||
|
{ |
||||||
|
var descriptor = Google.Protobuf.Reflection.FileDescriptor.DescriptorProtoFileDescriptor; |
||||||
|
Assert.AreEqual("google/protobuf/descriptor.proto", descriptor.Name); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2015 Google Inc. All rights reserved. |
||||||
|
// https://developers.google.com/protocol-buffers/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
#endregion |
||||||
|
|
||||||
|
namespace Google.Protobuf |
||||||
|
{ |
||||||
|
// Just a sample enum with positive and negative values to be used in tests. |
||||||
|
internal enum SampleEnum |
||||||
|
{ |
||||||
|
NegativeValue = -2, |
||||||
|
None = 0, |
||||||
|
PositiveValue = 3 |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
{ |
||||||
|
"buildOptions": { |
||||||
|
"debugType": "portable", |
||||||
|
"keyFile": "../../keys/Google.Protobuf.snk" |
||||||
|
}, |
||||||
|
|
||||||
|
"configurations": { |
||||||
|
"Debug": { |
||||||
|
"buildOptions": { |
||||||
|
"define": [ "DEBUG", "TRACE" ] |
||||||
|
} |
||||||
|
}, |
||||||
|
"Release": { |
||||||
|
"buildOptions": { |
||||||
|
"define": [ "RELEASE", "TRACE" ], |
||||||
|
"optimize": true |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
"dependencies": { |
||||||
|
"Google.Protobuf": { "target": "project" }, |
||||||
|
"NUnit": "3.4.0", |
||||||
|
"dotnet-test-nunit": "3.4.0-alpha-2", |
||||||
|
}, |
||||||
|
|
||||||
|
"testRunner": "nunit", |
||||||
|
|
||||||
|
"frameworks": { |
||||||
|
"netcoreapp1.0": { |
||||||
|
"imports" : [ "dnxcore50", "netcoreapp1.0", "portable-net45+win8" ], |
||||||
|
"buildOptions": { |
||||||
|
"define": [ "PCL" ] |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"Microsoft.NETCore.App": { |
||||||
|
"version": "1.0.0", |
||||||
|
"type": "platform" |
||||||
|
}, |
||||||
|
"System.Console": "4.0.0" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,102 @@ |
|||||||
|
#!/bin/bash |
||||||
|
|
||||||
|
function run_test() { |
||||||
|
# Generate test proto files. |
||||||
|
./protoc_1 -Iprotos/src -I../../../src/ --csharp_out=src/Google.Protobuf.Test \ |
||||||
|
--csharp_opt=base_namespace=Google.Protobuf \ |
||||||
|
protos/src/google/protobuf/unittest_import_proto3.proto \ |
||||||
|
protos/src/google/protobuf/unittest_import_public_proto3.proto \ |
||||||
|
protos/src/google/protobuf/unittest_well_known_types.proto |
||||||
|
|
||||||
|
./protoc_1 -Iprotos/csharp --csharp_out=src/Google.Protobuf.Test \ |
||||||
|
--csharp_opt=base_namespace=UnitTest.Issues \ |
||||||
|
protos/csharp/protos/unittest_issues.proto |
||||||
|
|
||||||
|
./protoc_2 -Iprotos/src --csharp_out=src/Google.Protobuf.Test \ |
||||||
|
--csharp_opt=base_namespace=Google.Protobuf \ |
||||||
|
protos/src/google/protobuf/unittest_proto3.proto \ |
||||||
|
protos/src/google/protobuf/map_unittest_proto3.proto |
||||||
|
|
||||||
|
# Build and test. |
||||||
|
dotnet build -c release src/Google.Protobuf src/Google.Protobuf.Test |
||||||
|
dotnet test -c release -f netcoreapp1.0 src/Google.Protobuf.Test |
||||||
|
} |
||||||
|
|
||||||
|
set -ex |
||||||
|
|
||||||
|
# Change to the script's directory. |
||||||
|
cd $(dirname $0) |
||||||
|
|
||||||
|
# Version of the tests (i.e., the version of protobuf from where we extracted |
||||||
|
# these tests). |
||||||
|
TEST_VERSION=3.0.0 |
||||||
|
|
||||||
|
# The old version of protobuf that we are testing compatibility against. This |
||||||
|
# is usually the same as TEST_VERSION (i.e., we use the tests extracted from |
||||||
|
# that version to test compatibility of the newest runtime against it), but it |
||||||
|
# is also possible to use this same test set to test the compatibiilty of the |
||||||
|
# latest version against other versions. |
||||||
|
case "$1" in |
||||||
|
""|3.0.0) |
||||||
|
OLD_VERSION=3.0.0 |
||||||
|
OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0/protoc-3.0.0-linux-x86_64.exe |
||||||
|
;; |
||||||
|
3.0.2) |
||||||
|
OLD_VERSION=3.0.2 |
||||||
|
OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.2/protoc-3.0.2-linux-x86_64.exe |
||||||
|
;; |
||||||
|
3.1.0) |
||||||
|
OLD_VERSION=3.1.0 |
||||||
|
OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.1.0/protoc-3.1.0-linux-x86_64.exe |
||||||
|
;; |
||||||
|
*) |
||||||
|
echo "[ERROR]: Unknown version number: $1" |
||||||
|
exit 1 |
||||||
|
;; |
||||||
|
esac |
||||||
|
|
||||||
|
echo "Running compatibility tests with $OLD_VERSION" |
||||||
|
|
||||||
|
# Check protoc |
||||||
|
[ -f ../../../src/protoc ] || { |
||||||
|
echo "[ERROR]: Please build protoc first." |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
|
||||||
|
# Download old version protoc compiler (for linux). |
||||||
|
wget $OLD_VERSION_PROTOC -O old_protoc |
||||||
|
chmod +x old_protoc |
||||||
|
|
||||||
|
# Test source compatibility. In these tests we recompile everything against |
||||||
|
# the new runtime (including old version generated code). |
||||||
|
# Copy the new runtime and keys. |
||||||
|
cp ../../src/Google.Protobuf src/Google.Protobuf -r |
||||||
|
cp ../../keys . -r |
||||||
|
dotnet restore |
||||||
|
|
||||||
|
# Test A.1: |
||||||
|
# proto set 1: use old version |
||||||
|
# proto set 2 which may import protos in set 1: use old version |
||||||
|
cp old_protoc protoc_1 |
||||||
|
cp old_protoc protoc_2 |
||||||
|
run_test |
||||||
|
|
||||||
|
# Test A.2: |
||||||
|
# proto set 1: use new version |
||||||
|
# proto set 2 which may import protos in set 1: use old version |
||||||
|
cp ../../../src/protoc protoc_1 |
||||||
|
cp old_protoc protoc_2 |
||||||
|
run_test |
||||||
|
|
||||||
|
# Test A.3: |
||||||
|
# proto set 1: use old version |
||||||
|
# proto set 2 which may import protos in set 1: use new version |
||||||
|
cp old_protoc protoc_1 |
||||||
|
cp ../../../src/protoc protoc_2 |
||||||
|
run_test |
||||||
|
|
||||||
|
rm protoc_1 |
||||||
|
rm protoc_2 |
||||||
|
rm old_protoc |
||||||
|
rm keys -r |
||||||
|
rm src/Google.Protobuf -r |
Loading…
Reference in new issue