• 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 //
5 // Use of this source code is governed by a BSD-style
6 // license that can be found in the LICENSE file or at
7 // https://developers.google.com/open-source/licenses/bsd
8 #endregion
9 
10 using Conformance;
11 using Google.Protobuf.Reflection;
12 using System;
13 using System.IO;
14 
15 namespace Google.Protobuf.Conformance
16 {
17     /// <summary>
18     /// Conformance tests. The test runner will provide JSON or proto data on stdin,
19     /// and this program will produce its output on stdout.
20     /// </summary>
21     class Program
22     {
Main()23         private static void Main()
24         {
25             // This way we get the binary streams instead of readers/writers.
26             var input = new BinaryReader(Console.OpenStandardInput());
27             var output = new BinaryWriter(Console.OpenStandardOutput());
28             var typeRegistry = TypeRegistry.FromMessages(
29                 ProtobufTestMessages.Proto3.TestAllTypesProto3.Descriptor,
30                 ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor,
31                 ProtobufTestMessages.Editions.TestAllTypesEdition2023.Descriptor,
32                 ProtobufTestMessages.Editions.Proto3.TestAllTypesProto3.Descriptor,
33                 ProtobufTestMessages.Editions.Proto2.TestAllTypesProto2.Descriptor);
34 
35             int count = 0;
36             while (RunTest(input, output, typeRegistry))
37             {
38                 count++;
39             }
40             Console.Error.WriteLine("Received EOF after {0} tests", count);
41         }
42 
RunTest(BinaryReader input, BinaryWriter output, TypeRegistry typeRegistry)43         private static bool RunTest(BinaryReader input, BinaryWriter output, TypeRegistry typeRegistry)
44         {
45             int? size = ReadInt32(input);
46             if (size == null)
47             {
48                 return false;
49             }
50             byte[] inputData = input.ReadBytes(size.Value);
51             if (inputData.Length != size.Value)
52             {
53                 throw new EndOfStreamException("Read " + inputData.Length + " bytes of data when expecting " + size);
54             }
55             ConformanceRequest request = ConformanceRequest.Parser.ParseFrom(inputData);
56             ConformanceResponse response = PerformRequest(request, typeRegistry);
57             byte[] outputData = response.ToByteArray();
58             output.Write(outputData.Length);
59             output.Write(outputData);
60             // Ready for another test...
61             return true;
62         }
63 
PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)64         private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)
65         {
66             ExtensionRegistry proto2ExtensionRegistry = new ExtensionRegistry
67             {
68                 ProtobufTestMessages.Proto2.TestMessagesProto2Extensions.ExtensionInt32,
69                 ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1.Extensions.MessageSetExtension,
70                 ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2.Extensions.MessageSetExtension
71             };
72             ExtensionRegistry editionsProto2ExtensionRegistry = new ExtensionRegistry
73             {
74               ProtobufTestMessages.Editions.Proto2.TestMessagesProto2EditionsExtensions
75                   .ExtensionInt32,
76               ProtobufTestMessages.Editions.Proto2.TestAllTypesProto2.Types
77                   .MessageSetCorrectExtension1.Extensions.MessageSetExtension,
78               ProtobufTestMessages.Editions.Proto2.TestAllTypesProto2.Types
79                   .MessageSetCorrectExtension2.Extensions.MessageSetExtension
80             };
81             ExtensionRegistry edition2023ExtensionRegistry = new ExtensionRegistry {
82               ProtobufTestMessages.Editions.TestMessagesEdition2023Extensions.ExtensionInt32,
83               ProtobufTestMessages.Editions.TestMessagesEdition2023Extensions.DelimitedExt,
84               ProtobufTestMessages.Editions.TestMessagesEdition2023Extensions.GroupLikeType
85             };
86             IMessage message;
87             try
88             {
89                 switch (request.PayloadCase)
90                 {
91                     case ConformanceRequest.PayloadOneofCase.JsonPayload:
92                         bool ignoreUnknownFields = request.TestCategory == global::Conformance.TestCategory.JsonIgnoreUnknownParsingTest;
93                         JsonParser parser = new JsonParser(new JsonParser.Settings(20, typeRegistry).WithIgnoreUnknownFields(ignoreUnknownFields));
94                         message = request.MessageType switch
95                         {
96                           "protobuf_test_messages.proto2.TestAllTypesProto2" =>
97                               parser.Parse<ProtobufTestMessages.Proto2.TestAllTypesProto2>(
98                                   request.JsonPayload),
99                           "protobuf_test_messages.proto3.TestAllTypesProto3" =>
100                               parser.Parse<ProtobufTestMessages.Proto3.TestAllTypesProto3>(
101                                   request.JsonPayload),
102                           "protobuf_test_messages.editions.TestAllTypesEdition2023" =>
103                               parser.Parse<ProtobufTestMessages.Editions.TestAllTypesEdition2023>(
104                                   request.JsonPayload),
105                           "protobuf_test_messages.editions.proto2.TestAllTypesProto2" =>
106                               parser.Parse<ProtobufTestMessages.Editions.Proto2.TestAllTypesProto2>(
107                                   request.JsonPayload),
108                           "protobuf_test_messages.editions.proto3.TestAllTypesProto3" =>
109                               parser.Parse<ProtobufTestMessages.Editions.Proto3.TestAllTypesProto3>(
110                                   request.JsonPayload),
111                           _ => throw new Exception(
112                               $" Protobuf request doesn't have specific payload type ({request.MessageType})"),
113                         };
114                         break;
115                     case ConformanceRequest.PayloadOneofCase.ProtobufPayload:
116                       message = request.MessageType switch
117                       {
118                         "protobuf_test_messages.proto2.TestAllTypesProto2" =>
119                             ProtobufTestMessages.Proto2.TestAllTypesProto2.Parser
120                                 .WithExtensionRegistry(proto2ExtensionRegistry)
121                                 .ParseFrom(request.ProtobufPayload),
122                         "protobuf_test_messages.proto3.TestAllTypesProto3" =>
123                             ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser.ParseFrom(
124                                 request.ProtobufPayload),
125                         "protobuf_test_messages.editions.TestAllTypesEdition2023" =>
126                             ProtobufTestMessages.Editions.TestAllTypesEdition2023.Parser
127                                 .WithExtensionRegistry(edition2023ExtensionRegistry)
128                                 .ParseFrom(request.ProtobufPayload),
129                         "protobuf_test_messages.editions.proto2.TestAllTypesProto2" =>
130                             ProtobufTestMessages.Editions.Proto2.TestAllTypesProto2.Parser
131                                 .WithExtensionRegistry(editionsProto2ExtensionRegistry)
132                                 .ParseFrom(request.ProtobufPayload),
133                         "protobuf_test_messages.editions.proto3.TestAllTypesProto3" =>
134                             ProtobufTestMessages.Editions.Proto3.TestAllTypesProto3.Parser
135                                 .ParseFrom(request.ProtobufPayload),
136                         _ => throw new Exception(
137                             $" Protobuf request doesn't have specific payload type ({request.MessageType})"),
138                       };
139                       break;
140                     case ConformanceRequest.PayloadOneofCase.TextPayload:
141                       return new ConformanceResponse { Skipped =
142                                                            "CSharp doesn't support text format" };
143                     default:
144                         throw new Exception("Unsupported request payload: " + request.PayloadCase);
145                 }
146             }
147             catch (InvalidProtocolBufferException e)
148             {
149                 return new ConformanceResponse { ParseError = e.Message };
150             }
151             catch (InvalidJsonException e)
152             {
153                 return new ConformanceResponse { ParseError = e.Message };
154             }
155             try
156             {
157                 switch (request.RequestedOutputFormat)
158                 {
159                     case global::Conformance.WireFormat.Json:
160                         var formatter = new JsonFormatter(new JsonFormatter.Settings(false, typeRegistry));
161                         return new ConformanceResponse { JsonPayload = formatter.Format(message) };
162                     case global::Conformance.WireFormat.Protobuf:
163                         return new ConformanceResponse { ProtobufPayload = message.ToByteString() };
164                     default:
165                         return new ConformanceResponse { Skipped = "CSharp doesn't support text format" };
166                 }
167             }
168             catch (InvalidOperationException e)
169             {
170                 return new ConformanceResponse { SerializeError = e.Message };
171             }
172         }
173 
ReadInt32(BinaryReader input)174         private static int? ReadInt32(BinaryReader input)
175         {
176             byte[] bytes = input.ReadBytes(4);
177             if (bytes.Length == 0)
178             {
179                 // Cleanly reached the end of the stream
180                 return null;
181             }
182             if (bytes.Length != 4)
183             {
184                 throw new EndOfStreamException("Read " + bytes.Length + " bytes of size when expecting 4");
185             }
186             return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
187         }
188     }
189 }
190