conformance_upb.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2021, Google LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of Google LLC nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /* This is a upb implementation of the upb conformance tests, see:
29  * https://github.com/google/protobuf/tree/master/conformance
30  */
31 
32 #include <errno.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 
38 #include "conformance/conformance.upb.h"
39 #include "conformance/conformance.upbdefs.h"
40 #include "src/google/protobuf/test_messages_proto2.upbdefs.h"
41 #include "src/google/protobuf/test_messages_proto3.upbdefs.h"
42 #include "upb/decode.h"
43 #include "upb/encode.h"
44 #include "upb/json_decode.h"
45 #include "upb/json_encode.h"
46 #include "upb/reflection.h"
47 #include "upb/text_encode.h"
48 
49 // Must be last.
50 #include "upb/port_def.inc"
51 
52 int test_count = 0;
53 bool verbose = false; /* Set to true to get req/resp printed on stderr. */
54 
55 bool CheckedRead(int fd, void* buf, size_t len) {
56  size_t ofs = 0;
57  while (len > 0) {
58  ssize_t bytes_read = read(fd, (char*)buf + ofs, len);
59 
60  if (bytes_read == 0) return false;
61 
62  if (bytes_read < 0) {
63  perror("reading from test runner");
64  exit(1);
65  }
66 
67  len -= bytes_read;
68  ofs += bytes_read;
69  }
70 
71  return true;
72 }
73 
74 void CheckedWrite(int fd, const void* buf, size_t len) {
75  if ((size_t)write(fd, buf, len) != len) {
76  perror("writing to test runner");
77  exit(1);
78  }
79 }
80 
81 typedef struct {
82  const conformance_ConformanceRequest* request;
83  conformance_ConformanceResponse* response;
86 } ctx;
87 
88 bool parse_proto(upb_Message* msg, const upb_MessageDef* m, const ctx* c) {
89  upb_StringView proto =
90  conformance_ConformanceRequest_protobuf_payload(c->request);
91  if (upb_Decode(proto.data, proto.size, msg, upb_MessageDef_MiniTable(m), NULL,
92  0, c->arena) == kUpb_DecodeStatus_Ok) {
93  return true;
94  } else {
95  static const char msg[] = "Parse error";
96  conformance_ConformanceResponse_set_parse_error(
97  c->response, upb_StringView_FromString(msg));
98  return false;
99  }
100 }
101 
103  const ctx* c) {
104  size_t len;
105  char* data = upb_Encode(msg, upb_MessageDef_MiniTable(m), 0, c->arena, &len);
106  if (data) {
107  conformance_ConformanceResponse_set_protobuf_payload(
109  } else {
110  static const char msg[] = "Error serializing.";
111  conformance_ConformanceResponse_set_serialize_error(
112  c->response, upb_StringView_FromString(msg));
113  }
114 }
115 
117  const ctx* c) {
118  size_t len;
119  size_t len2;
120  int opts = 0;
121  char* data;
122 
123  if (!conformance_ConformanceRequest_print_unknown_fields(c->request)) {
125  }
126 
127  len = upb_TextEncode(msg, m, c->symtab, opts, NULL, 0);
128  data = upb_Arena_Malloc(c->arena, len + 1);
129  len2 = upb_TextEncode(msg, m, c->symtab, opts, data, len + 1);
130  UPB_ASSERT(len == len2);
131  conformance_ConformanceResponse_set_text_payload(
133 }
134 
135 bool parse_json(upb_Message* msg, const upb_MessageDef* m, const ctx* c) {
136  upb_StringView json = conformance_ConformanceRequest_json_payload(c->request);
138  int opts = 0;
139 
140  if (conformance_ConformanceRequest_test_category(c->request) ==
141  conformance_JSON_IGNORE_UNKNOWN_PARSING_TEST) {
143  }
144 
146  if (upb_JsonDecode(json.data, json.size, msg, m, c->symtab, opts, c->arena,
147  &status)) {
148  return true;
149  } else {
150  const char* inerr = upb_Status_ErrorMessage(&status);
151  size_t len = strlen(inerr);
152  char* err = upb_Arena_Malloc(c->arena, len + 1);
153  memcpy(err, inerr, strlen(inerr));
154  err[len] = '\0';
155  conformance_ConformanceResponse_set_parse_error(
156  c->response, upb_StringView_FromString(err));
157  return false;
158  }
159 }
160 
162  const ctx* c) {
163  size_t len;
164  size_t len2;
165  int opts = 0;
166  char* data;
168 
170  len = upb_JsonEncode(msg, m, c->symtab, opts, NULL, 0, &status);
171 
172  if (len == (size_t)-1) {
173  const char* inerr = upb_Status_ErrorMessage(&status);
174  size_t len = strlen(inerr);
175  char* err = upb_Arena_Malloc(c->arena, len + 1);
176  memcpy(err, inerr, strlen(inerr));
177  err[len] = '\0';
178  conformance_ConformanceResponse_set_serialize_error(
179  c->response, upb_StringView_FromString(err));
180  return;
181  }
182 
183  data = upb_Arena_Malloc(c->arena, len + 1);
184  len2 = upb_JsonEncode(msg, m, c->symtab, opts, data, len + 1, &status);
185  UPB_ASSERT(len == len2);
186  conformance_ConformanceResponse_set_json_payload(
188 }
189 
190 bool parse_input(upb_Message* msg, const upb_MessageDef* m, const ctx* c) {
191  switch (conformance_ConformanceRequest_payload_case(c->request)) {
192  case conformance_ConformanceRequest_payload_protobuf_payload:
193  return parse_proto(msg, m, c);
194  case conformance_ConformanceRequest_payload_json_payload:
195  return parse_json(msg, m, c);
196  case conformance_ConformanceRequest_payload_NOT_SET:
197  fprintf(stderr, "conformance_upb: Request didn't have payload.\n");
198  return false;
199  default: {
200  static const char msg[] = "Unsupported input format.";
201  conformance_ConformanceResponse_set_skipped(
202  c->response, upb_StringView_FromString(msg));
203  return false;
204  }
205  }
206 }
207 
209  const ctx* c) {
210  switch (conformance_ConformanceRequest_requested_output_format(c->request)) {
211  case conformance_UNSPECIFIED:
212  fprintf(stderr, "conformance_upb: Unspecified output format.\n");
213  exit(1);
214  case conformance_PROTOBUF:
215  serialize_proto(msg, m, c);
216  break;
217  case conformance_TEXT_FORMAT:
218  serialize_text(msg, m, c);
219  break;
220  case conformance_JSON:
221  serialize_json(msg, m, c);
222  break;
223  default: {
224  static const char msg[] = "Unsupported output format.";
225  conformance_ConformanceResponse_set_skipped(
226  c->response, upb_StringView_FromString(msg));
227  break;
228  }
229  }
230 }
231 
232 void DoTest(const ctx* c) {
233  upb_Message* msg;
234  upb_StringView name = conformance_ConformanceRequest_message_type(c->request);
235  const upb_MessageDef* m =
236  upb_DefPool_FindMessageByNameWithSize(c->symtab, name.data, name.size);
237 #if 0
238  // Handy code for limiting conformance tests to a single input payload.
239  // This is a hack since the conformance runner doesn't give an easy way to
240  // specify what test should be run.
241  const char skip[] = "\343>\010\301\002\344>\230?\001\230?\002\230?\003";
242  upb_StringView skip_str = upb_StringView_FromDataAndSize(skip, sizeof(skip) - 1);
243  upb_StringView pb_payload =
244  conformance_ConformanceRequest_protobuf_payload(c->request);
245  if (!upb_StringView_IsEqual(pb_payload, skip_str)) m = NULL;
246 #endif
247 
248  if (!m) {
249  static const char msg[] = "Unknown message type.";
250  conformance_ConformanceResponse_set_skipped(c->response,
252  return;
253  }
254 
255  msg = upb_Message_New(m, c->arena);
256 
257  if (parse_input(msg, m, c)) {
258  write_output(msg, m, c);
259  }
260 }
261 
262 void debug_print(const char* label, const upb_Message* msg,
263  const upb_MessageDef* m, const ctx* c) {
264  char buf[512];
265  upb_TextEncode(msg, m, c->symtab, UPB_TXTENC_SINGLELINE, buf, sizeof(buf));
266  fprintf(stderr, "%s: %s\n", label, buf);
267 }
268 
271  char* input;
272  char* output;
273  uint32_t input_size;
274  size_t output_size;
275  ctx c;
276 
277  if (!CheckedRead(STDIN_FILENO, &input_size, sizeof(uint32_t))) {
278  /* EOF. */
279  return false;
280  }
281 
282  c.symtab = symtab;
283  c.arena = upb_Arena_New();
284  input = upb_Arena_Malloc(c.arena, input_size);
285 
286  if (!CheckedRead(STDIN_FILENO, input, input_size)) {
287  fprintf(stderr, "conformance_upb: unexpected EOF on stdin.\n");
288  exit(1);
289  }
290 
291  c.request = conformance_ConformanceRequest_parse(input, input_size, c.arena);
292  c.response = conformance_ConformanceResponse_new(c.arena);
293 
294  if (c.request) {
295  DoTest(&c);
296  } else {
297  fprintf(stderr, "conformance_upb: parse of ConformanceRequest failed: %s\n",
299  }
300 
301  output = conformance_ConformanceResponse_serialize(c.response, c.arena,
302  &output_size);
303 
304  uint32_t network_out = (uint32_t)output_size;
305  CheckedWrite(STDOUT_FILENO, &network_out, sizeof(uint32_t));
306  CheckedWrite(STDOUT_FILENO, output, output_size);
307 
308  test_count++;
309 
310  if (verbose) {
311  debug_print("Request", c.request,
312  conformance_ConformanceRequest_getmsgdef(symtab), &c);
313  debug_print("Response", c.response,
314  conformance_ConformanceResponse_getmsgdef(symtab), &c);
315  fprintf(stderr, "\n");
316  }
317 
318  upb_Arena_Free(c.arena);
319 
320  return true;
321 }
322 
323 int main(void) {
325 
326 #ifdef REBUILD_MINITABLES
328  symtab, &src_google_protobuf_test_messages_proto2_proto_upbdefinit, true);
330  symtab, &src_google_protobuf_test_messages_proto3_proto_upbdefinit, true);
331 #else
332  protobuf_test_messages_proto2_TestAllTypesProto2_getmsgdef(symtab);
333  protobuf_test_messages_proto3_TestAllTypesProto3_getmsgdef(symtab);
334 #endif
335 
336  while (1) {
337  if (!DoTestIo(symtab)) {
338  fprintf(stderr,
339  "conformance_upb: received EOF from test runner "
340  "after %d tests, exiting\n",
341  test_count);
343  return 0;
344  }
345  }
346 }
ctx::arena
upb_Arena * arena
Definition: conformance_upb.c:84
serialize_text
void serialize_text(const upb_Message *msg, const upb_MessageDef *m, const ctx *c)
Definition: conformance_upb.c:116
ctx
Definition: benchmark-async.c:30
upb_MessageDef_MiniTable
const upb_MiniTable * upb_MessageDef_MiniTable(const upb_MessageDef *m)
Definition: upb/upb/def.c:818
mkowners.skip
bool skip
Definition: mkowners.py:224
write
#define write
Definition: test-fs.c:47
encode.h
DoTest
void DoTest(const ctx *c)
Definition: conformance_upb.c:232
upb_StringView::data
const char * data
Definition: upb/upb/upb.h:73
upb_Decode
upb_DecodeStatus upb_Decode(const char *buf, size_t size, void *msg, const upb_MiniTable *l, const upb_ExtensionRegistry *extreg, int options, upb_Arena *arena)
Definition: decode.c:1076
upb_MessageDef
Definition: upb/upb/def.c:100
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
kUpb_DecodeStatus_Ok
@ kUpb_DecodeStatus_Ok
Definition: decode.h:72
error_ref_leak.err
err
Definition: error_ref_leak.py:35
cstest_report.opts
opts
Definition: cstest_report.py:81
status
absl::Status status
Definition: rls.cc:251
upb_JsonEncode
size_t upb_JsonEncode(const upb_Message *msg, const upb_MessageDef *m, const upb_DefPool *ext_pool, int options, char *buf, size_t size, upb_Status *status)
Definition: json_encode.c:757
ctx
static struct test_ctx ctx
Definition: test-ipc-send-recv.c:65
setup.name
name
Definition: setup.py:542
upb_Status_ErrorMessage
const char * upb_Status_ErrorMessage(const upb_Status *status)
Definition: upb/upb/upb.c:52
json_encode.h
upb_Arena_New
UPB_INLINE upb_Arena * upb_Arena_New(void)
Definition: upb/upb/upb.h:267
upb_Status_Clear
void upb_Status_Clear(upb_Status *status)
Definition: upb/upb/upb.c:44
json_decode.h
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
main
int main(void)
Definition: conformance_upb.c:323
upb_Message_New
upb_Message * upb_Message_New(const upb_MessageDef *m, upb_Arena *a)
Definition: reflection.c:95
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
test_count
int test_count
Definition: conformance_upb.c:52
c
void c(T a)
Definition: miscompile_with_no_unique_address_test.cc:40
ssize_t
intptr_t ssize_t
Definition: win.h:27
decode.h
gen_synthetic_protos.label
label
Definition: gen_synthetic_protos.py:102
upb_StringView::size
size_t size
Definition: upb/upb/upb.h:74
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
upb_Arena_Malloc
UPB_INLINE void * upb_Arena_Malloc(upb_Arena *a, size_t size)
Definition: upb/upb/upb.h:222
bytes_read
static size_t bytes_read
Definition: test-ipc-heavy-traffic-deadlock-bug.c:47
upb_DefPool_New
upb_DefPool * upb_DefPool_New(void)
Definition: upb/upb/def.c:1086
reflection.h
upb_Status
Definition: upb/upb/upb.h:52
UPB_ASSERT
#define UPB_ASSERT(expr)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:135
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
_upb_DefPool_LoadDefInitEx
bool _upb_DefPool_LoadDefInitEx(upb_DefPool *s, const _upb_DefPool_Init *init, bool rebuild_minitable)
Definition: upb/upb/def.c:3149
upb_StringView_IsEqual
UPB_INLINE bool upb_StringView_IsEqual(upb_StringView a, upb_StringView b)
Definition: upb/upb/upb.h:89
upb_Message
void upb_Message
Definition: msg.h:49
msg
std::string msg
Definition: client_interceptors_end2end_test.cc:372
symtab
upb_symtab * symtab
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:774
upb_TextEncode
size_t upb_TextEncode(const upb_Message *msg, const upb_MessageDef *m, const upb_DefPool *ext_pool, int options, char *buf, size_t size)
Definition: text_encode.c:455
parse_json
bool parse_json(upb_Message *msg, const upb_MessageDef *m, const ctx *c)
Definition: conformance_upb.c:135
upb_Encode
char * upb_Encode(const void *msg, const upb_MiniTable *l, int options, upb_Arena *arena, size_t *size)
Definition: encode.c:573
ctx::request
const conformance_ConformanceRequest * request
Definition: conformance_upb.c:82
read
int read(izstream &zs, T *x, Items items)
Definition: bloaty/third_party/zlib/contrib/iostream2/zstream.h:115
serialize_proto
void serialize_proto(const upb_Message *msg, const upb_MessageDef *m, const ctx *c)
Definition: conformance_upb.c:102
upb_JsonDecode_IgnoreUnknown
@ upb_JsonDecode_IgnoreUnknown
Definition: json_decode.h:37
upb_DefPool_Free
void upb_DefPool_Free(upb_DefPool *s)
Definition: upb/upb/def.c:1081
upb_StringView
Definition: upb/upb/upb.h:72
ctx::symtab
const upb_DefPool * symtab
Definition: conformance_upb.c:85
CheckedRead
bool CheckedRead(int fd, void *buf, size_t len)
Definition: conformance_upb.c:55
DoTestIo
bool DoTestIo(upb_DefPool *symtab)
Definition: conformance_upb.c:269
upb_DefPool_FindMessageByNameWithSize
const upb_MessageDef * upb_DefPool_FindMessageByNameWithSize(const upb_DefPool *s, const char *sym, size_t len)
Definition: upb/upb/def.c:1130
upb_JsonDecode
bool upb_JsonDecode(const char *buf, size_t size, upb_Message *msg, const upb_MessageDef *m, const upb_DefPool *symtab, int options, upb_Arena *arena, upb_Status *status)
Definition: json_decode.c:1486
upb_StringView_FromDataAndSize
UPB_INLINE upb_StringView upb_StringView_FromDataAndSize(const char *data, size_t size)
Definition: upb/upb/upb.h:77
verbose
bool verbose
Definition: conformance_upb.c:53
parse_input
bool parse_input(upb_Message *msg, const upb_MessageDef *m, const ctx *c)
Definition: conformance_upb.c:190
UPB_TXTENC_SKIPUNKNOWN
@ UPB_TXTENC_SKIPUNKNOWN
Definition: text_encode.h:42
CheckedWrite
void CheckedWrite(int fd, const void *buf, size_t len)
Definition: conformance_upb.c:74
input
std::string input
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc:197
upb_StringView_FromString
UPB_INLINE upb_StringView upb_StringView_FromString(const char *data)
Definition: upb/upb/upb.h:85
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
regress.m
m
Definition: regress/regress.py:25
ctx::response
conformance_ConformanceResponse * response
Definition: conformance_upb.c:83
serialize_json
void serialize_json(const upb_Message *msg, const upb_MessageDef *m, const ctx *c)
Definition: conformance_upb.c:161
upb_DefPool
Definition: upb/upb/def.c:217
text_encode.h
upb_Arena
Definition: upb_internal.h:36
upb_Arena_Free
void upb_Arena_Free(upb_Arena *a)
Definition: upb/upb/upb.c:273
errno.h
debug_print
void debug_print(const char *label, const upb_Message *msg, const upb_MessageDef *m, const ctx *c)
Definition: conformance_upb.c:262
UPB_TXTENC_SINGLELINE
@ UPB_TXTENC_SINGLELINE
Definition: text_encode.h:39
parse_proto
bool parse_proto(upb_Message *msg, const upb_MessageDef *m, const ctx *c)
Definition: conformance_upb.c:88
write_output
void write_output(const upb_Message *msg, const upb_MessageDef *m, const ctx *c)
Definition: conformance_upb.c:208


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:01