Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/tests/gtest/TestTokenizer.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/Tokenizer.h"
8
#include "mozilla/IncrementalTokenizer.h"
9
#include "mozilla/Unused.h"
10
#include "gtest/gtest.h"
11
12
using namespace mozilla;
13
14
template <typename Char>
15
static bool IsOperator(Char const c)
16
0
{
17
0
  return c == '+' || c == '*';
18
0
}
Unexecuted instantiation: Unified_cpp_xpcom_tests_gtest3.cpp:bool IsOperator<char>(char)
Unexecuted instantiation: Unified_cpp_xpcom_tests_gtest3.cpp:bool IsOperator<char16_t>(char16_t)
19
20
static bool HttpHeaderCharacter(char const c)
21
0
{
22
0
  return (c >= 'a' && c <= 'z') ||
23
0
         (c >= 'A' && c <= 'Z') ||
24
0
         (c >= '0' && c <= '9') ||
25
0
         (c == '_') ||
26
0
         (c == '-');
27
0
}
28
29
TEST(Tokenizer, HTTPResponse)
30
0
{
31
0
  Tokenizer::Token t;
32
0
33
0
  // Real life test, HTTP response
34
0
35
0
  Tokenizer p(NS_LITERAL_CSTRING(
36
0
    "HTTP/1.0 304 Not modified\r\n"
37
0
    "ETag: hallo\r\n"
38
0
    "Content-Length: 16\r\n"
39
0
    "\r\n"
40
0
    "This is the body"));
41
0
42
0
  EXPECT_TRUE(p.CheckWord("HTTP"));
43
0
  EXPECT_TRUE(p.CheckChar('/'));
44
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_INTEGER, t));
45
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_INTEGER);
46
0
  EXPECT_TRUE(t.AsInteger() == 1);
47
0
  EXPECT_TRUE(p.CheckChar('.'));
48
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_INTEGER, t));
49
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_INTEGER);
50
0
  EXPECT_TRUE(t.AsInteger() == 0);
51
0
  p.SkipWhites();
52
0
53
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_INTEGER, t));
54
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_INTEGER);
55
0
  EXPECT_TRUE(t.AsInteger() == 304);
56
0
  p.SkipWhites();
57
0
58
0
  p.Record();
59
0
  while (p.Next(t) && t.Type() != Tokenizer::TOKEN_EOL);
60
0
  EXPECT_FALSE(p.HasFailed());
61
0
  nsAutoCString h;
62
0
  p.Claim(h);
63
0
  EXPECT_TRUE(h == "Not modified");
64
0
65
0
  p.Record();
66
0
  while (p.CheckChar(HttpHeaderCharacter));
67
0
  p.Claim(h, Tokenizer::INCLUDE_LAST);
68
0
  EXPECT_TRUE(h == "ETag");
69
0
  p.SkipWhites();
70
0
  EXPECT_TRUE(p.CheckChar(':'));
71
0
  p.SkipWhites();
72
0
  p.Record();
73
0
  while (p.Next(t) && t.Type() != Tokenizer::TOKEN_EOL);
74
0
  EXPECT_FALSE(p.HasFailed());
75
0
  p.Claim(h);
76
0
  EXPECT_TRUE(h == "hallo");
77
0
78
0
  p.Record();
79
0
  while (p.CheckChar(HttpHeaderCharacter));
80
0
  p.Claim(h, Tokenizer::INCLUDE_LAST);
81
0
  EXPECT_TRUE(h == "Content-Length");
82
0
  p.SkipWhites();
83
0
  EXPECT_TRUE(p.CheckChar(':'));
84
0
  p.SkipWhites();
85
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_INTEGER, t));
86
0
  EXPECT_TRUE(t.AsInteger() == 16);
87
0
  EXPECT_TRUE(p.CheckEOL());
88
0
89
0
  EXPECT_TRUE(p.CheckEOL());
90
0
91
0
  p.Record();
92
0
  while (p.Next(t) && t.Type() != Tokenizer::TOKEN_EOF);
93
0
  nsAutoCString b;
94
0
  p.Claim(b);
95
0
  EXPECT_TRUE(b == "This is the body");
96
0
}
97
98
TEST(Tokenizer, Main)
99
0
{
100
0
  Tokenizer::Token t;
101
0
102
0
  // Synthetic code-specific test
103
0
104
0
  Tokenizer p(NS_LITERAL_CSTRING("test123 ,15  \t*\r\n%xx,-15\r\r"));
105
0
106
0
  EXPECT_TRUE(p.Next(t));
107
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_WORD);
108
0
  EXPECT_TRUE(t.AsString() == "test123");
109
0
110
0
  Tokenizer::Token u;
111
0
  EXPECT_FALSE(p.Check(u));
112
0
113
0
  EXPECT_FALSE(p.CheckChar('!'));
114
0
115
0
  EXPECT_FALSE(p.Check(Tokenizer::Token::Number(123)));
116
0
117
0
  EXPECT_TRUE(p.CheckWhite());
118
0
119
0
  EXPECT_TRUE(p.CheckChar(','));
120
0
121
0
  EXPECT_TRUE(p.Check(Tokenizer::Token::Number(15)));
122
0
123
0
  p.Rollback();
124
0
  EXPECT_TRUE(p.Check(Tokenizer::Token::Number(15)));
125
0
126
0
  p.Rollback();
127
0
  EXPECT_TRUE(p.Next(t));
128
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_INTEGER);
129
0
  EXPECT_TRUE(t.AsInteger() == 15);
130
0
131
0
  EXPECT_FALSE(p.CheckChar(IsOperator));
132
0
133
0
  EXPECT_TRUE(p.CheckWhite());
134
0
135
0
  p.SkipWhites();
136
0
137
0
  EXPECT_FALSE(p.CheckWhite());
138
0
139
0
  p.Rollback();
140
0
141
0
  EXPECT_TRUE(p.CheckWhite());
142
0
  EXPECT_TRUE(p.CheckWhite());
143
0
144
0
  p.Record(Tokenizer::EXCLUDE_LAST);
145
0
146
0
  EXPECT_TRUE(p.CheckChar(IsOperator));
147
0
148
0
  p.Rollback();
149
0
150
0
  EXPECT_TRUE(p.Next(t));
151
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_CHAR);
152
0
  EXPECT_TRUE(t.AsChar() == '*');
153
0
154
0
  EXPECT_TRUE(p.Next(t));
155
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_EOL);
156
0
157
0
  EXPECT_TRUE(p.Next(t));
158
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_CHAR);
159
0
  EXPECT_TRUE(t.AsChar() == '%');
160
0
161
0
  nsAutoCString claim;
162
0
  p.Claim(claim, Tokenizer::EXCLUDE_LAST);
163
0
  EXPECT_TRUE(claim == "*\r\n");
164
0
  p.Claim(claim, Tokenizer::INCLUDE_LAST);
165
0
  EXPECT_TRUE(claim == "*\r\n%");
166
0
167
0
  p.Rollback();
168
0
  EXPECT_TRUE(p.CheckChar('%'));
169
0
170
0
  p.Record(Tokenizer::INCLUDE_LAST);
171
0
172
0
  EXPECT_FALSE(p.CheckWord("xy"));
173
0
174
0
  EXPECT_TRUE(p.CheckWord("xx"));
175
0
176
0
177
0
  p.Claim(claim, Tokenizer::INCLUDE_LAST);
178
0
  EXPECT_TRUE(claim == "%xx");
179
0
180
0
  EXPECT_TRUE(p.Next(t));
181
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_CHAR);
182
0
  EXPECT_TRUE(t.AsChar() == ',');
183
0
184
0
  EXPECT_TRUE(p.CheckChar('-'));
185
0
186
0
  EXPECT_TRUE(p.Next(t));
187
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_INTEGER);
188
0
  EXPECT_TRUE(t.AsInteger() == 15);
189
0
190
0
  EXPECT_TRUE(p.Next(t));
191
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_EOL);
192
0
193
0
  EXPECT_TRUE(p.Next(t));
194
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_EOL);
195
0
196
0
  EXPECT_TRUE(p.Next(t));
197
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_EOF);
198
0
199
0
  EXPECT_FALSE(p.Next(t));
