|
|
|
@ -63,6 +63,8 @@ |
|
|
|
|
|
|
|
|
|
#define MAX_NESTING 64 |
|
|
|
|
|
|
|
|
|
#define LINE(x) x "\n" |
|
|
|
|
|
|
|
|
|
uint32_t filter_hash = 0; |
|
|
|
|
double completed; |
|
|
|
|
double total; |
|
|
|
@ -517,12 +519,13 @@ upb::pb::Decoder* CreateDecoder(upb::Environment* env, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t Hash(const string& proto, const string* expected_output, size_t seam1, |
|
|
|
|
size_t seam2) { |
|
|
|
|
size_t seam2, bool may_skip) { |
|
|
|
|
uint32_t hash = MurmurHash2(proto.c_str(), proto.size(), 0); |
|
|
|
|
if (expected_output) |
|
|
|
|
hash = MurmurHash2(expected_output->c_str(), expected_output->size(), hash); |
|
|
|
|
hash = MurmurHash2(&seam1, sizeof(seam1), hash); |
|
|
|
|
hash = MurmurHash2(&seam2, sizeof(seam2), hash); |
|
|
|
|
hash = MurmurHash2(&may_skip, sizeof(may_skip), hash); |
|
|
|
|
return hash; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -538,91 +541,88 @@ void CheckBytesParsed(const upb::pb::Decoder& decoder, size_t ofs) { |
|
|
|
|
ASSERT(ofs <= (decoder.BytesParsed() + MAX_BUFFERED)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool parse(upb::pb::Decoder* decoder, void* subc, const char* buf, |
|
|
|
|
size_t start, size_t end, size_t* ofs, upb::Status* status) { |
|
|
|
|
CheckBytesParsed(*decoder, *ofs); |
|
|
|
|
bool ret = parse_buffer(decoder->input(), subc, buf, start, end, ofs, status, |
|
|
|
|
filter_hash != 0); |
|
|
|
|
static bool parse(VerboseParserEnvironment* env, |
|
|
|
|
const upb::pb::Decoder& decoder, int bytes) { |
|
|
|
|
CheckBytesParsed(decoder, env->ofs()); |
|
|
|
|
bool ret = env->ParseBuffer(bytes); |
|
|
|
|
if (ret) { |
|
|
|
|
CheckBytesParsed(*decoder, *ofs); |
|
|
|
|
CheckBytesParsed(decoder, env->ofs()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define LINE(x) x "\n" |
|
|
|
|
void run_decoder(const string& proto, const string* expected_output) { |
|
|
|
|
upb::Status status; |
|
|
|
|
upb::Sink sink(global_handlers, &closures[0]); |
|
|
|
|
for (size_t i = 0; i < proto.size(); i++) { |
|
|
|
|
for (size_t j = i; j < UPB_MIN(proto.size(), i + 5); j++) { |
|
|
|
|
// TODO(haberman): hoist this again once the environment supports reset.
|
|
|
|
|
upb::Environment env; |
|
|
|
|
env.ReportErrorsTo(&status); |
|
|
|
|
upb::pb::Decoder *decoder = CreateDecoder(&env, global_method, &sink); |
|
|
|
|
|
|
|
|
|
testhash = Hash(proto, expected_output, i, j); |
|
|
|
|
if (filter_hash && testhash != filter_hash) continue; |
|
|
|
|
if (test_mode != COUNT_ONLY) { |
|
|
|
|
output.clear(); |
|
|
|
|
status.Clear(); |
|
|
|
|
size_t ofs = 0; |
|
|
|
|
upb::BytesSink* input = decoder->input(); |
|
|
|
|
void *sub; |
|
|
|
|
|
|
|
|
|
if (filter_hash) { |
|
|
|
|
fprintf(stderr, "RUNNING TEST CASE, hash=%x\n", testhash); |
|
|
|
|
fprintf(stderr, "JIT on: %s\n", |
|
|
|
|
global_method->is_native() ? "true" : "false"); |
|
|
|
|
fprintf(stderr, "Input (len=%u): ", (unsigned)proto.size()); |
|
|
|
|
PrintBinary(proto); |
|
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
if (expected_output) { |
|
|
|
|
fprintf(stderr, "Expected output: %s\n", expected_output->c_str()); |
|
|
|
|
} else { |
|
|
|
|
fprintf(stderr, "Expected to FAIL\n"); |
|
|
|
|
} |
|
|
|
|
fprintf(stderr, "Calling start()\n"); |
|
|
|
|
} |
|
|
|
|
void do_run_decoder(VerboseParserEnvironment* env, upb::pb::Decoder* decoder, |
|
|
|
|
const string& proto, const string* expected_output, |
|
|
|
|
size_t i, size_t j, bool may_skip) { |
|
|
|
|
env->Reset(proto.c_str(), proto.size(), may_skip); |
|
|
|
|
decoder->Reset(); |
|
|
|
|
|
|
|
|
|
bool ok = input->Start(proto.size(), &sub) && |
|
|
|
|
parse(decoder, sub, proto.c_str(), 0, i, &ofs, &status) && |
|
|
|
|
parse(decoder, sub, proto.c_str(), i, j, &ofs, &status) && |
|
|
|
|
parse(decoder, sub, proto.c_str(), j, proto.size(), &ofs, |
|
|
|
|
&status) && |
|
|
|
|
ofs == proto.size(); |
|
|
|
|
testhash = Hash(proto, expected_output, i, j, may_skip); |
|
|
|
|
if (filter_hash && testhash != filter_hash) return; |
|
|
|
|
if (test_mode != COUNT_ONLY) { |
|
|
|
|
output.clear(); |
|
|
|
|
|
|
|
|
|
if (filter_hash) { |
|
|
|
|
fprintf(stderr, "RUNNING TEST CASE, hash=%x\n", testhash); |
|
|
|
|
fprintf(stderr, "JIT on: %s\n", |
|
|
|
|
global_method->is_native() ? "true" : "false"); |
|
|
|
|
fprintf(stderr, "Input (len=%u): ", (unsigned)proto.size()); |
|
|
|
|
PrintBinary(proto); |
|
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
if (expected_output) { |
|
|
|
|
fprintf(stderr, "Expected output: %s\n", expected_output->c_str()); |
|
|
|
|
} else { |
|
|
|
|
fprintf(stderr, "Expected to FAIL\n"); |
|
|
|
|
} |
|
|
|
|
fprintf(stderr, "Calling start()\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool ok = env->Start() && |
|
|
|
|
parse(env, *decoder, i) && |
|
|
|
|
parse(env, *decoder, j - i) && |
|
|
|
|
parse(env, *decoder, -1) && |
|
|
|
|
env->End(); |
|
|
|
|
|
|
|
|
|
ASSERT(ok == env->status().ok()); |
|
|
|
|
|
|
|
|
|
if (test_mode == ALL_HANDLERS) { |
|
|
|
|
if (expected_output) { |
|
|
|
|
if (output != *expected_output) { |
|
|
|
|
fprintf(stderr, "Text mismatch: '%s' vs '%s'\n", |
|
|
|
|
output.c_str(), expected_output->c_str()); |
|
|
|
|
} |
|
|
|
|
if (!ok) { |
|
|
|
|
fprintf(stderr, "Failed: %s\n", env->status().error_message()); |
|
|
|
|
} |
|
|
|
|
ASSERT(ok); |
|
|
|
|
ASSERT(output == *expected_output); |
|
|
|
|
} else { |
|
|
|
|
if (ok) { |
|
|
|
|
if (filter_hash) { |
|
|
|
|
fprintf(stderr, "calling end()\n"); |
|
|
|
|
} |
|
|
|
|
ok = input->End(); |
|
|
|
|
fprintf(stderr, "Didn't expect ok result, but got output: '%s'\n", |
|
|
|
|
output.c_str()); |
|
|
|
|
} else if (filter_hash) { |
|
|
|
|
fprintf(stderr, "Failed as we expected, with message: %s\n", |
|
|
|
|
env->status().error_message()); |
|
|
|
|
} |
|
|
|
|
ASSERT(!ok); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
(*count)++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (test_mode == ALL_HANDLERS) { |
|
|
|
|
if (expected_output) { |
|
|
|
|
if (output != *expected_output) { |
|
|
|
|
fprintf(stderr, "Text mismatch: '%s' vs '%s'\n", |
|
|
|
|
output.c_str(), expected_output->c_str()); |
|
|
|
|
} |
|
|
|
|
if (!ok) { |
|
|
|
|
fprintf(stderr, "Failed: %s\n", status.error_message()); |
|
|
|
|
} |
|
|
|
|
ASSERT(ok); |
|
|
|
|
ASSERT(output == *expected_output); |
|
|
|
|
} else { |
|
|
|
|
if (ok) { |
|
|
|
|
fprintf(stderr, "Didn't expect ok result, but got output: '%s'\n", |
|
|
|
|
output.c_str()); |
|
|
|
|
} else if (filter_hash) { |
|
|
|
|
fprintf(stderr, "Failed as we expected, with message: %s\n", |
|
|
|
|
status.error_message()); |
|
|
|
|
} |
|
|
|
|
ASSERT(!ok); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
void run_decoder(const string& proto, const string* expected_output) { |
|
|
|
|
VerboseParserEnvironment env(filter_hash != 0); |
|
|
|
|
upb::Sink sink(global_handlers, &closures[0]); |
|
|
|
|
upb::pb::Decoder *decoder = CreateDecoder(env.env(), global_method, &sink); |
|
|
|
|
env.ResetBytesSink(decoder->input()); |
|
|
|
|
for (size_t i = 0; i < proto.size(); i++) { |
|
|
|
|
for (size_t j = i; j < UPB_MIN(proto.size(), i + 5); j++) { |
|
|
|
|
do_run_decoder(&env, decoder, proto, expected_output, i, j, true); |
|
|
|
|
if (env.SkippedWithNull()) { |
|
|
|
|
do_run_decoder(&env, decoder, proto, expected_output, i, j, false); |
|
|
|
|
} |
|
|
|
|
(*count)++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
testhash = 0; |
|
|
|
@ -1146,20 +1146,14 @@ upb::reffed_ptr<const upb::pb::DecoderMethod> method = |
|
|
|
|
{ NULL, 0 }, |
|
|
|
|
}; |
|
|
|
|
for (int i = 0; testdata[i].data; i++) { |
|
|
|
|
upb::Environment env; |
|
|
|
|
upb::Status status; |
|
|
|
|
env.ReportErrorsTo(&status); |
|
|
|
|
VerboseParserEnvironment env(filter_hash != 0); |
|
|
|
|
upb::Sink sink(method->dest_handlers(), &closures[0]); |
|
|
|
|
upb::pb::Decoder* decoder = CreateDecoder(&env, method.get(), &sink); |
|
|
|
|
upb::BytesSink* input = decoder->input(); |
|
|
|
|
void* subc; |
|
|
|
|
ASSERT(input->Start(0, &subc)); |
|
|
|
|
size_t ofs = 0; |
|
|
|
|
ASSERT(parse_buffer(input, subc, |
|
|
|
|
testdata[i].data, 0, testdata[i].length, |
|
|
|
|
&ofs, &status, false)); |
|
|
|
|
ASSERT(ofs == testdata[i].length); |
|
|
|
|
ASSERT(input->End()); |
|
|
|
|
upb::pb::Decoder* decoder = CreateDecoder(env.env(), method.get(), &sink); |
|
|
|
|
env.ResetBytesSink(decoder->input()); |
|
|
|
|
env.Reset(testdata[i].data, testdata[i].length, true); |
|
|
|
|
ASSERT(env.Start()); |
|
|
|
|
ASSERT(env.ParseBuffer(-1)); |
|
|
|
|
ASSERT(env.End()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|