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