]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/intltest/simpleformattertest.cpp
ICU-64260.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 331void SimpleFormatterTest::TestTextWithNoArguments() {
3d1f044b 332 IcuTestErrorCode status(*this, "TestTextWithNoArguments");
2ca993e8 333 SimpleFormatter fmt("{0} has no {1} arguments.", status);
3d1f044b
A
334 assertEquals("String output 1",
335 " has no arguments.", fmt.getTextWithNoArguments());
336
337 // Test offset positions
338 int32_t offsets[3];
339 assertEquals("String output 2",
340 u" has no arguments.", fmt.getTextWithNoArguments(offsets, 3));
341 assertEquals("Offset at 0",
342 0, offsets[0]);
343 assertEquals("Offset at 1",
344 8, offsets[1]);
345 assertEquals("Offset at 2",
346 -1, offsets[2]);
b331163b
A
347}
348
2ca993e8 349void SimpleFormatterTest::TestFormatReplaceNoOptimization() {
b331163b 350 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
351 SimpleFormatter fmt;
352 fmt.applyPattern("{2}, {0}, {1} and {3}", status);
b331163b
A
353 if (!assertSuccess("Status", status)) {
354 return;
355 }
356 UnicodeString result("original");
f3c0d7a5 357 int32_t offsets[4];
b331163b
A
358 UnicodeString freddy("freddy");
359 UnicodeString frog("frog");
360 UnicodeString by("by");
361 const UnicodeString *params[] = {&result, &freddy, &frog, &by};
362 assertEquals(
363 "",
364 "frog, original, freddy and by",
365 fmt.formatAndReplace(
366 params,
367 UPRV_LENGTHOF(params),
368 result,
369 offsets,
370 UPRV_LENGTHOF(offsets),
371 status));
372 if (!assertSuccess("Status", status)) {
373 return;
374 }
375 int32_t expectedOffsets[] = {6, 16, 0, 27};
376 verifyOffsets(expectedOffsets, offsets, UPRV_LENGTHOF(expectedOffsets));
377}
378
2ca993e8 379void SimpleFormatterTest::TestFormatReplaceNoOptimizationLeadingText() {
b331163b 380 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
381 SimpleFormatter fmt;
382 fmt.applyPattern("boo {2}, {0}, {1} and {3}", status);
b331163b
A
383 if (!assertSuccess("Status", status)) {
384 return;
385 }
386 UnicodeString result("original");
f3c0d7a5 387 int32_t offsets[4];
b331163b
A
388 UnicodeString freddy("freddy");
389 UnicodeString frog("frog");
390 UnicodeString by("by");
391 const UnicodeString *params[] = {&freddy, &frog, &result, &by};
392 assertEquals(
393 "",
394 "boo original, freddy, frog and by",
395 fmt.formatAndReplace(
396 params,
397 UPRV_LENGTHOF(params),
398 result,
399 offsets,
400 UPRV_LENGTHOF(offsets),
401 status));
402 if (!assertSuccess("Status", status)) {
403 return;
404 }
405 int32_t expectedOffsets[] = {14, 22, 4, 31};
406 verifyOffsets(expectedOffsets, offsets, UPRV_LENGTHOF(expectedOffsets));
407}
408
2ca993e8 409void SimpleFormatterTest::TestFormatReplaceOptimization() {
b331163b 410 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
411 SimpleFormatter fmt;
412 fmt.applyPattern("{2}, {0}, {1} and {3}", status);
b331163b
A
413 if (!assertSuccess("Status", status)) {
414 return;
415 }
416 UnicodeString result("original");
f3c0d7a5 417 int32_t offsets[4];
b331163b
A
418 UnicodeString freddy("freddy");
419 UnicodeString frog("frog");
420 UnicodeString by("by");
421 const UnicodeString *params[] = {&freddy, &frog, &result, &by};
422 assertEquals(
423 "",
424 "original, freddy, frog and by",
425 fmt.formatAndReplace(
426 params,
427 UPRV_LENGTHOF(params),
428 result,
429 offsets,
430 UPRV_LENGTHOF(offsets),
431 status));
432 if (!assertSuccess("Status", status)) {
433 return;
434 }
435 int32_t expectedOffsets[] = {10, 18, 0, 27};
436 verifyOffsets(expectedOffsets, offsets, UPRV_LENGTHOF(expectedOffsets));
437}
438
2ca993e8 439void SimpleFormatterTest::TestFormatReplaceNoOptimizationLeadingArgumentUsedTwice() {
b331163b 440 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
441 SimpleFormatter fmt;
442 fmt.applyPattern("{2}, {0}, {1} and {3} {2}", status);
b331163b
A
443 if (!assertSuccess("Status", status)) {
444 return;
445 }
446 UnicodeString result("original");
f3c0d7a5 447 int32_t offsets[4];
b331163b
A
448 UnicodeString freddy("freddy");
449 UnicodeString frog("frog");
450 UnicodeString by("by");
451 const UnicodeString *params[] = {&freddy, &frog, &result, &by};
452 assertEquals(
453 "",
454 "original, freddy, frog and by original",
455 fmt.formatAndReplace(
456 params,
457 UPRV_LENGTHOF(params),
458 result,
459 offsets,
460 UPRV_LENGTHOF(offsets),
461 status));
462 if (!assertSuccess("Status", status)) {
463 return;
464 }
465 int32_t expectedOffsets[] = {10, 18, 30, 27};
466 verifyOffsets(expectedOffsets, offsets, UPRV_LENGTHOF(expectedOffsets));
467}
468
2ca993e8 469void SimpleFormatterTest::TestFormatReplaceOptimizationNoOffsets() {
b331163b 470 UErrorCode status = U_ZERO_ERROR;
2ca993e8
A
471 SimpleFormatter fmt;
472 fmt.applyPattern("{2}, {0}, {1} and {3}", status);
b331163b
A
473 if (!assertSuccess("Status", status)) {
474 return;
475 }
476 UnicodeString result("original");
477 UnicodeString freddy("freddy");
478 UnicodeString frog("frog");
479 UnicodeString by("by");
480 const UnicodeString *params[] = {&freddy, &frog, &result, &by};
481 assertEquals(
482 "",
483 "original, freddy, frog and by",
484 fmt.formatAndReplace(
485 params,
486 UPRV_LENGTHOF(params),
487 result,
488 NULL,
489 0,
490 status));
491 assertSuccess("Status", status);
492}
493
2ca993e8 494void SimpleFormatterTest::TestFormatReplaceNoOptimizationNoOffsets() {
b331163b 495 UErrorCode status = U_ZERO_ERROR;
2ca993e8 496 SimpleFormatter fmt("Arguments {0} and {1}", status);
b331163b
A
497 UnicodeString result("previous:");
498 UnicodeString frog("frog");
499 const UnicodeString *params[] = {&result, &frog};
500 assertEquals(
501 "",
2ca993e8 502 "Arguments previous: and frog",
b331163b
A
503 fmt.formatAndReplace(
504 params,
505 UPRV_LENGTHOF(params),
506 result,
507 NULL,
508 0,
509 status));
510 assertSuccess("Status", status);
511}
512
2ca993e8
A
513void SimpleFormatterTest::TestQuotingLikeMessageFormat() {
514#if !UCONFIG_NO_FORMATTING
515 UErrorCode status = U_ZERO_ERROR;
516 UnicodeString pattern = "{0} don't can''t '{5}''}{a' again '}'{1} to the '{end";
517 SimpleFormatter spf(pattern, status);
518 MessageFormat mf(pattern, Locale::getRoot(), status);
519 UnicodeString expected = "X don't can't {5}'}{a again }Y to the {end";
520 UnicodeString x("X"), y("Y");
521 Formattable values[] = { x, y };
522 UnicodeString result;
523 FieldPosition ignore(FieldPosition::DONT_CARE);
524 assertEquals("MessageFormat", expected, mf.format(values, 2, result, ignore, status));
525 assertEquals("SimpleFormatter", expected, spf.format(x, y, result.remove(), status));
526#endif /* !UCONFIG_NO_FORMATTING */
527}
528
529void SimpleFormatterTest::verifyOffsets(
b331163b
A
530 const int32_t *expected, const int32_t *actual, int32_t count) {
531 for (int32_t i = 0; i < count; ++i) {
532 if (expected[i] != actual[i]) {
533 errln("Expected %d, got %d", expected[i], actual[i]);
534 }
535 }
536}
537
2ca993e8
A
538extern IntlTest *createSimpleFormatterTest() {
539 return new SimpleFormatterTest();
57a6839d 540}