summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test.proto24
-rw-r--r--tests/test_cpp.cc11
-rw-r--r--tests/test_decoder.cc (renamed from tests/test_decoder.c)543
-rw-r--r--tests/test_def.c171
-rw-r--r--tests/test_table.cc134
-rw-r--r--tests/test_vs_proto2.cc294
-rw-r--r--tests/tests.c121
-rw-r--r--tests/upb_test.h22
8 files changed, 691 insertions, 629 deletions
diff --git a/tests/test.proto b/tests/test.proto
index f3dde24..e634ed2 100644
--- a/tests/test.proto
+++ b/tests/test.proto
@@ -1,14 +1,10 @@
// A series of messages with various kinds of cycles in them.
-// +-+---+ +---+
-// V | | | |
-// A -> B-+-> C -> D<--+
-// ^ | |
-// +----------+----+
-//
-// This tests the following cases:
-// - B and C are together in multiple cycles
-// - B and D are cycles to themselves.
+// +-+---+ +---+ +---+
+// V | | V | V |
+// A -> B-+-> C -> D---+--->E---+
+// ^ |`---|--------^
+// +----------+----+ F
message A {
optional B b = 1;
@@ -23,11 +19,21 @@ message C {
optional A a = 1;
optional B b = 2;
optional D d = 3;
+ optional E e = 4;
}
message D {
optional A a = 1;
optional D d = 2;
+ optional E e = 3;
+}
+
+message E {
+ optional E e = 1;
+}
+
+message F {
+ optional E e = 1;
}
// A proto with a bunch of simple primitives.
diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc
index 5182217..4d70e85 100644
--- a/tests/test_cpp.cc
+++ b/tests/test_cpp.cc
@@ -15,6 +15,7 @@
#include "upb/upb.hpp"
#include "upb/pb/decoder.hpp"
#include "upb/pb/glue.hpp"
+#include "upb_test.h"
static void TestSymbolTable(const char *descriptor_file) {
upb::SymbolTable *s = upb::SymbolTable::New();
@@ -23,20 +24,20 @@ static void TestSymbolTable(const char *descriptor_file) {
std::cerr << "Couldn't load descriptor: " << status;
exit(1);
}
- const upb::MessageDef *md = s->LookupMessage("A");
- assert(md);
+ const upb::MessageDef *md = s->LookupMessage("A", &md);
+ ASSERT(md);
s->Unref();
- md->Unref();
+ md->Unref(&md);
}
static void TestByteStream() {
upb::StringSource stringsrc;
stringsrc.Reset("testing", 7);
upb::ByteRegion* byteregion = stringsrc.AllBytes();
- assert(byteregion->FetchAll() == UPB_BYTE_OK);
+ ASSERT(byteregion->FetchAll() == UPB_BYTE_OK);
char* str = byteregion->StrDup();
- assert(strcmp(str, "testing") == 0);
+ ASSERT(strcmp(str, "testing") == 0);
free(str);
}
diff --git a/tests/test_decoder.c b/tests/test_decoder.cc
index 14d0e2d..13403bb 100644
--- a/tests/test_decoder.c
+++ b/tests/test_decoder.cc
@@ -21,6 +21,10 @@
* of submsg/sequences, etc.
*/
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS // For PRIuS, etc.
+#endif
+
#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
@@ -32,95 +36,133 @@
#include "upb/upb.h"
#include "upb_test.h"
+// Copied from decoder.c, since this is not a public interface.
typedef struct {
- char *buf;
- size_t len;
-} buffer;
+ uint8_t native_wire_type;
+ bool is_numeric;
+} upb_decoder_typeinfo;
+
+static const upb_decoder_typeinfo upb_decoder_types[] = {
+ {UPB_WIRE_TYPE_END_GROUP, false}, // ENDGROUP
+ {UPB_WIRE_TYPE_64BIT, true}, // DOUBLE
+ {UPB_WIRE_TYPE_32BIT, true}, // FLOAT
+ {UPB_WIRE_TYPE_VARINT, true}, // INT64
+ {UPB_WIRE_TYPE_VARINT, true}, // UINT64
+ {UPB_WIRE_TYPE_VARINT, true}, // INT32
+ {UPB_WIRE_TYPE_64BIT, true}, // FIXED64
+ {UPB_WIRE_TYPE_32BIT, true}, // FIXED32
+ {UPB_WIRE_TYPE_VARINT, true}, // BOOL
+ {UPB_WIRE_TYPE_DELIMITED, false}, // STRING
+ {UPB_WIRE_TYPE_START_GROUP, false}, // GROUP
+ {UPB_WIRE_TYPE_DELIMITED, false}, // MESSAGE
+ {UPB_WIRE_TYPE_DELIMITED, false}, // BYTES
+ {UPB_WIRE_TYPE_VARINT, true}, // UINT32
+ {UPB_WIRE_TYPE_VARINT, true}, // ENUM
+ {UPB_WIRE_TYPE_32BIT, true}, // SFIXED32
+ {UPB_WIRE_TYPE_64BIT, true}, // SFIXED64
+ {UPB_WIRE_TYPE_VARINT, true}, // SINT32
+ {UPB_WIRE_TYPE_VARINT, true}, // SINT64
+};
+
+
+class buffer {
+ public:
+ buffer(const void *data, size_t len) : len_(0) { append(data, len); }
+ explicit buffer(const char *data) : len_(0) { append(data); }
+ explicit buffer(size_t len) : len_(len) { memset(buf_, 0, len); }
+ buffer(const buffer& buf) : len_(0) { append(buf); }
+ buffer() : len_(0) {}
+
+ void append(const void *data, size_t len) {
+ ASSERT_NOCOUNT(len + len_ < sizeof(buf_));
+ memcpy(buf_ + len_, data, len);
+ len_ += len;
+ buf_[len_] = NULL;
+ }
-// 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;
-}
+ void append(const buffer& buf) {
+ append(buf.buf_, buf.len_);
+ }
-buffer *buffer_new2(const void *data, size_t len) {
- buffer *buf = buffer_new(len);
- memcpy(buf->buf, data, len);
- return buf;
-}
+ void append(const char *str) {
+ append(str, strlen(str));
+ }
-buffer *buffer_new3(const char *data) {
- return buffer_new2(data, strlen(data));
-}
+ void vappendf(const char *fmt, va_list args) {
+ size_t avail = sizeof(buf_) - len_;
+ size_t size = vsnprintf(buf_ + len_, avail, fmt, args);
+ ASSERT_NOCOUNT(avail > size);
+ len_ += size;
+ }
-buffer *buffer_dup(buffer *buf) { return buffer_new2(buf->buf, buf->len); }
+ void appendf(const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vappendf(fmt, args);
+ va_end(args);
+ }
-void buffer_free(buffer *buf) {
- free(buf->buf);
- free(buf);
-}
+ void assign(const buffer& buf) {
+ clear();
+ append(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);
-}
+ bool eql(const buffer& other) const {
+ return len_ == other.len_ && memcmp(buf_, other.buf_, len_) == 0;
+ }
-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);
-}
+ void clear() { len_ = 0; }
+ size_t len() const { return len_; }
+ const char *buf() const { return buf_; }
-bool buffer_eql(buffer *buf, buffer *buf2) {
- return buf->len == buf2->len && memcmp(buf->buf, buf2->buf, buf->len) == 0;
-}
+ private:
+ // Has to be big enough for the largest string used in the test.
+ char buf_[32768];
+ size_t len_;
+};
/* 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;
+const buffer empty;
+
+buffer cat(const buffer& a, const buffer& b,
+ const buffer& c = empty,
+ const buffer& d = empty,
+ const buffer& e = empty) {
+ buffer ret;
+ ret.append(a);
+ ret.append(b);
+ ret.append(c);
+ ret.append(d);
+ ret.append(e);
+ return ret;
}
-buffer *varint(uint64_t x) {
- buffer *buf = buffer_new(UPB_PB_VARINT_MAX_LEN + 1);
- buf->len = upb_vencode64(x, buf->buf);
- return buf;
+buffer varint(uint64_t x) {
+ char buf[UPB_PB_VARINT_MAX_LEN];
+ size_t len = upb_vencode64(x, buf);
+ return buffer(buf, len);
}
// 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) {
+buffer fixed32(void *data) { return buffer(data, 4); }
+buffer fixed64(void *data) { return buffer(data, 8); }
+
+buffer delim(const buffer& buf) { return cat(varint(buf.len()), buf); }
+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 );
+buffer submsg(uint32_t fn, const buffer& buf) {
+ return cat( tag(fn, UPB_WIRE_TYPE_DELIMITED), delim(buf) );
}
@@ -128,11 +170,26 @@ buffer *submsg(uint32_t fn, buffer *buf) {
// 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.
+// number instead of name and sequences are explicitly delimited. We indent
+// using the closure depth to test that the stack of closures is properly
+// handled.
+
+int closures[UPB_MAX_NESTING];
+buffer output;
+
+void indentbuf(buffer *buf, int depth) {
+ for (int i = 0; i < depth; i++)
+ buf->append(" ", 2);
+}
+
+void indent(void *depth) {
+ indentbuf(&output, *(int*)depth);
+}
#define VALUE_HANDLER(member, fmt) \
upb_flow_t value_ ## member(void *closure, upb_value fval, upb_value val) { \
- buffer_appendf(closure, "%" PRIu32 ":%" fmt "; ", \
+ indent(closure); \
+ output.appendf("%" PRIu32 ":%" fmt "\n", \
upb_value_getuint32(fval), upb_value_get ## member(val)); \
return UPB_CONTINUE; \
}
@@ -145,7 +202,8 @@ 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; ",
+ indent(closure);
+ output.appendf("%" PRIu32 ":%s\n",
upb_value_getuint32(fval),
upb_value_getbool(val) ? "true" : "false");
return UPB_CONTINUE;
@@ -153,34 +211,49 @@ upb_flow_t value_bool(void *closure, upb_value fval, upb_value val) {
upb_flow_t value_string(void *closure, upb_value fval, upb_value val) {
// Note: won't work with strings that contain NULL.
+ indent(closure);
char *str = upb_byteregion_strdup(upb_value_getbyteregion(val));
- buffer_appendf(closure, "%" PRIu32 ":%s; ", upb_value_getuint32(fval), str);
+ output.appendf("%" PRIu32 ":%s\n", 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);
+ indent(closure);
+ output.appendf("%" PRIu32 ":{\n", upb_value_getuint32(fval));
+ return UPB_CONTINUE_WITH(((int*)closure) + 1);
}
upb_flow_t endsubmsg(void *closure, upb_value fval) {
- (void)fval;
- buffer_appendf(closure, "} ");
+ indent(closure);
+ output.append("}\n");
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);
+ indent(closure);
+ output.appendf("%" PRIu32 ":[\n", upb_value_getuint32(fval));
+ return UPB_CONTINUE_WITH(((int*)closure) + 1);
}
upb_flow_t endseq(void *closure, upb_value fval) {
- (void)fval;
- buffer_appendf(closure, "] ");
+ indent(closure);
+ output.append("]\n");
return UPB_CONTINUE;
}
+upb_flow_t startmsg(void *closure) {
+ indent(closure);
+ output.append("<\n");
+ return UPB_CONTINUE;
+}
+
+void endmsg(void *closure, upb_status *status) {
+ (void)status;
+ indent(closure);
+ output.append(">\n");
+}
+
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);
@@ -221,6 +294,9 @@ void reg_subm(upb_mhandlers *m, uint32_t num, upb_fieldtype_t type,
}
void reghandlers(upb_mhandlers *m) {
+ upb_mhandlers_setstartmsg(m, &startmsg);
+ upb_mhandlers_setendmsg(m, &endmsg);
+
// Register handlers for each type.
reg(m, UPB_TYPE(DOUBLE), &value_double);
reg(m, UPB_TYPE(FLOAT), &value_float);
@@ -267,7 +343,7 @@ size_t upb_seamsrc_avail(const upb_seamsrc *src, size_t ofs) {
}
upb_bytesuccess_t upb_seamsrc_fetch(void *_src, uint64_t ofs, size_t *read) {
- upb_seamsrc *src = _src;
+ upb_seamsrc *src = (upb_seamsrc*)_src;
assert(ofs < src->len);
if (ofs == src->len) {
upb_status_seteof(&src->bytesrc.status);
@@ -279,7 +355,7 @@ upb_bytesuccess_t upb_seamsrc_fetch(void *_src, uint64_t ofs, size_t *read) {
void upb_seamsrc_copy(const void *_src, uint64_t ofs,
size_t len, char *dst) {
- const upb_seamsrc *src = _src;
+ const upb_seamsrc *src = (const upb_seamsrc*)_src;
assert(ofs + len <= src->len);
memcpy(dst, src->str + ofs, len);
}
@@ -290,7 +366,7 @@ void upb_seamsrc_discard(void *src, uint64_t ofs) {
}
const char *upb_seamsrc_getptr(const void *_s, uint64_t ofs, size_t *len) {
- const upb_seamsrc *src = _s;
+ const upb_seamsrc *src = (const upb_seamsrc*)_s;
*len = upb_seamsrc_avail(src, ofs);
return src->str + ofs;
}
@@ -314,7 +390,7 @@ void upb_seamsrc_init(upb_seamsrc *s, const char *str, size_t len) {
}
void upb_seamsrc_resetseams(upb_seamsrc *s, size_t seam1, size_t seam2) {
- ASSERT(seam1 <= seam2);
+ assert(seam1 <= seam2);
s->seam1 = seam1;
s->seam2 = seam2;
s->byteregion.discard = 0;
@@ -337,83 +413,68 @@ upb_byteregion *upb_seamsrc_allbytes(upb_seamsrc *s) {
/* Running of test cases ******************************************************/
upb_decoderplan *plan;
-
-void run_decoder(buffer *proto, buffer *expected_output) {
+#define LINE(x) x "\n"
+void run_decoder(const buffer& proto, const buffer* expected_output) {
upb_seamsrc src;
- upb_seamsrc_init(&src, proto->buf, proto->len);
+ 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++) {
+ 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);
- buffer *output = buffer_new(0);
- upb_decoder_resetinput(&d, input, output);
+ output.clear();
+ upb_decoder_resetinput(&d, input, &closures[0]);
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);
+ 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 (!buffer_eql(output, expected_output)) {
+ if (!output.eql(*expected_output)) {
fprintf(stderr, "Text mismatch: '%s' vs '%s'\n",
- output->buf, expected_output->buf);
+ output.buf(), expected_output->buf());
}
- ASSERT(strcmp(output->buf, expected_output->buf) == 0);
+ ASSERT(output.eql(*expected_output));
} 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);
+ upb_seamsrc_uninit(&src);
}
-void assert_does_not_parse_at_eof(buffer *proto) {
- run_decoder(proto, NULL);
-}
+const static buffer thirty_byte_nop = buffer(cat(
+ tag(NOP_FIELD, UPB_WIRE_TYPE_DELIMITED), delim(buffer(30)) ));
-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;
+void assert_successful_parse(const buffer& proto,
+ const char *expected_fmt, ...) {
+ buffer expected_text;
+ va_list args;
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);
+ expected_text.vappendf(expected_fmt, args);
va_end(args);
- va_end(args2);
+ // 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.
+ run_decoder(proto, &expected_text);
+ run_decoder(cat( proto, thirty_byte_nop ), &expected_text);
}
-void assert_does_not_parse(buffer *proto) {
+void assert_does_not_parse_at_eof(const buffer& proto) {
+ run_decoder(proto, NULL);
+}
+
+void assert_does_not_parse(const 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 ));
+ assert_does_not_parse_at_eof(proto);
+ assert_does_not_parse_at_eof(cat( proto, thirty_byte_nop ));
}
@@ -421,19 +482,19 @@ void assert_does_not_parse(buffer *proto) {
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
+ static const buffer incompletes[6] = {
+ buffer("\x80"), // UPB_WIRE_TYPE_VARINT
+ buffer("abcdefg"), // UPB_WIRE_TYPE_64BIT
+ buffer("\x80"), // UPB_WIRE_TYPE_DELIMITED (partial length)
+ buffer(), // UPB_WIRE_TYPE_START_GROUP (no value required)
+ buffer(), // UPB_WIRE_TYPE_END_GROUP (no value required)
+ buffer("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];
+ int wire_type = upb_decoder_types[type].native_wire_type;
+ const buffer& incomplete = incompletes[wire_type];
// EOF before a known non-repeated value.
assert_does_not_parse_at_eof(tag(fieldnum, wire_type));
@@ -446,108 +507,128 @@ void test_premature_eof_for_type(upb_fieldtype_t type) {
// EOF inside a known non-repeated value.
assert_does_not_parse_at_eof(
- cat( tag(fieldnum, wire_type), buffer_new3(incomplete), NULL ));
+ cat( tag(fieldnum, wire_type), incomplete ));
// EOF inside a known repeated value.
assert_does_not_parse_at_eof(
- cat( tag(rep_fieldnum, wire_type), buffer_new3(incomplete), NULL ));
+ cat( tag(rep_fieldnum, wire_type), incomplete ));
// EOF inside an unknown value.
assert_does_not_parse_at_eof(
- cat( tag(UNKNOWN_FIELD, wire_type), buffer_new3(incomplete), NULL ));
+ cat( tag(UNKNOWN_FIELD, wire_type), incomplete ));
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 ));
+ cat( tag(fieldnum, wire_type), varint(1) ));
// 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 ));
+ cat( tag(rep_fieldnum, wire_type), varint(1) ));
// 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 ));
+ cat( tag(UNKNOWN_FIELD, wire_type), varint(1) ));
if (type == UPB_TYPE(MESSAGE)) {
// Submessage ends in the middle of a value.
- buffer *incomplete_submsg =
+ buffer incomplete_submsg =
cat ( tag(UPB_TYPE(INT32), UPB_WIRE_TYPE_VARINT),
- buffer_new3(incompletes[UPB_WIRE_TYPE_VARINT]), NULL );
+ incompletes[UPB_WIRE_TYPE_VARINT] );
assert_does_not_parse(
cat( tag(fieldnum, UPB_WIRE_TYPE_DELIMITED),
- varint(incomplete_submsg->len),
- incomplete_submsg, NULL ));
+ varint(incomplete_submsg.len()),
+ incomplete_submsg ));
}
} 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 ));
+ varint(incomplete.len()),
+ incomplete ));
// EOF in the middle of packed region.
assert_does_not_parse_at_eof(
- cat( tag(rep_fieldnum, UPB_WIRE_TYPE_DELIMITED), varint(1), NULL ));
+ cat( tag(rep_fieldnum, UPB_WIRE_TYPE_DELIMITED), varint(1) ));
}
}
// "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) {
+ const buffer& enc33, const buffer& enc66) {
uint32_t fieldnum = type;
uint32_t rep_fieldnum = rep_fn(type);
- int wire_type = upb_types[type].native_wire_type;
+ int wire_type = upb_decoder_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);
+ cat( tag(fieldnum, wire_type), enc33,
+ tag(fieldnum, wire_type), enc66 ),
+ LINE("<")
+ LINE("%u:33")
+ LINE("%u:66")
+ LINE(">"), 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);
+ cat( tag(rep_fieldnum, wire_type), enc33,
+ tag(rep_fieldnum, wire_type), enc66 ),
+ LINE("<")
+ LINE("%u:[")
+ LINE(" %u:33")
+ LINE(" %u:66")
+ LINE("]")
+ LINE(">"), 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);
+ delim(cat( enc33, enc66 )) ),
+ LINE("<")
+ LINE("%u:[")
+ LINE(" %u:33")
+ LINE(" %u:66")
+ LINE("]")
+ LINE(">"), rep_fieldnum, rep_fieldnum, rep_fieldnum);
}
void test_valid_data_for_signed_type(upb_fieldtype_t type,
- buffer *enc33, buffer *enc66) {
+ const buffer& enc33, const buffer& enc66) {
uint32_t fieldnum = type;
uint32_t rep_fieldnum = rep_fn(type);
- int wire_type = upb_types[type].native_wire_type;
+ int wire_type = upb_decoder_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);
+ cat( tag(fieldnum, wire_type), enc33,
+ tag(fieldnum, wire_type), enc66 ),
+ LINE("<")
+ LINE("%u:33")
+ LINE("%u:-66")
+ LINE(">"), 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);
+ cat( tag(rep_fieldnum, wire_type), enc33,
+ tag(rep_fieldnum, wire_type), enc66 ),
+ LINE("<")
+ LINE("%u:[")
+ LINE(" %u:33")
+ LINE(" %u:-66")
+ LINE("]")
+ LINE(">"), 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);
+ delim(cat( enc33, enc66 )) ),
+ LINE("<")
+ LINE("%u:[")
+ LINE(" %u:33")
+ LINE(" %u:-66")
+ LINE("]")
+ LINE(">"), rep_fieldnum, rep_fieldnum, rep_fieldnum);
}
// Test that invalid protobufs are properly detected (without crashing) and
@@ -571,7 +652,7 @@ void test_invalid() {
test_premature_eof_for_type(UPB_TYPE(SINT64));
// EOF inside a tag's varint.
- assert_does_not_parse_at_eof( buffer_new3("\x80") );
+ assert_does_not_parse_at_eof( buffer("\x80") );
// EOF inside a known group.
assert_does_not_parse_at_eof( tag(4, UPB_WIRE_TYPE_START_GROUP) );
@@ -584,33 +665,19 @@ void test_invalid() {
// Field number is 0.
assert_does_not_parse(
- cat( tag(0, UPB_WIRE_TYPE_DELIMITED), varint(0), NULL ));
+ cat( tag(0, UPB_WIRE_TYPE_DELIMITED), varint(0) ));
// Field number is too large.
assert_does_not_parse(
cat( tag(UPB_MAX_FIELDNUMBER + 1, UPB_WIRE_TYPE_DELIMITED),
- varint(0), NULL ));
+ varint(0) ));
// Test exceeding the resource limit of stack depth.
- buffer *buf = buffer_new3("");
+ buffer buf;
for (int i = 0; i < UPB_MAX_NESTING; i++) {
- buf = submsg(UPB_TYPE(MESSAGE), buf);
+ buf.assign(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() {
@@ -629,16 +696,80 @@ void test_valid() {
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 implicit startseq/endseq.
+ uint32_t repfl_fn = rep_fn(UPB_TYPE(FLOAT));
+ uint32_t repdb_fn = rep_fn(UPB_TYPE(DOUBLE));
+ assert_successful_parse(
+ cat( tag(repfl_fn, UPB_WIRE_TYPE_32BIT), flt(33),
+ tag(repdb_fn, UPB_WIRE_TYPE_64BIT), dbl(66) ),
+ LINE("<")
+ LINE("%u:[")
+ LINE(" %u:33")
+ LINE("]")
+ LINE("%u:[")
+ LINE(" %u:66")
+ LINE("]")
+ LINE(">"), repfl_fn, repfl_fn, repdb_fn, repdb_fn);
+
// 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);
+ submsg(msg_fn, submsg(msg_fn, submsg(msg_fn, buffer()))),
+ LINE("<")
+ LINE("%u:{")
+ LINE(" <")
+ LINE(" %u:{")
+ LINE(" <")
+ LINE(" %u:{")
+ LINE(" <")
+ LINE(" >")
+ LINE(" }")
+ LINE(" >")
+ LINE(" }")
+ LINE(" >")
+ LINE("}")
+ LINE(">"), 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);
+ submsg(repm_fn, submsg(repm_fn, buffer())),
+ LINE("<")
+ LINE("%u:[")
+ LINE(" %u:{")
+ LINE(" <")
+ LINE(" %u:[")
+ LINE(" %u:{")
+ LINE(" <")
+ LINE(" >")
+ LINE(" }")
+ LINE(" ]")
+ LINE(" >")
+ LINE(" }")
+ LINE("]")
+ LINE(">"), repm_fn, repm_fn, repm_fn, repm_fn);
+
+ // Staying within the stack limit should work properly.
+ buffer buf;
+ buffer textbuf;
+ int total = UPB_MAX_NESTING - 1;
+ for (int i = 0; i < total; i++) {
+ buf.assign(submsg(UPB_TYPE(MESSAGE), buf));
+ indentbuf(&textbuf, i);
+ textbuf.append("<\n");
+ indentbuf(&textbuf, i);
+ textbuf.appendf("%u:{\n", UPB_TYPE(MESSAGE));
+ }
+ indentbuf(&textbuf, total);
+ textbuf.append("<\n");
+ indentbuf(&textbuf, total);
+ textbuf.append(">\n");
+ for (int i = 0; i < total; i++) {
+ indentbuf(&textbuf, total - i - 1);
+ textbuf.append("}\n");
+ indentbuf(&textbuf, total - i - 1);
+ textbuf.append(">\n");
+ }
+ assert_successful_parse(buf, "%s", textbuf.buf());
}
void run_tests() {
@@ -647,10 +778,17 @@ void run_tests() {
}
int main() {
+ for (int i = 0; i < UPB_MAX_NESTING; i++) {
+ closures[i] = i;
+ }
// Construct decoder plan.
upb_handlers *h = upb_handlers_new();
reghandlers(upb_handlers_newmhandlers(h));
+ // Create an empty handlers to make sure that the decoder can handle empty
+ // messages.
+ upb_handlers_newmhandlers(h);
+
// Test without JIT.
plan = upb_decoderplan_new(h, false);
run_tests();
@@ -658,6 +796,11 @@ int main() {
// Test JIT.
plan = upb_decoderplan_new(h, true);
+#ifdef UPB_USE_JIT_X64
+ ASSERT(upb_decoderplan_hasjitcode(plan));
+#else
+ ASSERT(!upb_decoderplan_hasjitcode(plan));
+#endif
run_tests();
upb_decoderplan_unref(plan);
diff --git a/tests/test_def.c b/tests/test_def.c
index 3ca3064..698532e 100644
--- a/tests/test_def.c
+++ b/tests/test_def.c
@@ -1,19 +1,174 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2011 Google Inc. See LICENSE for details.
+ *
+ * Test of defs and symtab. There should be far more tests of edge conditions
+ * (like attempts to link defs that don't have required properties set).
+ */
-#undef NDEBUG /* ensure tests always assert. */
#include "upb/def.h"
+#include "upb/pb/glue.h"
+#include "upb_test.h"
#include <stdlib.h>
+#include <string.h>
-int main() {
- upb_symtab *s = upb_symtab_new();
+const char *descriptor_file;
- // Will be empty atm since we haven't added anything to the symtab.
+static void test_empty_symtab() {
+ upb_symtab *s = upb_symtab_new();
int count;
- const upb_def **defs = upb_symtab_getdefs(s, &count, UPB_DEF_ANY);
- for (int i = 0; i < count; i++) {
- upb_def_unref(defs[i]);
- }
+ const upb_def **defs = upb_symtab_getdefs(s, &count, UPB_DEF_ANY, NULL);
+ ASSERT(count == 0);
free(defs);
+ upb_symtab_unref(s);
+}
+static upb_symtab *load_test_proto() {
+ upb_symtab *s = upb_symtab_new();
+ ASSERT(s);
+ upb_status status = UPB_STATUS_INIT;
+ if (!upb_load_descriptor_file_into_symtab(s, descriptor_file, &status)) {
+ fprintf(stderr, "Error loading descriptor file: %s\n",
+ upb_status_getstr(&status));
+ exit(1);
+ }
+ upb_status_uninit(&status);
+ return s;
+}
+
+static void test_cycles() {
+ upb_symtab *s = load_test_proto();
+
+ // Test cycle detection by making a cyclic def's main refcount go to zero
+ // and then be incremented to one again.
+ const upb_def *def = upb_symtab_lookup(s, "A", &def);
+ ASSERT(def);
+ ASSERT(upb_def_isfinalized(def));
upb_symtab_unref(s);
+
+ // Message A has only one subfield: "optional B b = 1".
+ const upb_msgdef *m = upb_downcast_msgdef_const(def);
+ upb_fielddef *f = upb_msgdef_itof(m, 1);
+ ASSERT(f);
+ ASSERT(upb_hassubdef(f));
+ const upb_def *def2 = upb_fielddef_subdef(f);
+ ASSERT(upb_downcast_msgdef_const(def2));
+ ASSERT(strcmp(upb_def_fullname(def2), "B") == 0);
+
+ upb_def_ref(def2, &def2);
+ upb_def_unref(def, &def);
+ upb_def_unref(def2, &def2);
+}
+
+static void test_fielddef_unref() {
+ upb_symtab *s = load_test_proto();
+ const upb_msgdef *md = upb_symtab_lookupmsg(s, "A", &md);
+ upb_fielddef *f = upb_msgdef_itof(md, 1);
+ upb_fielddef_ref(f, &f);
+
+ // Unref symtab and msgdef; now fielddef is the only thing keeping the msgdef
+ // alive.
+ upb_symtab_unref(s);
+ upb_msgdef_unref(md, &md);
+ // Check that md is still alive.
+ ASSERT(strcmp(upb_def_fullname(UPB_UPCAST(md)), "A") == 0);
+
+ // Check that unref of fielddef frees the whole remaining graph.
+ upb_fielddef_unref(f, &f);
+}
+
+static void test_fielddef_accessors() {
+ upb_fielddef *f1 = upb_fielddef_new(&f1);
+ upb_fielddef *f2 = upb_fielddef_new(&f2);
+
+ ASSERT(upb_fielddef_ismutable(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));
+ ASSERT(upb_fielddef_number(f1) == 1937);
+
+ ASSERT(upb_fielddef_ismutable(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));
+ ASSERT(upb_fielddef_number(f2) == 1572);
+
+ upb_fielddef_unref(f1, &f1);
+ upb_fielddef_unref(f2, &f2);
+}
+
+static upb_fielddef *newfield(
+ const char *name, int32_t num, uint8_t type, uint8_t label,
+ const char *type_name, void *owner) {
+ upb_fielddef *f = upb_fielddef_new(owner);
+ upb_fielddef_setname(f, name);
+ upb_fielddef_setnumber(f, num);
+ upb_fielddef_settype(f, type);
+ upb_fielddef_setlabel(f, label);
+ upb_fielddef_setsubtypename(f, type_name);
+ return f;
+}
+
+static upb_msgdef *upb_msgdef_newnamed(const char *name, void *owner) {
+ upb_msgdef *m = upb_msgdef_new(owner);
+ upb_def_setfullname(UPB_UPCAST(m), name);
+ return m;
+}
+
+INLINE 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;
+}
+
+void test_replacement() {
+ upb_symtab *s = upb_symtab_new();
+
+ upb_msgdef *m = upb_msgdef_newnamed("MyMessage", &s);
+ upb_msgdef_addfield(m, newfield(
+ "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);
+
+ upb_def *newdefs[] = {UPB_UPCAST(m), UPB_UPCAST(m2), UPB_UPCAST(e)};
+ upb_status status = UPB_STATUS_INIT;
+ ASSERT_STATUS(upb_symtab_add(s, newdefs, 3, &s, &status), &status);
+
+ // Try adding a new definition of MyEnum, MyMessage should get replaced with
+ // a new version.
+ upb_enumdef *e2 = upb_enumdef_new(&s);
+ upb_def_setfullname(UPB_UPCAST(e2), "MyEnum");
+ upb_def *newdefs2[] = {UPB_UPCAST(e2)};
+ ASSERT_STATUS(upb_symtab_add(s, newdefs2, 1, &s, &status), &status);
+
+ const upb_msgdef *m3 = upb_symtab_lookupmsg(s, "MyMessage", &m3);
+ ASSERT(m3);
+ // Must be different because it points to MyEnum which was replaced.
+ ASSERT(m3 != m);
+ upb_msgdef_unref(m3, &m3);
+
+ m3 = upb_symtab_lookupmsg(s, "MyMessage2", &m3);
+ // Should be the same because it was not replaced, nor were any defs that
+ // are reachable from it.
+ ASSERT(m3 == m2);
+ upb_msgdef_unref(m3, &m3);
+
+ upb_symtab_unref(s);
+}
+
+int main(int argc, char *argv[]) {
+ if (argc < 2) {
+ fprintf(stderr, "Usage: test_def <test.proto.pb>\n");
+ return 1;
+ }
+ descriptor_file = argv[1];
+ test_empty_symtab();
+ test_cycles();
+ test_fielddef_accessors();
+ test_fielddef_unref();
+ test_replacement();
return 0;
}
diff --git a/tests/test_table.cc b/tests/test_table.cc
index 47e083f..2538e35 100644
--- a/tests/test_table.cc
+++ b/tests/test_table.cc
@@ -1,8 +1,11 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2012 Google Inc. See LICENSE for details.
+ *
+ * Tests for upb_table.
+ */
-#undef NDEBUG /* ensure tests always assert. */
-#include "upb/table.h"
-#include "test_util.h"
-#include <assert.h>
#include <string.h>
#include <sys/resource.h>
#include <ext/hash_map>
@@ -11,55 +14,45 @@
#include <set>
#include <string>
#include <vector>
+#include "tests/test_util.h"
+#include "tests/upb_test.h"
+#include "upb/table.h"
bool benchmark = false;
#define CPU_TIME_PER_TEST 0.5
using std::vector;
-typedef struct {
- uint32_t value; /* key*2 */
-} inttable_entry;
-
-typedef struct {
- int32_t value; /* ASCII Value of first letter */
-} strtable_entry;
-
-double get_usertime()
-{
+double get_usertime() {
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
return usage.ru_utime.tv_sec + (usage.ru_utime.tv_usec/1000000.0);
}
/* num_entries must be a power of 2. */
-void test_strtable(const vector<std::string>& keys, uint32_t num_to_insert)
-{
+void test_strtable(const vector<std::string>& keys, uint32_t num_to_insert) {
/* Initialize structures. */
upb_strtable table;
std::map<std::string, int32_t> m;
- upb_strtable_init(&table, 0, sizeof(strtable_entry));
+ upb_strtable_init(&table);
std::set<std::string> all;
for(size_t i = 0; i < num_to_insert; i++) {
const std::string& key = keys[i];
all.insert(key);
- strtable_entry e;
- e.value = key[0];
- upb_strtable_insert(&table, key.c_str(), &e);
+ upb_strtable_insert(&table, key.c_str(), upb_value_int32(key[0]));
m[key] = key[0];
}
/* Test correctness. */
for(uint32_t i = 0; i < keys.size(); i++) {
const std::string& key = keys[i];
- strtable_entry *e =
- (strtable_entry*)upb_strtable_lookup(&table, key.c_str());
+ const upb_value *v = upb_strtable_lookup(&table, key.c_str());
if(m.find(key) != m.end()) { /* Assume map implementation is correct. */
- assert(e);
- assert(e->value == key[0]);
- assert(m[key] == key[0]);
+ ASSERT(v);
+ ASSERT(upb_value_getint32(*v) == key[0]);
+ ASSERT(m[key] == key[0]);
} else {
- assert(e == NULL);
+ ASSERT(v == NULL);
}
}
@@ -69,66 +62,83 @@ void test_strtable(const vector<std::string>& keys, uint32_t num_to_insert)
const char *key = upb_strtable_iter_key(&iter);
std::string tmp(key, strlen(key));
std::set<std::string>::iterator i = all.find(tmp);
- assert(i != all.end());
+ ASSERT(i != all.end());
all.erase(i);
}
- assert(all.empty());
+ ASSERT(all.empty());
- upb_strtable_free(&table);
+ upb_strtable_uninit(&table);
}
/* num_entries must be a power of 2. */
-void test_inttable(int32_t *keys, uint16_t num_entries, const char *desc)
-{
+void test_inttable(int32_t *keys, uint16_t num_entries, const char *desc) {
/* Initialize structures. */
upb_inttable table;
uint32_t largest_key = 0;
std::map<uint32_t, uint32_t> m;
__gnu_cxx::hash_map<uint32_t, uint32_t> hm;
- upb_inttable_init(&table, num_entries, sizeof(inttable_entry));
+ upb_inttable_init(&table);
for(size_t i = 0; i < num_entries; i++) {
int32_t key = keys[i];
largest_key = UPB_MAX((int32_t)largest_key, key);
- inttable_entry e;
- e.value = (key*2) << 1;
- upb_inttable_insert(&table, key, &e);
+ upb_inttable_insert(&table, key, upb_value_uint32(key * 2));
m[key] = key*2;
hm[key] = key*2;
}
/* Test correctness. */
for(uint32_t i = 0; i <= largest_key; i++) {
- inttable_entry *e = (inttable_entry*)upb_inttable_lookup(
- &table, i);
+ const upb_value *v = upb_inttable_lookup(&table, i);
+ if(m.find(i) != m.end()) { /* Assume map implementation is correct. */
+ ASSERT(v);
+ ASSERT(upb_value_getuint32(*v) == i*2);
+ ASSERT(m[i] == i*2);
+ ASSERT(hm[i] == i*2);
+ } else {
+ ASSERT(v == NULL);
+ }
+ }
+
+ for(uint16_t i = 0; i < num_entries; i += 2) {
+ upb_value val;
+ bool ret = upb_inttable_remove(&table, keys[i], &val);
+ ASSERT(ret == (m.erase(keys[i]) == 1));
+ if (ret) ASSERT(upb_value_getuint32(val) == keys[i] * 2);
+ hm.erase(keys[i]);
+ m.erase(keys[i]);
+ }
+
+ ASSERT(upb_inttable_count(&table) == hm.size());
+
+ /* Test correctness. */
+ for(uint32_t i = 0; i <= largest_key; i++) {
+ const upb_value *v = upb_inttable_lookup(&table, i);
if(m.find(i) != m.end()) { /* Assume map implementation is correct. */
- assert(e);
- //printf("addr: %p, expected: %d, actual: %d\n", e, i*2, e->value);
- assert(((e->value) >> 1) == i*2);
- assert(m[i] == i*2);
- assert(hm[i] == i*2);
+ ASSERT(v);
+ ASSERT(upb_value_getuint32(*v) == i*2);
+ ASSERT(m[i] == i*2);
+ ASSERT(hm[i] == i*2);
} else {
- assert(e == NULL);
+ ASSERT(v == NULL);
}
}
// Compact and test correctness again.
upb_inttable_compact(&table);
for(uint32_t i = 0; i <= largest_key; i++) {
- inttable_entry *e = (inttable_entry*)upb_inttable_lookup(
- &table, i);
+ const upb_value *v = upb_inttable_lookup(&table, i);
if(m.find(i) != m.end()) { /* Assume map implementation is correct. */
- assert(e);
- //printf("addr: %p, expected: %d, actual: %d\n", e, i*2, e->value);
- assert(((e->value) >> 1) == i*2);
- assert(m[i] == i*2);
- assert(hm[i] == i*2);
+ ASSERT(v);
+ ASSERT(upb_value_getuint32(*v) == i*2);
+ ASSERT(m[i] == i*2);
+ ASSERT(hm[i] == i*2);
} else {
- assert(e == NULL);
+ ASSERT(v == NULL);
}
}
if(!benchmark) {
- upb_inttable_free(&table);
+ upb_inttable_uninit(&table);
return;
}
@@ -141,7 +151,7 @@ void test_inttable(int32_t *keys, uint16_t num_entries, const char *desc)
}
for(uint16_t i = num_entries - 1; i >= 1; i--) {
uint16_t rand_i = (random() / (double)RAND_MAX) * i;
- assert(rand_i <= i);
+ ASSERT(rand_i <= i);
uint16_t tmp = rand_order[rand_i];
rand_order[rand_i] = rand_order[i];
rand_order[i] = tmp;
@@ -162,8 +172,8 @@ 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];
- inttable_entry *e = (inttable_entry*)upb_inttable_lookup(&table, key);
- x += (uintptr_t)e;
+ const upb_value *v = upb_inttable_lookup32(&table, key);
+ x += (uintptr_t)v;
}
double total = get_usertime() - before;
printf("%s/s\n", eng(i/total, 3, false));
@@ -174,8 +184,8 @@ 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]];
- inttable_entry *e = (inttable_entry*)upb_inttable_lookup(&table, key);
- x += (uintptr_t)e;
+ const upb_value *v = upb_inttable_lookup32(&table, key);
+ x += (uintptr_t)v;
}
total = get_usertime() - before;
printf("%s/s\n", eng(i/total, 3, false));
@@ -223,20 +233,18 @@ void test_inttable(int32_t *keys, uint16_t num_entries, const char *desc)
}
total = get_usertime() - before;
printf("%s/s\n\n", eng(i/total, 3, false));
- upb_inttable_free(&table);
+ upb_inttable_uninit(&table);
delete rand_order;
}
-int32_t *get_contiguous_keys(int32_t num)
-{
+int32_t *get_contiguous_keys(int32_t num) {
int32_t *buf = new int32_t[num];
for(int32_t i = 0; i < num; i++)
- buf[i] = i+1;
+ buf[i] = i;
return buf;
}
-int main(int argc, char *argv[])
-{
+int main(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--benchmark") == 0) benchmark = true;
}
diff --git a/tests/test_vs_proto2.cc b/tests/test_vs_proto2.cc
index 53b2498..020dca5 100644
--- a/tests/test_vs_proto2.cc
+++ b/tests/test_vs_proto2.cc
@@ -1,7 +1,7 @@
/*
* upb - a minimalist implementation of protocol buffers.
*
- * Copyright (c) 2011 Google Inc. See LICENSE for details.
+ * Copyright (c) 2011-2012 Google Inc. See LICENSE for details.
*
* A test that verifies that our results are identical to proto2 for a
* given proto type and input protobuf.
@@ -9,230 +9,87 @@
#define __STDC_LIMIT_MACROS // So we get UINT32_MAX
#include <assert.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/wire_format_lite.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/wire_format_lite.h>
#include "benchmarks/google_messages.pb.h"
-#include "upb/def.h"
-#include "upb/msg.h"
+#include "upb/def.hpp"
+#include "upb/handlers.hpp"
+#include "upb/msg.hpp"
+#include "upb/pb/decoder.hpp"
#include "upb/pb/glue.h"
#include "upb/pb/varint.h"
+#include "upb/proto2_bridge.hpp"
#include "upb_test.h"
-size_t string_size;
-
-void compare(const google::protobuf::Message& proto2_msg,
- void *upb_msg, const upb_msgdef *upb_md);
-
-void compare_arrays(const google::protobuf::Reflection *r,
- const google::protobuf::Message& proto2_msg,
- const google::protobuf::FieldDescriptor *proto2_f,
- void *upb_msg, upb_fielddef *upb_f)
-{
- ASSERT(upb_msg_has(upb_msg, upb_f));
- ASSERT(upb_isseq(upb_f));
- const void *arr = upb_value_getptr(upb_msg_getseq(upb_msg, upb_f));
- const void *iter = upb_seq_begin(arr, upb_f);
- for(int i = 0;
- i < r->FieldSize(proto2_msg, proto2_f);
- i++, iter = upb_seq_next(arr, iter, upb_f)) {
- ASSERT(!upb_seq_done(iter));
- upb_value v = upb_seq_get(iter, upb_f);
- switch(upb_f->type) {
- default:
- ASSERT(false);
- case UPB_TYPE(DOUBLE):
- ASSERT(r->GetRepeatedDouble(proto2_msg, proto2_f, i) == upb_value_getdouble(v));
- break;
- case UPB_TYPE(FLOAT):
- ASSERT(r->GetRepeatedFloat(proto2_msg, proto2_f, i) == upb_value_getfloat(v));
- break;
- case UPB_TYPE(INT64):
- case UPB_TYPE(SINT64):
- case UPB_TYPE(SFIXED64):
- ASSERT(r->GetRepeatedInt64(proto2_msg, proto2_f, i) == upb_value_getint64(v));
- break;
- case UPB_TYPE(UINT64):
- case UPB_TYPE(FIXED64):
- ASSERT(r->GetRepeatedUInt64(proto2_msg, proto2_f, i) == upb_value_getuint64(v));
- break;
- case UPB_TYPE(SFIXED32):
- case UPB_TYPE(SINT32):
- case UPB_TYPE(INT32):
- case UPB_TYPE(ENUM):
- ASSERT(r->GetRepeatedInt32(proto2_msg, proto2_f, i) == upb_value_getint32(v));
- break;
- case UPB_TYPE(FIXED32):
- case UPB_TYPE(UINT32):
- ASSERT(r->GetRepeatedUInt32(proto2_msg, proto2_f, i) == upb_value_getuint32(v));
- break;
- case UPB_TYPE(BOOL):
- ASSERT(r->GetRepeatedBool(proto2_msg, proto2_f, i) == upb_value_getbool(v));
- break;
- case UPB_TYPE(STRING):
- case UPB_TYPE(BYTES): {
- std::string str = r->GetRepeatedString(proto2_msg, proto2_f, i);
- upb_stdarray *upbstr = (upb_stdarray*)upb_value_getptr(v);
- std::string str2(upbstr->ptr, upbstr->len);
- string_size += upbstr->len;
- ASSERT(str == str2);
- break;
- }
- case UPB_TYPE(GROUP):
- case UPB_TYPE(MESSAGE):
- ASSERT(upb_dyncast_msgdef(upb_f->def) != NULL);
- compare(r->GetRepeatedMessage(proto2_msg, proto2_f, i),
- upb_value_getptr(v), upb_downcast_msgdef(upb_f->def));
- }
- }
- ASSERT(upb_seq_done(iter));
-}
-
-void compare_values(const google::protobuf::Reflection *r,
- const google::protobuf::Message& proto2_msg,
- const google::protobuf::FieldDescriptor *proto2_f,
- void *upb_msg, upb_fielddef *upb_f)
-{
- upb_value v = upb_msg_get(upb_msg, upb_f);
- switch(upb_f->type) {
- default:
- ASSERT(false);
- case UPB_TYPE(DOUBLE):
- ASSERT(r->GetDouble(proto2_msg, proto2_f) == upb_value_getdouble(v));
- break;
- case UPB_TYPE(FLOAT):
- ASSERT(r->GetFloat(proto2_msg, proto2_f) == upb_value_getfloat(v));
- break;
- case UPB_TYPE(INT64):
- case UPB_TYPE(SINT64):
- case UPB_TYPE(SFIXED64):
- ASSERT(r->GetInt64(proto2_msg, proto2_f) == upb_value_getint64(v));
- break;
- case UPB_TYPE(UINT64):
- case UPB_TYPE(FIXED64):
- ASSERT(r->GetUInt64(proto2_msg, proto2_f) == upb_value_getuint64(v));
- break;
- case UPB_TYPE(SFIXED32):
- case UPB_TYPE(SINT32):
- case UPB_TYPE(INT32):
- case UPB_TYPE(ENUM):
- ASSERT(r->GetInt32(proto2_msg, proto2_f) == upb_value_getint32(v));
- break;
- case UPB_TYPE(FIXED32):
- case UPB_TYPE(UINT32):
- ASSERT(r->GetUInt32(proto2_msg, proto2_f) == upb_value_getuint32(v));
- break;
- case UPB_TYPE(BOOL):
- ASSERT(r->GetBool(proto2_msg, proto2_f) == upb_value_getbool(v));
- break;
- case UPB_TYPE(STRING):
- case UPB_TYPE(BYTES): {
- std::string str = r->GetString(proto2_msg, proto2_f);
- upb_stdarray *upbstr = (upb_stdarray*)upb_value_getptr(v);
- std::string str2(upbstr->ptr, upbstr->len);
- string_size += upbstr->len;
- ASSERT(str == str2);
- break;
- }
- case UPB_TYPE(GROUP):
- case UPB_TYPE(MESSAGE):
- // XXX: getstr
- compare(r->GetMessage(proto2_msg, proto2_f),
- upb_value_getptr(v), upb_downcast_msgdef(upb_f->def));
- }
-}
-
-void compare(const google::protobuf::Message& proto2_msg,
- void *upb_msg, const upb_msgdef *upb_md)
-{
- const google::protobuf::Reflection *r = proto2_msg.GetReflection();
- const google::protobuf::Descriptor *d = proto2_msg.GetDescriptor();
-
- ASSERT(d->field_count() == upb_msgdef_numfields(upb_md));
- upb_msg_iter i;
- for(i = upb_msg_begin(upb_md); !upb_msg_done(i); i = upb_msg_next(upb_md, i)) {
- upb_fielddef *upb_f = upb_msg_iter_field(i);
+void compare_metadata(const google::protobuf::Descriptor* d,
+ const upb::MessageDef *upb_md) {
+ ASSERT(d->field_count() == upb_md->field_count());
+ for (upb::MessageDef::ConstIterator i(upb_md); !i.Done(); i.Next()) {
+ const upb::FieldDef* upb_f = i.field();
const google::protobuf::FieldDescriptor *proto2_f =
- d->FindFieldByNumber(upb_f->number);
- // Make sure the definitions are equal.
+ d->FindFieldByNumber(upb_f->number());
ASSERT(upb_f);
ASSERT(proto2_f);
- ASSERT(upb_f->number == proto2_f->number());
- ASSERT(std::string(upb_f->name) == proto2_f->name());
- ASSERT(upb_f->type == proto2_f->type());
- ASSERT(upb_isseq(upb_f) == proto2_f->is_repeated());
-
- if(!upb_msg_has(upb_msg, upb_f)) {
- if(upb_isseq(upb_f))
- ASSERT(r->FieldSize(proto2_msg, proto2_f) == 0);
- else
- ASSERT(r->HasField(proto2_msg, proto2_f) == false);
- } else {
- if(upb_isseq(upb_f)) {
- compare_arrays(r, proto2_msg, proto2_f, upb_msg, upb_f);
- } else {
- ASSERT(r->HasField(proto2_msg, proto2_f) == true);
- compare_values(r, proto2_msg, proto2_f, upb_msg, upb_f);
- }
- }
+ ASSERT(upb_f->number() == proto2_f->number());
+ ASSERT(std::string(upb_f->name()) == proto2_f->name());
+ ASSERT(upb_f->type() == static_cast<upb::FieldType>(proto2_f->type()));
+ ASSERT(upb_f->IsSequence() == proto2_f->is_repeated());
}
}
-void parse_and_compare(MESSAGE_CIDENT *proto2_msg,
- void *upb_msg, const upb_msgdef *upb_md,
- const char *str, size_t len, bool allow_jit)
-{
+void parse_and_compare(MESSAGE_CIDENT *msg1, MESSAGE_CIDENT *msg2,
+ const upb::MessageDef *upb_md,
+ const char *str, size_t len, bool allow_jit) {
// Parse to both proto2 and upb.
- ASSERT(proto2_msg->ParseFromArray(str, len));
- upb_status status = UPB_STATUS_INIT;
- upb_msg_clear(upb_msg, upb_md);
- upb_strtomsg(str, len, upb_msg, upb_md, allow_jit, &status);
- if (!upb_ok(&status)) {
- fprintf(stderr, "Error parsing protobuf: %s", upb_status_getstr(&status));
- exit(1);
- }
- string_size = 0;
- compare(*proto2_msg, upb_msg, upb_md);
- printf("Total size: %zd, string size: %zd (%0.2f%%)\n", len,
- string_size, (double)string_size / len * 100);
- upb_status_uninit(&status);
+ ASSERT(msg1->ParseFromArray(str, len));
+
+ upb::Handlers* handlers = upb::Handlers::New();
+ upb::RegisterWriteHandlers(handlers, upb_md);
+ upb::DecoderPlan* plan = upb::DecoderPlan::New(handlers, allow_jit);
+ upb::StringSource src(str, len);
+ upb::Decoder decoder;
+ decoder.ResetPlan(plan, 0);
+ decoder.ResetInput(src.AllBytes(), msg2);
+ msg2->Clear();
+ ASSERT(decoder.Decode() == UPB_OK);
+ plan->Unref();
+ handlers->Unref();
+
+ // Would like to just compare the message objects themselves, but
+ // unfortunately MessageDifferencer is not part of the open-source release of
+ // proto2, so we compare their serialized strings, which we expect will be
+ // equivalent.
+ std::string str1;
+ std::string str2;
+ msg1->SerializeToString(&str1);
+ msg2->SerializeToString(&str2);
+ ASSERT(str1 == str2);
+ ASSERT(std::string(str, len) == str2);
}
-int main(int argc, char *argv[])
-{
- if (argc < 3) {
- fprintf(stderr, "Usage: test_vs_proto2 <descriptor file> <message file>\n");
- return 1;
+void test_zig_zag() {
+ for (uint64_t num = 5; num * 1.5 > num; num *= 1.5) {
+ ASSERT(upb_zzenc_64(num) ==
+ google::protobuf::internal::WireFormatLite::ZigZagEncode64(num));
+ if (num < UINT32_MAX) {
+ ASSERT(upb_zzenc_32(num) ==
+ google::protobuf::internal::WireFormatLite::ZigZagEncode32(num));
+ }
}
- const char *descriptor_file = argv[1];
- const char *message_file = argv[2];
- // Initialize upb state, parse descriptor.
- upb_status status = UPB_STATUS_INIT;
- upb_symtab *symtab = upb_symtab_new();
- size_t fds_len;
- const char *fds = upb_readfile(descriptor_file, &fds_len);
- if(fds == NULL) {
- fprintf(stderr, "Couldn't read %s.\n", descriptor_file);
- return 1;
- }
- upb_load_descriptor_into_symtab(symtab, fds, fds_len, &status);
- if(!upb_ok(&status)) {
- fprintf(stderr, "Error importing %s: %s", descriptor_file,
- upb_status_getstr(&status));
- return 1;
- }
- free((void*)fds);
+}
- const upb_def *def = upb_symtab_lookup(symtab, MESSAGE_NAME);
- const upb_msgdef *msgdef;
- if(!def || !(msgdef = upb_dyncast_msgdef_const(def))) {
- fprintf(stderr, "Error finding symbol '%s'.\n", MESSAGE_NAME);
+int main(int argc, char *argv[])
+{
+ if (argc < 2) {
+ fprintf(stderr, "Usage: test_vs_proto2 <message file>\n");
return 1;
}
+ const char *message_file = argv[1];
// Read the message data itself.
size_t len;
@@ -242,32 +99,25 @@ int main(int argc, char *argv[])
return 1;
}
+ MESSAGE_CIDENT msg1;
+ MESSAGE_CIDENT msg2;
+
+ const upb::MessageDef* m = upb::proto2_bridge::NewFinalMessageDef(msg1, &m);
+
+ compare_metadata(msg1.GetDescriptor(), m);
+
// Run twice to test proper object reuse.
- MESSAGE_CIDENT proto2_msg;
- void *upb_msg = upb_stdmsg_new(msgdef);
- parse_and_compare(&proto2_msg, upb_msg, msgdef, str, len, true);
- parse_and_compare(&proto2_msg, upb_msg, msgdef, str, len, false);
- parse_and_compare(&proto2_msg, upb_msg, msgdef, str, len, true);
- parse_and_compare(&proto2_msg, upb_msg, msgdef, str, len, false);
+ parse_and_compare(&msg1, &msg2, m, str, len, true);
+ parse_and_compare(&msg1, &msg2, m, str, len, false);
+ parse_and_compare(&msg1, &msg2, m, str, len, true);
+ parse_and_compare(&msg1, &msg2, m, str, len, false);
printf("All tests passed, %d assertions.\n", num_assertions);
- upb_stdmsg_free(upb_msg, msgdef);
- upb_def_unref(UPB_UPCAST(msgdef));
+ m->Unref(&m);
free((void*)str);
- upb_symtab_unref(symtab);
- upb_status_uninit(&status);
- // Test Zig-Zag encoding/decoding.
- for (uint64_t num = 5; num * 1.5 > num; num *= 1.5) {
- ASSERT(upb_zzenc_64(num) ==
- google::protobuf::internal::WireFormatLite::ZigZagEncode64(num));
- if (num < UINT32_MAX) {
- ASSERT(upb_zzenc_32(num) ==
- google::protobuf::internal::WireFormatLite::ZigZagEncode32(num));
- }
- }
+ test_zig_zag();
google::protobuf::ShutdownProtobufLibrary();
-
return 0;
}
diff --git a/tests/tests.c b/tests/tests.c
deleted file mode 100644
index 12ff4bb..0000000
--- a/tests/tests.c
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "upb/def.h"
-#include "upb/handlers.h"
-#include "upb/pb/decoder.h"
-#include "upb/pb/glue.h"
-#include "upb_test.h"
-
-const char *descriptor_file;
-
-static upb_symtab *load_test_proto() {
- upb_symtab *s = upb_symtab_new();
- ASSERT(s);
- upb_status status = UPB_STATUS_INIT;
- if (!upb_load_descriptor_file_into_symtab(s, descriptor_file, &status)) {
- fprintf(stderr, "Error loading descriptor file: %s\n",
- upb_status_getstr(&status));
- exit(1);
- }
- upb_status_uninit(&status);
- return s;
-}
-
-static upb_flow_t upb_test_onvalue(void *c, upb_value fval, upb_value val) {
- (void)c;
- (void)fval;
- (void)val;
- return UPB_CONTINUE;
-}
-
-static void test_upb_jit() {
- upb_symtab *s = load_test_proto();
- const upb_def *def = upb_symtab_lookup(s, "SimplePrimitives");
- ASSERT(def);
-
- upb_handlers *h = upb_handlers_new();
- upb_handlerset hset = {NULL, NULL, &upb_test_onvalue, NULL, NULL, NULL, NULL};
- upb_handlers_reghandlerset(h, upb_downcast_msgdef_const(def), &hset);
- upb_decoderplan *p = upb_decoderplan_new(h, true);
-#ifdef UPB_USE_JIT_X64
- ASSERT(upb_decoderplan_hasjitcode(p));
-#else
- ASSERT(!upb_decoderplan_hasjitcode(p));
-#endif
- upb_decoderplan_unref(p);
- upb_symtab_unref(s);
- upb_def_unref(def);
- upb_handlers_unref(h);
-}
-
-static void test_upb_symtab() {
- upb_symtab *s = load_test_proto();
-
- // Test cycle detection by making a cyclic def's main refcount go to zero
- // and then be incremented to one again.
- const upb_def *def = upb_symtab_lookup(s, "A");
- ASSERT(def);
- upb_symtab_unref(s);
- const upb_msgdef *m = upb_downcast_msgdef_const(def);
- upb_msg_iter i = upb_msg_begin(m);
- ASSERT(!upb_msg_done(i));
- upb_fielddef *f = upb_msg_iter_field(i);
- ASSERT(upb_hassubdef(f));
- upb_def *def2 = f->def;
-
- i = upb_msg_next(m, i);
- ASSERT(upb_msg_done(i)); // "A" should only have one field.
-
- ASSERT(upb_downcast_msgdef(def2));
- upb_def_ref(def2);
- upb_def_unref(def);
- upb_def_unref(def2);
-}
-
-static void test_upb_two_fielddefs() {
- upb_fielddef *f1 = upb_fielddef_new();
- upb_fielddef *f2 = upb_fielddef_new();
-
- ASSERT(upb_fielddef_ismutable(f1));
- upb_fielddef_setname(f1, "");
- upb_fielddef_setnumber(f1, 1937);
- upb_fielddef_settype(f1, UPB_TYPE(FIXED64));
- upb_fielddef_setlabel(f1, UPB_LABEL(REPEATED));
- upb_fielddef_settypename(f1, "");
- ASSERT(upb_fielddef_number(f1) == 1937);
-
- ASSERT(upb_fielddef_ismutable(f2));
- upb_fielddef_setname(f2, "");
- upb_fielddef_setnumber(f2, 1572);
- upb_fielddef_settype(f2, UPB_TYPE(BYTES));
- upb_fielddef_setlabel(f2, UPB_LABEL(REPEATED));
- upb_fielddef_settypename(f2, "");
- ASSERT(upb_fielddef_number(f2) == 1572);
-
- upb_fielddef_unref(f1);
- upb_fielddef_unref(f2);
-}
-
-int main(int argc, char *argv[])
-{
- if (argc < 2) {
- fprintf(stderr, "Usage: test_cpp <descriptor file>\n");
- return 1;
- }
- descriptor_file = argv[1];
-#define TEST(func) do { \
- int assertions_before = num_assertions; \
- printf("Running " #func "..."); fflush(stdout); \
- func(); \
- printf("ok (%d assertions).\n", num_assertions - assertions_before); \
- } while (0)
-
- TEST(test_upb_symtab);
- TEST(test_upb_jit);
- TEST(test_upb_two_fielddefs);
- printf("All tests passed (%d assertions).\n", num_assertions);
- return 0;
-}
diff --git a/tests/upb_test.h b/tests/upb_test.h
index 2bd340e..652977b 100644
--- a/tests/upb_test.h
+++ b/tests/upb_test.h
@@ -7,6 +7,7 @@
#ifndef UPB_TEST_H_
#define UPB_TEST_H_
+#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
@@ -18,9 +19,28 @@ int num_assertions = 0;
++num_assertions; \
if (!(expr)) { \
fprintf(stderr, "Assertion failed: %s:%d\n", __FILE__, __LINE__); \
+ fprintf(stderr, "expr: %s\n", #expr); \
abort(); \
} \
-} while(0)
+} while (0)
+
+#define ASSERT_NOCOUNT(expr) do { \
+ if (!(expr)) { \
+ fprintf(stderr, "Assertion failed: %s:%d\n", __FILE__, __LINE__); \
+ fprintf(stderr, "expr: %s\n", #expr); \
+ abort(); \
+ } \
+} while (0)
+
+#define ASSERT_STATUS(expr, status) do { \
+ ++num_assertions; \
+ if (!(expr)) { \
+ fprintf(stderr, "Assertion failed: %s:%d\n", __FILE__, __LINE__); \
+ fprintf(stderr, "expr: %s\n", #expr); \
+ fprintf(stderr, "failed status: %s\n", upb_status_getstr(status)); \
+ abort(); \
+ } \
+} while (0)
#ifdef __cplusplus
} /* extern "C" */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback