diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_cpp.cc | 14 | ||||
-rw-r--r-- | tests/test_decoder.cc | 404 | ||||
-rw-r--r-- | tests/test_def.c | 14 | ||||
-rw-r--r-- | tests/test_pipeline.c | 116 | ||||
-rw-r--r-- | tests/test_table.cc | 47 | ||||
-rw-r--r-- | tests/test_vs_proto2.cc | 53 |
6 files changed, 377 insertions, 271 deletions
diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc index 59603d9..db2337e 100644 --- a/tests/test_cpp.cc +++ b/tests/test_cpp.cc @@ -10,9 +10,10 @@ #include <stdio.h> #include <string.h> #include <iostream> -#include "upb/bytestream.h" #include "upb/def.h" +#include "upb/descriptor/reader.h" #include "upb/handlers.h" +#include "upb/pb/decoder.h" #include "upb/pb/glue.h" #include "upb_test.h" #include "upb/upb.h" @@ -31,16 +32,6 @@ static void TestSymbolTable(const char *descriptor_file) { md->Unref(&md); } -static void TestByteStream() { - upb::StringSource stringsrc; - stringsrc.Reset("testing", 7); - upb::ByteRegion* byteregion = stringsrc.AllBytes(); - ASSERT(byteregion->FetchAll() == UPB_BYTE_OK); - char* str = byteregion->StrDup(); - ASSERT(strcmp(str, "testing") == 0); - free(str); -} - extern "C" { int run_tests(int argc, char *argv[]) { @@ -49,7 +40,6 @@ int run_tests(int argc, char *argv[]) { return 1; } TestSymbolTable(argv[1]); - TestByteStream(); return 0; } diff --git a/tests/test_decoder.cc b/tests/test_decoder.cc index d42c0fe..1f0e87e 100644 --- a/tests/test_decoder.cc +++ b/tests/test_decoder.cc @@ -31,11 +31,12 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> +#include "upb/bytestream.h" #include "upb/handlers.h" #include "upb/pb/decoder.h" #include "upb/pb/varint.h" -#include "upb/upb.h" #include "upb_test.h" +#include "upb/upb.h" #include "third_party/upb/tests/test_decoder_schema.upb.h" uint32_t filter_hash = 0; @@ -186,16 +187,13 @@ void indentbuf(buffer *buf, int depth) { buf->append(" ", 2); } -void indent(void *depth) { - indentbuf(&output, *(int*)depth); -} - #define NUMERIC_VALUE_HANDLER(member, ctype, fmt) \ - bool value_ ## member(void *closure, void *fval, ctype val) { \ - indent(closure); \ - uint32_t *num = static_cast<uint32_t*>(fval); \ - output.appendf("%" PRIu32 ":%" fmt "\n", *num, val); \ - return true; \ + bool value_ ## member(const upb::SinkFrame *frame, ctype val) { \ + int *depth = (int*)frame->userdata(); \ + indentbuf(&output, *depth); \ + uint32_t *num = static_cast<uint32_t*>(frame->handler_data()); \ + output.appendf("%" PRIu32 ":%" fmt "\n", *num, val); \ + return true; \ } NUMERIC_VALUE_HANDLER(uint32, uint32_t, PRIu32) @@ -205,68 +203,73 @@ NUMERIC_VALUE_HANDLER(int64, int64_t, PRId64) NUMERIC_VALUE_HANDLER(float, float, "g") NUMERIC_VALUE_HANDLER(double, double, "g") -bool value_bool(void *closure, void *fval, bool val) { - indent(closure); - uint32_t *num = static_cast<uint32_t*>(fval); +bool value_bool(const upb::SinkFrame *frame, bool val) { + int *depth = (int*)frame->userdata(); + indentbuf(&output, *depth); + uint32_t *num = static_cast<uint32_t*>(frame->handler_data()); output.appendf("%" PRIu32 ":%s\n", *num, val ? "true" : "false"); return true; } -void* startstr(void *closure, void *fval, size_t size_hint) { - indent(closure); - uint32_t *num = static_cast<uint32_t*>(fval); +void* startstr(const upb::SinkFrame* frame, size_t size_hint) { + int *depth = (int*)frame->userdata(); + indentbuf(&output, *depth); + uint32_t *num = static_cast<uint32_t*>(frame->handler_data()); output.appendf("%" PRIu32 ":(%zu)\"", *num, size_hint); - return ((int*)closure) + 1; + return depth + 1; } -size_t value_string(void *closure, void *fval, const char *buf, size_t n) { +size_t value_string(const upb::SinkFrame* frame, const char* buf, size_t n) { output.append(buf, n); return n; } -bool endstr(void *closure, void *fval) { - UPB_UNUSED(fval); +bool endstr(const upb::SinkFrame* frame) { output.append("\"\n"); return true; } -void* startsubmsg(void *closure, void *fval) { - indent(closure); - uint32_t *num = static_cast<uint32_t*>(fval); +void* startsubmsg(const upb::SinkFrame* frame) { + int *depth = (int*)frame->userdata(); + indentbuf(&output, *depth); + uint32_t *num = static_cast<uint32_t*>(frame->handler_data()); output.appendf("%" PRIu32 ":{\n", *num); - return ((int*)closure) + 1; + return depth + 1; } -bool endsubmsg(void *closure, void *fval) { - UPB_UNUSED(fval); - indent(closure); +bool endsubmsg(const upb::SinkFrame* frame) { + int *depth = (int*)frame->userdata(); + indentbuf(&output, *depth); output.append("}\n"); return true; } -void* startseq(void *closure, void *fval) { - indent(closure); - uint32_t *num = static_cast<uint32_t*>(fval); +void* startseq(const upb::SinkFrame* frame) { + int *depth = (int*)frame->userdata(); + indentbuf(&output, *depth); + uint32_t *num = static_cast<uint32_t*>(frame->handler_data()); output.appendf("%" PRIu32 ":[\n", *num); - return ((int*)closure) + 1; + return depth + 1; } -bool endseq(void *closure, void *fval) { - UPB_UNUSED(fval); - indent(closure); +bool endseq(const upb::SinkFrame* frame) { + int *depth = (int*)frame->userdata(); + indentbuf(&output, *depth); output.append("]\n"); return true; } -bool startmsg(void *closure) { - indent(closure); +bool startmsg(const upb::SinkFrame* frame) { + int *depth = (int*)frame->userdata(); + indentbuf(&output, *depth); output.append("<\n"); return true; } -void endmsg(void *closure, upb_status *status) { +void endmsg(const upb::SinkFrame* frame, upb_status* status) { (void)status; - indent(closure); + int *depth = (int*)frame->userdata(); + indentbuf(&output, *depth); output.append(">\n"); } @@ -299,7 +302,7 @@ uint32_t rep_fn(uint32_t fn) { #define UNKNOWN_FIELD 666 template <class T> -void reg(upb_handlers *h, upb_fieldtype_t type, +void reg(upb_handlers *h, upb_descriptortype_t type, typename upb::Handlers::Value<T>::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 @@ -346,167 +349,111 @@ void reghandlers(upb_handlers *h) { upb_handlers_setendmsg(h, &endmsg); // Register handlers for each type. - reg<double> (h, UPB_TYPE(DOUBLE), &value_double); - reg<float> (h, UPB_TYPE(FLOAT), &value_float); - reg<int64_t> (h, UPB_TYPE(INT64), &value_int64); - reg<uint64_t>(h, UPB_TYPE(UINT64), &value_uint64); - reg<int32_t> (h, UPB_TYPE(INT32) , &value_int32); - reg<uint64_t>(h, UPB_TYPE(FIXED64), &value_uint64); - reg<uint32_t>(h, UPB_TYPE(FIXED32), &value_uint32); - reg<bool> (h, UPB_TYPE(BOOL), &value_bool); - reg<uint32_t>(h, UPB_TYPE(UINT32), &value_uint32); - reg<int32_t> (h, UPB_TYPE(ENUM), &value_int32); - reg<int32_t> (h, UPB_TYPE(SFIXED32), &value_int32); - reg<int64_t> (h, UPB_TYPE(SFIXED64), &value_int64); - reg<int32_t> (h, UPB_TYPE(SINT32), &value_int32); - reg<int64_t> (h, UPB_TYPE(SINT64), &value_int64); - - reg_str(h, UPB_TYPE(STRING)); - reg_str(h, UPB_TYPE(BYTES)); - reg_str(h, rep_fn(UPB_TYPE(STRING))); - reg_str(h, rep_fn(UPB_TYPE(BYTES))); + reg<double> (h, UPB_DESCRIPTOR_TYPE_DOUBLE, &value_double); + reg<float> (h, UPB_DESCRIPTOR_TYPE_FLOAT, &value_float); + reg<int64_t> (h, UPB_DESCRIPTOR_TYPE_INT64, &value_int64); + reg<uint64_t>(h, UPB_DESCRIPTOR_TYPE_UINT64, &value_uint64); + reg<int32_t> (h, UPB_DESCRIPTOR_TYPE_INT32 , &value_int32); + reg<uint64_t>(h, UPB_DESCRIPTOR_TYPE_FIXED64, &value_uint64); + reg<uint32_t>(h, UPB_DESCRIPTOR_TYPE_FIXED32, &value_uint32); + reg<bool> (h, UPB_DESCRIPTOR_TYPE_BOOL, &value_bool); + reg<uint32_t>(h, UPB_DESCRIPTOR_TYPE_UINT32, &value_uint32); + reg<int32_t> (h, UPB_DESCRIPTOR_TYPE_ENUM, &value_int32); + reg<int32_t> (h, UPB_DESCRIPTOR_TYPE_SFIXED32, &value_int32); + reg<int64_t> (h, UPB_DESCRIPTOR_TYPE_SFIXED64, &value_int64); + reg<int32_t> (h, UPB_DESCRIPTOR_TYPE_SINT32, &value_int32); + reg<int64_t> (h, UPB_DESCRIPTOR_TYPE_SINT64, &value_int64); + + reg_str(h, UPB_DESCRIPTOR_TYPE_STRING); + reg_str(h, UPB_DESCRIPTOR_TYPE_BYTES); + reg_str(h, rep_fn(UPB_DESCRIPTOR_TYPE_STRING)); + reg_str(h, rep_fn(UPB_DESCRIPTOR_TYPE_BYTES)); // Register submessage/group handlers that are self-recursive // to this type, eg: message M { optional M m = 1; } - reg_subm(h, UPB_TYPE(MESSAGE)); - reg_subm(h, rep_fn(UPB_TYPE(MESSAGE))); + reg_subm(h, UPB_DESCRIPTOR_TYPE_MESSAGE); + reg_subm(h, rep_fn(UPB_DESCRIPTOR_TYPE_MESSAGE)); // For NOP_FIELD we register no handlers, so we can pad a proto freely without // changing the output. } -/* 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 = (upb_seamsrc*)_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 = (const upb_seamsrc*)_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 = (const upb_seamsrc*)_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; +const upb::Handlers *handlers; +const upb::Handlers *plan; uint32_t Hash(const buffer& proto, const buffer* expected_output) { uint32_t hash = MurmurHash2(proto.buf(), proto.len(), 0); if (expected_output) hash = MurmurHash2(expected_output->buf(), expected_output->len(), hash); - bool hasjit = upb_decoderplan_hasjitcode(plan); + bool hasjit = upb::pb::HasJitCode(plan); hash = MurmurHash2(&hasjit, 1, hash); return hash; } +bool parse( + upb_sink *s, const char *buf, size_t start, size_t end, size_t *ofs) { + start = UPB_MAX(start, *ofs); + if (start <= end) { + size_t len = end - start; + size_t parsed = + s->PutStringBuffer(UPB_BYTESTREAM_BYTES_STRING, buf + start, len); + if (s->pipeline()->status().ok() != (parsed >= len)) { + ASSERT(false); + } + if (!s->pipeline()->status().ok()) + return false; + *ofs += parsed; + } + return true; +} + #define LINE(x) x "\n" void run_decoder(const buffer& proto, const buffer* expected_output) { testhash = Hash(proto, expected_output); if (filter_hash && testhash != filter_hash) return; - upb_seamsrc src; - upb_seamsrc_init(&src, proto.buf(), proto.len()); - upb_decoder d; - upb_decoder_init(&d); - upb_decoder_resetplan(&d, plan); + upb::Pipeline pipeline(NULL, 0, upb_realloc, NULL); + upb::Sink* sink = pipeline.NewSink(handlers); + upb::Sink* decoder_sink = pipeline.NewSink(plan); + upb::pb::Decoder* d = decoder_sink->base()->GetUserdata<upb::pb::Decoder>(); + upb::pb::ResetDecoderSink(d, sink); for (size_t i = 0; i < proto.len(); i++) { for (size_t j = i; j < UPB_MIN(proto.len(), i + 5); j++) { - upb_seamsrc_resetseams(&src, i, j); - upb_byteregion *input = upb_seamsrc_allbytes(&src); + pipeline.Reset(); output.clear(); - upb_decoder_resetinput(&d, input, &closures[0]); - upb_success_t success = upb_decoder_decode(&d); - ASSERT(upb_ok(upb_decoder_status(&d)) == (success == UPB_OK)); + sink->Reset(&closures[0]); + size_t ofs = 0; + bool ok = + decoder_sink->StartMessage() && + decoder_sink->StartString( + UPB_BYTESTREAM_BYTES_STARTSTR, proto.len()) && + parse(decoder_sink, proto.buf(), 0, i, &ofs) && + parse(decoder_sink, proto.buf(), i, j, &ofs) && + parse(decoder_sink, proto.buf(), j, proto.len(), &ofs) && + ofs == proto.len() && + decoder_sink->EndString(UPB_BYTESTREAM_BYTES_ENDSTR); + if (ok) decoder_sink->EndMessage(); if (expected_output) { - ASSERT_STATUS(success == UPB_OK, upb_decoder_status(&d)); - // 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 (!output.eql(*expected_output)) { fprintf(stderr, "Text mismatch: '%s' vs '%s'\n", output.buf(), expected_output->buf()); } + if (!ok) { + fprintf(stderr, "Failed: %s\n", pipeline.status().GetString()); + } + ASSERT(ok); ASSERT(output.eql(*expected_output)); } else { - ASSERT(success == UPB_ERROR); + if (ok) { + fprintf(stderr, "Didn't expect ok result, but got output: '%s'\n", + output.buf()); + } + ASSERT(!ok); } } } - upb_decoder_uninit(&d); - upb_seamsrc_uninit(&src); testhash = 0; } @@ -540,7 +487,7 @@ void assert_does_not_parse(const buffer& proto) { /* The actual tests ***********************************************************/ -void test_premature_eof_for_type(upb_fieldtype_t type) { +void test_premature_eof_for_type(upb_descriptortype_t type) { // Incomplete values for each wire type. static const buffer incompletes[6] = { buffer("\x80"), // UPB_WIRE_TYPE_VARINT @@ -590,10 +537,10 @@ void test_premature_eof_for_type(upb_fieldtype_t type) { assert_does_not_parse_at_eof( cat( tag(UNKNOWN_FIELD, wire_type), varint(1) )); - if (type == UPB_TYPE(MESSAGE)) { + if (type == UPB_DESCRIPTOR_TYPE_MESSAGE) { // Submessage ends in the middle of a value. buffer incomplete_submsg = - cat ( tag(UPB_TYPE(INT32), UPB_WIRE_TYPE_VARINT), + cat ( tag(UPB_DESCRIPTOR_TYPE_INT32, UPB_WIRE_TYPE_VARINT), incompletes[UPB_WIRE_TYPE_VARINT] ); assert_does_not_parse( cat( tag(fieldnum, UPB_WIRE_TYPE_DELIMITED), @@ -615,7 +562,7 @@ void test_premature_eof_for_type(upb_fieldtype_t type) { // "33" and "66" are just two random values that all numeric types can // represent. -void test_valid_data_for_type(upb_fieldtype_t type, +void test_valid_data_for_type(upb_descriptortype_t type, const buffer& enc33, const buffer& enc66) { uint32_t fieldnum = type; uint32_t rep_fieldnum = rep_fn(type); @@ -653,7 +600,7 @@ void test_valid_data_for_type(upb_fieldtype_t type, LINE(">"), rep_fieldnum, rep_fieldnum, rep_fieldnum); } -void test_valid_data_for_signed_type(upb_fieldtype_t type, +void test_valid_data_for_signed_type(upb_descriptortype_t type, const buffer& enc33, const buffer& enc66) { uint32_t fieldnum = type; uint32_t rep_fieldnum = rep_fn(type); @@ -694,22 +641,22 @@ void test_valid_data_for_signed_type(upb_fieldtype_t type, // 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)); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_DOUBLE); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_FLOAT); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_INT64); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_UINT64); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_INT32); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_FIXED64); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_FIXED32); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_BOOL); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_STRING); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_BYTES); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_UINT32); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_ENUM); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_SFIXED32); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_SFIXED64); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_SINT32); + test_premature_eof_for_type(UPB_DESCRIPTOR_TYPE_SINT64); // EOF inside a tag's varint. assert_does_not_parse_at_eof( buffer("\x80") ); @@ -734,31 +681,47 @@ void test_invalid() { // Test exceeding the resource limit of stack depth. buffer buf; - for (int i = 0; i < UPB_MAX_NESTING; i++) { - buf.assign(submsg(UPB_TYPE(MESSAGE), buf)); + for (int i = 0; i <= UPB_MAX_NESTING; i++) { + buf.assign(submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, buf)); } assert_does_not_parse(buf); } 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)); + test_valid_data_for_signed_type(UPB_DESCRIPTOR_TYPE_DOUBLE, + dbl(33), + dbl(-66)); + test_valid_data_for_signed_type(UPB_DESCRIPTOR_TYPE_FLOAT, flt(33), flt(-66)); + test_valid_data_for_signed_type(UPB_DESCRIPTOR_TYPE_INT64, + varint(33), + varint(-66)); + test_valid_data_for_signed_type(UPB_DESCRIPTOR_TYPE_INT32, + varint(33), + varint(-66)); + test_valid_data_for_signed_type(UPB_DESCRIPTOR_TYPE_ENUM, + varint(33), + varint(-66)); + test_valid_data_for_signed_type(UPB_DESCRIPTOR_TYPE_SFIXED32, + uint32(33), + uint32(-66)); + test_valid_data_for_signed_type(UPB_DESCRIPTOR_TYPE_SFIXED64, + uint64(33), + uint64(-66)); + test_valid_data_for_signed_type(UPB_DESCRIPTOR_TYPE_SINT32, + zz32(33), + zz32(-66)); + test_valid_data_for_signed_type(UPB_DESCRIPTOR_TYPE_SINT64, + zz64(33), + zz64(-66)); + + test_valid_data_for_type(UPB_DESCRIPTOR_TYPE_UINT64, varint(33), varint(66)); + test_valid_data_for_type(UPB_DESCRIPTOR_TYPE_UINT32, varint(33), varint(66)); + test_valid_data_for_type(UPB_DESCRIPTOR_TYPE_FIXED64, uint64(33), uint64(66)); + test_valid_data_for_type(UPB_DESCRIPTOR_TYPE_FIXED32, uint32(33), uint32(66)); // Test implicit startseq/endseq. - uint32_t repfl_fn = rep_fn(UPB_TYPE(FLOAT)); - uint32_t repdb_fn = rep_fn(UPB_TYPE(DOUBLE)); + uint32_t repfl_fn = rep_fn(UPB_DESCRIPTOR_TYPE_FLOAT); + uint32_t repdb_fn = rep_fn(UPB_DESCRIPTOR_TYPE_DOUBLE); assert_successful_parse( cat( tag(repfl_fn, UPB_WIRE_TYPE_32BIT), flt(33), tag(repdb_fn, UPB_WIRE_TYPE_64BIT), dbl(66) ), @@ -772,7 +735,7 @@ void test_valid() { LINE(">"), repfl_fn, repfl_fn, repdb_fn, repdb_fn); // Submessage tests. - uint32_t msg_fn = UPB_TYPE(MESSAGE); + uint32_t msg_fn = UPB_DESCRIPTOR_TYPE_MESSAGE; assert_successful_parse( submsg(msg_fn, submsg(msg_fn, submsg(msg_fn, buffer()))), LINE("<") @@ -790,7 +753,7 @@ void test_valid() { LINE("}") LINE(">"), msg_fn, msg_fn, msg_fn); - uint32_t repm_fn = rep_fn(UPB_TYPE(MESSAGE)); + uint32_t repm_fn = rep_fn(UPB_DESCRIPTOR_TYPE_MESSAGE); assert_successful_parse( submsg(repm_fn, submsg(repm_fn, buffer())), LINE("<") @@ -813,11 +776,11 @@ void test_valid() { buffer textbuf; int total = UPB_MAX_NESTING - 1; for (int i = 0; i < total; i++) { - buf.assign(submsg(UPB_TYPE(MESSAGE), buf)); + buf.assign(submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, buf)); indentbuf(&textbuf, i); textbuf.append("<\n"); indentbuf(&textbuf, i); - textbuf.appendf("%u:{\n", UPB_TYPE(MESSAGE)); + textbuf.appendf("%u:{\n", UPB_DESCRIPTOR_TYPE_MESSAGE); } indentbuf(&textbuf, total); textbuf.append("<\n"); @@ -848,35 +811,36 @@ int run_tests(int argc, char *argv[]) { // Create an empty handlers to make sure that the decoder can handle empty // messages. - upb_handlers *h = upb_handlers_new(UPB_TEST_DECODER_EMPTYMESSAGE, &h); - bool ok = upb_handlers_freeze(&h, 1, NULL); + upb::Handlers *h = upb_handlers_new(UPB_TEST_DECODER_EMPTYMESSAGE, NULL, &h); + bool ok = upb::Handlers::Freeze(&h, 1, NULL); ASSERT(ok); - plan = upb_decoderplan_new(h, true); - upb_handlers_unref(h, &h); - upb_decoderplan_unref(plan); + plan = upb::pb::GetDecoderHandlers(h, true, &plan); + h->Unref(&h); + plan->Unref(&plan); // Construct decoder plan. - h = upb_handlers_new(UPB_TEST_DECODER_DECODERTEST, &h); + h = upb::Handlers::New(UPB_TEST_DECODER_DECODERTEST, NULL, &handlers); reghandlers(h); - ok = upb_handlers_freeze(&h, 1, NULL); + ok = upb::Handlers::Freeze(&h, 1, NULL); + handlers = h; // Test without JIT. - plan = upb_decoderplan_new(h, false); - ASSERT(!upb_decoderplan_hasjitcode(plan)); + plan = upb::pb::GetDecoderHandlers(handlers, false, &plan); + ASSERT(!upb::pb::HasJitCode(plan)); run_tests(); - upb_decoderplan_unref(plan); + plan->Unref(&plan); #ifdef UPB_USE_JIT_X64 // Test JIT. - plan = upb_decoderplan_new(h, true); - ASSERT(upb_decoderplan_hasjitcode(plan)); + plan = upb::pb::GetDecoderHandlers(handlers, true, &plan); + ASSERT(upb::pb::HasJitCode(plan)); run_tests(); - upb_decoderplan_unref(plan); + plan->Unref(&plan); #endif plan = NULL; printf("All tests passed, %d assertions.\n", num_assertions); - upb_handlers_unref(h, &h); + handlers->Unref(&handlers); return 0; } diff --git a/tests/test_def.c b/tests/test_def.c index 7f089d7..d048b3e 100644 --- a/tests/test_def.c +++ b/tests/test_def.c @@ -88,15 +88,15 @@ static void test_fielddef_accessors() { ASSERT(!upb_fielddef_isfrozen(f1)); upb_fielddef_setname(f1, "f1"); upb_fielddef_setnumber(f1, 1937); - upb_fielddef_settype(f1, UPB_TYPE(FIXED64)); - upb_fielddef_setlabel(f1, UPB_LABEL(REPEATED)); + upb_fielddef_settype(f1, UPB_TYPE_INT64); + upb_fielddef_setlabel(f1, UPB_LABEL_REPEATED); ASSERT(upb_fielddef_number(f1) == 1937); ASSERT(!upb_fielddef_isfrozen(f2)); upb_fielddef_setname(f2, "f2"); upb_fielddef_setnumber(f2, 1572); - upb_fielddef_settype(f2, UPB_TYPE(BYTES)); - upb_fielddef_setlabel(f2, UPB_LABEL(REPEATED)); + upb_fielddef_settype(f2, UPB_TYPE_BYTES); + upb_fielddef_setlabel(f2, UPB_LABEL_REPEATED); ASSERT(upb_fielddef_number(f2) == 1572); upb_fielddef_unref(f1, &f1); @@ -104,7 +104,7 @@ static void test_fielddef_accessors() { // Test that we don't leak an unresolved subdef name. f1 = upb_fielddef_new(&f1); - upb_fielddef_settype(f1, UPB_TYPE(MESSAGE)); + upb_fielddef_settype(f1, UPB_TYPE_MESSAGE); upb_fielddef_setsubdefname(f1, "YO"); upb_fielddef_unref(f1, &f1); } @@ -127,7 +127,7 @@ static upb_msgdef *upb_msgdef_newnamed(const char *name, void *owner) { return m; } -INLINE upb_enumdef *upb_enumdef_newnamed(const char *name, void *owner) { +static upb_enumdef *upb_enumdef_newnamed(const char *name, void *owner) { upb_enumdef *e = upb_enumdef_new(owner); upb_def_setfullname(upb_upcast(e), name); return e; @@ -138,7 +138,7 @@ static void test_replacement() { upb_msgdef *m = upb_msgdef_newnamed("MyMessage", &s); upb_msgdef_addfield(m, newfield( - "field1", 1, UPB_TYPE(ENUM), UPB_LABEL(OPTIONAL), ".MyEnum", &s), &s); + "field1", 1, UPB_TYPE_ENUM, UPB_LABEL_OPTIONAL, ".MyEnum", &s), &s); upb_msgdef *m2 = upb_msgdef_newnamed("MyMessage2", &s); upb_enumdef *e = upb_enumdef_newnamed("MyEnum", &s); diff --git a/tests/test_pipeline.c b/tests/test_pipeline.c new file mode 100644 index 0000000..d54d15c --- /dev/null +++ b/tests/test_pipeline.c @@ -0,0 +1,116 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2013 Google Inc. See LICENSE for details. + * + * Test of upb_pipeline. + */ + +#include "upb/sink.h" +#include "tests/upb_test.h" + +static void *count_realloc(void *ud, void *ptr, size_t size) { + int *count = ud; + *count += 1; + return upb_realloc(ud, ptr, size); +} + +static void test_empty() { + // A pipeline with no initial memory or allocation function should return + // NULL from attempts to allocate. + upb_pipeline pipeline; + upb_pipeline_init(&pipeline, NULL, 0, NULL, NULL); + ASSERT(upb_pipeline_alloc(&pipeline, 1) == NULL); + ASSERT(upb_pipeline_alloc(&pipeline, 1) == NULL); + ASSERT(upb_pipeline_realloc(&pipeline, NULL, 0, 1) == NULL); + upb_pipeline_uninit(&pipeline); +} + +static void test_only_initial() { + upb_pipeline pipeline; + char initial[152]; // 128 + a conservative 24 bytes overhead. + upb_pipeline_init(&pipeline, initial, sizeof(initial), NULL, NULL); + void *p1 = upb_pipeline_alloc(&pipeline, 64); + void *p2 = upb_pipeline_alloc(&pipeline, 64); + void *p3 = upb_pipeline_alloc(&pipeline, 64); + ASSERT(p1); + ASSERT(p2); + ASSERT(!p3); + ASSERT(p1 != p2); + ASSERT((void*)initial <= p1); + ASSERT(p1 < p2); + ASSERT(p2 < (void*)(initial + sizeof(initial))); + upb_pipeline_uninit(&pipeline); +} + +static void test_with_alloc_func() { + upb_pipeline pipeline; + char initial[152]; // 128 + a conservative 24 bytes overhead. + int count = 0; + upb_pipeline_init(&pipeline, initial, sizeof(initial), count_realloc, &count); + void *p1 = upb_pipeline_alloc(&pipeline, 64); + void *p2 = upb_pipeline_alloc(&pipeline, 64); + ASSERT(p1); + ASSERT(p2); + ASSERT(p1 != p2); + ASSERT(count == 0); + + void *p3 = upb_pipeline_alloc(&pipeline, 64); + ASSERT(p3); + ASSERT(p3 != p2); + ASSERT(count == 1); + + // Allocation larger than internal block size should force another alloc. + char *p4 = upb_pipeline_alloc(&pipeline, 16384); + ASSERT(p4); + p4[16383] = 1; // Verify memory is writable without crashing. + ASSERT(p4[16383] == 1); + ASSERT(count == 2); + + upb_pipeline_uninit(&pipeline); + ASSERT(count == 4); // From two calls to free the memory. +} + +static void test_realloc() { + upb_pipeline pipeline; + char initial[152]; // 128 + a conservative 24 bytes overhead. + int count = 0; + upb_pipeline_init(&pipeline, initial, sizeof(initial), count_realloc, &count); + void *p1 = upb_pipeline_alloc(&pipeline, 64); + // This realloc should work in-place. + void *p2 = upb_pipeline_realloc(&pipeline, p1, 64, 128); + ASSERT(p1); + ASSERT(p2); + ASSERT(p1 == p2); + ASSERT(count == 0); + + // This realloc will *not* work in place, due to size. + void *p3 = upb_pipeline_realloc(&pipeline, p2, 128, 256); + ASSERT(p3); + ASSERT(p3 != p2); + ASSERT(count == 1); + + void *p4 = upb_pipeline_alloc(&pipeline, 64); + void *p5 = upb_pipeline_alloc(&pipeline, 64); + // This realloc will *not* work in place because it was not the last + // allocation. + void *p6 = upb_pipeline_realloc(&pipeline, p4, 64, 128); + ASSERT(p4); + ASSERT(p5); + ASSERT(p6); + ASSERT(p4 != p6); + ASSERT(p4 < p5); + ASSERT(p5 < p6); + ASSERT(count == 1); // These should all fit in the first dynamic block. + + upb_pipeline_uninit(&pipeline); + ASSERT(count == 2); +} + +int run_tests(int argc, char *argv[]) { + test_empty(); + test_only_initial(); + test_with_alloc_func(); + test_realloc(); + return 0; +} diff --git a/tests/test_table.cc b/tests/test_table.cc index bb75fc4..80b0139 100644 --- a/tests/test_table.cc +++ b/tests/test_table.cc @@ -46,13 +46,14 @@ void test_strtable(const vector<std::string>& keys, uint32_t num_to_insert) { /* Test correctness. */ for(uint32_t i = 0; i < keys.size(); i++) { const std::string& key = keys[i]; - const upb_value *v = upb_strtable_lookup(&table, key.c_str()); + upb_value v; + bool found = upb_strtable_lookup(&table, key.c_str(), &v); if(m.find(key) != m.end()) { /* Assume map implementation is correct. */ - ASSERT(v); - ASSERT(upb_value_getint32(*v) == key[0]); + ASSERT(found); + ASSERT(upb_value_getint32(v) == key[0]); ASSERT(m[key] == key[0]); } else { - ASSERT(v == NULL); + ASSERT(!found); } } @@ -88,14 +89,15 @@ void test_inttable(int32_t *keys, uint16_t num_entries, const char *desc) { /* Test correctness. */ for(uint32_t i = 0; i <= largest_key; i++) { - const upb_value *v = upb_inttable_lookup(&table, i); + upb_value v; + bool found = upb_inttable_lookup(&table, i, &v); if(m.find(i) != m.end()) { /* Assume map implementation is correct. */ - ASSERT(v); - ASSERT(upb_value_getuint32(*v) == i*2); + ASSERT(found); + ASSERT(upb_value_getuint32(v) == i*2); ASSERT(m[i] == i*2); ASSERT(hm[i] == i*2); } else { - ASSERT(v == NULL); + ASSERT(!found); } } @@ -112,28 +114,30 @@ void test_inttable(int32_t *keys, uint16_t num_entries, const char *desc) { /* Test correctness. */ for(uint32_t i = 0; i <= largest_key; i++) { - const upb_value *v = upb_inttable_lookup(&table, i); + upb_value v; + bool found = upb_inttable_lookup(&table, i, &v); if(m.find(i) != m.end()) { /* Assume map implementation is correct. */ - ASSERT(v); - ASSERT(upb_value_getuint32(*v) == i*2); + ASSERT(found); + ASSERT(upb_value_getuint32(v) == i*2); ASSERT(m[i] == i*2); ASSERT(hm[i] == i*2); } else { - ASSERT(v == NULL); + ASSERT(!found); } } // Compact and test correctness again. upb_inttable_compact(&table); for(uint32_t i = 0; i <= largest_key; i++) { - const upb_value *v = upb_inttable_lookup(&table, i); + upb_value v; + bool found = upb_inttable_lookup(&table, i, &v); if(m.find(i) != m.end()) { /* Assume map implementation is correct. */ - ASSERT(v); - ASSERT(upb_value_getuint32(*v) == i*2); + ASSERT(found); + ASSERT(upb_value_getuint32(v) == i*2); ASSERT(m[i] == i*2); ASSERT(hm[i] == i*2); } else { - ASSERT(v == NULL); + ASSERT(!found); } } @@ -172,8 +176,9 @@ void test_inttable(int32_t *keys, uint16_t num_entries, const char *desc) { for(i = 0; true; i++) { MAYBE_BREAK; int32_t key = keys[i & mask]; - const upb_value *v = upb_inttable_lookup32(&table, key); - x += (uintptr_t)v; + upb_value v; + bool ok = upb_inttable_lookup32(&table, key, &v); + x += (uintptr_t)ok; } double total = get_usertime() - before; printf("%s/s\n", eng(i/total, 3, false)); @@ -184,8 +189,9 @@ void test_inttable(int32_t *keys, uint16_t num_entries, const char *desc) { for(i = 0; true; i++) { MAYBE_BREAK; int32_t key = keys[rand_order[i & mask]]; - const upb_value *v = upb_inttable_lookup32(&table, key); - x += (uintptr_t)v; + upb_value v; + bool ok = upb_inttable_lookup32(&table, key, &v); + x += (uintptr_t)ok; } total = get_usertime() - before; printf("%s/s\n", eng(i/total, 3, false)); @@ -232,6 +238,7 @@ void test_inttable(int32_t *keys, uint16_t num_entries, const char *desc) { x += hm[key]; } total = get_usertime() - before; + if (x == INT_MAX) abort(); printf("%s/s\n\n", eng(i/total, 3, false)); upb_inttable_uninit(&table); delete rand_order; diff --git a/tests/test_vs_proto2.cc b/tests/test_vs_proto2.cc index 5eca399..b1a6053 100644 --- a/tests/test_vs_proto2.cc +++ b/tests/test_vs_proto2.cc @@ -10,6 +10,7 @@ #define __STDC_LIMIT_MACROS // So we get UINT32_MAX #include <assert.h> #include <google/protobuf/descriptor.h> +#include <google/protobuf/dynamic_message.h> #include <google/protobuf/message.h> #include <google/protobuf/wire_format_lite.h> #include <inttypes.h> @@ -17,10 +18,11 @@ #include <stdio.h> #include <stdlib.h> #include "benchmarks/google_messages.pb.h" -#include "bindings/cpp/upb/pb/decoder.hpp" +#include "upb/bytestream.h" #include "upb/def.h" #include "upb/google/bridge.h" #include "upb/handlers.h" +#include "upb/pb/decoder.h" #include "upb/pb/glue.h" #include "upb/pb/varint.h" #include "upb_test.h" @@ -36,25 +38,36 @@ void compare_metadata(const google::protobuf::Descriptor* d, ASSERT(proto2_f); ASSERT(upb_f->number() == proto2_f->number()); ASSERT(std::string(upb_f->name()) == proto2_f->name()); - ASSERT(upb_f->type() == static_cast<upb::FieldDef::Type>(proto2_f->type())); + ASSERT(upb_f->descriptor_type() == + static_cast<upb::FieldDef::DescriptorType>(proto2_f->type())); ASSERT(upb_f->IsSequence() == proto2_f->is_repeated()); } } -void parse_and_compare(MESSAGE_CIDENT *msg1, MESSAGE_CIDENT *msg2, - const upb::Handlers *handlers, +void parse_and_compare(google::protobuf::Message *msg1, + google::protobuf::Message *msg2, + const upb::Handlers *protomsg_handlers, const char *str, size_t len, bool allow_jit) { // Parse to both proto2 and upb. ASSERT(msg1->ParseFromArray(str, len)); - upb::DecoderPlan* plan = upb::DecoderPlan::New(handlers, allow_jit); - upb::StringSource src(str, len); - upb::Decoder decoder; - decoder.ResetPlan(plan); - decoder.ResetInput(src.AllBytes(), msg2); + const upb::Handlers* decoder_handlers = upb::pb::GetDecoderHandlers( + protomsg_handlers, allow_jit, &decoder_handlers); + + upb::Pipeline pipeline(NULL, 0, upb_realloc, NULL); + pipeline.DonateRef(decoder_handlers, &decoder_handlers); + upb::Sink* protomsg_sink = pipeline.NewSink(protomsg_handlers); + upb::Sink* decoder_sink = pipeline.NewSink(decoder_handlers); + + protomsg_sink->Reset(msg2); + upb::pb::Decoder* decoder = + decoder_sink->base()->GetUserdata<upb::pb::Decoder>(); + upb::pb::ResetDecoderSink(decoder, protomsg_sink); + msg2->Clear(); - ASSERT(decoder.Decode() == UPB_OK); - plan->Unref(); + bool ok = upb::PutStringToBytestream(decoder_sink, str, len); + ASSERT(ok); + ASSERT(pipeline.status().ok()); // Would like to just compare the message objects themselves, but // unfortunately MessageDifferencer is not part of the open-source release of @@ -110,13 +123,29 @@ int run_tests(int argc, char *argv[]) parse_and_compare(&msg1, &msg2, h, str, len, true); parse_and_compare(&msg1, &msg2, h, str, len, false); parse_and_compare(&msg1, &msg2, h, str, len, true); - printf("All tests passed, %d assertions.\n", num_assertions); + h->Unref(&h); + // Test with DynamicMessage. + google::protobuf::DynamicMessageFactory* factory = + new google::protobuf::DynamicMessageFactory; + const google::protobuf::Message* prototype = + factory->GetPrototype(msg1.descriptor()); + google::protobuf::Message* dyn_msg1 = prototype->New(); + google::protobuf::Message* dyn_msg2 = prototype->New(); + h = upb::google::NewWriteHandlers(*dyn_msg1, &h); + parse_and_compare(dyn_msg1, dyn_msg2, h, str, len, false); + parse_and_compare(dyn_msg1, dyn_msg2, h, str, len, true); + delete dyn_msg1; + delete dyn_msg2; + delete factory; h->Unref(&h); + free((void*)str); test_zig_zag(); + printf("All tests passed, %d assertions.\n", num_assertions); + google::protobuf::ShutdownProtobufLibrary(); return 0; } |