blob: ab751c81de4b9b4917040a2c2d674a7a9ffe2af8 [file] [log] [blame]
Thomas Van Lenten1745f7e2015-11-17 10:18:49 -05001// Protocol Buffers - Google's data interchange format
2// Copyright 2015 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#import <Foundation/Foundation.h>
32
33#import "Conformance.pbobjc.h"
Thomas Van Lentenc2831a32017-07-26 15:58:07 -040034#import "google/protobuf/TestMessagesProto2.pbobjc.h"
Joshua Habermanf1ce60e2016-12-03 11:51:25 -050035#import "google/protobuf/TestMessagesProto3.pbobjc.h"
Thomas Van Lenten1745f7e2015-11-17 10:18:49 -050036
37static void Die(NSString *format, ...) __dead2;
38
39static BOOL verbose = NO;
40static int32_t testCount = 0;
41
42static void Die(NSString *format, ...) {
43 va_list args;
44 va_start(args, format);
45 NSString *msg = [[NSString alloc] initWithFormat:format arguments:args];
46 NSLog(@"%@", msg);
47 va_end(args);
48 [msg release];
49 exit(66);
50}
51
52static NSData *CheckedReadDataOfLength(NSFileHandle *handle, NSUInteger numBytes) {
53 NSData *data = [handle readDataOfLength:numBytes];
54 NSUInteger dataLen = data.length;
55 if (dataLen == 0) {
56 return nil; // EOF.
57 }
58 if (dataLen != numBytes) {
59 Die(@"Failed to read the request length (%d), only got: %@",
60 numBytes, data);
61 }
62 return data;
63}
64
65static ConformanceResponse *DoTest(ConformanceRequest *request) {
66 ConformanceResponse *response = [ConformanceResponse message];
Thomas Van Lentenc2831a32017-07-26 15:58:07 -040067 GPBMessage *testMessage = nil;
Thomas Van Lenten1745f7e2015-11-17 10:18:49 -050068
69 switch (request.payloadOneOfCase) {
70 case ConformanceRequest_Payload_OneOfCase_GPBUnsetOneOfCase:
Thomas Van Lenten400d3882019-07-18 17:17:01 -040071 response.runtimeError =
72 [NSString stringWithFormat:@"Request didn't have a payload: %@", request];
Thomas Van Lenten1745f7e2015-11-17 10:18:49 -050073 break;
74
75 case ConformanceRequest_Payload_OneOfCase_ProtobufPayload: {
Thomas Van Lentenc2831a32017-07-26 15:58:07 -040076 Class msgClass = nil;
77 if ([request.messageType isEqual:@"protobuf_test_messages.proto3.TestAllTypesProto3"]) {
78 msgClass = [Proto3TestAllTypesProto3 class];
79 } else if ([request.messageType isEqual:@"protobuf_test_messages.proto2.TestAllTypesProto2"]) {
80 msgClass = [TestAllTypesProto2 class];
81 } else {
Thomas Van Lenten400d3882019-07-18 17:17:01 -040082 response.runtimeError =
Rafi Kamal4f02f052019-08-22 16:14:22 -070083 [NSString stringWithFormat:@"Protobuf request had an unknown message_type: %@",
84 request.messageType];
Thomas Van Lenten400d3882019-07-18 17:17:01 -040085 break;
Thomas Van Lentenc2831a32017-07-26 15:58:07 -040086 }
Thomas Van Lenten3caf9fd2017-07-26 16:24:05 -040087 NSError *error = nil;
88 testMessage = [msgClass parseFromData:request.protobufPayload error:&error];
89 if (!testMessage) {
90 response.parseError =
91 [NSString stringWithFormat:@"Parse error: %@", error];
Thomas Van Lenten1745f7e2015-11-17 10:18:49 -050092 }
93 break;
94 }
95
96 case ConformanceRequest_Payload_OneOfCase_JsonPayload:
97 response.skipped = @"ObjC doesn't support parsing JSON";
98 break;
Thomas Van Lenten24d344c2019-01-07 17:03:37 -050099
100 case ConformanceRequest_Payload_OneOfCase_JspbPayload:
101 response.skipped =
102 @"ConformanceRequest had a jspb_payload ConformanceRequest.payload;"
103 " those aren't supposed to happen with opensource.";
104 break;
Thomas Van Lenten0c957912019-01-14 10:28:21 -0500105
106 case ConformanceRequest_Payload_OneOfCase_TextPayload:
107 response.skipped = @"ObjC doesn't support parsing TextFormat";
108 break;
Thomas Van Lenten1745f7e2015-11-17 10:18:49 -0500109 }
110
111 if (testMessage) {
112 switch (request.requestedOutputFormat) {
113 case WireFormat_GPBUnrecognizedEnumeratorValue:
114 case WireFormat_Unspecified:
Thomas Van Lenten400d3882019-07-18 17:17:01 -0400115 response.runtimeError =
116 [NSString stringWithFormat:@"Unrecognized/unspecified output format: %@", request];
Thomas Van Lenten1745f7e2015-11-17 10:18:49 -0500117 break;
118
119 case WireFormat_Protobuf:
120 response.protobufPayload = testMessage.data;
121 if (!response.protobufPayload) {
Thomas Van Lentendf4e4d82016-01-05 16:31:40 -0500122 response.serializeError =
Thomas Van Lenten1745f7e2015-11-17 10:18:49 -0500123 [NSString stringWithFormat:@"Failed to make data from: %@", testMessage];
124 }
125 break;
126
127 case WireFormat_Json:
128 response.skipped = @"ObjC doesn't support generating JSON";
129 break;
Thomas Van Lenten24d344c2019-01-07 17:03:37 -0500130
131 case WireFormat_Jspb:
132 response.skipped =
133 @"ConformanceRequest had a requested_output_format of JSPB WireFormat; that"
134 " isn't supposed to happen with opensource.";
135 break;
Thomas Van Lenten0c957912019-01-14 10:28:21 -0500136
137 case WireFormat_TextFormat:
138 // ObjC only has partial objc generation, so don't attempt any tests that need
139 // support.
140 response.skipped = @"ObjC doesn't support generating TextFormat";
141 break;
Thomas Van Lenten1745f7e2015-11-17 10:18:49 -0500142 }
143 }
144
145 return response;
146}
147
148static uint32_t UInt32FromLittleEndianData(NSData *data) {
149 if (data.length != sizeof(uint32_t)) {
150 Die(@"Data not the right size for uint32_t: %@", data);
151 }
152 uint32_t value;
153 memcpy(&value, data.bytes, sizeof(uint32_t));
154 return CFSwapInt32LittleToHost(value);
155}
156
157static NSData *UInt32ToLittleEndianData(uint32_t num) {
158 uint32_t value = CFSwapInt32HostToLittle(num);
159 return [NSData dataWithBytes:&value length:sizeof(uint32_t)];
160}
161
162static BOOL DoTestIo(NSFileHandle *input, NSFileHandle *output) {
163 // See conformance_test_runner.cc for the wire format.
164 NSData *data = CheckedReadDataOfLength(input, sizeof(uint32_t));
165 if (!data) {
166 // EOF.
167 return NO;
168 }
169 uint32_t numBytes = UInt32FromLittleEndianData(data);
170 data = CheckedReadDataOfLength(input, numBytes);
171 if (!data) {
172 Die(@"Failed to read request");
173 }
174
175 NSError *error = nil;
176 ConformanceRequest *request = [ConformanceRequest parseFromData:data
177 error:&error];
178 if (!request) {
179 Die(@"Failed to parse the message data: %@", error);
180 }
181
182 ConformanceResponse *response = DoTest(request);
183 if (!response) {
184 Die(@"Failed to make a reply from %@", request);
185 }
186
187 data = response.data;
188 [output writeData:UInt32ToLittleEndianData((int32_t)data.length)];
189 [output writeData:data];
190
191 if (verbose) {
192 NSLog(@"Request: %@", request);
193 NSLog(@"Response: %@", response);
194 }
195
196 ++testCount;
197 return YES;
198}
199
200int main(int argc, const char *argv[]) {
201 @autoreleasepool {
202 NSFileHandle *input = [[NSFileHandle fileHandleWithStandardInput] retain];
203 NSFileHandle *output = [[NSFileHandle fileHandleWithStandardOutput] retain];
204
205 BOOL notDone = YES;
206 while (notDone) {
207 @autoreleasepool {
208 notDone = DoTestIo(input, output);
209 }
210 }
211
212 NSLog(@"Received EOF from test runner after %d tests, exiting.", testCount);
213 }
214 return 0;
215}