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(TestAllTypes.Descriptor);
52 
53             int count = 0;
54             while (RunTest(input, output, typeRegistry))
55             {
56                 count++;
57             }
58             Console.Error.WriteLine("Received EOF after {0} tests", count);
59         }
60 
RunTest(BinaryReader input, BinaryWriter output, TypeRegistry typeRegistry)61         private static bool RunTest(BinaryReader input, BinaryWriter output, TypeRegistry typeRegistry)
62         {
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);
74             ConformanceResponse response = PerformRequest(request, typeRegistry);
75             byte[] outputData = response.ToByteArray();
76             output.Write(outputData.Length);
77             output.Write(outputData);
78             // Ready for another test...
79             return true;
80         }
81 
PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)82         private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)
83         {
84             TestAllTypes message;
85             try
86             {
87                 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:
94                         message = TestAllTypes.Parser.ParseFrom(request.ProtobufPayload);
95                         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 };
103             }
104             catch (InvalidJsonException e)
105             {
106                 return new ConformanceResponse { ParseError = e.Message };
107             }
108             try
109             {
110                 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 };
124             }
125         }
126 
ReadInt32(BinaryReader input)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 }
143