diff options
Diffstat (limited to 'tests/test_decoder.c')
-rw-r--r-- | tests/test_decoder.c | 668 |
1 files changed, 0 insertions, 668 deletions
diff --git a/tests/test_decoder.c b/tests/test_decoder.c deleted file mode 100644 index 14d0e2d..0000000 --- a/tests/test_decoder.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2011 Google Inc. See LICENSE for details. - * - * An exhaustive set of tests for parsing both valid and invalid protobuf - * input, with buffer breaks in arbitrary places. - * - * Tests to add: - * - unknown field handler called appropriately - * - unknown fields can be inserted in random places - * - fuzzing of valid input - * - resource limits (max stack depth, max string len) - * - testing of groups - * - more throrough testing of sequences - * - test skipping of submessages - * - test suspending the decoder - * - buffers that are close enough to the end of the address space that - * pointers overflow (this might be difficult). - * - a few "kitchen sink" examples (one proto that uses all types, lots - * of submsg/sequences, etc. - */ - -#include <inttypes.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include "upb/handlers.h" -#include "upb/pb/decoder.h" -#include "upb/pb/varint.h" -#include "upb/upb.h" -#include "upb_test.h" - -typedef struct { - char *buf; - size_t len; -} buffer; - -// Mem is initialized to NULL. -buffer *buffer_new(size_t len) { - buffer *buf = malloc(sizeof(*buf)); - buf->buf = malloc(len); - buf->len = len; - memset(buf->buf, 0, buf->len); - return buf; -} - -buffer *buffer_new2(const void *data, size_t len) { - buffer *buf = buffer_new(len); - memcpy(buf->buf, data, len); - return buf; -} - -buffer *buffer_new3(const char *data) { - return buffer_new2(data, strlen(data)); -} - -buffer *buffer_dup(buffer *buf) { return buffer_new2(buf->buf, buf->len); } - -void buffer_free(buffer *buf) { - free(buf->buf); - free(buf); -} - -void buffer_appendf(buffer *buf, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - size_t size = buf->len; - buf->len += upb_vrprintf(&buf->buf, &size, buf->len, fmt, args); - va_end(args); -} - -void buffer_cat(buffer *buf, buffer *buf2) { - size_t newlen = buf->len + buf2->len; - buf->buf = realloc(buf->buf, newlen); - memcpy(buf->buf + buf->len, buf2->buf, buf2->len); - buf->len = newlen; - buffer_free(buf2); -} - -bool buffer_eql(buffer *buf, buffer *buf2) { - return buf->len == buf2->len && memcmp(buf->buf, buf2->buf, buf->len) == 0; -} - - -/* Routines for building arbitrary protos *************************************/ - -buffer *cat(buffer *arg1, ...) { - va_list ap; - buffer *arg; - va_start(ap, arg1); - while ((arg = va_arg(ap, buffer*)) != NULL) { - buffer_cat(arg1, arg); - } - va_end(ap); - return arg1; -} - -buffer *varint(uint64_t x) { - buffer *buf = buffer_new(UPB_PB_VARINT_MAX_LEN + 1); - buf->len = upb_vencode64(x, buf->buf); - return buf; -} - -// TODO: proper byte-swapping for big-endian machines. -buffer *fixed32(void *data) { return buffer_new2(data, 4); } -buffer *fixed64(void *data) { return buffer_new2(data, 8); } - -buffer *delim(buffer *buf) { return cat( varint(buf->len), buf, NULL ); } -buffer *uint32(uint32_t u32) { return fixed32(&u32); } -buffer *uint64(uint64_t u64) { return fixed64(&u64); } -buffer *flt(float f) { return fixed32(&f); } -buffer *dbl(double d) { return fixed64(&d); } -buffer *zz32(int32_t x) { return varint(upb_zzenc_32(x)); } -buffer *zz64(int64_t x) { return varint(upb_zzenc_64(x)); } - -buffer *tag(uint32_t fieldnum, char wire_type) { - return varint((fieldnum << 3) | wire_type); -} - -buffer *submsg(uint32_t fn, buffer *buf) { - return cat( tag(fn, UPB_WIRE_TYPE_DELIMITED), delim(buf), NULL ); -} - - -/* A set of handlers that covers all .proto types *****************************/ - -// The handlers simply append to a string indicating what handlers were called. -// This string is similar to protobuf text format but fields are referred to by -// number instead of name and sequences are explicitly delimited. - -#define VALUE_HANDLER(member, fmt) \ - upb_flow_t value_ ## member(void *closure, upb_value fval, upb_value val) { \ - buffer_appendf(closure, "%" PRIu32 ":%" fmt "; ", \ - upb_value_getuint32(fval), upb_value_get ## member(val)); \ - return UPB_CONTINUE; \ - } - -VALUE_HANDLER(uint32, PRIu32) -VALUE_HANDLER(uint64, PRIu64) -VALUE_HANDLER(int32, PRId32) -VALUE_HANDLER(int64, PRId64) -VALUE_HANDLER(float, "g") -VALUE_HANDLER(double, "g") - -upb_flow_t value_bool(void *closure, upb_value fval, upb_value val) { - buffer_appendf(closure, "%" PRIu32 ":%s; ", - upb_value_getuint32(fval), - upb_value_getbool(val) ? "true" : "false"); - return UPB_CONTINUE; -} - -upb_flow_t value_string(void *closure, upb_value fval, upb_value val) { - // Note: won't work with strings that contain NULL. - char *str = upb_byteregion_strdup(upb_value_getbyteregion(val)); - buffer_appendf(closure, "%" PRIu32 ":%s; ", upb_value_getuint32(fval), str); - free(str); - return UPB_CONTINUE; -} - -upb_sflow_t startsubmsg(void *closure, upb_value fval) { - buffer_appendf(closure, "%" PRIu32 ":{ ", upb_value_getuint32(fval)); - return UPB_CONTINUE_WITH(closure); -} - -upb_flow_t endsubmsg(void *closure, upb_value fval) { - (void)fval; - buffer_appendf(closure, "} "); - return UPB_CONTINUE; -} - -upb_sflow_t startseq(void *closure, upb_value fval) { - buffer_appendf(closure, "%" PRIu32 ":[ ", upb_value_getuint32(fval)); - return UPB_CONTINUE_WITH(closure); -} - -upb_flow_t endseq(void *closure, upb_value fval) { - (void)fval; - buffer_appendf(closure, "] "); - return UPB_CONTINUE; -} - -void doreg(upb_mhandlers *m, uint32_t num, upb_fieldtype_t type, bool repeated, - upb_value_handler *handler) { - upb_fhandlers *f = upb_mhandlers_newfhandlers(m, num, type, repeated); - ASSERT(f); - upb_fhandlers_setvalue(f, handler); - upb_fhandlers_setstartseq(f, &startseq); - upb_fhandlers_setendseq(f, &endseq); - upb_fhandlers_setfval(f, upb_value_uint32(num)); -} - -// The repeated field number to correspond to the given non-repeated field -// number. -uint32_t rep_fn(uint32_t fn) { - return (UPB_MAX_FIELDNUMBER - 1000) + fn; -} - -#define NOP_FIELD 40 -#define UNKNOWN_FIELD 666 - -void reg(upb_mhandlers *m, upb_fieldtype_t type, upb_value_handler *handler) { - // We register both a repeated and a non-repeated field for every type. - // For the non-repeated field we make the field number the same as the - // type. For the repeated field we make it a function of the type. - doreg(m, type, type, false, handler); - doreg(m, rep_fn(type), type, true, handler); -} - -void reg_subm(upb_mhandlers *m, uint32_t num, upb_fieldtype_t type, - bool repeated) { - upb_fhandlers *f = - upb_mhandlers_newfhandlers_subm(m, num, type, repeated, m); - ASSERT(f); - upb_fhandlers_setstartseq(f, &startseq); - upb_fhandlers_setendseq(f, &endseq); - upb_fhandlers_setstartsubmsg(f, &startsubmsg); - upb_fhandlers_setendsubmsg(f, &endsubmsg); - upb_fhandlers_setfval(f, upb_value_uint32(num)); -} - -void reghandlers(upb_mhandlers *m) { - // Register handlers for each type. - reg(m, UPB_TYPE(DOUBLE), &value_double); - reg(m, UPB_TYPE(FLOAT), &value_float); - reg(m, UPB_TYPE(INT64), &value_int64); - reg(m, UPB_TYPE(UINT64), &value_uint64); - reg(m, UPB_TYPE(INT32) , &value_int32); - reg(m, UPB_TYPE(FIXED64), &value_uint64); - reg(m, UPB_TYPE(FIXED32), &value_uint32); - reg(m, UPB_TYPE(BOOL), &value_bool); - reg(m, UPB_TYPE(STRING), &value_string); - reg(m, UPB_TYPE(BYTES), &value_string); - reg(m, UPB_TYPE(UINT32), &value_uint32); - reg(m, UPB_TYPE(ENUM), &value_int32); - reg(m, UPB_TYPE(SFIXED32), &value_int32); - reg(m, UPB_TYPE(SFIXED64), &value_int64); - reg(m, UPB_TYPE(SINT32), &value_int32); - reg(m, UPB_TYPE(SINT64), &value_int64); - - // Register submessage/group handlers that are self-recursive - // to this type, eg: message M { optional M m = 1; } - reg_subm(m, UPB_TYPE(MESSAGE), UPB_TYPE(MESSAGE), false); - reg_subm(m, UPB_TYPE(GROUP), UPB_TYPE(GROUP), false); - reg_subm(m, rep_fn(UPB_TYPE(MESSAGE)), UPB_TYPE(MESSAGE), true); - reg_subm(m, rep_fn(UPB_TYPE(GROUP)), UPB_TYPE(GROUP), true); - - // Register a no-op string field so we can pad the proto wherever we want. - upb_mhandlers_newfhandlers(m, NOP_FIELD, UPB_TYPE(STRING), false); -} - - -/* Custom bytesrc that can insert buffer seams in arbitrary places ************/ - -typedef struct { - upb_bytesrc bytesrc; - const char *str; - size_t len, seam1, seam2; - upb_byteregion byteregion; -} upb_seamsrc; - -size_t upb_seamsrc_avail(const upb_seamsrc *src, size_t ofs) { - if (ofs < src->seam1) return src->seam1 - ofs; - if (ofs < src->seam2) return src->seam2 - ofs; - return src->len - ofs; -} - -upb_bytesuccess_t upb_seamsrc_fetch(void *_src, uint64_t ofs, size_t *read) { - upb_seamsrc *src = _src; - assert(ofs < src->len); - if (ofs == src->len) { - upb_status_seteof(&src->bytesrc.status); - return UPB_BYTE_EOF; - } - *read = upb_seamsrc_avail(src, ofs); - return UPB_BYTE_OK; -} - -void upb_seamsrc_copy(const void *_src, uint64_t ofs, - size_t len, char *dst) { - const upb_seamsrc *src = _src; - assert(ofs + len <= src->len); - memcpy(dst, src->str + ofs, len); -} - -void upb_seamsrc_discard(void *src, uint64_t ofs) { - (void)src; - (void)ofs; -} - -const char *upb_seamsrc_getptr(const void *_s, uint64_t ofs, size_t *len) { - const upb_seamsrc *src = _s; - *len = upb_seamsrc_avail(src, ofs); - return src->str + ofs; -} - -void upb_seamsrc_init(upb_seamsrc *s, const char *str, size_t len) { - static upb_bytesrc_vtbl vtbl = { - &upb_seamsrc_fetch, - &upb_seamsrc_discard, - &upb_seamsrc_copy, - &upb_seamsrc_getptr, - }; - upb_bytesrc_init(&s->bytesrc, &vtbl); - s->seam1 = 0; - s->seam2 = 0; - s->str = str; - s->len = len; - s->byteregion.bytesrc = &s->bytesrc; - s->byteregion.toplevel = true; - s->byteregion.start = 0; - s->byteregion.end = len; -} - -void upb_seamsrc_resetseams(upb_seamsrc *s, size_t seam1, size_t seam2) { - ASSERT(seam1 <= seam2); - s->seam1 = seam1; - s->seam2 = seam2; - s->byteregion.discard = 0; - s->byteregion.fetch = 0; -} - -void upb_seamsrc_uninit(upb_seamsrc *s) { (void)s; } - -upb_bytesrc *upb_seamsrc_bytesrc(upb_seamsrc *s) { - return &s->bytesrc; -} - -// Returns the top-level upb_byteregion* for this seamsrc. Invalidated when -// the seamsrc is reset. -upb_byteregion *upb_seamsrc_allbytes(upb_seamsrc *s) { - return &s->byteregion; -} - - -/* Running of test cases ******************************************************/ - -upb_decoderplan *plan; - -void run_decoder(buffer *proto, buffer *expected_output) { - upb_seamsrc src; - upb_seamsrc_init(&src, proto->buf, proto->len); - upb_decoder d; - upb_decoder_init(&d); - upb_decoder_resetplan(&d, plan, 0); - for (size_t i = 0; i < proto->len; i++) { - for (size_t j = i; j < proto->len; j++) { - upb_seamsrc_resetseams(&src, i, j); - upb_byteregion *input = upb_seamsrc_allbytes(&src); - buffer *output = buffer_new(0); - upb_decoder_resetinput(&d, input, output); - upb_success_t success = UPB_SUSPENDED; - while (success == UPB_SUSPENDED) - success = upb_decoder_decode(&d); - ASSERT(upb_ok(upb_decoder_status(&d)) == (success == UPB_OK)); - if (expected_output) { - ASSERT(success == UPB_OK); - // The input should be fully consumed. - ASSERT(upb_byteregion_fetchofs(input) == upb_byteregion_endofs(input)); - ASSERT(upb_byteregion_discardofs(input) == - upb_byteregion_endofs(input)); - if (!buffer_eql(output, expected_output)) { - fprintf(stderr, "Text mismatch: '%s' vs '%s'\n", - output->buf, expected_output->buf); - } - ASSERT(strcmp(output->buf, expected_output->buf) == 0); - } else { - ASSERT(success == UPB_ERROR); - } - buffer_free(output); - } - } - upb_seamsrc_uninit(&src); - upb_decoder_uninit(&d); - buffer_free(proto); -} - -void assert_successful_parse_at_eof(buffer *proto, const char *expected_fmt, - va_list args) { - buffer *expected_text = buffer_new(0); - size_t size = expected_text->len; - expected_text->len += upb_vrprintf(&expected_text->buf, &size, - expected_text->len, expected_fmt, args); - run_decoder(proto, expected_text); - buffer_free(expected_text); -} - -void assert_does_not_parse_at_eof(buffer *proto) { - run_decoder(proto, NULL); -} - -void assert_successful_parse(buffer *proto, const char *expected_fmt, ...) { - // The JIT is only used for data >=20 bytes from end-of-buffer, so - // repeat once with no-op padding data at the end of buffer. - va_list args, args2; - va_start(args, expected_fmt); - va_copy(args2, args); - assert_successful_parse_at_eof(buffer_dup(proto), expected_fmt, args); - assert_successful_parse_at_eof( - cat( proto, - tag(NOP_FIELD, UPB_WIRE_TYPE_DELIMITED), delim(buffer_new(30)), - NULL ), - expected_fmt, args2); - va_end(args); - va_end(args2); -} - -void assert_does_not_parse(buffer *proto) { - // The JIT is only used for data >=20 bytes from end-of-buffer, so - // repeat once with no-op padding data at the end of buffer. - assert_does_not_parse_at_eof(buffer_dup(proto)); - assert_does_not_parse_at_eof( - cat( proto, - tag(NOP_FIELD, UPB_WIRE_TYPE_DELIMITED), delim( buffer_new(30)), - NULL )); -} - - -/* The actual tests ***********************************************************/ - -void test_premature_eof_for_type(upb_fieldtype_t type) { - // Incomplete values for each wire type. - static const char *incompletes[] = { - "\x80", // UPB_WIRE_TYPE_VARINT - "abcdefg", // UPB_WIRE_TYPE_64BIT - "\x80", // UPB_WIRE_TYPE_DELIMITED (partial length) - NULL, // UPB_WIRE_TYPE_START_GROUP (no value required) - NULL, // UPB_WIRE_TYPE_END_GROUP (no value required) - "abc" // UPB_WIRE_TYPE_32BIT - }; - - uint32_t fieldnum = type; - uint32_t rep_fieldnum = rep_fn(type); - int wire_type = upb_types[type].native_wire_type; - const char *incomplete = incompletes[wire_type]; - - // EOF before a known non-repeated value. - assert_does_not_parse_at_eof(tag(fieldnum, wire_type)); - - // EOF before a known repeated value. - assert_does_not_parse_at_eof(tag(rep_fieldnum, wire_type)); - - // EOF before an unknown value. - assert_does_not_parse_at_eof(tag(UNKNOWN_FIELD, wire_type)); - - // EOF inside a known non-repeated value. - assert_does_not_parse_at_eof( - cat( tag(fieldnum, wire_type), buffer_new3(incomplete), NULL )); - - // EOF inside a known repeated value. - assert_does_not_parse_at_eof( - cat( tag(rep_fieldnum, wire_type), buffer_new3(incomplete), NULL )); - - // EOF inside an unknown value. - assert_does_not_parse_at_eof( - cat( tag(UNKNOWN_FIELD, wire_type), buffer_new3(incomplete), NULL )); - - if (wire_type == UPB_WIRE_TYPE_DELIMITED) { - // EOF in the middle of delimited data for known non-repeated value. - assert_does_not_parse_at_eof( - cat( tag(fieldnum, wire_type), varint(1), NULL )); - - // EOF in the middle of delimited data for known repeated value. - assert_does_not_parse_at_eof( - cat( tag(rep_fieldnum, wire_type), varint(1), NULL )); - - // EOF in the middle of delimited data for unknown value. - assert_does_not_parse_at_eof( - cat( tag(UNKNOWN_FIELD, wire_type), varint(1), NULL )); - - if (type == UPB_TYPE(MESSAGE)) { - // Submessage ends in the middle of a value. - buffer *incomplete_submsg = - cat ( tag(UPB_TYPE(INT32), UPB_WIRE_TYPE_VARINT), - buffer_new3(incompletes[UPB_WIRE_TYPE_VARINT]), NULL ); - assert_does_not_parse( - cat( tag(fieldnum, UPB_WIRE_TYPE_DELIMITED), - varint(incomplete_submsg->len), - incomplete_submsg, NULL )); - } - } else { - // Packed region ends in the middle of a value. - assert_does_not_parse( - cat( tag(rep_fieldnum, UPB_WIRE_TYPE_DELIMITED), - varint(strlen(incomplete)), - buffer_new3(incomplete), NULL )); - - // EOF in the middle of packed region. - assert_does_not_parse_at_eof( - cat( tag(rep_fieldnum, UPB_WIRE_TYPE_DELIMITED), varint(1), NULL )); - } -} - -// "33" and "66" are just two random values that all numeric types can -// represent. -void test_valid_data_for_type(upb_fieldtype_t type, - buffer *enc33, buffer *enc66) { - uint32_t fieldnum = type; - uint32_t rep_fieldnum = rep_fn(type); - int wire_type = upb_types[type].native_wire_type; - - // Non-repeated - assert_successful_parse( - cat( tag(fieldnum, wire_type), buffer_dup(enc33), - tag(fieldnum, wire_type), buffer_dup(enc66), NULL ), - "%u:33; %u:66; ", fieldnum, fieldnum); - - // Non-packed repeated. - assert_successful_parse( - cat( tag(rep_fieldnum, wire_type), buffer_dup(enc33), - tag(rep_fieldnum, wire_type), buffer_dup(enc66), NULL ), - "%u:[ %u:33; %u:66; ] ", rep_fieldnum, rep_fieldnum, rep_fieldnum); - - // Packed repeated. - assert_successful_parse( - cat( tag(rep_fieldnum, UPB_WIRE_TYPE_DELIMITED), - delim(cat( buffer_dup(enc33), buffer_dup(enc66), NULL )), NULL ), - "%u:[ %u:33; %u:66; ] ", rep_fieldnum, rep_fieldnum, rep_fieldnum); - - buffer_free(enc33); - buffer_free(enc66); -} - -void test_valid_data_for_signed_type(upb_fieldtype_t type, - buffer *enc33, buffer *enc66) { - uint32_t fieldnum = type; - uint32_t rep_fieldnum = rep_fn(type); - int wire_type = upb_types[type].native_wire_type; - - // Non-repeated - assert_successful_parse( - cat( tag(fieldnum, wire_type), buffer_dup(enc33), - tag(fieldnum, wire_type), buffer_dup(enc66), NULL ), - "%u:33; %u:-66; ", fieldnum, fieldnum); - - // Non-packed repeated. - assert_successful_parse( - cat( tag(rep_fieldnum, wire_type), buffer_dup(enc33), - tag(rep_fieldnum, wire_type), buffer_dup(enc66), NULL ), - "%u:[ %u:33; %u:-66; ] ", rep_fieldnum, rep_fieldnum, rep_fieldnum); - - // Packed repeated. - assert_successful_parse( - cat( tag(rep_fieldnum, UPB_WIRE_TYPE_DELIMITED), - delim(cat( buffer_dup(enc33), buffer_dup(enc66), NULL )), NULL ), - "%u:[ %u:33; %u:-66; ] ", rep_fieldnum, rep_fieldnum, rep_fieldnum); - - buffer_free(enc33); - buffer_free(enc66); -} - -// Test that invalid protobufs are properly detected (without crashing) and -// have an error reported. Field numbers match registered handlers above. -void test_invalid() { - test_premature_eof_for_type(UPB_TYPE(DOUBLE)); - test_premature_eof_for_type(UPB_TYPE(FLOAT)); - test_premature_eof_for_type(UPB_TYPE(INT64)); - test_premature_eof_for_type(UPB_TYPE(UINT64)); - test_premature_eof_for_type(UPB_TYPE(INT32)); - test_premature_eof_for_type(UPB_TYPE(FIXED64)); - test_premature_eof_for_type(UPB_TYPE(FIXED32)); - test_premature_eof_for_type(UPB_TYPE(BOOL)); - test_premature_eof_for_type(UPB_TYPE(STRING)); - test_premature_eof_for_type(UPB_TYPE(BYTES)); - test_premature_eof_for_type(UPB_TYPE(UINT32)); - test_premature_eof_for_type(UPB_TYPE(ENUM)); - test_premature_eof_for_type(UPB_TYPE(SFIXED32)); - test_premature_eof_for_type(UPB_TYPE(SFIXED64)); - test_premature_eof_for_type(UPB_TYPE(SINT32)); - test_premature_eof_for_type(UPB_TYPE(SINT64)); - - // EOF inside a tag's varint. - assert_does_not_parse_at_eof( buffer_new3("\x80") ); - - // EOF inside a known group. - assert_does_not_parse_at_eof( tag(4, UPB_WIRE_TYPE_START_GROUP) ); - - // EOF inside an unknown group. - assert_does_not_parse_at_eof( tag(UNKNOWN_FIELD, UPB_WIRE_TYPE_START_GROUP) ); - - // End group that we are not currently in. - assert_does_not_parse( tag(4, UPB_WIRE_TYPE_END_GROUP) ); - - // Field number is 0. - assert_does_not_parse( - cat( tag(0, UPB_WIRE_TYPE_DELIMITED), varint(0), NULL )); - - // Field number is too large. - assert_does_not_parse( - cat( tag(UPB_MAX_FIELDNUMBER + 1, UPB_WIRE_TYPE_DELIMITED), - varint(0), NULL )); - - // Test exceeding the resource limit of stack depth. - buffer *buf = buffer_new3(""); - for (int i = 0; i < UPB_MAX_NESTING; i++) { - buf = submsg(UPB_TYPE(MESSAGE), buf); - } - assert_does_not_parse(buf); - - // Staying within the stack limit should work properly. - buf = buffer_new3(""); - buffer *textbuf = buffer_new3(""); - int total = UPB_MAX_NESTING - 1; - for (int i = 0; i < total; i++) { - buf = submsg(UPB_TYPE(MESSAGE), buf); - buffer_appendf(textbuf, "%u:{ ", UPB_TYPE(MESSAGE)); - } - for (int i = 0; i < total; i++) { - buffer_appendf(textbuf, "} "); - } - assert_successful_parse(buf, "%s", textbuf->buf); - buffer_free(textbuf); -} - -void test_valid() { - test_valid_data_for_signed_type(UPB_TYPE(DOUBLE), dbl(33), dbl(-66)); - test_valid_data_for_signed_type(UPB_TYPE(FLOAT), flt(33), flt(-66)); - test_valid_data_for_signed_type(UPB_TYPE(INT64), varint(33), varint(-66)); - test_valid_data_for_signed_type(UPB_TYPE(INT32), varint(33), varint(-66)); - test_valid_data_for_signed_type(UPB_TYPE(ENUM), varint(33), varint(-66)); - test_valid_data_for_signed_type(UPB_TYPE(SFIXED32), uint32(33), uint32(-66)); - test_valid_data_for_signed_type(UPB_TYPE(SFIXED64), uint64(33), uint64(-66)); - test_valid_data_for_signed_type(UPB_TYPE(SINT32), zz32(33), zz32(-66)); - test_valid_data_for_signed_type(UPB_TYPE(SINT64), zz64(33), zz64(-66)); - - test_valid_data_for_type(UPB_TYPE(UINT64), varint(33), varint(66)); - test_valid_data_for_type(UPB_TYPE(UINT32), varint(33), varint(66)); - test_valid_data_for_type(UPB_TYPE(FIXED64), uint64(33), uint64(66)); - test_valid_data_for_type(UPB_TYPE(FIXED32), uint32(33), uint32(66)); - - // Submessage tests. - uint32_t msg_fn = UPB_TYPE(MESSAGE); - assert_successful_parse( - submsg(msg_fn, submsg(msg_fn, submsg(msg_fn, buffer_new3("")))), - "%u:{ %u:{ %u:{ } } } ", msg_fn, msg_fn, msg_fn); - - uint32_t repm_fn = rep_fn(UPB_TYPE(MESSAGE)); - assert_successful_parse( - submsg(repm_fn, submsg(repm_fn, buffer_new3(""))), - "%u:[ %u:{ %u:[ %u:{ } ] } ] ", repm_fn, repm_fn, repm_fn, repm_fn); -} - -void run_tests() { - test_invalid(); - test_valid(); -} - -int main() { - // Construct decoder plan. - upb_handlers *h = upb_handlers_new(); - reghandlers(upb_handlers_newmhandlers(h)); - - // Test without JIT. - plan = upb_decoderplan_new(h, false); - run_tests(); - upb_decoderplan_unref(plan); - - // Test JIT. - plan = upb_decoderplan_new(h, true); - run_tests(); - upb_decoderplan_unref(plan); - - plan = NULL; - printf("All tests passed, %d assertions.\n", num_assertions); - upb_handlers_unref(h); - return 0; -} |