blob: f3f7e2957af51c2fe36342305b90f046ee8593e0 [file] [log] [blame]
Jon Skeet044c36e2015-08-04 09:25:38 +01001#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
33using Conformance;
Jon Skeeta4dc5962015-12-07 13:25:35 +000034using Google.Protobuf.Reflection;
Jon Skeet044c36e2015-08-04 09:25:38 +010035using System;
36using System.IO;
37
38namespace 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 {
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());
Jon Skeeta4dc5962015-12-07 13:25:35 +000051 var typeRegistry = TypeRegistry.FromMessages(TestAllTypes.Descriptor);
Jon Skeet044c36e2015-08-04 09:25:38 +010052
53 int count = 0;
Jon Skeeta4dc5962015-12-07 13:25:35 +000054 while (RunTest(input, output, typeRegistry))
Jon Skeet044c36e2015-08-04 09:25:38 +010055 {
56 count++;
57 }
58 Console.Error.WriteLine("Received EOF after {0} tests", count);
59 }
60
Jon Skeeta4dc5962015-12-07 13:25:35 +000061 private static bool RunTest(BinaryReader input, BinaryWriter output, TypeRegistry typeRegistry)
Jon Skeet044c36e2015-08-04 09:25:38 +010062 {
63 int? size = ReadInt32(input);
64 if (size == null)
65 {
66 return false;
67 }
68 byte[] inputData = input.ReadBytes(size.Value);
69 if (inputData.Length != size.Value)
70 {
71 throw new EndOfStreamException("Read " + inputData.Length + " bytes of data when expecting " + size);
72 }
73 ConformanceRequest request = ConformanceRequest.Parser.ParseFrom(inputData);
Jon Skeeta4dc5962015-12-07 13:25:35 +000074 ConformanceResponse response = PerformRequest(request, typeRegistry);
Jon Skeet044c36e2015-08-04 09:25:38 +010075 byte[] outputData = response.ToByteArray();
76 output.Write(outputData.Length);
77 output.Write(outputData);
78 // Ready for another test...
79 return true;
80 }
81
Jon Skeeta4dc5962015-12-07 13:25:35 +000082 private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)
Jon Skeet044c36e2015-08-04 09:25:38 +010083 {
84 TestAllTypes message;
Jon Skeeta4dc5962015-12-07 13:25:35 +000085 try
Jon Skeet044c36e2015-08-04 09:25:38 +010086 {
Jon Skeeta4dc5962015-12-07 13:25:35 +000087 switch (request.PayloadCase)
88 {
89 case ConformanceRequest.PayloadOneofCase.JsonPayload:
90 var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry));
91 message = parser.Parse<TestAllTypes>(request.JsonPayload);
92 break;
93 case ConformanceRequest.PayloadOneofCase.ProtobufPayload:
Jon Skeet044c36e2015-08-04 09:25:38 +010094 message = TestAllTypes.Parser.ParseFrom(request.ProtobufPayload);
Jon Skeeta4dc5962015-12-07 13:25:35 +000095 break;
96 default:
97 throw new Exception("Unsupported request payload: " + request.PayloadCase);
98 }
99 }
100 catch (InvalidProtocolBufferException e)
101 {
102 return new ConformanceResponse { ParseError = e.Message };
Jon Skeet044c36e2015-08-04 09:25:38 +0100103 }
Jon Skeetf2fe50b2016-01-13 14:05:06 +0000104 catch (InvalidJsonException e)
105 {
106 return new ConformanceResponse { ParseError = e.Message };
107 }
Jon Skeetc74676f2016-01-15 10:55:57 +0000108 try
Jon Skeet044c36e2015-08-04 09:25:38 +0100109 {
Jon Skeetc74676f2016-01-15 10:55:57 +0000110 switch (request.RequestedOutputFormat)
111 {
112 case global::Conformance.WireFormat.JSON:
113 var formatter = new JsonFormatter(new JsonFormatter.Settings(false, typeRegistry));
114 return new ConformanceResponse { JsonPayload = formatter.Format(message) };
115 case global::Conformance.WireFormat.PROTOBUF:
116 return new ConformanceResponse { ProtobufPayload = message.ToByteString() };
117 default:
118 throw new Exception("Unsupported request output format: " + request.PayloadCase);
119 }
120 }
121 catch (InvalidOperationException e)
122 {
123 return new ConformanceResponse { SerializeError = e.Message };
Jon Skeet044c36e2015-08-04 09:25:38 +0100124 }
125 }
126
127 private static int? ReadInt32(BinaryReader input)
128 {
129 byte[] bytes = input.ReadBytes(4);
130 if (bytes.Length == 0)
131 {
132 // Cleanly reached the end of the stream
133 return null;
134 }
135 if (bytes.Length != 4)
136 {
137 throw new EndOfStreamException("Read " + bytes.Length + " bytes of size when expecting 4");
138 }
139 return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
140 }
141 }
142}