1 | // Copyright 2005 The RE2 Authors. All Rights Reserved. |
2 | // Use of this source code is governed by a BSD-style |
3 | // license that can be found in the LICENSE file. |
4 | |
5 | // This tests to make sure numbers are parsed from strings |
6 | // correctly. |
7 | // Todo: Expand the test to validate strings parsed to the other types |
8 | // supported by RE2::Arg class |
9 | |
10 | #include <stdint.h> |
11 | #include <string.h> |
12 | |
13 | #include "util/test.h" |
14 | #include "re2/re2.h" |
15 | |
16 | namespace re2 { |
17 | |
18 | struct SuccessTable { |
19 | const char * value_string; |
20 | int64_t value; |
21 | bool success[6]; |
22 | }; |
23 | |
24 | // Test boundary cases for different integral sizes. |
25 | // Specifically I want to make sure that values outside the boundries |
26 | // of an integral type will fail and that negative numbers will fail |
27 | // for unsigned types. The following table contains the boundaries for |
28 | // the various integral types and has entries for whether or not each |
29 | // type can contain the given value. |
30 | const SuccessTable kSuccessTable[] = { |
31 | // string integer value i16 u16 i32 u32 i64 u64 |
32 | // 0 to 2^7-1 |
33 | { "0" , 0, { true, true, true, true, true, true }}, |
34 | { "127" , 127, { true, true, true, true, true, true }}, |
35 | |
36 | // -1 to -2^7 |
37 | { "-1" , -1, { true, false, true, false, true, false }}, |
38 | { "-128" , -128, { true, false, true, false, true, false }}, |
39 | |
40 | // 2^7 to 2^8-1 |
41 | { "128" , 128, { true, true, true, true, true, true }}, |
42 | { "255" , 255, { true, true, true, true, true, true }}, |
43 | |
44 | // 2^8 to 2^15-1 |
45 | { "256" , 256, { true, true, true, true, true, true }}, |
46 | { "32767" , 32767, { true, true, true, true, true, true }}, |
47 | |
48 | // -2^7-1 to -2^15 |
49 | { "-129" , -129, { true, false, true, false, true, false }}, |
50 | { "-32768" , -32768, { true, false, true, false, true, false }}, |
51 | |
52 | // 2^15 to 2^16-1 |
53 | { "32768" , 32768, { false, true, true, true, true, true }}, |
54 | { "65535" , 65535, { false, true, true, true, true, true }}, |
55 | |
56 | // 2^16 to 2^31-1 |
57 | { "65536" , 65536, { false, false, true, true, true, true }}, |
58 | { "2147483647" , 2147483647, { false, false, true, true, true, true }}, |
59 | |
60 | // -2^15-1 to -2^31 |
61 | { "-32769" , -32769, { false, false, true, false, true, false }}, |
62 | { "-2147483648" , static_cast<int64_t>(0xFFFFFFFF80000000LL), |
63 | { false, false, true, false, true, false }}, |
64 | |
65 | // 2^31 to 2^32-1 |
66 | { "2147483648" , 2147483648U, { false, false, false, true, true, true }}, |
67 | { "4294967295" , 4294967295U, { false, false, false, true, true, true }}, |
68 | |
69 | // 2^32 to 2^63-1 |
70 | { "4294967296" , 4294967296LL, { false, false, false, false, true, true }}, |
71 | { "9223372036854775807" , |
72 | 9223372036854775807LL, { false, false, false, false, true, true }}, |
73 | |
74 | // -2^31-1 to -2^63 |
75 | { "-2147483649" , -2147483649LL, { false, false, false, false, true, false }}, |
76 | { "-9223372036854775808" , static_cast<int64_t>(0x8000000000000000LL), |
77 | { false, false, false, false, true, false }}, |
78 | |
79 | // 2^63 to 2^64-1 |
80 | { "9223372036854775808" , static_cast<int64_t>(9223372036854775808ULL), |
81 | { false, false, false, false, false, true }}, |
82 | { "18446744073709551615" , static_cast<int64_t>(18446744073709551615ULL), |
83 | { false, false, false, false, false, true }}, |
84 | |
85 | // >= 2^64 |
86 | { "18446744073709551616" , 0, { false, false, false, false, false, false }}, |
87 | }; |
88 | |
89 | const int kNumStrings = arraysize(kSuccessTable); |
90 | |
91 | // It's ugly to use a macro, but we apparently can't use the EXPECT_EQ |
92 | // macro outside of a TEST block and this seems to be the only way to |
93 | // avoid code duplication. I can also pull off a couple nice tricks |
94 | // using concatenation for the type I'm checking against. |
95 | #define PARSE_FOR_TYPE(type, column) { \ |
96 | type r; \ |
97 | for (int i = 0; i < kNumStrings; ++i) { \ |
98 | RE2::Arg arg(&r); \ |
99 | const char* const p = kSuccessTable[i].value_string; \ |
100 | bool retval = arg.Parse(p, strlen(p)); \ |
101 | bool success = kSuccessTable[i].success[column]; \ |
102 | EXPECT_EQ(retval, success) \ |
103 | << "Parsing '" << p << "' for type " #type " should return " \ |
104 | << success; \ |
105 | if (success) { \ |
106 | EXPECT_EQ(r, (type)kSuccessTable[i].value); \ |
107 | } \ |
108 | } \ |
109 | } |
110 | |
111 | TEST(RE2ArgTest, Int16Test) { |
112 | PARSE_FOR_TYPE(int16_t, 0); |
113 | } |
114 | |
115 | TEST(RE2ArgTest, Uint16Test) { |
116 | PARSE_FOR_TYPE(uint16_t, 1); |
117 | } |
118 | |
119 | TEST(RE2ArgTest, Int32Test) { |
120 | PARSE_FOR_TYPE(int32_t, 2); |
121 | } |
122 | |
123 | TEST(RE2ArgTest, Uint32Test) { |
124 | PARSE_FOR_TYPE(uint32_t, 3); |
125 | } |
126 | |
127 | TEST(RE2ArgTest, Int64Test) { |
128 | PARSE_FOR_TYPE(int64_t, 4); |
129 | } |
130 | |
131 | TEST(RE2ArgTest, Uint64Test) { |
132 | PARSE_FOR_TYPE(uint64_t, 5); |
133 | } |
134 | |
135 | } // namespace re2 |
136 | |