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