]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/intltest/simpleformattertest.cpp
ICU-62123.0.1.tar.gz
[apple/icu.git] / icuSources / test / intltest / simpleformattertest.cpp
CommitLineData
f3c0d7a5
A
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
57a6839d
A
3/*
4*******************************************************************************
2ca993e8
A
5* Copyright (C) 2014-2016, International Business Machines Corporation and
6* others. All Rights Reserved.
57a6839d
A
7*******************************************************************************
8*
2ca993e8 9* simpleformattertest.cpp
57a6839d
A
10*
11********************************************************************************
12*/
2ca993e8
A
13
14#include "unicode/msgfmt.h"
15#include "unicode/unistr.h"
57a6839d
A
16#include "cstring.h"
17#include "intltest.h"
2ca993e8 18#include "unicode/simpleformatter.h"
57a6839d 19
2ca993e8 20class SimpleFormatterTest : public IntlTest {
57a6839d 21public:
2ca993e8 22 SimpleFormatterTest() {
57a6839d 23 }
2ca993e8
A
24 void TestNoArguments();
25 void TestSyntaxErrors();
26 void TestOneArgument();
27 void TestBigArgument();
28 void TestManyArguments();
29 void TestTooFewArgumentValues();
b331163b 30 void TestBadArguments();
2ca993e8 31 void TestTextWithNoArguments();
b331163b
A
32 void TestFormatReplaceNoOptimization();
33 void TestFormatReplaceNoOptimizationLeadingText();
34 void TestFormatReplaceOptimization();
2ca993e8 35 void TestFormatReplaceNoOptimizationLeadingArgumentUsedTwice();
b331163b
A
36 void TestFormatReplaceOptimizationNoOffsets();
37 void TestFormatReplaceNoOptimizationNoOffsets();
2ca993e8 38 void TestQuotingLikeMessageFormat();
57a6839d
A
39 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0);
40private:
b331163b
A
41 void verifyOffsets(
42 const int32_t *expected,
43 const int32_t *actual,
44 int32_t count);
57a6839d
A
45};
46
2ca993e8 47void SimpleFormatterTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par*/) {
57a6839d 48 TESTCASE_AUTO_BEGIN;
2ca993e8
A
49 TESTCASE_AUTO(TestNoArguments);
50 TESTCASE_AUTO(TestSyntaxErrors);
51 TESTCASE_AUTO(TestOneArgument);
52 TESTCASE_AUTO(TestBigArgument);
53 TESTCASE_AUTO(TestManyArguments);
54 TESTCASE_AUTO(TestTooFewArgumentValues);
b331163b 55 TESTCASE_AUTO(TestBadArguments);
2ca993e8 56 TESTCASE_AUTO(TestTextWithNoArguments);
b331163b
A
57 TESTCASE_AUTO(TestFormatReplaceNoOptimization);
58 TESTCASE_AUTO(TestFormatReplaceNoOptimizationLeadingText);
59 TESTCASE_AUTO(TestFormatReplaceOptimization);
2ca993e8 60 TESTCASE_AUTO(TestFormatReplaceNoOptimizationLeadingArgumentUsedTwice);
b331163b
A
61 TESTCASE_AUTO(TestFormatReplaceOptimizationNoOffsets);
62 TESTCASE_AUTO(TestFormatReplaceNoOptimizationNoOffsets);
2ca993e8 63 TESTCASE_AUTO(TestQuotingLikeMessageFormat);
57a6839d
A
64 TESTCASE_AUTO_END;
65}
66
2ca993e8 67void SimpleFormatterTest::TestNoArguments() {
57a6839d 68 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
69 SimpleFormatter fmt("This doesn''t have templates '{0}", status);
70 assertEquals("getArgumentLimit", 0, fmt.getArgumentLimit());
57a6839d
A
71 UnicodeString appendTo;
72 assertEquals(
b331163b 73 "format",
57a6839d
A
74 "This doesn't have templates {0}",
75 fmt.format("unused", appendTo, status));
57a6839d 76 appendTo.remove();
2ca993e8 77 int32_t offsets[] = { 0 };
57a6839d 78 assertEquals(
2ca993e8
A
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));
57a6839d
A
87 assertSuccess("Status", status);
88}
89
2ca993e8 90void SimpleFormatterTest::TestSyntaxErrors() {
57a6839d 91 UErrorCode status = U_ZERO_ERROR;
2ca993e8 92 SimpleFormatter fmt("{}", status);
f3c0d7a5 93 assertEquals("syntax error {}", (int32_t)U_ILLEGAL_ARGUMENT_ERROR, status);
2ca993e8
A
94 status = U_ZERO_ERROR;
95 fmt.applyPattern("{12d", status);
f3c0d7a5 96 assertEquals("syntax error {12d", (int32_t)U_ILLEGAL_ARGUMENT_ERROR, status);
2ca993e8
A
97}
98
99void SimpleFormatterTest::TestOneArgument() {
100 UErrorCode status = U_ZERO_ERROR;
101 SimpleFormatter fmt;
102 fmt.applyPattern("{0} meter", status);
b331163b
A
103 if (!assertSuccess("Status", status)) {
104 return;
105 }
2ca993e8 106 assertEquals("getArgumentLimit", 1, fmt.getArgumentLimit());
57a6839d
A
107 UnicodeString appendTo;
108 assertEquals(
b331163b 109 "format",
57a6839d
A
110 "1 meter",
111 fmt.format("1", appendTo, status));
57a6839d
A
112
113 // assignment
2ca993e8 114 SimpleFormatter s;
57a6839d
A
115 s = fmt;
116 appendTo.remove();
117 assertEquals(
118 "Assignment",
119 "1 meter",
120 s.format("1", appendTo, status));
121
122 // Copy constructor
2ca993e8 123 SimpleFormatter r(fmt);
57a6839d
A
124 appendTo.remove();
125 assertEquals(
126 "Copy constructor",
127 "1 meter",
128 r.format("1", appendTo, status));
129 assertSuccess("Status", status);
130}
131
2ca993e8
A
132void 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
150void SimpleFormatterTest::TestManyArguments() {
57a6839d 151 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
152 SimpleFormatter fmt;
153 fmt.applyPattern(
57a6839d 154 "Templates {2}{1}{5} and {4} are out of order.", status);
b331163b
A
155 if (!assertSuccess("Status", status)) {
156 return;
157 }
2ca993e8 158 assertEquals("getArgumentLimit", 6, fmt.getArgumentLimit());
57a6839d
A
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(
b331163b 167 "format",
57a6839d 168 "Prefix: Templates frogtommy{0} and leg are out of order.",
b331163b 169 fmt.formatAndAppend(
57a6839d 170 params,
b331163b 171 UPRV_LENGTHOF(params),
57a6839d
A
172 appendTo,
173 offsets,
b331163b 174 UPRV_LENGTHOF(offsets),
57a6839d 175 status));
b331163b
A
176 if (!assertSuccess("Status", status)) {
177 return;
57a6839d 178 }
b331163b 179 verifyOffsets(expectedOffsets, offsets, UPRV_LENGTHOF(expectedOffsets));
57a6839d 180 appendTo.remove();
b331163b
A
181
182 // Ensure we don't write to offsets array beyond its length.
57a6839d 183 status = U_ZERO_ERROR;
b331163b 184 offsets[UPRV_LENGTHOF(offsets) - 1] = 289;
57a6839d 185 appendTo.remove();
b331163b 186 fmt.formatAndAppend(
57a6839d 187 params,
b331163b 188 UPRV_LENGTHOF(params),
57a6839d
A
189 appendTo,
190 offsets,
b331163b 191 UPRV_LENGTHOF(offsets) - 1,
57a6839d 192 status);
b331163b 193 assertEquals("Offsets buffer length", 289, offsets[UPRV_LENGTHOF(offsets) - 1]);
57a6839d
A
194
195 // Test assignment
2ca993e8 196 SimpleFormatter s;
57a6839d
A
197 s = fmt;
198 appendTo.remove();
199 assertEquals(
200 "Assignment",
201 "Templates frogtommy{0} and leg are out of order.",
b331163b 202 s.formatAndAppend(
57a6839d 203 params,
b331163b 204 UPRV_LENGTHOF(params),
57a6839d
A
205 appendTo,
206 NULL,
207 0,
208 status));
209
210 // Copy constructor
2ca993e8 211 SimpleFormatter r(fmt);
57a6839d
A
212 appendTo.remove();
213 assertEquals(
214 "Copy constructor",
215 "Templates frogtommy{0} and leg are out of order.",
b331163b 216 r.formatAndAppend(
57a6839d 217 params,
b331163b 218 UPRV_LENGTHOF(params),
57a6839d
A
219 appendTo,
220 NULL,
221 0,
222 status));
2ca993e8
A
223 r.applyPattern("{0} meter", status);
224 assertEquals("getArgumentLimit", 1, r.getArgumentLimit());
57a6839d
A
225 appendTo.remove();
226 assertEquals(
2ca993e8 227 "Replace with new applyPattern",
57a6839d
A
228 "freddy meter",
229 r.format("freddy", appendTo, status));
2ca993e8
A
230 r.applyPattern("{0}, {1}", status);
231 assertEquals("getArgumentLimit", 2, r.getArgumentLimit());
57a6839d
A
232 appendTo.remove();
233 assertEquals(
234 "2 arg",
235 "foo, bar",
236 r.format("foo", "bar", appendTo, status));
2ca993e8
A
237 r.applyPattern("{0}, {1} and {2}", status);
238 assertEquals("getArgumentLimit", 3, r.getArgumentLimit());
57a6839d
A
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
2ca993e8
A
247void SimpleFormatterTest::TestTooFewArgumentValues() {
248 UErrorCode status = U_ZERO_ERROR;
249 SimpleFormatter fmt("{0} and {1}", status);
b331163b
A
250 UnicodeString appendTo;
251 UnicodeString firstValue;
252 UnicodeString *params[] = {&firstValue};
253
b331163b
A
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
2ca993e8 275void SimpleFormatterTest::TestBadArguments() {
b331163b 276 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
277 SimpleFormatter fmt("pickle", status);
278 UnicodeString appendTo;
b331163b
A
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) {
2ca993e8 292 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndAppend() values=NULL but length=1");
b331163b
A
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) {
2ca993e8 300 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndAppend() offsets=NULL but length=1");
b331163b
A
301 }
302 status = U_ZERO_ERROR;
303
304 // fails because appendTo used as a parameter value
2ca993e8
A
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);
b331163b 309 if (status != U_ILLEGAL_ARGUMENT_ERROR) {
2ca993e8 310 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndAppend() value=appendTo");
b331163b
A
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) {
2ca993e8 319 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndReplace() values=NULL but length=1");
b331163b
A
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) {
2ca993e8 327 errln("Expected U_ILLEGAL_ARGUMENT_ERROR: formatAndReplace() offsets=NULL but length=1");
b331163b
A
328 }
329}
330
2ca993e8
A
331void SimpleFormatterTest::TestTextWithNoArguments() {
332 UErrorCode status = U_ZERO_ERROR;
333 SimpleFormatter fmt("{0} has no {1} arguments.", status);
b331163b 334 assertEquals(
2ca993e8 335 "", " has no arguments.", fmt.getTextWithNoArguments());
b331163b
A
336}
337
2ca993e8 338void SimpleFormatterTest::TestFormatReplaceNoOptimization() {
b331163b 339 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
340 SimpleFormatter fmt;
341 fmt.applyPattern("{2}, {0}, {1} and {3}", status);
b331163b
A
342 if (!assertSuccess("Status", status)) {
343 return;
344 }
345 UnicodeString result("original");
f3c0d7a5 346 int32_t offsets[4];
b331163b
A
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
2ca993e8 368void SimpleFormatterTest::TestFormatReplaceNoOptimizationLeadingText() {
b331163b 369 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
370 SimpleFormatter fmt;
371 fmt.applyPattern("boo {2}, {0}, {1} and {3}", status);
b331163b
A
372 if (!assertSuccess("Status", status)) {
373 return;
374 }
375 UnicodeString result("original");
f3c0d7a5 376 int32_t offsets[4];
b331163b
A
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
2ca993e8 398void SimpleFormatterTest::TestFormatReplaceOptimization() {
b331163b 399 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
400 SimpleFormatter fmt;
401 fmt.applyPattern("{2}, {0}, {1} and {3}", status);
b331163b
A
402 if (!assertSuccess("Status", status)) {
403 return;
404 }
405 UnicodeString result("original");
f3c0d7a5 406 int32_t offsets[4];
b331163b
A
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
2ca993e8 428void SimpleFormatterTest::TestFormatReplaceNoOptimizationLeadingArgumentUsedTwice() {
b331163b 429 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
430 SimpleFormatter fmt;
431 fmt.applyPattern("{2}, {0}, {1} and {3} {2}", status);
b331163b
A
432 if (!assertSuccess("Status", status)) {
433 return;
434 }
435 UnicodeString result("original");
f3c0d7a5 436 int32_t offsets[4];
b331163b
A
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
2ca993e8 458void SimpleFormatterTest::TestFormatReplaceOptimizationNoOffsets() {
b331163b 459 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
460 SimpleFormatter fmt;
461 fmt.applyPattern("{2}, {0}, {1} and {3}", status);
b331163b
A
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
2ca993e8 483void SimpleFormatterTest::TestFormatReplaceNoOptimizationNoOffsets() {
b331163b 484 UErrorCode status = U_ZERO_ERROR;
2ca993e8 485 SimpleFormatter fmt("Arguments {0} and {1}", status);
b331163b
A
486 UnicodeString result("previous:");
487 UnicodeString frog("frog");
488 const UnicodeString *params[] = {&result, &frog};
489 assertEquals(
490 "",
2ca993e8 491 "Arguments previous: and frog",
b331163b
A
492 fmt.formatAndReplace(
493 params,
494 UPRV_LENGTHOF(params),
495 result,
496 NULL,
497 0,
498 status));
499 assertSuccess("Status", status);
500}
501
2ca993e8
A
502void 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
518void SimpleFormatterTest::verifyOffsets(
b331163b
A
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
2ca993e8
A
527extern IntlTest *createSimpleFormatterTest() {
528 return new SimpleFormatterTest();
57a6839d 529}