This function will generate all permutations of tokens to test that the parsing and formatting is correct (position of tokens should be irrelevant). Note that separators are also combined with EACH token permutation to get the widest coverage on formats. This forces out the parsing and format logic edge cases.
| 166 | // are also combined with EACH token permutation to get the widest coverage on formats. |
| 167 | // This forces out the parsing and format logic edge cases. |
| 168 | void TestTimestampTokens(vector<TimestampToken>* toks, int year, int month, |
| 169 | int day, int hours, int mins, int secs, int frac) { |
| 170 | const char* SEPARATORS = " ~!@%^&*_+-:;|\\,./"; |
| 171 | int toks_len = toks->size(); |
| 172 | sort(toks->begin(), toks->end()); |
| 173 | string fmt; |
| 174 | string val; |
| 175 | do { |
| 176 | // Validate we can parse date/time raw tokens (no separators) |
| 177 | { |
| 178 | for (int i = 0; i < toks_len; ++i) { |
| 179 | fmt.append((*toks)[i].fmt); |
| 180 | if ((*toks)[i].str != NULL) { |
| 181 | val.append(string((*toks)[i].str)); |
| 182 | } else { |
| 183 | val.append(lexical_cast<string>((*toks)[i].val)); |
| 184 | } |
| 185 | } |
| 186 | string fmt_val = StrCat("Format: ", fmt, ", Val: ", val); |
| 187 | DateTimeFormatContext dt_ctx(fmt.c_str()); |
| 188 | ASSERT_TRUE(SimpleDateFormatTokenizer::Tokenize(&dt_ctx, PARSE)) << fmt_val; |
| 189 | TimestampValue tv = |
| 190 | TimestampValue::ParseSimpleDateFormat(val.c_str(), val.length(), dt_ctx); |
| 191 | ValidateTimestamp(tv, fmt, val, fmt_val, year, month, day, hours, mins, secs, |
| 192 | frac); |
| 193 | string buff; |
| 194 | tv.Format(dt_ctx, buff); |
| 195 | EXPECT_TRUE(!buff.empty()) << fmt_val; |
| 196 | EXPECT_LE(buff.length(), dt_ctx.fmt_len) << fmt_val; |
| 197 | EXPECT_EQ(buff, val) << fmt_val << " " << buff; |
| 198 | fmt.clear(); |
| 199 | val.clear(); |
| 200 | } |
| 201 | // Validate we can parse date/time with separators |
| 202 | { |
| 203 | for (const char* separator = SEPARATORS; *separator != 0; |
| 204 | ++separator) { |
| 205 | for (int i = 0; i < toks_len; ++i) { |
| 206 | fmt.append((*toks)[i].fmt); |
| 207 | if (i + 1 < toks_len) fmt.push_back(*separator); |
| 208 | if ((*toks)[i].str != NULL) { |
| 209 | val.append(string((*toks)[i].str)); |
| 210 | } else { |
| 211 | val.append(lexical_cast<string>((*toks)[i].val)); |
| 212 | } |
| 213 | if (i + 1 < toks_len) val.push_back(*separator); |
| 214 | } |
| 215 | |
| 216 | string fmt_val = StrCat("Format: ", fmt, ", Val: ", val); |
| 217 | DateTimeFormatContext dt_ctx(fmt.c_str()); |
| 218 | ASSERT_TRUE(SimpleDateFormatTokenizer::Tokenize(&dt_ctx, PARSE)) << fmt_val; |
| 219 | TimestampValue tv = |
| 220 | TimestampValue::ParseSimpleDateFormat(val.c_str(), val.length(), dt_ctx); |
| 221 | ValidateTimestamp(tv, fmt, val, fmt_val, year, month, day, hours, mins, secs, |
| 222 | frac); |
| 223 | string buff; |
| 224 | tv.Format(dt_ctx, buff); |
| 225 | EXPECT_TRUE(!buff.empty()) << fmt_val; |
no test coverage detected