Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc / deps / grpc / third_party / upb / tests / test_util.h
1 /*
2 ** Common functionality for tests.
3 **/
4
5 #ifndef UPB_TEST_UTIL_H_
6 #define UPB_TEST_UTIL_H_
7
8 #include <stdio.h>
9 #include <math.h>
10 #include "tests/upb_test.h"
11 #include "upb/sink.h"
12
13 #include "upb/port_def.inc"
14
15 #ifdef __cplusplus
16
17 upb_bufhandle global_handle;
18
19 /* A convenience class for parser tests.  Provides some useful features:
20  *
21  *   - can support multiple calls to parse, to test the parser's handling
22  *     of buffer seams.
23  *
24  *   - can output verbose output about each parse call when requested, for
25  *     ease of debugging.
26  *
27  *   - can pass NULL for skipped regions of the input if requested.
28  *
29  *   - allocates and passes a separate buffer for each parsed region, to
30  *     ensure that the parser is not erroneously overreading its buffer.
31  */
32 class VerboseParserEnvironment {
33  public:
34   /* Pass verbose=true to print detailed diagnostics to stderr. */
35   VerboseParserEnvironment(bool verbose) : verbose_(verbose) {}
36
37   void Reset(const char *buf, size_t len, bool may_skip, bool expect_error) {
38     buf_ = buf;
39     len_ = len;
40     ofs_ = 0;
41     expect_error_ = expect_error;
42     end_ok_set_ = false;
43     skip_until_ = may_skip ? 0 : -1;
44     skipped_with_null_ = false;
45   }
46
47   /* The user should call a series of:
48    *
49    * Reset(buf, len, may_skip);
50    * Start()
51    * ParseBuffer(X);
52    * ParseBuffer(Y);
53    * // Repeat ParseBuffer as desired, but last call should pass -1.
54    * ParseBuffer(-1);
55    * End();
56    */
57
58
59   bool Start() {
60     if (verbose_) {
61       fprintf(stderr, "Calling start()\n");
62     }
63     return sink_.Start(len_, &subc_);
64   }
65
66   bool End() {
67     if (verbose_) {
68       fprintf(stderr, "Calling end()\n");
69     }
70     end_ok_ = sink_.End();
71     end_ok_set_ = true;
72
73     return end_ok_;
74   }
75
76   bool CheckConsistency() {
77     /* If we called end (which we should only do when previous bytes are fully
78      * accepted), then end() should return true iff there were no errors. */
79     if (end_ok_set_ && end_ok_ != status_.ok()) {
80       fprintf(stderr, "End() status and saw_error didn't match.\n");
81       return false;
82     }
83
84     if (expect_error_ && status_.ok()) {
85       fprintf(stderr, "Expected error but saw none.\n");
86       return false;
87     }
88
89     if (!status_.ok()) {
90       if (expect_error_ && verbose_) {
91         fprintf(stderr, "Encountered error, as expected: %s",
92                 status_.error_message());
93       } else if (!expect_error_) {
94         fprintf(stderr, "Encountered unexpected error: %s",
95                 status_.error_message());
96         return false;
97       }
98     }
99
100     return true;
101   }
102
103   bool ParseBuffer(int bytes) {
104     if (bytes < 0) {
105       bytes = len_ - ofs_;
106     }
107
108     ASSERT((size_t)bytes <= (len_ - ofs_));
109
110     /* Copy buffer into a separate, temporary buffer.
111      * This is necessary to verify that the parser is not erroneously
112      * reading outside the specified bounds. */
113     char *buf2 = NULL;
114
115     if ((int)(ofs_ + bytes) <= skip_until_) {
116       skipped_with_null_ = true;
117     } else {
118       buf2 = (char*)malloc(bytes);
119       UPB_ASSERT(buf2);
120       memcpy(buf2, buf_ + ofs_, bytes);
121     }
122
123     if (buf2 == NULL && bytes == 0) {
124       /* Decoders dont' support buf=NULL, bytes=0. */
125       return true;
126     }
127
128     if (verbose_) {
129       fprintf(stderr, "Calling parse(%u) for bytes %u-%u of the input\n",
130               (unsigned)bytes, (unsigned)ofs_, (unsigned)(ofs_ + bytes));
131     }
132
133     int parsed = sink_.PutBuffer(subc_, buf2, bytes, &global_handle);
134     free(buf2);
135
136     if (verbose_) {
137       if (parsed == bytes) {
138         fprintf(stderr,
139                 "parse(%u) = %u, complete byte count indicates success\n",
140                 (unsigned)bytes, (unsigned)bytes);
141       } else if (parsed > bytes) {
142         fprintf(stderr,
143                 "parse(%u) = %u, long byte count indicates success and skip "
144                 "of the next %u bytes\n",
145                 (unsigned)bytes, (unsigned)parsed, (unsigned)(parsed - bytes));
146       } else {
147         fprintf(stderr,
148                 "parse(%u) = %u, short byte count indicates failure; "
149                 "last %u bytes were not consumed\n",
150                 (unsigned)bytes, (unsigned)parsed, (unsigned)(bytes - parsed));
151       }
152     }
153
154     if (!status_.ok()) {
155       return false;
156     }
157
158     if (parsed > bytes && skip_until_ >= 0) {
159       skip_until_ = ofs_ + parsed;
160     }
161
162     ofs_ += UPB_MIN(parsed, bytes);
163
164     return true;
165   }
166
167   void ResetBytesSink(upb::BytesSink sink) {
168     sink_ = sink;
169   }
170
171   size_t ofs() { return ofs_; }
172
173   bool SkippedWithNull() { return skipped_with_null_; }
174
175   upb::Arena* arena() { return &arena_; }
176   upb::Status* status() { return &status_; }
177
178  private:
179   upb::Arena arena_;
180   upb::Status status_;
181   upb::BytesSink sink_;
182   const char* buf_;
183   size_t len_;
184   bool verbose_;
185   size_t ofs_;
186   void *subc_;
187   bool expect_error_;
188   bool end_ok_;
189   bool end_ok_set_;
190
191   /* When our parse call returns a value greater than the number of bytes
192    * we passed in, the decoder is indicating to us that the next N bytes
193    * in the stream are not needed and can be skipped.  The user is allowed
194    * to pass a NULL buffer for those N bytes.
195    *
196    * skip_until_ is initially set to 0 if we should do this NULL-buffer
197    * skipping or -1 if we should not.  If we are open to doing NULL-buffer
198    * skipping and we get an opportunity to do it, we set skip_until to the
199    * stream offset where we can skip until.  The user can then test whether
200    * this happened by testing SkippedWithNull(). */
201   int skip_until_;
202   bool skipped_with_null_;
203 };
204
205 #endif  /* __cplusplus */
206
207 UPB_INLINE char *upb_readfile(const char *filename, size_t *len) {
208   long size;
209   char *buf;
210   FILE *f = fopen(filename, "rb");
211   if(!f) return NULL;
212   if(fseek(f, 0, SEEK_END) != 0) goto error;
213   size = ftell(f);
214   if(size < 0) goto error;
215   if(fseek(f, 0, SEEK_SET) != 0) goto error;
216   buf = (char*)malloc(size + 1);
217   if(size && fread(buf, size, 1, f) != 1) goto error;
218   fclose(f);
219   if (len) *len = size;
220   buf[size] = '\0';
221   return buf;
222
223 error:
224   fclose(f);
225   return NULL;
226 }
227
228 #include "upb/port_undef.inc"
229
230 #endif /* UPB_TEST_UTIL_H_ */