200
0
201
0
  p.Rollback();
202
0
  EXPECT_TRUE(p.Next(t));
203
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_EOF);
204
0
205
0
  EXPECT_FALSE(p.Next(t));
206
0
207
0
  p.Rollback();
208
0
  EXPECT_TRUE(p.CheckEOF());
209
0
210
0
  EXPECT_FALSE(p.CheckEOF());
211
0
}
212
213
TEST(Tokenizer, Main16)
214
0
{
215
0
  Tokenizer16::Token t;
216
0
217
0
  // Synthetic code-specific test
218
0
219
0
  Tokenizer16 p(NS_LITERAL_STRING("test123 ,15  \t*\r\n%xx,-15\r\r"));
220
0
221
0
  EXPECT_TRUE(p.Next(t));
222
0
  EXPECT_TRUE(t.Type() == Tokenizer16::TOKEN_WORD);
223
0
  EXPECT_TRUE(t.AsString() == NS_LITERAL_STRING("test123"));
224
0
225
0
  Tokenizer16::Token u;
226
0
  EXPECT_FALSE(p.Check(u));
227
0
228
0
  EXPECT_FALSE(p.CheckChar('!'));
229
0
230
0
  EXPECT_FALSE(p.Check(Tokenizer16::Token::Number(123)));
231
0
232
0
  EXPECT_TRUE(p.CheckWhite());
233
0
234
0
  EXPECT_TRUE(p.CheckChar(','));
235
0
236
0
  EXPECT_TRUE(p.Check(Tokenizer16::Token::Number(15)));
237
0
238
0
  p.Rollback();
239
0
  EXPECT_TRUE(p.Check(Tokenizer16::Token::Number(15)));
240
0
241
0
  p.Rollback();
242
0
  EXPECT_TRUE(p.Next(t));
243
0
  EXPECT_TRUE(t.Type() == Tokenizer16::TOKEN_INTEGER);
244
0
  EXPECT_TRUE(t.AsInteger() == 15);
245
0
246
0
  EXPECT_FALSE(p.CheckChar(IsOperator));
247
0
248
0
  EXPECT_TRUE(p.CheckWhite());
249
0
250
0
  p.SkipWhites();
251
0
252
0
  EXPECT_FALSE(p.CheckWhite());
253
0
254
0
  p.Rollback();
255
0
256
0
  EXPECT_TRUE(p.CheckWhite());
257
0
  EXPECT_TRUE(p.CheckWhite());
258
0
259
0
  p.Record(Tokenizer16::EXCLUDE_LAST);
260
0
261
0
  EXPECT_TRUE(p.CheckChar(IsOperator));
262
0
263
0
  p.Rollback();
264
0
265
0
  EXPECT_TRUE(p.Next(t));
266
0
  EXPECT_TRUE(t.Type() == Tokenizer16::TOKEN_CHAR);
267
0
  EXPECT_TRUE(t.AsChar() == '*');
268
0
269
0
  EXPECT_TRUE(p.Next(t));
270
0
  EXPECT_TRUE(t.Type() == Tokenizer16::TOKEN_EOL);
271
0
272
0
  EXPECT_TRUE(p.Next(t));
273
0
  EXPECT_TRUE(t.Type() == Tokenizer16::TOKEN_CHAR);
274
0
  EXPECT_TRUE(t.AsChar() == '%');
275
0
276
0
  nsAutoString claim;
277
0
  p.Claim(claim, Tokenizer16::EXCLUDE_LAST);
278
0
  EXPECT_TRUE(claim == NS_LITERAL_STRING("*\r\n"));
279
0
  p.Claim(claim, Tokenizer16::INCLUDE_LAST);
280
0
  EXPECT_TRUE(claim == NS_LITERAL_STRING("*\r\n%"));
281
0
282
0
  p.Rollback();
283
0
  EXPECT_TRUE(p.CheckChar('%'));
284
0
285
0
  p.Record(Tokenizer16::INCLUDE_LAST);
286
0
287
0
  EXPECT_FALSE(p.CheckWord(NS_LITERAL_STRING("xy")));
288
0
289
0
  EXPECT_TRUE(p.CheckWord(NS_LITERAL_STRING("xx")));
290
0
291
0
292
0
  p.Claim(claim, Tokenizer16::INCLUDE_LAST);
293
0
  EXPECT_TRUE(claim == NS_LITERAL_STRING("%xx"));
294
0
295
0
  EXPECT_TRUE(p.Next(t));
296
0
  EXPECT_TRUE(t.Type() == Tokenizer16::TOKEN_CHAR);
297
0
  EXPECT_TRUE(t.AsChar() == ',');
298
0
299
0
  EXPECT_TRUE(p.CheckChar('-'));
300
0
301
0
  EXPECT_TRUE(p.Next(t));
302
0
  EXPECT_TRUE(t.Type() == Tokenizer16::TOKEN_INTEGER);
303
0
  EXPECT_TRUE(t.AsInteger() == 15);
304
0
305
0
  EXPECT_TRUE(p.Next(t));
306
0
  EXPECT_TRUE(t.Type() == Tokenizer16::TOKEN_EOL);
307
0
308
0
  EXPECT_TRUE(p.Next(t));
309
0
  EXPECT_TRUE(t.Type() == Tokenizer16::TOKEN_EOL);
310
0
311
0
  EXPECT_TRUE(p.Next(t));
312
0
  EXPECT_TRUE(t.Type() == Tokenizer16::TOKEN_EOF);
313
0
314
0
  EXPECT_FALSE(p.Next(t));
315
0
316
0
  p.Rollback();
317
0
  EXPECT_TRUE(p.Next(t));
318
0
  EXPECT_TRUE(t.Type() == Tokenizer16::TOKEN_EOF);
319
0
320
0
  EXPECT_FALSE(p.Next(t));
321
0
322
0
  p.Rollback();
323
0
  EXPECT_TRUE(p.CheckEOF());
324
0
325
0
  EXPECT_FALSE(p.CheckEOF());
326
0
}
327
328
TEST(Tokenizer, SingleWord)
329
0
{
330
0
  // Single word with numbers in it test
331
0
332
0
  Tokenizer p(NS_LITERAL_CSTRING("test123"));
333
0
334
0
  EXPECT_TRUE(p.CheckWord("test123"));
335
0
  EXPECT_TRUE(p.CheckEOF());
336
0
}
337
338
TEST(Tokenizer, EndingAfterNumber)
339
0
{
340
0
  // An end handling after a number
341
0
342
0
  Tokenizer p(NS_LITERAL_CSTRING("123"));
343
0
344
0
  EXPECT_FALSE(p.CheckWord("123"));
345
0
  EXPECT_TRUE(p.Check(Tokenizer::Token::Number(123)));
346
0
  EXPECT_TRUE(p.CheckEOF());
347
0
}
348
349
TEST(Tokenizer, BadInteger)
350
0
{
351
0
  Tokenizer::Token t;
352
0
353
0
  // A bad integer test
354
0
355
0
  Tokenizer p(NS_LITERAL_CSTRING("189234891274981758617846178651647620587135"));
356
0
357
0
  EXPECT_TRUE(p.Next(t));
358
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_ERROR);
359
0
  EXPECT_TRUE(p.CheckEOF());
360
0
}
361
362
TEST(Tokenizer, CheckExpectedTokenValue)
363
0
{
364
0
  Tokenizer::Token t;
365
0
366
0
  // Check expected token value test
367
0
368
0
  Tokenizer p(NS_LITERAL_CSTRING("blue velvet"));
369
0
370
0
  EXPECT_FALSE(p.Check(Tokenizer::TOKEN_INTEGER, t));
371
0
372
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_WORD, t));
373
0
  EXPECT_TRUE(t.AsString() == "blue");
374
0
375
0
  EXPECT_FALSE(p.Check(Tokenizer::TOKEN_WORD, t));
376
0
377
0
  EXPECT_TRUE(p.CheckWhite());
378
0
379
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_WORD, t));
380
0
  EXPECT_TRUE(t.AsString() == "velvet");
381
0
382
0
  EXPECT_TRUE(p.CheckEOF());
