/* * upb - a minimalist implementation of protocol buffers. * * Copyright (c) 2014 Google Inc. See LICENSE for details. * * Common functionality for tests. */ #ifndef UPB_TEST_UTIL_H_ #define UPB_TEST_UTIL_H_ #include #include #include "tests/upb_test.h" #include "upb/sink.h" upb::BufferHandle global_handle; // Puts a region of the given buffer [start, end) into the given sink (which // probably represents a parser. Can gracefully handle the case where the // parser returns a "parsed" length that is less or greater than the input // buffer length, and tracks the overall parse offset in *ofs. // // Pass verbose=true to print detailed diagnostics to stderr. bool parse_buffer(upb::BytesSink* sink, void* subc, const char* buf, size_t start, size_t end, size_t* ofs, upb::Status* status, bool verbose) { start = UPB_MAX(start, *ofs); if (start <= end) { size_t len = end - start; // Copy buffer into a separate, temporary buffer. // This is necessary to verify that the parser is not erroneously // reading outside the specified bounds. char *buf2 = (char*)malloc(len); assert(buf2); memcpy(buf2, buf + start, len); if (verbose) { fprintf(stderr, "Calling parse(%zu) for bytes %zu-%zu of the input\n", len, start, end); } size_t parsed = sink->PutBuffer(subc, buf2, len, &global_handle); free(buf2); if (verbose) { if (parsed == len) { fprintf(stderr, "parse(%zu) = %zu, complete byte count indicates success\n", len, len); } else if (parsed > len) { fprintf(stderr, "parse(%zu) = %zu, long byte count indicates success and skip" "of the next %zu bytes\n", len, parsed, parsed - len); } else { fprintf(stderr, "parse(%zu) = %zu, short byte count indicates failure; " "last %zu bytes were not consumed\n", len, parsed, len - parsed); } } if (status->ok() != (parsed >= len)) { if (status->ok()) { fprintf(stderr, "Error: decode function returned short byte count but set no " "error status\n"); } else { fprintf(stderr, "Error: decode function returned complete byte count but set " "error status\n"); } fprintf(stderr, "Status: %s, parsed=%zu, len=%zu\n", status->error_message(), parsed, len); ASSERT(false); } if (!status->ok()) return false; *ofs += parsed; } return true; } #endif