Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc / deps / grpc / third_party / upb / tests / test_util.h
diff --git a/legacy-libs/grpc/deps/grpc/third_party/upb/tests/test_util.h b/legacy-libs/grpc/deps/grpc/third_party/upb/tests/test_util.h
new file mode 100644 (file)
index 0000000..4854100
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+** 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"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+
+upb_bufhandle global_handle;
+
+/* A convenience class for parser tests.  Provides some useful features:
+ *
+ *   - can support multiple calls to parse, to test the parser's handling
+ *     of buffer seams.
+ *
+ *   - can output verbose output about each parse call when requested, for
+ *     ease of debugging.
+ *
+ *   - can pass NULL for skipped regions of the input if requested.
+ *
+ *   - allocates and passes a separate buffer for each parsed region, to
+ *     ensure that the parser is not erroneously overreading its buffer.
+ */
+class VerboseParserEnvironment {
+ public:
+  /* Pass verbose=true to print detailed diagnostics to stderr. */
+  VerboseParserEnvironment(bool verbose) : verbose_(verbose) {}
+
+  void Reset(const char *buf, size_t len, bool may_skip, bool expect_error) {
+    buf_ = buf;
+    len_ = len;
+    ofs_ = 0;
+    expect_error_ = expect_error;
+    end_ok_set_ = false;
+    skip_until_ = may_skip ? 0 : -1;
+    skipped_with_null_ = false;
+  }
+
+  /* The user should call a series of:
+   *
+   * Reset(buf, len, may_skip);
+   * Start()
+   * ParseBuffer(X);
+   * ParseBuffer(Y);
+   * // Repeat ParseBuffer as desired, but last call should pass -1.
+   * ParseBuffer(-1);
+   * End();
+   */
+
+
+  bool Start() {
+    if (verbose_) {
+      fprintf(stderr, "Calling start()\n");
+    }
+    return sink_.Start(len_, &subc_);
+  }
+
+  bool End() {
+    if (verbose_) {
+      fprintf(stderr, "Calling end()\n");
+    }
+    end_ok_ = sink_.End();
+    end_ok_set_ = true;
+
+    return end_ok_;
+  }
+
+  bool CheckConsistency() {
+    /* If we called end (which we should only do when previous bytes are fully
+     * accepted), then end() should return true iff there were no errors. */
+    if (end_ok_set_ && end_ok_ != status_.ok()) {
+      fprintf(stderr, "End() status and saw_error didn't match.\n");
+      return false;
+    }
+
+    if (expect_error_ && status_.ok()) {
+      fprintf(stderr, "Expected error but saw none.\n");
+      return false;
+    }
+
+    if (!status_.ok()) {
+      if (expect_error_ && verbose_) {
+        fprintf(stderr, "Encountered error, as expected: %s",
+                status_.error_message());
+      } else if (!expect_error_) {
+        fprintf(stderr, "Encountered unexpected error: %s",
+                status_.error_message());
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  bool ParseBuffer(int bytes) {
+    if (bytes < 0) {
+      bytes = len_ - ofs_;
+    }
+
+    ASSERT((size_t)bytes <= (len_ - ofs_));
+
+    /* 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 = NULL;
+
+    if ((int)(ofs_ + bytes) <= skip_until_) {
+      skipped_with_null_ = true;
+    } else {
+      buf2 = (char*)malloc(bytes);
+      UPB_ASSERT(buf2);
+      memcpy(buf2, buf_ + ofs_, bytes);
+    }
+
+    if (buf2 == NULL && bytes == 0) {
+      /* Decoders dont' support buf=NULL, bytes=0. */
+      return true;
+    }
+
+    if (verbose_) {
+      fprintf(stderr, "Calling parse(%u) for bytes %u-%u of the input\n",
+              (unsigned)bytes, (unsigned)ofs_, (unsigned)(ofs_ + bytes));
+    }
+
+    int parsed = sink_.PutBuffer(subc_, buf2, bytes, &global_handle);
+    free(buf2);
+
+    if (verbose_) {
+      if (parsed == bytes) {
+        fprintf(stderr,
+                "parse(%u) = %u, complete byte count indicates success\n",
+                (unsigned)bytes, (unsigned)bytes);
+      } else if (parsed > bytes) {
+        fprintf(stderr,
+                "parse(%u) = %u, long byte count indicates success and skip "
+                "of the next %u bytes\n",
+                (unsigned)bytes, (unsigned)parsed, (unsigned)(parsed - bytes));
+      } else {
+        fprintf(stderr,
+                "parse(%u) = %u, short byte count indicates failure; "
+                "last %u bytes were not consumed\n",
+                (unsigned)bytes, (unsigned)parsed, (unsigned)(bytes - parsed));
+      }
+    }
+
+    if (!status_.ok()) {
+      return false;
+    }
+
+    if (parsed > bytes && skip_until_ >= 0) {
+      skip_until_ = ofs_ + parsed;
+    }
+
+    ofs_ += UPB_MIN(parsed, bytes);
+
+    return true;
+  }
+
+  void ResetBytesSink(upb::BytesSink sink) {
+    sink_ = sink;
+  }
+
+  size_t ofs() { return ofs_; }
+
+  bool SkippedWithNull() { return skipped_with_null_; }
+
+  upb::Arena* arena() { return &arena_; }
+  upb::Status* status() { return &status_; }
+
+ private:
+  upb::Arena arena_;
+  upb::Status status_;
+  upb::BytesSink sink_;
+  const char* buf_;
+  size_t len_;
+  bool verbose_;
+  size_t ofs_;
+  void *subc_;
+  bool expect_error_;
+  bool end_ok_;
+  bool end_ok_set_;
+
+  /* When our parse call returns a value greater than the number of bytes
+   * we passed in, the decoder is indicating to us that the next N bytes
+   * in the stream are not needed and can be skipped.  The user is allowed
+   * to pass a NULL buffer for those N bytes.
+   *
+   * skip_until_ is initially set to 0 if we should do this NULL-buffer
+   * skipping or -1 if we should not.  If we are open to doing NULL-buffer
+   * skipping and we get an opportunity to do it, we set skip_until to the
+   * stream offset where we can skip until.  The user can then test whether
+   * this happened by testing SkippedWithNull(). */
+  int skip_until_;
+  bool skipped_with_null_;
+};
+
+#endif  /* __cplusplus */
+
+UPB_INLINE char *upb_readfile(const char *filename, size_t *len) {
+  long size;
+  char *buf;
+  FILE *f = fopen(filename, "rb");
+  if(!f) return NULL;
+  if(fseek(f, 0, SEEK_END) != 0) goto error;
+  size = ftell(f);
+  if(size < 0) goto error;
+  if(fseek(f, 0, SEEK_SET) != 0) goto error;
+  buf = (char*)malloc(size + 1);
+  if(size && fread(buf, size, 1, f) != 1) goto error;
+  fclose(f);
+  if (len) *len = size;
+  buf[size] = '\0';
+  return buf;
+
+error:
+  fclose(f);
+  return NULL;
+}
+
+#include "upb/port_undef.inc"
+
+#endif /* UPB_TEST_UTIL_H_ */