383
0
384
0
  EXPECT_FALSE(p.Next(t));
385
0
}
386
387
TEST(Tokenizer, HasFailed)
388
0
{
389
0
  Tokenizer::Token t;
390
0
391
0
  // HasFailed test
392
0
393
0
  Tokenizer p1(NS_LITERAL_CSTRING("a b"));
394
0
395
0
  while (p1.Next(t) && t.Type() != Tokenizer::TOKEN_CHAR);
396
0
  EXPECT_TRUE(p1.HasFailed());
397
0
398
0
399
0
  Tokenizer p2(NS_LITERAL_CSTRING("a b ?!c"));
400
0
401
0
  EXPECT_FALSE(p2.CheckChar('c'));
402
0
  EXPECT_TRUE(p2.HasFailed());
403
0
  EXPECT_TRUE(p2.CheckChar(HttpHeaderCharacter));
404
0
  EXPECT_FALSE(p2.HasFailed());
405
0
  p2.SkipWhites();
406
0
  EXPECT_FALSE(p2.HasFailed());
407
0
  EXPECT_FALSE(p2.CheckChar('c'));
408
0
  EXPECT_TRUE(p2.HasFailed());
409
0
  EXPECT_TRUE(p2.Next(t));
410
0
  EXPECT_FALSE(p2.HasFailed());
411
0
  EXPECT_TRUE(p2.Next(t));
412
0
  EXPECT_FALSE(p2.HasFailed());
413
0
  EXPECT_FALSE(p2.CheckChar('c'));
414
0
  EXPECT_TRUE(p2.HasFailed());
415
0
  EXPECT_TRUE(p2.Check(Tokenizer::TOKEN_CHAR, t));
416
0
  EXPECT_FALSE(p2.HasFailed());
417
0
  EXPECT_FALSE(p2.CheckChar('#'));
418
0
  EXPECT_TRUE(p2.HasFailed());
419
0
  t = Tokenizer::Token::Char('!');
420
0
  EXPECT_TRUE(p2.Check(t));
421
0
  EXPECT_FALSE(p2.HasFailed());
422
0
423
0
  while (p2.Next(t) && t.Type() != Tokenizer::TOKEN_CHAR);
424
0
  EXPECT_TRUE(p2.HasFailed());
425
0
}
426
427
TEST(Tokenizer, Construction)
428
0
{
429
0
  {
430
0
    nsCString a("test");
431
0
    Tokenizer p1(a);
432
0
    EXPECT_TRUE(p1.CheckWord("test"));
433
0
    EXPECT_TRUE(p1.CheckEOF());
434
0
  }
435
0
436
0
  {
437
0
    nsAutoCString a("test");
438
0
    Tokenizer p1(a);
439
0
    EXPECT_TRUE(p1.CheckWord("test"));
440
0
    EXPECT_TRUE(p1.CheckEOF());
441
0
  }
442
0
443
0
  {
444
0
    static const char _a[] = "test";
445
0
    nsDependentCString a(_a);
446
0
    Tokenizer p1(a);
447
0
    EXPECT_TRUE(p1.CheckWord("test"));
448
0
    EXPECT_TRUE(p1.CheckEOF());
449
0
  }
450
0
451
0
  {
452
0
    static const char* _a = "test";
453
0
    nsDependentCString a(_a);
454
0
    Tokenizer p1(a);
455
0
    EXPECT_TRUE(p1.CheckWord("test"));
456
0
    EXPECT_TRUE(p1.CheckEOF());
457
0
  }
458
0
459
0
  {
460
0
    Tokenizer p1(nsDependentCString("test"));
461
0
    EXPECT_TRUE(p1.CheckWord("test"));
462
0
    EXPECT_TRUE(p1.CheckEOF());
463
0
  }
464
0
465
0
  {
466
0
    Tokenizer p1(NS_LITERAL_CSTRING("test"));
467
0
    EXPECT_TRUE(p1.CheckWord("test"));
468
0
    EXPECT_TRUE(p1.CheckEOF());
469
0
  }
470
0
471
0
  {
472
0
    Tokenizer p1("test");
473
0
    EXPECT_TRUE(p1.CheckWord("test"));
474
0
    EXPECT_TRUE(p1.CheckEOF());
475
0
  }
476
0
}
477
478
TEST(Tokenizer, Customization)
479
0
{
480
0
  Tokenizer p1(NS_LITERAL_CSTRING("test-custom*words and\tdefault-whites"), nullptr, "-*");
481
0
  EXPECT_TRUE(p1.CheckWord("test-custom*words"));
482
0
  EXPECT_TRUE(p1.CheckWhite());
483
0
  EXPECT_TRUE(p1.CheckWord("and"));
484
0
  EXPECT_TRUE(p1.CheckWhite());
485
0
  EXPECT_TRUE(p1.CheckWord("default-whites"));
486
0
487
0
  Tokenizer p2(NS_LITERAL_CSTRING("test, custom,whites"), ", ");
488
0
  EXPECT_TRUE(p2.CheckWord("test"));
489
0
  EXPECT_TRUE(p2.CheckWhite());
490
0
  EXPECT_TRUE(p2.CheckWhite());
491
0
  EXPECT_TRUE(p2.CheckWord("custom"));
492
0
  EXPECT_TRUE(p2.CheckWhite());
493
0
  EXPECT_TRUE(p2.CheckWord("whites"));
494
0
495
0
  Tokenizer p3(NS_LITERAL_CSTRING("test, custom, whites-and#word-chars"), ",", "-#");
496
0
  EXPECT_TRUE(p3.CheckWord("test"));
497
0
  EXPECT_TRUE(p3.CheckWhite());
498
0
  EXPECT_FALSE(p3.CheckWhite());
499
0
  EXPECT_TRUE(p3.CheckChar(' '));
500
0
  EXPECT_TRUE(p3.CheckWord("custom"));
501
0
  EXPECT_TRUE(p3.CheckWhite());
502
0
  EXPECT_FALSE(p3.CheckWhite());
503
0
  EXPECT_TRUE(p3.CheckChar(' '));
504
0
  EXPECT_TRUE(p3.CheckWord("whites-and#word-chars"));
505
0
}
506
507
TEST(Tokenizer, ShortcutChecks)
508
0
{
509
0
  Tokenizer p("test1 test2,123");
510
0
511
0
  nsAutoCString test1;
512
0
  nsDependentCSubstring test2;
513
0
  char comma;
514
0
  uint32_t integer;
515
0
516
0
  EXPECT_TRUE(p.ReadWord(test1));
517
0
  EXPECT_TRUE(test1 == "test1");
518
0
  p.SkipWhites();
519
0
  EXPECT_TRUE(p.ReadWord(test2));
520
0
  EXPECT_TRUE(test2 == "test2");
521
0
  EXPECT_TRUE(p.ReadChar(&comma));
522
0
  EXPECT_TRUE(comma == ',');
523
0
  EXPECT_TRUE(p.ReadInteger(&integer));
524
0
  EXPECT_TRUE(integer == 123);
525
0
  EXPECT_TRUE(p.CheckEOF());
526
0
}
527
528
static bool ABChar(const char aChar)
529
0
{
530
0
  return aChar == 'a' || aChar == 'b';
531
0
}
532
533
TEST(Tokenizer, ReadCharClassified)
534
0
{
535
0
  Tokenizer p("abc");
536
0
537
0
  char c;
538
0
  EXPECT_TRUE(p.ReadChar(ABChar, &c));
539
0
  EXPECT_TRUE(c == 'a');
540
0
  EXPECT_TRUE(p.ReadChar(ABChar, &c));
541
0
  EXPECT_TRUE(c == 'b');
542
0
  EXPECT_FALSE(p.ReadChar(ABChar, &c));
543
0
  nsDependentCSubstring w;
544
0
  EXPECT_TRUE(p.ReadWord(w));
545
0
  EXPECT_TRUE(w == "c");
546
0
  EXPECT_TRUE(p.CheckEOF());
547
0
}
548
549
TEST(Tokenizer, ClaimSubstring)
550
0
{
551
0
  Tokenizer p(" abc ");
552
0
553
0
  EXPECT_TRUE(p.CheckWhite());
554
0
555
0
  p.Record();
556
0
  EXPECT_TRUE(p.CheckWord("abc"));
557
0
  nsDependentCSubstring v;
558
0
  p.Claim(v, Tokenizer::INCLUDE_LAST);
559
0
  EXPECT_TRUE(v == "abc");
560
0
  EXPECT_TRUE(p.CheckWhite());
561
0
  EXPECT_TRUE(p.CheckEOF());
562
0
}
563
564
TEST(Tokenizer, Fragment)
565
0
{
566
0
  const char str[] = "ab;cd:10 ";
567
0
  Tokenizer p(str);
568
0
  nsDependentCSubstring f;
569
0
570
0
  Tokenizer::Token t1, t2;
571
0
572
0
  EXPECT_TRUE(p.Next(t1));
573
0
  EXPECT_TRUE(t1.Type() == Tokenizer::TOKEN_WORD);
574
0
  EXPECT_TRUE(t1.Fragment() == "ab");
575
0
  EXPECT_TRUE(t1.Fragment().BeginReading() == &str[0]);
576
0
577
0
  p.Rollback();
578
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_WORD, t2));
579
0
  EXPECT_TRUE(t2.Fragment() == "ab");
