• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 // Protocol Buffers - Google's data interchange format
3 // Copyright 2015 Google Inc.  All rights reserved.
4 // https://developers.google.com/protocol-buffers/
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 //     * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #endregion
32 
33 using Conformance;
34 using Google.Protobuf.Reflection;
35 using System;
36 using System.IO;
37 
38 namespace Google.Protobuf.Conformance
39 {
40     /// <summary>
41     /// Conformance tests. The test runner will provide JSON or proto data on stdin,
42     /// and this program will produce its output on stdout.
43     /// </summary>
44     class Program
45     {
Main(string[] args)46         private static void Main(string[] args)
47         {
48             // This way we get the binary streams instead of readers/writers.
49             var input = new BinaryReader(Console.OpenStandardInput());
50             var output = new BinaryWriter(Console.OpenStandardOutput());
51             var typeRegistry = TypeRegistry.FromMessages(
52                 ProtobufTestMessages.Proto3.TestAllTypesProto3.Descriptor,
53                 ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor);
54 
55             int count = 0;
56             while (RunTest(input, output, typeRegistry))
57             {
58                 count++;
59             }
60             Console.Error.WriteLine("Received EOF after {0} tests", count);
61         }
62 
RunTest(BinaryReader input, BinaryWriter output, TypeRegistry typeRegistry)63         private static bool RunTest(BinaryReader input, BinaryWriter output, TypeRegistry typeRegistry)
64         {
65             int? size = ReadInt32(input);
66             if (size == null)
67             {
68                 return false;
69             }
70             byte[] inputData = input.ReadBytes(size.Value);
71             if (inputData.Length != size.Value)
72             {
73                 throw new EndOfStreamException("Read " + inputData.Length + " bytes of data when expecting " + size);
74             }
75             ConformanceRequest request = ConformanceRequest.Parser.ParseFrom(inputData);
76             ConformanceResponse response = PerformRequest(request, typeRegistry);
77             byte[] outputData = response.ToByteArray();
78             output.Write(outputData.Length);
79             output.Write(outputData);
80             // Ready for another test...
81             return true;
82         }
83 
PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)84         private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)
85         {
86             ExtensionRegistry proto2ExtensionRegistry = new ExtensionRegistry
87             {
88                 ProtobufTestMessages.Proto2.TestMessagesProto2Extensions.ExtensionInt32,
89                 ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1.Extensions.MessageSetExtension,
90                 ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2.Extensions.MessageSetExtension
91             };
92             IMessage message;
93             try
94             {
95                 switch (request.PayloadCase)
96                 {
97                     case ConformanceRequest.PayloadOneofCase.JsonPayload:
98                         if (request.TestCategory == global::Conformance.TestCategory.JsonIgnoreUnknownParsingTest)
99                         {
100                             return new ConformanceResponse { Skipped = "CSharp doesn't support skipping unknown fields in json parsing." };
101                         }
102                         var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry));
103                         switch (request.MessageType)
104                         {
105                             case "protobuf_test_messages.proto3.TestAllTypesProto3":
106                                 message = parser.Parse<ProtobufTestMessages.Proto3.TestAllTypesProto3>(request.JsonPayload);
107                                 break;
108                             case "protobuf_test_messages.proto2.TestAllTypesProto2":
109                                 message = parser.Parse<ProtobufTestMessages.Proto2.TestAllTypesProto2>(request.JsonPayload);
110                                 break;
111                             default:
112                                 throw new Exception($" Protobuf request doesn't have specific payload type ({request.MessageType})");
113                         }
114                         break;
115                     case ConformanceRequest.PayloadOneofCase.ProtobufPayload:
116                         switch (request.MessageType)
117                         {
118                             case "protobuf_test_messages.proto3.TestAllTypesProto3":
119                                 message = ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser.ParseFrom(request.ProtobufPayload);
120                                 break;
121                             case "protobuf_test_messages.proto2.TestAllTypesProto2":
122                                 message = ProtobufTestMessages.Proto2.TestAllTypesProto2.Parser
123                                     .WithExtensionRegistry(proto2ExtensionRegistry)
124                                     .ParseFrom(request.ProtobufPayload);
125                                 break;
126                             default:
127                                 throw new Exception($" Protobuf request doesn't have specific payload type ({request.MessageType})");
128                         }
129                         break;
130 					case ConformanceRequest.PayloadOneofCase.TextPayload:
131 						return new ConformanceResponse { Skipped = "CSharp doesn't support text format" };
132                     default:
133                         throw new Exception("Unsupported request payload: " + request.PayloadCase);
134                 }
135             }
136             catch (InvalidProtocolBufferException e)
137             {
138                 return new ConformanceResponse { ParseError = e.Message };
139             }
140             catch (InvalidJsonException e)
141             {
142                 return new ConformanceResponse { ParseError = e.Message };
143             }
144             try
145             {
146                 switch (request.RequestedOutputFormat)
147                 {
148                     case global::Conformance.WireFormat.Json:
149                         var formatter = new JsonFormatter(new JsonFormatter.Settings(false, typeRegistry));
150                         return new ConformanceResponse { JsonPayload = formatter.Format(message) };
151                     case global::Conformance.WireFormat.Protobuf:
152                         return new ConformanceResponse { ProtobufPayload = message.ToByteString() };
153                     default:
154                         throw new Exception("Unsupported request output format: " + request.RequestedOutputFormat);
155                 }
156             }
157             catch (InvalidOperationException e)
158             {
159                 return new ConformanceResponse { SerializeError = e.Message };
160             }
161         }
162 
ReadInt32(BinaryReader input)163         private static int? ReadInt32(BinaryReader input)
164         {
165             byte[] bytes = input.ReadBytes(4);
166             if (bytes.Length == 0)
167             {
168                 // Cleanly reached the end of the stream
169                 return null;
170             }
171             if (bytes.Length != 4)
172             {
173                 throw new EndOfStreamException("Read " + bytes.Length + " bytes of size when expecting 4");
174             }
175             return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
176         }
177     }
178 }
179