2 *******************************************************************************
3 * Copyright (C) 2014-2016, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 *******************************************************************************
7 * simpleformattertest.cpp
9 ********************************************************************************
12 #include "unicode/msgfmt.h"
13 #include "unicode/unistr.h"
16 #include "unicode/simpleformatter.h"
18 class SimpleFormatterTest
: public IntlTest
{
20 SimpleFormatterTest() {
22 void TestNoArguments();
23 void TestSyntaxErrors();
24 void TestOneArgument();
25 void TestBigArgument();
26 void TestManyArguments();
27 void TestTooFewArgumentValues();
28 void TestBadArguments();
29 void TestTextWithNoArguments();
30 void TestFormatReplaceNoOptimization();
31 void TestFormatReplaceNoOptimizationLeadingText();
32 void TestFormatReplaceOptimization();
33 void TestFormatReplaceNoOptimizationLeadingArgumentUsedTwice();
34 void TestFormatReplaceOptimizationNoOffsets();
35 void TestFormatReplaceNoOptimizationNoOffsets();
36 void TestQuotingLikeMessageFormat();
37 void runIndexedTest(int32_t index
, UBool exec
, const char *&name
, char *par
=0);
40 const int32_t *expected
,
41 const int32_t *actual
,
45 void SimpleFormatterTest::runIndexedTest(int32_t index
, UBool exec
, const char* &name
, char* /*par*/) {
47 TESTCASE_AUTO(TestNoArguments
);
48 TESTCASE_AUTO(TestSyntaxErrors
);
49 TESTCASE_AUTO(TestOneArgument
);
50 TESTCASE_AUTO(TestBigArgument
);
51 TESTCASE_AUTO(TestManyArguments
);
52 TESTCASE_AUTO(TestTooFewArgumentValues
);
53 TESTCASE_AUTO(TestBadArguments
);
54 TESTCASE_AUTO(TestTextWithNoArguments
);
55 TESTCASE_AUTO(TestFormatReplaceNoOptimization
);
56 TESTCASE_AUTO(TestFormatReplaceNoOptimizationLeadingText
);
57 TESTCASE_AUTO(TestFormatReplaceOptimization
);
58 TESTCASE_AUTO(TestFormatReplaceNoOptimizationLeadingArgumentUsedTwice
);
59 TESTCASE_AUTO(TestFormatReplaceOptimizationNoOffsets
);
60 TESTCASE_AUTO(TestFormatReplaceNoOptimizationNoOffsets
);
61 TESTCASE_AUTO(TestQuotingLikeMessageFormat
);
65 void SimpleFormatterTest::TestNoArguments() {
66 UErrorCode status
= U_ZERO_ERROR
;
67 SimpleFormatter
fmt("This doesn''t have templates '{0}", status
);
68 assertEquals("getArgumentLimit", 0, fmt
.getArgumentLimit());
69 UnicodeString appendTo
;
72 "This doesn't have templates {0}",
73 fmt
.format("unused", appendTo
, status
));
75 int32_t offsets
[] = { 0 };
78 "This doesn't have templates {0}",
79 fmt
.formatAndAppend(NULL
, 0, appendTo
, offsets
, 1, status
));
80 assertEquals("formatAndAppend offsets[0]", -1, offsets
[0]);
83 "This doesn't have templates {0}",
84 fmt
.formatAndReplace(NULL
, 0, appendTo
, NULL
, 0, status
));
85 assertSuccess("Status", status
);
88 void SimpleFormatterTest::TestSyntaxErrors() {
89 UErrorCode status
= U_ZERO_ERROR
;
90 SimpleFormatter
fmt("{}", status
);
91 assertEquals("syntax error {}", U_ILLEGAL_ARGUMENT_ERROR
, status
);
92 status
= U_ZERO_ERROR
;
93 fmt
.applyPattern("{12d", status
);
94 assertEquals("syntax error {12d", U_ILLEGAL_ARGUMENT_ERROR
, status
);
97 void SimpleFormatterTest::TestOneArgument() {
98 UErrorCode status
= U_ZERO_ERROR
;
100 fmt
.applyPattern("{0} meter", status
);
101 if (!assertSuccess("Status", status
)) {
104 assertEquals("getArgumentLimit", 1, fmt
.getArgumentLimit());
105 UnicodeString appendTo
;
109 fmt
.format("1", appendTo
, status
));
118 s
.format("1", appendTo
, status
));
121 SimpleFormatter
r(fmt
);
126 r
.format("1", appendTo
, status
));
127 assertSuccess("Status", status
);
130 void SimpleFormatterTest::TestBigArgument() {
131 UErrorCode status
= U_ZERO_ERROR
;
132 SimpleFormatter
fmt("a{20}c", status
);
133 if (!assertSuccess("Status", status
)) {
136 assertEquals("{20} count", 21, fmt
.getArgumentLimit());
137 UnicodeString
b("b");
138 UnicodeString
*values
[] = {
139 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
140 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
143 UnicodeString result
;
144 assertEquals("{20}=b", "abc", fmt
.formatAndAppend(values
, 21, result
, NULL
, 0, status
));
145 assertSuccess("Status", status
);
148 void SimpleFormatterTest::TestManyArguments() {
149 UErrorCode status
= U_ZERO_ERROR
;
152 "Templates {2}{1}{5} and {4} are out of order.", status
);
153 if (!assertSuccess("Status", status
)) {
156 assertEquals("getArgumentLimit", 6, fmt
.getArgumentLimit());
157 UnicodeString values
[] = {
158 "freddy", "tommy", "frog", "billy", "leg", "{0}"};
159 UnicodeString
*params
[] = {
160 &values
[0], &values
[1], &values
[2], &values
[3], &values
[4], &values
[5]};
162 int32_t expectedOffsets
[6] = {-1, 22, 18, -1, 35, 27};
163 UnicodeString
appendTo("Prefix: ");
166 "Prefix: Templates frogtommy{0} and leg are out of order.",
169 UPRV_LENGTHOF(params
),
172 UPRV_LENGTHOF(offsets
),
174 if (!assertSuccess("Status", status
)) {
177 verifyOffsets(expectedOffsets
, offsets
, UPRV_LENGTHOF(expectedOffsets
));
180 // Ensure we don't write to offsets array beyond its length.
181 status
= U_ZERO_ERROR
;
182 offsets
[UPRV_LENGTHOF(offsets
) - 1] = 289;
186 UPRV_LENGTHOF(params
),
189 UPRV_LENGTHOF(offsets
) - 1,
191 assertEquals("Offsets buffer length", 289, offsets
[UPRV_LENGTHOF(offsets
) - 1]);
199 "Templates frogtommy{0} and leg are out of order.",
202 UPRV_LENGTHOF(params
),
209 SimpleFormatter
r(fmt
);
213 "Templates frogtommy{0} and leg are out of order.",
216 UPRV_LENGTHOF(params
),
221 r
.applyPattern("{0} meter", status
);
222 assertEquals("getArgumentLimit", 1, r
.getArgumentLimit());
225 "Replace with new applyPattern",
227 r
.format("freddy", appendTo
, status
));
228 r
.applyPattern("{0}, {1}", status
);
229 assertEquals("getArgumentLimit", 2, r
.getArgumentLimit());
234 r
.format("foo", "bar", appendTo
, status
));
235 r
.applyPattern("{0}, {1} and {2}", status
);
236 assertEquals("getArgumentLimit", 3, r
.getArgumentLimit());
241 r
.format("foo", "bar", "baz", appendTo
, status
));
242 assertSuccess("Status", status
);
245 void SimpleFormatterTest::TestTooFewArgumentValues() {
246 UErrorCode status
= U_ZERO_ERROR
;
247 SimpleFormatter
fmt("{0} and {1}", status
);
248 UnicodeString appendTo
;
249 UnicodeString firstValue
;
250 UnicodeString
*params
[] = {&firstValue
};
253 firstValue
, appendTo
, status
);
254 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
255 errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
258 status
= U_ZERO_ERROR
;
260 params
, UPRV_LENGTHOF(params
), appendTo
, NULL
, 0, status
);
261 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
262 errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
265 status
= U_ZERO_ERROR
;
266 fmt
.formatAndReplace(
267 params
, UPRV_LENGTHOF(params
), appendTo
, NULL
, 0, status
);
268 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
269 errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
273 void SimpleFormatterTest::TestBadArguments() {
274 UErrorCode status
= U_ZERO_ERROR
;
275 SimpleFormatter
fmt("pickle", status
);
276 UnicodeString appendTo
;
280 NULL
, 0, appendTo
, NULL
, 0, status
);
281 fmt
.formatAndReplace(
282 NULL
, 0, appendTo
, NULL
, 0, status
);
283 assertSuccess("", status
);
284 status
= U_ZERO_ERROR
;
288 NULL
, 1, appendTo
, NULL
, 0, status
);
289 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
290 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndAppend() values=NULL but length=1");
292 status
= U_ZERO_ERROR
;
296 NULL
, 0, appendTo
, NULL
, 1, status
);
297 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
298 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndAppend() offsets=NULL but length=1");
300 status
= U_ZERO_ERROR
;
302 // fails because appendTo used as a parameter value
303 SimpleFormatter
fmt2("Arguments {0} and {1}", status
);
304 UnicodeString
frog("frog");
305 const UnicodeString
*params
[] = { &appendTo
, &frog
};
306 fmt2
.formatAndAppend(params
, 2, appendTo
, NULL
, 0, status
);
307 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
308 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndAppend() value=appendTo");
310 status
= U_ZERO_ERROR
;
314 fmt
.formatAndReplace(
315 NULL
, 1, appendTo
, NULL
, 0, status
);
316 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
317 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndReplace() values=NULL but length=1");
319 status
= U_ZERO_ERROR
;
322 fmt
.formatAndReplace(
323 NULL
, 0, appendTo
, NULL
, 1, status
);
324 if (status
!= U_ILLEGAL_ARGUMENT_ERROR
) {
325 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndReplace() offsets=NULL but length=1");
329 void SimpleFormatterTest::TestTextWithNoArguments() {
330 UErrorCode status
= U_ZERO_ERROR
;
331 SimpleFormatter
fmt("{0} has no {1} arguments.", status
);
333 "", " has no arguments.", fmt
.getTextWithNoArguments());
336 void SimpleFormatterTest::TestFormatReplaceNoOptimization() {
337 UErrorCode status
= U_ZERO_ERROR
;
339 fmt
.applyPattern("{2}, {0}, {1} and {3}", status
);
340 if (!assertSuccess("Status", status
)) {
343 UnicodeString
result("original");
345 UnicodeString
freddy("freddy");
346 UnicodeString
frog("frog");
347 UnicodeString
by("by");
348 const UnicodeString
*params
[] = {&result
, &freddy
, &frog
, &by
};
351 "frog, original, freddy and by",
352 fmt
.formatAndReplace(
354 UPRV_LENGTHOF(params
),
357 UPRV_LENGTHOF(offsets
),
359 if (!assertSuccess("Status", status
)) {
362 int32_t expectedOffsets
[] = {6, 16, 0, 27};
363 verifyOffsets(expectedOffsets
, offsets
, UPRV_LENGTHOF(expectedOffsets
));
366 void SimpleFormatterTest::TestFormatReplaceNoOptimizationLeadingText() {
367 UErrorCode status
= U_ZERO_ERROR
;
369 fmt
.applyPattern("boo {2}, {0}, {1} and {3}", status
);
370 if (!assertSuccess("Status", status
)) {
373 UnicodeString
result("original");
375 UnicodeString
freddy("freddy");
376 UnicodeString
frog("frog");
377 UnicodeString
by("by");
378 const UnicodeString
*params
[] = {&freddy
, &frog
, &result
, &by
};
381 "boo original, freddy, frog and by",
382 fmt
.formatAndReplace(
384 UPRV_LENGTHOF(params
),
387 UPRV_LENGTHOF(offsets
),
389 if (!assertSuccess("Status", status
)) {
392 int32_t expectedOffsets
[] = {14, 22, 4, 31};
393 verifyOffsets(expectedOffsets
, offsets
, UPRV_LENGTHOF(expectedOffsets
));
396 void SimpleFormatterTest::TestFormatReplaceOptimization() {
397 UErrorCode status
= U_ZERO_ERROR
;
399 fmt
.applyPattern("{2}, {0}, {1} and {3}", status
);
400 if (!assertSuccess("Status", status
)) {
403 UnicodeString
result("original");
405 UnicodeString
freddy("freddy");
406 UnicodeString
frog("frog");
407 UnicodeString
by("by");
408 const UnicodeString
*params
[] = {&freddy
, &frog
, &result
, &by
};
411 "original, freddy, frog and by",
412 fmt
.formatAndReplace(
414 UPRV_LENGTHOF(params
),
417 UPRV_LENGTHOF(offsets
),
419 if (!assertSuccess("Status", status
)) {
422 int32_t expectedOffsets
[] = {10, 18, 0, 27};
423 verifyOffsets(expectedOffsets
, offsets
, UPRV_LENGTHOF(expectedOffsets
));
426 void SimpleFormatterTest::TestFormatReplaceNoOptimizationLeadingArgumentUsedTwice() {
427 UErrorCode status
= U_ZERO_ERROR
;
429 fmt
.applyPattern("{2}, {0}, {1} and {3} {2}", status
);
430 if (!assertSuccess("Status", status
)) {
433 UnicodeString
result("original");
435 UnicodeString
freddy("freddy");
436 UnicodeString
frog("frog");
437 UnicodeString
by("by");
438 const UnicodeString
*params
[] = {&freddy
, &frog
, &result
, &by
};
441 "original, freddy, frog and by original",
442 fmt
.formatAndReplace(
444 UPRV_LENGTHOF(params
),
447 UPRV_LENGTHOF(offsets
),
449 if (!assertSuccess("Status", status
)) {
452 int32_t expectedOffsets
[] = {10, 18, 30, 27};
453 verifyOffsets(expectedOffsets
, offsets
, UPRV_LENGTHOF(expectedOffsets
));
456 void SimpleFormatterTest::TestFormatReplaceOptimizationNoOffsets() {
457 UErrorCode status
= U_ZERO_ERROR
;
459 fmt
.applyPattern("{2}, {0}, {1} and {3}", status
);
460 if (!assertSuccess("Status", status
)) {
463 UnicodeString
result("original");
464 UnicodeString
freddy("freddy");
465 UnicodeString
frog("frog");
466 UnicodeString
by("by");
467 const UnicodeString
*params
[] = {&freddy
, &frog
, &result
, &by
};
470 "original, freddy, frog and by",
471 fmt
.formatAndReplace(
473 UPRV_LENGTHOF(params
),
478 assertSuccess("Status", status
);
481 void SimpleFormatterTest::TestFormatReplaceNoOptimizationNoOffsets() {
482 UErrorCode status
= U_ZERO_ERROR
;
483 SimpleFormatter
fmt("Arguments {0} and {1}", status
);
484 UnicodeString
result("previous:");
485 UnicodeString
frog("frog");
486 const UnicodeString
*params
[] = {&result
, &frog
};
489 "Arguments previous: and frog",
490 fmt
.formatAndReplace(
492 UPRV_LENGTHOF(params
),
497 assertSuccess("Status", status
);
500 void SimpleFormatterTest::TestQuotingLikeMessageFormat() {
501 #if !UCONFIG_NO_FORMATTING
502 UErrorCode status
= U_ZERO_ERROR
;
503 UnicodeString pattern
= "{0} don't can''t '{5}''}{a' again '}'{1} to the '{end";
504 SimpleFormatter
spf(pattern
, status
);
505 MessageFormat
mf(pattern
, Locale::getRoot(), status
);
506 UnicodeString expected
= "X don't can't {5}'}{a again }Y to the {end";
507 UnicodeString
x("X"), y("Y");
508 Formattable values
[] = { x
, y
};
509 UnicodeString result
;
510 FieldPosition
ignore(FieldPosition::DONT_CARE
);
511 assertEquals("MessageFormat", expected
, mf
.format(values
, 2, result
, ignore
, status
));
512 assertEquals("SimpleFormatter", expected
, spf
.format(x
, y
, result
.remove(), status
));
513 #endif /* !UCONFIG_NO_FORMATTING */
516 void SimpleFormatterTest::verifyOffsets(
517 const int32_t *expected
, const int32_t *actual
, int32_t count
) {
518 for (int32_t i
= 0; i
< count
; ++i
) {
519 if (expected
[i
] != actual
[i
]) {
520 errln("Expected %d, got %d", expected
[i
], actual
[i
]);
525 extern IntlTest
*createSimpleFormatterTest() {
526 return new SimpleFormatterTest();