580
0
  EXPECT_TRUE(t2.Fragment().BeginReading() == &str[0]);
581
0
582
0
583
0
  EXPECT_TRUE(p.Next(t1));
584
0
  EXPECT_TRUE(t1.Type() == Tokenizer::TOKEN_CHAR);
585
0
  EXPECT_TRUE(t1.Fragment() == ";");
586
0
  EXPECT_TRUE(t1.Fragment().BeginReading() == &str[2]);
587
0
588
0
  p.Rollback();
589
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_CHAR, t2));
590
0
  EXPECT_TRUE(t2.Fragment() == ";");
591
0
  EXPECT_TRUE(t2.Fragment().BeginReading() == &str[2]);
592
0
593
0
594
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_WORD, t2));
595
0
  EXPECT_TRUE(t2.Fragment() == "cd");
596
0
  EXPECT_TRUE(t2.Fragment().BeginReading() == &str[3]);
597
0
598
0
  p.Rollback();
599
0
  EXPECT_TRUE(p.Next(t1));
600
0
  EXPECT_TRUE(t1.Type() == Tokenizer::TOKEN_WORD);
601
0
  EXPECT_TRUE(t1.Fragment() == "cd");
602
0
  EXPECT_TRUE(t1.Fragment().BeginReading() == &str[3]);
603
0
604
0
605
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_CHAR, t2));
606
0
  EXPECT_TRUE(t2.Fragment() == ":");
607
0
  EXPECT_TRUE(t2.Fragment().BeginReading() == &str[5]);
608
0
609
0
  p.Rollback();
610
0
  EXPECT_TRUE(p.Next(t1));
611
0
  EXPECT_TRUE(t1.Type() == Tokenizer::TOKEN_CHAR);
612
0
  EXPECT_TRUE(t1.Fragment() == ":");
613
0
  EXPECT_TRUE(t1.Fragment().BeginReading() == &str[5]);
614
0
615
0
616
0
  EXPECT_TRUE(p.Next(t1));
617
0
  EXPECT_TRUE(t1.Type() == Tokenizer::TOKEN_INTEGER);
618
0
  EXPECT_TRUE(t1.Fragment() == "10");
619
0
  EXPECT_TRUE(t1.Fragment().BeginReading() == &str[6]);
620
0
621
0
622
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_WS, t2));
623
0
  EXPECT_TRUE(t2.Fragment() == " ");
624
0
  EXPECT_TRUE(t2.Fragment().BeginReading() == &str[8]);
625
0
626
0
627
0
  EXPECT_TRUE(p.Check(Tokenizer::TOKEN_EOF, t1));
628
0
  EXPECT_TRUE(t1.Fragment() == "");
629
0
  EXPECT_TRUE(t1.Fragment().BeginReading() == &str[9]);
630
0
}
631
632
TEST(Tokenizer, SkipWhites)
633
0
{
634
0
  Tokenizer p("Text1 \nText2 \nText3\n Text4\n ");
635
0
636
0
  EXPECT_TRUE(p.CheckWord("Text1"));
637
0
  p.SkipWhites();
638
0
  EXPECT_TRUE(p.CheckEOL());
639
0
640
0
  EXPECT_TRUE(p.CheckWord("Text2"));
641
0
  p.SkipWhites(Tokenizer::INCLUDE_NEW_LINE);
642
0
643
0
  EXPECT_TRUE(p.CheckWord("Text3"));
644
0
  p.SkipWhites();
645
0
  EXPECT_TRUE(p.CheckEOL());
646
0
  p.SkipWhites();
647
0
648
0
  EXPECT_TRUE(p.CheckWord("Text4"));
649
0
  p.SkipWhites(Tokenizer::INCLUDE_NEW_LINE);
650
0
  EXPECT_TRUE(p.CheckEOF());
651
0
}
652
653
TEST(Tokenizer, SkipCustomWhites)
654
0
{
655
0
  Tokenizer p("Text1 \n\r\t.Text2 \n\r\t.", " \n\r\t.");
656
0
657
0
  EXPECT_TRUE(p.CheckWord("Text1"));
658
0
  p.SkipWhites();
659
0
  EXPECT_TRUE(p.CheckWord("Text2"));
660
0
  EXPECT_TRUE(p.CheckWhite());
661
0
  EXPECT_TRUE(p.CheckWhite());
662
0
  EXPECT_TRUE(p.CheckWhite());
663
0
  EXPECT_TRUE(p.CheckWhite());
664
0
  EXPECT_TRUE(p.CheckWhite());
665
0
  EXPECT_TRUE(p.CheckEOF());
666
0
}
667
668
TEST(Tokenizer, IntegerReading)
669
0
{
670
0
#define INT_6_BITS                 64U
671
0
#define INT_30_BITS                1073741824UL
672
0
#define INT_32_BITS                4294967295UL
673
0
#define INT_50_BITS                1125899906842624ULL
674
0
#define STR_INT_MORE_THAN_64_BITS "922337203685477580899"
675
0
676
0
  {
677
0
    Tokenizer p(NS_STRINGIFY(INT_6_BITS));
678
0
    uint8_t u8;
679
0
    uint16_t u16;
680
0
    uint32_t u32;
681
0
    uint64_t u64;
682
0
    EXPECT_TRUE(p.ReadInteger(&u8));
683
0
    EXPECT_TRUE(u8 == INT_6_BITS);
684
0
    p.Rollback();
685
0
    EXPECT_TRUE(p.ReadInteger(&u16));
686
0
    EXPECT_TRUE(u16 == INT_6_BITS);
687
0
    p.Rollback();
688
0
    EXPECT_TRUE(p.ReadInteger(&u32));
689
0
    EXPECT_TRUE(u32 == INT_6_BITS);
690
0
    p.Rollback();
691
0
    EXPECT_TRUE(p.ReadInteger(&u64));
692
0
    EXPECT_TRUE(u64 == INT_6_BITS);
693
0
694
0
    p.Rollback();
695
0
696
0
    int8_t s8;
697
0
    int16_t s16;
698
0
    int32_t s32;
699
0
    int64_t s64;
700
0
    EXPECT_TRUE(p.ReadInteger(&s8));
701
0
    EXPECT_TRUE(s8 == INT_6_BITS);
702
0
    p.Rollback();
703
0
    EXPECT_TRUE(p.ReadInteger(&s16));
704
0
    EXPECT_TRUE(s16 == INT_6_BITS);
705
0
    p.Rollback();
706
0
    EXPECT_TRUE(p.ReadInteger(&s32));
707
0
    EXPECT_TRUE(s32 == INT_6_BITS);
708
0
    p.Rollback();
709
0
    EXPECT_TRUE(p.ReadInteger(&s64));
710
0
    EXPECT_TRUE(s64 == INT_6_BITS);
711
0
712
0
    EXPECT_TRUE(p.CheckWord("U"));
713
0
    EXPECT_TRUE(p.CheckEOF());
714
0
  }
715
0
716
0
  {
717
0
    Tokenizer p(NS_STRINGIFY(INT_30_BITS));
718
0
    uint8_t u8;
719
0
    uint16_t u16;
720
0
    uint32_t u32;
721
0
    uint64_t u64;
722
0
    EXPECT_FALSE(p.ReadInteger(&u8));
723
0
    EXPECT_FALSE(p.ReadInteger(&u16));
724
0
    EXPECT_TRUE(p.ReadInteger(&u32));
725
0
    EXPECT_TRUE(u32 == INT_30_BITS);
726
0
    p.Rollback();
727
0
    EXPECT_TRUE(p.ReadInteger(&u64));
728
0
    EXPECT_TRUE(u64 == INT_30_BITS);
729
0
730
0
    p.Rollback();
731
0
732
0
    int8_t s8;
733
0
    int16_t s16;
734
0
    int32_t s32;
735
0
    int64_t s64;
736
0
    EXPECT_FALSE(p.ReadInteger(&s8));
737
0
    EXPECT_FALSE(p.ReadInteger(&s16));
738
0
    EXPECT_TRUE(p.ReadInteger(&s32));
739
0
    EXPECT_TRUE(s32 == INT_30_BITS);
740
0
    p.Rollback();
741
0
    EXPECT_TRUE(p.ReadInteger(&s64));
742
0
    EXPECT_TRUE(s64 == INT_30_BITS);
743
0
    EXPECT_TRUE(p.CheckWord("UL"));
744
0
    EXPECT_TRUE(p.CheckEOF());
745
0
  }
746
0
747
0
  {
748
0
    Tokenizer p(NS_STRINGIFY(INT_32_BITS));
749
0
    uint32_t u32;
750
0
    int32_t s32;
751
0
    EXPECT_FALSE(p.ReadInteger(&s32));
752
0
    EXPECT_TRUE(p.ReadInteger(&u32));
753
0
    EXPECT_TRUE(u32 == INT_32_BITS);
754
0
    EXPECT_TRUE(p.CheckWord("UL"));
755
0
    EXPECT_TRUE(p.CheckEOF());
756
0
  }
757
0
758
0
  {
759
0
    Tokenizer p(NS_STRINGIFY(INT_50_BITS));
760
0
    uint8_t u8;
761
0
    uint16_t u16;
762
0
    uint32_t u32;
763
0
    uint64_t u64;
764
0
    EXPECT_FALSE(p.ReadInteger(&u8));
765
0
    EXPECT_FALSE(p.ReadInteger(&u16));
766
0
    EXPECT_FALSE(p.ReadInteger(&u32));
767
0
    EXPECT_TRUE(p.ReadInteger(&u64));
768
0
    EXPECT_TRUE(u64 == INT_50_BITS);
769
0
    EXPECT_TRUE(p.CheckWord("ULL"));
770
0
    EXPECT_TRUE(p.CheckEOF());
771
0
  }
772
0
773
0
  {
774
0
    Tokenizer p(STR_INT_MORE_THAN_64_BITS);
775
0
    int64_t i;
776
0
    EXPECT_FALSE(p.ReadInteger(&i));
777
0
    uint64_t u;
778
0
    EXPECT_FALSE(p.ReadInteger(&u));
779
0
    EXPECT_FALSE(p.CheckEOF());
780
0
  }
781
0
}
782
783
TEST(Tokenizer, ReadUntil)
784
0
{
785
0
  Tokenizer p("Hello;test 4,");
786
0
  nsDependentCSubstring f;
787
0
  EXPECT_TRUE(p.ReadUntil(Tokenizer::Token::Char(';'), f));
788
0
  EXPECT_TRUE(f == "Hello");
789
0
  p.Rollback();
790
0
791
0
  EXPECT_TRUE(p.ReadUntil(Tokenizer::Token::Char(';'), f, Tokenizer::INCLUDE_LAST));
792
0
  EXPECT_TRUE(f == "Hello;");
793
0
  p.Rollback();
794
0
795
0
  EXPECT_FALSE(p.ReadUntil(Tokenizer::Token::Char('!'), f));
796
0
  EXPECT_TRUE(f == "Hello;test 4,");
797
0
  p.Rollback();
798
0
799
0
  EXPECT_TRUE(p.ReadUntil(Tokenizer::Token::Word(NS_LITERAL_CSTRING("test")), f));
800
0
  EXPECT_TRUE(f == "Hello;");
801
0
  p.Rollback();
802
0
803
0
  EXPECT_TRUE(p.ReadUntil(Tokenizer::Token::Word(NS_LITERAL_CSTRING("test")), f, Tokenizer::INCLUDE_LAST));
804
0
  EXPECT_TRUE(f == "Hello;test");
805
0
  EXPECT_TRUE(p.ReadUntil(Tokenizer::Token::Char(','), f));
806
0
  EXPECT_TRUE(f == " 4");
807
0
}
808
809
TEST(Tokenizer, SkipUntil)
810
0
{
811
0
  {
812
0
    Tokenizer p("test1,test2,,,test3");
813
0
814
0
    p.SkipUntil(Tokenizer::Token::Char(','));
815
0
    EXPECT_TRUE(p.CheckChar(','));
816
0
    EXPECT_TRUE(p.CheckWord("test2"));
817
0
818
0
    p.SkipUntil(Tokenizer::Token::Char(',')); // must not move
819
0
    EXPECT_TRUE(p.CheckChar(',')); // check the first comma of the ',,,' string
820
0
821
0
    p.Rollback(); // moves cursor back to the first comma of the ',,,' string
822
0
823
0
    p.SkipUntil(Tokenizer::Token::Char(',')); // must not move, we are on the ',' char
824
0
    EXPECT_TRUE(p.CheckChar(','));
825
0
    EXPECT_TRUE(p.CheckChar(','));
826
0
    EXPECT_TRUE(p.CheckChar(','));
827
0
    EXPECT_TRUE(p.CheckWord("test3"));
828
0
    p.Rollback();
829
0
830
0
    p.SkipUntil(Tokenizer::Token::Char(','));
831
0
    EXPECT_TRUE(p.CheckEOF());
832
0
  }
833
0
834
0
  {
835
0
    Tokenizer p("test0,test1,test2");
836
0
837
0
    p.SkipUntil(Tokenizer::Token::Char(','));
838
0
    EXPECT_TRUE(p.CheckChar(','));
839
0
840
0
    p.SkipUntil(Tokenizer::Token::Char(','));
841
0
    p.Rollback();
842
0
843
0
    EXPECT_TRUE(p.CheckWord("test1"));
844
0
    EXPECT_TRUE(p.CheckChar(','));
845
0
846
0
    p.SkipUntil(Tokenizer::Token::Char(','));
847
0
    p.Rollback();
848
0
849
0
    EXPECT_TRUE(p.CheckWord("test2"));
850
0
    EXPECT_TRUE(p.CheckEOF());
851
0
  }
852
0
}
853
854
TEST(Tokenizer, Custom)
855
0
{
856
0
  Tokenizer p("aaaaaacustom-1\r,custom-1,Custom-1,Custom-1,00custom-2xxxx,CUSTOM-2");
857
0
858
0
  Tokenizer::Token c1 = p.AddCustomToken("custom-1", Tokenizer::CASE_INSENSITIVE);
859
0
  Tokenizer::Token c2 = p.AddCustomToken("custom-2", Tokenizer::CASE_SENSITIVE);
860
0
861
0
  // It's expected to NOT FIND the custom token if it's not on an edge
862
0
  // between other recognizable tokens.
863
0
  EXPECT_TRUE(p.CheckWord("aaaaaacustom"));
864
0
  EXPECT_TRUE(p.CheckChar('-'));
865
0
  EXPECT_TRUE(p.Check(Tokenizer::Token::Number(1)));
866
0
  EXPECT_TRUE(p.CheckEOL());
867
0
  EXPECT_TRUE(p.CheckChar(','));
868
0
869
0
  EXPECT_TRUE(p.Check(c1));
870
0
  EXPECT_TRUE(p.CheckChar(','));
871
0
872
0
  EXPECT_TRUE(p.Check(c1));
873
0
  EXPECT_TRUE(p.CheckChar(','));
874
0
875
0
  p.EnableCustomToken(c1, false);
876
0
  EXPECT_TRUE(p.CheckWord("Custom"));
877
0
  EXPECT_TRUE(p.CheckChar('-'));
878
0
  EXPECT_TRUE(p.Check(Tokenizer::Token::Number(1)));
879
0
  EXPECT_TRUE(p.CheckChar(','));
880
0
881
0
  EXPECT_TRUE(p.Check(Tokenizer::Token::Number(0)));
882
0
  EXPECT_TRUE(p.Check(c2));
883
0
  EXPECT_TRUE(p.CheckWord("xxxx"));
884
0
  EXPECT_TRUE(p.CheckChar(','));
885
0
886
0
  EXPECT_TRUE(p.CheckWord("CUSTOM"));
887
0
  EXPECT_TRUE(p.CheckChar('-'));
888
0
  EXPECT_TRUE(p.Check(Tokenizer::Token::Number(2)));
889
0
890
0
  EXPECT_TRUE(p.CheckEOF());
891
0
}
892
893
TEST(Tokenizer, CustomRaw)
894
0
{
895
0
  Tokenizer p("aaaaaacustom-1\r,custom-1,Custom-1,Custom-1,00custom-2xxxx,CUSTOM-2");
896
0
897
0
  Tokenizer::Token c1 = p.AddCustomToken("custom-1", Tokenizer::CASE_INSENSITIVE);
898
0
  Tokenizer::Token c2 = p.AddCustomToken("custom-2", Tokenizer::CASE_SENSITIVE);
899
0
900
0
  // In this mode it's expected to find all custom tokens among any kind of input.
901
0
  p.SetTokenizingMode(Tokenizer::Mode::CUSTOM_ONLY);
902
0
903
0
  Tokenizer::Token t;
904
0
905
0
  EXPECT_TRUE(p.Next(t));
906
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_RAW);
907
0
  EXPECT_TRUE(t.Fragment().EqualsLiteral("aaaaaa"));
