summaryrefslogtreecommitdiff
path: root/tests/test_util.h
blob: 73a5c19b8f284ac519731c5ac480a17e2d323e69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*
 * 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 <stdio.h>
#include <math.h>
#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(%u) for bytes %u-%u of the input\n",
              (unsigned)len, (unsigned)start, (unsigned)end);
    }

    size_t parsed = sink->PutBuffer(subc, buf2, len, &global_handle);
    free(buf2);

    if (verbose) {
      if (parsed == len) {
        fprintf(stderr,
                "parse(%u) = %u, complete byte count indicates success\n",
                (unsigned)len, (unsigned)len);
      } else if (parsed > len) {
        fprintf(stderr,
                "parse(%u) = %u, long byte count indicates success and skip"
                "of the next %u bytes\n",
                (unsigned)len, (unsigned)parsed, (unsigned)(parsed - len));
      } else {
        fprintf(stderr,
                "parse(%u) = %u, short byte count indicates failure; "
                "last %u bytes were not consumed\n",
                (unsigned)len, (unsigned)parsed, (unsigned)(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=%u, len=%u\n",
              status->error_message(), (unsigned)parsed, (unsigned)len);
      ASSERT(false);
    }

    if (!status->ok())
      return false;

    *ofs += parsed;
  }
  return true;
}

#endif
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback