]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/simpleformattertest.cpp
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / test / intltest / simpleformattertest.cpp
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 * Copyright (C) 2014-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 *******************************************************************************
8 *
9 * simpleformattertest.cpp
10 *
11 ********************************************************************************
12 */
13
14 #include "unicode/msgfmt.h"
15 #include "unicode/unistr.h"
16 #include "cstring.h"
17 #include "intltest.h"
18 #include "unicode/simpleformatter.h"
19
20 class SimpleFormatterTest : public IntlTest {
21 public:
22 SimpleFormatterTest() {
23 }
24 void TestNoArguments();
25 void TestSyntaxErrors();
26 void TestOneArgument();
27 void TestBigArgument();
28 void TestManyArguments();
29 void TestTooFewArgumentValues();
30 void TestBadArguments();
31 void TestTextWithNoArguments();
32 void TestFormatReplaceNoOptimization();
33 void TestFormatReplaceNoOptimizationLeadingText();
34 void TestFormatReplaceOptimization();
35 void TestFormatReplaceNoOptimizationLeadingArgumentUsedTwice();
36 void TestFormatReplaceOptimizationNoOffsets();
37 void TestFormatReplaceNoOptimizationNoOffsets();
38 void TestQuotingLikeMessageFormat();
39 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0);
40 private:
41 void verifyOffsets(
42 const int32_t *expected,
43 const int32_t *actual,
44 int32_t count);
45 };
46
47 void SimpleFormatterTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par*/) {
48 TESTCASE_AUTO_BEGIN;
49 TESTCASE_AUTO(TestNoArguments);
50 TESTCASE_AUTO(TestSyntaxErrors);
51 TESTCASE_AUTO(TestOneArgument);
52 TESTCASE_AUTO(TestBigArgument);
53 TESTCASE_AUTO(TestManyArguments);
54 TESTCASE_AUTO(TestTooFewArgumentValues);
55 TESTCASE_AUTO(TestBadArguments);
56 TESTCASE_AUTO(TestTextWithNoArguments);
57 TESTCASE_AUTO(TestFormatReplaceNoOptimization);
58 TESTCASE_AUTO(TestFormatReplaceNoOptimizationLeadingText);
59 TESTCASE_AUTO(TestFormatReplaceOptimization);
60 TESTCASE_AUTO(TestFormatReplaceNoOptimizationLeadingArgumentUsedTwice);
61 TESTCASE_AUTO(TestFormatReplaceOptimizationNoOffsets);
62 TESTCASE_AUTO(TestFormatReplaceNoOptimizationNoOffsets);
63 TESTCASE_AUTO(TestQuotingLikeMessageFormat);
64 TESTCASE_AUTO_END;
65 }
66
67 void SimpleFormatterTest::TestNoArguments() {
68 UErrorCode status = U_ZERO_ERROR;
69 SimpleFormatter fmt("This doesn''t have templates '{0}", status);
70 assertEquals("getArgumentLimit", 0, fmt.getArgumentLimit());
71 UnicodeString appendTo;
72 assertEquals(
73 "format",
74 "This doesn't have templates {0}",
75 fmt.format("unused", appendTo, status));
76 appendTo.remove();
77 int32_t offsets[] = { 0 };
78 assertEquals(
79 "formatAndAppend",
80 "This doesn't have templates {0}",
81 fmt.formatAndAppend(NULL, 0, appendTo, offsets, 1, status));
82 assertEquals("formatAndAppend offsets[0]", -1, offsets[0]);
83 assertEquals(
84 "formatAndReplace",
85 "This doesn't have templates {0}",
86 fmt.formatAndReplace(NULL, 0, appendTo, NULL, 0, status));
87 assertSuccess("Status", status);
88 }
89
90 void SimpleFormatterTest::TestSyntaxErrors() {
91 UErrorCode status = U_ZERO_ERROR;
92 SimpleFormatter fmt("{}", status);
93 assertEquals("syntax error {}", (int32_t)U_ILLEGAL_ARGUMENT_ERROR, status);
94 status = U_ZERO_ERROR;
95 fmt.applyPattern("{12d", status);
96 assertEquals("syntax error {12d", (int32_t)U_ILLEGAL_ARGUMENT_ERROR, status);
97 }
98
99 void SimpleFormatterTest::TestOneArgument() {
100 UErrorCode status = U_ZERO_ERROR;
101 SimpleFormatter fmt;
102 fmt.applyPattern("{0} meter", status);
103 if (!assertSuccess("Status", status)) {
104 return;
105 }
106 assertEquals("getArgumentLimit", 1, fmt.getArgumentLimit());
107 UnicodeString appendTo;
108 assertEquals(
109 "format",
110 "1 meter",
111 fmt.format("1", appendTo, status));
112
113 // assignment
114 SimpleFormatter s;
115 s = fmt;
116 appendTo.remove();
117 assertEquals(
118 "Assignment",
119 "1 meter",
120 s.format("1", appendTo, status));
121
122 // Copy constructor
123 SimpleFormatter r(fmt);
124 appendTo.remove();
125 assertEquals(
126 "Copy constructor",
127 "1 meter",
128 r.format("1", appendTo, status));
129 assertSuccess("Status", status);
130 }
131
132 void SimpleFormatterTest::TestBigArgument() {
133 UErrorCode status = U_ZERO_ERROR;
134 SimpleFormatter fmt("a{20}c", status);
135 if (!assertSuccess("Status", status)) {
136 return;
137 }
138 assertEquals("{20} count", 21, fmt.getArgumentLimit());
139 UnicodeString b("b");
140 UnicodeString *values[] = {
141 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
142 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
143 &b
144 };
145 UnicodeString result;
146 assertEquals("{20}=b", "abc", fmt.formatAndAppend(values, 21, result, NULL, 0, status));
147 assertSuccess("Status", status);
148 }
149
150 void SimpleFormatterTest::TestManyArguments() {
151 UErrorCode status = U_ZERO_ERROR;
152 SimpleFormatter fmt;
153 fmt.applyPattern(
154 "Templates {2}{1}{5} and {4} are out of order.", status);
155 if (!assertSuccess("Status", status)) {
156 return;
157 }
158 assertEquals("getArgumentLimit", 6, fmt.getArgumentLimit());
159 UnicodeString values[] = {
160 "freddy", "tommy", "frog", "billy", "leg", "{0}"};
161 UnicodeString *params[] = {
162 &values[0], &values[1], &values[2], &values[3], &values[4], &values[5]};
163 int32_t offsets[6];
164 int32_t expectedOffsets[6] = {-1, 22, 18, -1, 35, 27};
165 UnicodeString appendTo("Prefix: ");
166 assertEquals(
167 "format",
168 "Prefix: Templates frogtommy{0} and leg are out of order.",
169 fmt.formatAndAppend(
170 params,
171 UPRV_LENGTHOF(params),
172 appendTo,
173 offsets,
174 UPRV_LENGTHOF(offsets),
175 status));
176 if (!assertSuccess("Status", status)) {
177 return;
178 }
179 verifyOffsets(expectedOffsets, offsets, UPRV_LENGTHOF(expectedOffsets));
180 appendTo.remove();
181
182 // Ensure we don't write to offsets array beyond its length.
183 status = U_ZERO_ERROR;
184 offsets[UPRV_LENGTHOF(offsets) - 1] = 289;
185 appendTo.remove();
186 fmt.formatAndAppend(
187 params,
188 UPRV_LENGTHOF(params),
189 appendTo,
190 offsets,
191 UPRV_LENGTHOF(offsets) - 1,
192 status);
193 assertEquals("Offsets buffer length", 289, offsets[UPRV_LENGTHOF(offsets) - 1]);
194
195 // Test assignment
196 SimpleFormatter s;
197 s = fmt;
198 appendTo.remove();
199 assertEquals(
200 "Assignment",
201 "Templates frogtommy{0} and leg are out of order.",
202 s.formatAndAppend(
203 params,
204 UPRV_LENGTHOF(params),
205 appendTo,
206 NULL,
207 0,
208 status));
209
210 // Copy constructor
211 SimpleFormatter r(fmt);
212 appendTo.remove();
213 assertEquals(
214 "Copy constructor",
215 "Templates frogtommy{0} and leg are out of order.",
216 r.formatAndAppend(
217 params,
218 UPRV_LENGTHOF(params),
219 appendTo,
220 NULL,
221 0,
222 status));
223 r.applyPattern("{0} meter", status);
224 assertEquals("getArgumentLimit", 1, r.getArgumentLimit());
225 appendTo.remove();
226 assertEquals(
227 "Replace with new applyPattern",
228 "freddy meter",
229 r.format("freddy", appendTo, status));
230 r.applyPattern("{0}, {1}", status);
231 assertEquals("getArgumentLimit", 2, r.getArgumentLimit());
232 appendTo.remove();
233 assertEquals(
234 "2 arg",
235 "foo, bar",
236 r.format("foo", "bar", appendTo, status));
237 r.applyPattern("{0}, {1} and {2}", status);
238 assertEquals("getArgumentLimit", 3, r.getArgumentLimit());
239 appendTo.remove();
240 assertEquals(
241 "3 arg",
242 "foo, bar and baz",
243 r.format("foo", "bar", "baz", appendTo, status));
244 assertSuccess("Status", status);
245 }
246
247 void SimpleFormatterTest::TestTooFewArgumentValues() {
248 UErrorCode status = U_ZERO_ERROR;
249 SimpleFormatter fmt("{0} and {1}", status);
250 UnicodeString appendTo;
251 UnicodeString firstValue;
252 UnicodeString *params[] = {&firstValue};
253
254 fmt.format(
255 firstValue, appendTo, status);
256 if (status != U_ILLEGAL_ARGUMENT_ERROR) {
257 errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
258 }
259
260 status = U_ZERO_ERROR;
261 fmt.formatAndAppend(
262 params, UPRV_LENGTHOF(params), appendTo, NULL, 0, status);
263 if (status != U_ILLEGAL_ARGUMENT_ERROR) {
264 errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
265 }
266
267 status = U_ZERO_ERROR;
268 fmt.formatAndReplace(
269 params, UPRV_LENGTHOF(params), appendTo, NULL, 0, status);
270 if (status != U_ILLEGAL_ARGUMENT_ERROR) {
271 errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
272 }
273 }
274
275 void SimpleFormatterTest::TestBadArguments() {
276 UErrorCode status = U_ZERO_ERROR;
277 SimpleFormatter fmt("pickle", status);
278 UnicodeString appendTo;
279
280 // These succeed
281 fmt.formatAndAppend(
282 NULL, 0, appendTo, NULL, 0, status);
283 fmt.formatAndReplace(
284 NULL, 0, appendTo, NULL, 0, status);
285 assertSuccess("", status);
286 status = U_ZERO_ERROR;
287
288 // fails
289 fmt.formatAndAppend(
290 NULL, 1, appendTo, NULL, 0, status);
291 if (status != U_ILLEGAL_ARGUMENT_ERROR) {
292 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndAppend() values=NULL but length=1");
293 }
294 status = U_ZERO_ERROR;
295
296 // fails
297 fmt.formatAndAppend(
298 NULL, 0, appendTo, NULL, 1, status);
299 if (status != U_ILLEGAL_ARGUMENT_ERROR) {
300 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndAppend() offsets=NULL but length=1");
301 }
302 status = U_ZERO_ERROR;
303
304 // fails because appendTo used as a parameter value
305 SimpleFormatter fmt2("Arguments {0} and {1}", status);
306 UnicodeString frog("frog");
307 const UnicodeString *params[] = { &appendTo, &frog };
308 fmt2.formatAndAppend(params, 2, appendTo, NULL, 0, status);
309 if (status != U_ILLEGAL_ARGUMENT_ERROR) {
310 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndAppend() value=appendTo");
311 }
312 status = U_ZERO_ERROR;
313
314
315 // fails
316 fmt.formatAndReplace(
317 NULL, 1, appendTo, NULL, 0, status);
318 if (status != U_ILLEGAL_ARGUMENT_ERROR) {
319 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndReplace() values=NULL but length=1");
320 }
321 status = U_ZERO_ERROR;
322
323 // fails
324 fmt.formatAndReplace(
325 NULL, 0, appendTo, NULL, 1, status);
326 if (status != U_ILLEGAL_ARGUMENT_ERROR) {
327 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndReplace() offsets=NULL but length=1");
328 }
329 }
330
331 void SimpleFormatterTest::TestTextWithNoArguments() {
332 UErrorCode status = U_ZERO_ERROR;
333 SimpleFormatter fmt("{0} has no {1} arguments.", status);
334 assertEquals(
335 "", " has no arguments.", fmt.getTextWithNoArguments());
336 }
337
338 void SimpleFormatterTest::TestFormatReplaceNoOptimization() {
339 UErrorCode status = U_ZERO_ERROR;
340 SimpleFormatter fmt;
341 fmt.applyPattern("{2}, {0}, {1} and {3}", status);
342 if (!assertSuccess("Status", status)) {
343 return;
344 }
345 UnicodeString result("original");
346 int32_t offsets[4];
347 UnicodeString freddy("freddy");
348 UnicodeString frog("frog");
349 UnicodeString by("by");
350 const UnicodeString *params[] = {&result, &freddy, &frog, &by};
351 assertEquals(
352 "",
353 "frog, original, freddy and by",
354 fmt.formatAndReplace(
355 params,
356 UPRV_LENGTHOF(params),
357 result,
358 offsets,
359 UPRV_LENGTHOF(offsets),
360 status));
361 if (!assertSuccess("Status", status)) {
362 return;
363 }
364 int32_t expectedOffsets[] = {6, 16, 0, 27};
365 verifyOffsets(expectedOffsets, offsets, UPRV_LENGTHOF(expectedOffsets));
366 }
367
368 void SimpleFormatterTest::TestFormatReplaceNoOptimizationLeadingText() {
369 UErrorCode status = U_ZERO_ERROR;
370 SimpleFormatter fmt;
371 fmt.applyPattern("boo {2}, {0}, {1} and {3}", status);
372 if (!assertSuccess("Status", status)) {
373 return;
374 }
375 UnicodeString result("original");
376 int32_t offsets[4];
377 UnicodeString freddy("freddy");
378 UnicodeString frog("frog");
379 UnicodeString by("by");
380 const UnicodeString *params[] = {&freddy, &frog, &result, &by};
381 assertEquals(
382 "",
383 "boo original, freddy, frog and by",
384 fmt.formatAndReplace(
385 params,
386 UPRV_LENGTHOF(params),
387 result,
388 offsets,
389 UPRV_LENGTHOF(offsets),
390 status));
391 if (!assertSuccess("Status", status)) {
392 return;
393 }
394 int32_t expectedOffsets[] = {14, 22, 4, 31};
395 verifyOffsets(expectedOffsets, offsets, UPRV_LENGTHOF(expectedOffsets));
396 }
397
398 void SimpleFormatterTest::TestFormatReplaceOptimization() {
399 UErrorCode status = U_ZERO_ERROR;
400 SimpleFormatter fmt;
401 fmt.applyPattern("{2}, {0}, {1} and {3}", status);
402 if (!assertSuccess("Status", status)) {
403 return;
404 }
405 UnicodeString result("original");
406 int32_t offsets[4];
407 UnicodeString freddy("freddy");
408 UnicodeString frog("frog");
409 UnicodeString by("by");
410 const UnicodeString *params[] = {&freddy, &frog, &result, &by};
411 assertEquals(
412 "",
413 "original, freddy, frog and by",
414 fmt.formatAndReplace(
415 params,
416 UPRV_LENGTHOF(params),
417 result,
418 offsets,
419 UPRV_LENGTHOF(offsets),
420 status));
421 if (!assertSuccess("Status", status)) {
422 return;
423 }
424 int32_t expectedOffsets[] = {10, 18, 0, 27};
425 verifyOffsets(expectedOffsets, offsets, UPRV_LENGTHOF(expectedOffsets));
426 }
427
428 void SimpleFormatterTest::TestFormatReplaceNoOptimizationLeadingArgumentUsedTwice() {
429 UErrorCode status = U_ZERO_ERROR;
430 SimpleFormatter fmt;
431 fmt.applyPattern("{2}, {0}, {1} and {3} {2}", status);
432 if (!assertSuccess("Status", status)) {
433 return;
434 }
435 UnicodeString result("original");
436 int32_t offsets[4];
437 UnicodeString freddy("freddy");
438 UnicodeString frog("frog");
439 UnicodeString by("by");
440 const UnicodeString *params[] = {&freddy, &frog, &result, &by};
441 assertEquals(
442 "",
443 "original, freddy, frog and by original",
444 fmt.formatAndReplace(
445 params,
446 UPRV_LENGTHOF(params),
447 result,
448 offsets,
449 UPRV_LENGTHOF(offsets),
450 status));
451 if (!assertSuccess("Status", status)) {
452 return;
453 }
454 int32_t expectedOffsets[] = {10, 18, 30, 27};
455 verifyOffsets(expectedOffsets, offsets, UPRV_LENGTHOF(expectedOffsets));
456 }
457
458 void SimpleFormatterTest::TestFormatReplaceOptimizationNoOffsets() {
459 UErrorCode status = U_ZERO_ERROR;
460 SimpleFormatter fmt;
461 fmt.applyPattern("{2}, {0}, {1} and {3}", status);
462 if (!assertSuccess("Status", status)) {
463 return;
464 }
465 UnicodeString result("original");
466 UnicodeString freddy("freddy");
467 UnicodeString frog("frog");
468 UnicodeString by("by");
469 const UnicodeString *params[] = {&freddy, &frog, &result, &by};
470 assertEquals(
471 "",
472 "original, freddy, frog and by",
473 fmt.formatAndReplace(
474 params,
475 UPRV_LENGTHOF(params),
476 result,
477 NULL,
478 0,
479 status));
480 assertSuccess("Status", status);
481 }
482
483 void SimpleFormatterTest::TestFormatReplaceNoOptimizationNoOffsets() {
484 UErrorCode status = U_ZERO_ERROR;
485 SimpleFormatter fmt("Arguments {0} and {1}", status);
486 UnicodeString result("previous:");
487 UnicodeString frog("frog");
488 const UnicodeString *params[] = {&result, &frog};
489 assertEquals(
490 "",
491 "Arguments previous: and frog",
492 fmt.formatAndReplace(
493 params,
494 UPRV_LENGTHOF(params),
495 result,
496 NULL,
497 0,
498 status));
499 assertSuccess("Status", status);
500 }
501
502 void SimpleFormatterTest::TestQuotingLikeMessageFormat() {
503 #if !UCONFIG_NO_FORMATTING
504 UErrorCode status = U_ZERO_ERROR;
505 UnicodeString pattern = "{0} don't can''t '{5}''}{a' again '}'{1} to the '{end";
506 SimpleFormatter spf(pattern, status);
507 MessageFormat mf(pattern, Locale::getRoot(), status);
508 UnicodeString expected = "X don't can't {5}'}{a again }Y to the {end";
509 UnicodeString x("X"), y("Y");
510 Formattable values[] = { x, y };
511 UnicodeString result;
512 FieldPosition ignore(FieldPosition::DONT_CARE);
513 assertEquals("MessageFormat", expected, mf.format(values, 2, result, ignore, status));
514 assertEquals("SimpleFormatter", expected, spf.format(x, y, result.remove(), status));
515 #endif /* !UCONFIG_NO_FORMATTING */
516 }
517
518 void SimpleFormatterTest::verifyOffsets(
519 const int32_t *expected, const int32_t *actual, int32_t count) {
520 for (int32_t i = 0; i < count; ++i) {
521 if (expected[i] != actual[i]) {
522 errln("Expected %d, got %d", expected[i], actual[i]);
523 }
524 }
525 }
526
527 extern IntlTest *createSimpleFormatterTest() {
528 return new SimpleFormatterTest();
529 }