908
0
909
0
  EXPECT_TRUE(p.Check(c1));
910
0
911
0
  EXPECT_TRUE(p.Next(t));
912
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_RAW);
913
0
  EXPECT_TRUE(t.Fragment().EqualsLiteral("\r,"));
914
0
915
0
  EXPECT_TRUE(p.Check(c1));
916
0
917
0
  EXPECT_TRUE(p.Next(t));
918
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_RAW);
919
0
  EXPECT_TRUE(t.Fragment().EqualsLiteral(","));
920
0
921
0
  EXPECT_TRUE(p.Check(c1));
922
0
923
0
  EXPECT_TRUE(p.Next(t));
924
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_RAW);
925
0
  EXPECT_TRUE(t.Fragment().EqualsLiteral(","));
926
0
927
0
  EXPECT_TRUE(p.Check(c1));
928
0
929
0
  EXPECT_TRUE(p.Next(t));
930
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_RAW);
931
0
  EXPECT_TRUE(t.Fragment().EqualsLiteral(",00"));
932
0
933
0
  EXPECT_TRUE(p.Check(c2));
934
0
935
0
  EXPECT_TRUE(p.Next(t));
936
0
  EXPECT_TRUE(t.Type() == Tokenizer::TOKEN_RAW);
937
0
  EXPECT_TRUE(t.Fragment().EqualsLiteral("xxxx,CUSTOM-2"));
938
0
939
0
  EXPECT_TRUE(p.CheckEOF());
940
0
}
941
942
TEST(Tokenizer, Incremental)
943
0
{
944
0
  typedef IncrementalTokenizer::Token Token;
945
0
946
0
  int test = 0;
947
0
  IncrementalTokenizer i([&](Token const& t, IncrementalTokenizer& i) -> nsresult
948
0
  {
949
0
    switch (++test) {
950
0
      case 1: EXPECT_TRUE(t.Equals(Token::Word(NS_LITERAL_CSTRING("test1")))); break;
951
0
      case 2: EXPECT_TRUE(t.Equals(Token::Char(','))); break;
952
0
      case 3: EXPECT_TRUE(t.Equals(Token::Word(NS_LITERAL_CSTRING("test2")))); break;
953
0
      case 4: EXPECT_TRUE(t.Equals(Token::Char(','))); break;
954
0
      case 5: EXPECT_TRUE(t.Equals(Token::Char(','))); break;
955
0
      case 6: EXPECT_TRUE(t.Equals(Token::Char(','))); break;
956
0
      case 7: EXPECT_TRUE(t.Equals(Token::Word(NS_LITERAL_CSTRING("test3")))); break;
957
0
      case 8: EXPECT_TRUE(t.Equals(Token::EndOfFile())); break;
958
0
    }
959
0
960
0
    return NS_OK;
961
0
  });
962
0
963
0
  NS_NAMED_LITERAL_CSTRING(input, "test1,test2,,,test3");
964
0
  auto cur = input.BeginReading();
965
0
  auto end = input.EndReading();
966
0
  for (; cur < end; ++cur) {
967
0
    i.FeedInput(nsDependentCSubstring(cur, 1));
968
0
  }
969
0
970
0
  EXPECT_TRUE(test == 6);
971
0
  i.FinishInput();
972
0
  EXPECT_TRUE(test == 8);
973
0
}
974
975
TEST(Tokenizer, IncrementalRollback)
976
0
{
977
0
  typedef IncrementalTokenizer::Token Token;
978
0
979
0
  int test = 0;
980
0
  IncrementalTokenizer i([&](Token const& t, IncrementalTokenizer& i) -> nsresult
981
0
  {
982
0
    switch (++test) {
983
0
      case 1: EXPECT_TRUE(t.Equals(Token::Word(NS_LITERAL_CSTRING("test1")))); break;
984
0
      case 2: EXPECT_TRUE(t.Equals(Token::Char(','))); break;
985
0
      case 3: EXPECT_TRUE(t.Equals(Token::Word(NS_LITERAL_CSTRING("test2"))));
986
0
        i.Rollback(); // so that we get the token again
987
0
        break;
988
0
      case 4: EXPECT_TRUE(t.Equals(Token::Word(NS_LITERAL_CSTRING("test2")))); break;
989
0
      case 5: EXPECT_TRUE(t.Equals(Token::Char(','))); break;
990
0
      case 6: EXPECT_TRUE(t.Equals(Token::Char(','))); break;
991
0
      case 7: EXPECT_TRUE(t.Equals(Token::Char(','))); break;
992
0
      case 8: EXPECT_TRUE(t.Equals(Token::Word(NS_LITERAL_CSTRING("test3")))); break;
993
0
      case 9: EXPECT_TRUE(t.Equals(Token::EndOfFile())); break;
994
0
    }
995
0
996
0
    return NS_OK;
997
0
  });
998
0
999
0
  NS_NAMED_LITERAL_CSTRING(input, "test1,test2,,,test3");
1000
0
  auto cur = input.BeginReading();
1001
0
  auto end = input.EndReading();
1002
0
  for (; cur < end; ++cur) {
1003
0
    i.FeedInput(nsDependentCSubstring(cur, 1));
1004
0
  }
1005
0
1006
0
  EXPECT_TRUE(test == 7);
1007
0
  i.FinishInput();
1008
0
  EXPECT_TRUE(test == 9);
1009
0
}
1010
1011
TEST(Tokenizer, IncrementalNeedMoreInput)
1012
0
{
1013
0
  typedef IncrementalTokenizer::Token Token;
1014
0
1015
0
  int test = 0;
1016
0
  IncrementalTokenizer i([&](Token const& t, IncrementalTokenizer& i) -> nsresult
1017
0
  {
1018
0
    Token t2;
1019
0
    switch (++test) {
1020
0
    case 1:
1021
0
      EXPECT_TRUE(t.Equals(Token::Word(NS_LITERAL_CSTRING("a"))));
1022
0
      break;
1023
0
    case 2:
1024
0
    case 3:
1025
0
    case 4:
1026
0
    case 5:
1027
0
      EXPECT_TRUE(t.Equals(Token::Whitespace()));
1028
0
      if (i.Next(t2)) {
1029
0
        EXPECT_TRUE(test == 5);
1030
0
        EXPECT_TRUE(t2.Equals(Token::Word(NS_LITERAL_CSTRING("bb"))));
1031
0
      } else {
1032
0
        EXPECT_TRUE(test < 5);
1033
0
        i.NeedMoreInput();
1034
0
      }
1035
0
      break;
1036
0
    case 6:
1037
0
      EXPECT_TRUE(t.Equals(Token::Char(',')));
1038
0
      break;
1039
0
    case 7:
1040
0
      EXPECT_TRUE(t.Equals(Token::Word(NS_LITERAL_CSTRING("c"))));
1041
0
      return NS_ERROR_FAILURE;
1042
0
    default:
1043
0
      EXPECT_TRUE(false);
1044
0
      break;
1045
0
    }
1046
0
1047
0
    return NS_OK;
1048
0
  });
1049
0
1050
0
  NS_NAMED_LITERAL_CSTRING(input, "a bb,c");
1051
0
  auto cur = input.BeginReading();
1052
0
  auto end = input.EndReading();
1053
0
1054
0
  nsresult rv;
1055
0
  for (; cur < end; ++cur) {
1056
0
    rv = i.FeedInput(nsDependentCSubstring(cur, 1));
1057
0
    if (NS_FAILED(rv)) {
1058
0
      break;
1059
0
    }
1060
0
  }
1061
0
1062
0
  EXPECT_TRUE(rv == NS_OK);
1063
0
  EXPECT_TRUE(test == 6);
1064
0
1065
0
  rv = i.FinishInput();
1066
0
  EXPECT_TRUE(rv == NS_ERROR_FAILURE);
1067
0
  EXPECT_TRUE(test == 7);
1068
0
}
1069
1070
TEST(Tokenizer, IncrementalCustom)
1071
0
{
1072
0
  typedef IncrementalTokenizer::Token Token;
1073
0
1074
0
  int test = 0;
1075
0
  Token custom;
1076
0
  IncrementalTokenizer i([&](Token const& t, IncrementalTokenizer& i) -> nsresult
1077
0
  {
1078
0
    switch (++test) {
1079
0
      case 1: EXPECT_TRUE(t.Equals(custom)); break;
1080
0
      case 2: EXPECT_TRUE(t.Equals(Token::Word(NS_LITERAL_CSTRING("bla")))); break;
1081
0
      case 3: EXPECT_TRUE(t.Equals(Token::EndOfFile())); break;
1082
0
    }
1083
0
1084
0
    return NS_OK;
1085
0
  }, nullptr, "-");
1086
0
1087
0
  custom = i.AddCustomToken("some-test", Tokenizer::CASE_SENSITIVE);
1088
0
  i.FeedInput(NS_LITERAL_CSTRING("some-"));
1089
0
  EXPECT_TRUE(test == 0);
1090
0
  i.FeedInput(NS_LITERAL_CSTRING("tes"));
1091
0
  EXPECT_TRUE(test == 0);
1092
0
  i.FeedInput(NS_LITERAL_CSTRING("tbla"));
1093
0
  EXPECT_TRUE(test == 1);
1094
0
  i.FinishInput();
1095
0
  EXPECT_TRUE(test == 3);
1096
0
}
1097
1098
TEST(Tokenizer, IncrementalCustomRaw)
1099
0
{
1100
0
  typedef IncrementalTokenizer::Token Token;
1101
0
1102
0
  int test = 0;
1103
0
  Token custom;
1104
0
  IncrementalTokenizer i([&](Token const& t, IncrementalTokenizer& i) -> nsresult
1105
0
  {
1106
0
    switch (++test) {
1107
0
      case 1: EXPECT_TRUE(t.Fragment().EqualsLiteral("test1,")); break;
1108
0
      case 2: EXPECT_TRUE(t.Equals(custom)); break;
1109
0
      case 3: EXPECT_TRUE(t.Fragment().EqualsLiteral("!,,test3"));
1110
0
        i.Rollback();
1111
0
        i.SetTokenizingMode(Tokenizer::Mode::FULL);
1112
0
        break;
1113
0
      case 4: EXPECT_TRUE(t.Equals(Token::Char('!')));
1114
0
        i.SetTokenizingMode(Tokenizer::Mode::CUSTOM_ONLY);
1115
0
        break;
1116
0
      case 5: EXPECT_TRUE(t.Fragment().EqualsLiteral(",,test3")); break;
1117
0
      case 6: EXPECT_TRUE(t.Equals(custom)); break;
1118
0
      case 7: EXPECT_TRUE(t.Fragment().EqualsLiteral("tes")); break;
1119
0
      case 8: EXPECT_TRUE(t.Equals(Token::EndOfFile())); break;
1120
0
    }
1121
0
1122
0
    return NS_OK;
1123
0
  });
1124
0
1125
0
  custom = i.AddCustomToken("test2", Tokenizer::CASE_SENSITIVE);
1126
0
  i.SetTokenizingMode(Tokenizer::Mode::CUSTOM_ONLY);
1127
0
1128
0
  NS_NAMED_LITERAL_CSTRING(input, "test1,test2!,,test3test2tes");
1129
0
  auto cur = input.BeginReading();
1130
0
  auto end = input.EndReading();
1131
0
  for (; cur < end; ++cur) {
1132
0
    i.FeedInput(nsDependentCSubstring(cur, 1));
1133
0
  }
1134
0
1135
0
  EXPECT_TRUE(test == 6);
1136
0
  i.FinishInput();
1137
0
  EXPECT_TRUE(test == 8);
1138
0
}
1139
1140
TEST(Tokenizer, IncrementalCustomRemove)
1141
0
{
1142
0
  typedef IncrementalTokenizer::Token Token;
1143
0
1144
0
  int test = 0;
1145
0
  Token custom;
1146
0
  IncrementalTokenizer i([&](Token const& t, IncrementalTokenizer& i) -> nsresult
1147
0
  {
1148
0
    switch (++test) {
1149
0
      case 1: EXPECT_TRUE(t.Equals(custom));
1150
0
        i.RemoveCustomToken(custom);
1151
0
        break;
1152
0
      case 2: EXPECT_FALSE(t.Equals(custom)); break;
1153
0
      case 3: EXPECT_TRUE(t.Equals(Token::EndOfFile())); break;
1154
0
    }
1155
0
1156
0
    return NS_OK;
1157
0
  });
1158
0
1159
0
  custom = i.AddCustomToken("custom1", Tokenizer::CASE_SENSITIVE);
1160
0
1161
0
  NS_NAMED_LITERAL_CSTRING(input, "custom1custom1");
1162
0
  i.FeedInput(input);
1163
0
  EXPECT_TRUE(test == 1);
1164
0
  i.FinishInput();
1165
0
  EXPECT_TRUE(test == 3);
1166
0
}
1167
1168
TEST(Tokenizer, IncrementalBuffering1)
1169
0
{
1170
0
  typedef IncrementalTokenizer::Token Token;
1171
0
1172
0
  int test = 0;
1173
0
  Token custom;
1174
0
  nsDependentCSubstring observedFragment;
1175
0
  IncrementalTokenizer i([&](Token const& t, IncrementalTokenizer& i) -> nsresult
1176
0
  {
1177
0
    switch (++test) {
1178
0
      case 1: EXPECT_TRUE(t.Fragment().EqualsLiteral("012")); break;
1179
0
      case 2: EXPECT_TRUE(t.Fragment().EqualsLiteral("3456789")); break;
1180
0
      case 3: EXPECT_TRUE(t.Equals(custom)); break;
1181
0
      case 4: EXPECT_TRUE(t.Fragment().EqualsLiteral("qwe")); break;
1182
0
      case 5: EXPECT_TRUE(t.Fragment().EqualsLiteral("rt")); break;
1183
0
      case 6: EXPECT_TRUE(t.Equals(Token::EndOfFile())); break;
1184
0
    }
1185
0
1186
0
    observedFragment.Rebind(t.Fragment().BeginReading(),
1187
0
                            t.Fragment().Length());
1188
0
    return NS_OK;
1189
0
  }, nullptr, nullptr, 3);
1190
0
1191
0
  custom = i.AddCustomToken("aaa", Tokenizer::CASE_SENSITIVE);
1192
0
  // This externally unused token is added only to check the internal algorithm
1193
0
  // does work correctly as expected when there are two different length tokens.
1194
0
  Unused << i.AddCustomToken("bb", Tokenizer::CASE_SENSITIVE);
1195
0
  i.SetTokenizingMode(Tokenizer::Mode::CUSTOM_ONLY);
1196
0
1197
0
  i.FeedInput(NS_LITERAL_CSTRING("01234"));
1198
0
  EXPECT_TRUE(test == 1);
1199
0
  EXPECT_TRUE(observedFragment.EqualsLiteral("012"));
1200
0
1201
0
  i.FeedInput(NS_LITERAL_CSTRING("5"));
1202
0
  EXPECT_TRUE(test == 1);
1203
0
  i.FeedInput(NS_LITERAL_CSTRING("6789aa"));
1204
0
  EXPECT_TRUE(test == 2);
1205
0
  EXPECT_TRUE(observedFragment.EqualsLiteral("3456789"));
1206
0
1207
0
  i.FeedInput(NS_LITERAL_CSTRING("aqwert"));
1208
0
  EXPECT_TRUE(test == 4);
1209
0
  EXPECT_TRUE(observedFragment.EqualsLiteral("qwe"));
1210
0
1211
0
  i.FinishInput();
1212
0
  EXPECT_TRUE(test == 6);
1213
0
}
1214
1215
TEST(Tokenizer, IncrementalBuffering2)
1216
0
{
1217
0
  typedef IncrementalTokenizer::Token Token;
1218
0
1219
0
  int test = 0;
1220
0
  Token custom;
1221
0
  IncrementalTokenizer i([&](Token const& t, IncrementalTokenizer& i) -> nsresult
1222
0
  {
1223
0
    switch (++test) {
1224
0
      case 1: EXPECT_TRUE(t.Fragment().EqualsLiteral("01")); break;
1225
0
      case 2: EXPECT_TRUE(t.Fragment().EqualsLiteral("234567")); break;
1226
0
      case 3: EXPECT_TRUE(t.Fragment().EqualsLiteral("89")); break;
1227
0
      case 4: EXPECT_TRUE(t.Equals(custom)); break;
1228
0
      case 5: EXPECT_TRUE(t.Fragment().EqualsLiteral("qwert")); break;
1229
0
      case 6: EXPECT_TRUE(t.Equals(Token::EndOfFile())); break;
1230
0
    }
1231
0
    return NS_OK;
1232
0
  }, nullptr, nullptr, 3);
1233
0
1234
0
  custom = i.AddCustomToken("aaa", Tokenizer::CASE_SENSITIVE);
1235
0
  // This externally unused token is added only to check the internal algorithm
1236
0
  // does work correctly as expected when there are two different length tokens.
1237
0
  Unused << i.AddCustomToken("bbbbb", Tokenizer::CASE_SENSITIVE);
1238
0
  i.SetTokenizingMode(Tokenizer::Mode::CUSTOM_ONLY);
1239
0
1240
0
  i.FeedInput(NS_LITERAL_CSTRING("01234"));
1241
0
  EXPECT_TRUE(test == 0);
1242
0
  i.FeedInput(NS_LITERAL_CSTRING("5"));
1243
0
  EXPECT_TRUE(test == 1);
1244
0
  i.FeedInput(NS_LITERAL_CSTRING("6789aa"));
1245
0
  EXPECT_TRUE(test == 2);
1246
0
  i.FeedInput(NS_LITERAL_CSTRING("aqwert"));
1247
0
  EXPECT_TRUE(test == 4);
1248
0
  i.FinishInput();
1249
0
  EXPECT_TRUE(test == 6);
1250
0
}
1251
1252
TEST(Tokenizer, RecordAndReadUntil)
1253
0
{
1254
0
  Tokenizer t("aaaa,bbbb");
1255
0
  t.SkipWhites();
1256
0
  nsDependentCSubstring subject;
1257
0
1258
0
  EXPECT_TRUE(t.ReadUntil(mozilla::Tokenizer::Token::Char(','), subject));
1259
0
  EXPECT_FALSE(t.CheckChar(','));
1260
0
  EXPECT_TRUE(subject.Length() == 4);
1261
0
  EXPECT_TRUE(subject == "aaaa");
1262
0
1263
0
  EXPECT_FALSE(t.ReadUntil(mozilla::Tokenizer::Token::Char(','), subject));
1264
0
  EXPECT_TRUE(subject.Length() == 4);
1265
0
  EXPECT_TRUE(subject == "bbbb");
1266
0
1267
0
  EXPECT_FALSE(t.ReadUntil(mozilla::Tokenizer::Token::Char(','), subject));
1268
0
  EXPECT_TRUE(subject.Length() == 0);
1269
0
1270
0
  EXPECT_TRUE(t.CheckEOF());
1271
0
}
1272
1273
TEST(Tokenizer, ReadIntegers)
1274
0
{
1275
0
  // Make sure that adding dash (the 'minus' sign) as an additional char
1276
0
  // doesn't break reading negative numbers.
1277
0
  Tokenizer t("100,-100,200,-200,4294967295,-4294967295,-2147483647", nullptr, "-");
1278
0
1279
0
  uint32_t unsigned_value32;
1280
0
  int32_t signed_value32;
1281
0
  int64_t signed_value64;
1282
0
1283
0
  // "100,"
1284
0
  EXPECT_TRUE(t.ReadInteger(&unsigned_value32));
1285
0
  EXPECT_TRUE(unsigned_value32 == 100);
1286
0
  EXPECT_TRUE(t.CheckChar(','));
1287
0
1288
0
  // "-100,"
1289
0
  EXPECT_FALSE(t.ReadInteger(&unsigned_value32));
1290
0
  EXPECT_FALSE(t.CheckChar(','));
1291
0
1292
0
  EXPECT_TRUE(t.ReadSignedInteger(&signed_value32));
1293
0
  EXPECT_TRUE(signed_value32 == -100);
1294
0
  EXPECT_TRUE(t.CheckChar(','));
1295
0
1296
0
  // "200,"
1297
0
  EXPECT_TRUE(t.ReadSignedInteger(&signed_value32));
1298
0
  EXPECT_TRUE(signed_value32 == 200);
1299
0
  EXPECT_TRUE(t.CheckChar(','));
1300
0
1301
0
  // "-200,"
1302
0
  EXPECT_TRUE(t.ReadSignedInteger(&signed_value32));
1303
0
  EXPECT_TRUE(signed_value32 == -200);
1304
0
  EXPECT_TRUE(t.CheckChar(','));
1305
0
1306
0
  // "4294967295,"
1307
0
  EXPECT_FALSE(t.ReadSignedInteger(&signed_value32));
1308
0
  EXPECT_FALSE(t.CheckChar(','));
1309
0
1310
0
  EXPECT_TRUE(t.ReadInteger(&unsigned_value32));
1311
0
  EXPECT_TRUE(unsigned_value32 == 4294967295UL);
1312
0
  EXPECT_TRUE(t.CheckChar(','));
1313
0
1314
0
  // "-4294967295,"
1315
0
  EXPECT_FALSE(t.ReadSignedInteger(&signed_value32));
1316
0
  EXPECT_FALSE(t.CheckChar(','));
1317
0
1318
0
  EXPECT_FALSE(t.ReadInteger(&unsigned_value32));
1319
0
  EXPECT_FALSE(t.CheckChar(','));
1320
0
1321
0
  EXPECT_TRUE(t.ReadSignedInteger(&signed_value64));
1322
0
  EXPECT_TRUE(signed_value64 == -4294967295LL);
1323
0
  EXPECT_TRUE(t.CheckChar(','));
1324
0
1325
0
  // "-2147483647"
1326
0
  EXPECT_FALSE(t.ReadInteger(&unsigned_value32));
1327
0
  EXPECT_FALSE(t.CheckChar(','));
1328
0
1329
0
  EXPECT_TRUE(t.ReadSignedInteger(&signed_value32));
1330
0
  EXPECT_TRUE(signed_value32 == -2147483647L);
1331
0
  EXPECT_TRUE(t.CheckEOF());
1332
0
}