xref: /haiku/src/tests/kits/locale/StringFormatTest.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
1 /*
2  * Copyright 2014 Haiku, Inc.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "StringFormatTest.h"
8 
9 #include <Locale.h>
10 #include <StringFormat.h>
11 
12 #include <cppunit/TestCaller.h>
13 #include <cppunit/TestSuite.h>
14 
15 
16 StringFormatTest::StringFormatTest()
17 {
18 }
19 
20 
21 StringFormatTest::~StringFormatTest()
22 {
23 }
24 
25 
26 void
27 StringFormatTest::TestFormat()
28 {
29 	BString output;
30 
31 	struct Test {
32 		const char* locale;
33 		const char* pattern;
34 		int32 number;
35 		const char* expected;
36 	};
37 
38 	static const char* polishTemplate = "{0, plural, one{Wybrano # obiekt} "
39 		"few{Wybrano # obiekty} many{Wybrano # obiektów} "
40 		"other{Wybrano # obyektu}}";
41 
42 	// There are 4 rules in russian: one (1, 21, ...), few (2-4, 22-24, ...),
43 	// many (anything else), and other (non-integer numbers). When formatting
44 	// integers only, either both many and other must be there (with other
45 	// not being used), or one/few/other must be used.
46 	static const char* russianTemplate = "{0, plural, one{# объект} "
47 		"few{# объекта} other{# объектов}}";
48 
49 	static const Test tests[] = {
50 		{"en_US", "A QA engineer walks into a bar.", 0,
51 			"A QA engineer walks into a bar."},
52 		{"en_US", "Orders {0, plural, one{# beer} other{# beers}}.", 1,
53 			"Orders 1 beer."},
54 		{"en_US", "Orders {0, plural, one{# beer} other{# beers}}.", 0,
55 			"Orders 0 beers."},
56 		{"en_US", "Orders {0, plural, one{# beer} other{# beers}}.", 99999999,
57 			"Orders 99,999,999 beers."},
58 		{"en_US", "Orders {0, plural, one{# beer} other{# beers}}.", -INT_MAX,
59 			"Orders -2,147,483,647 beers."},
60 		{"en_US", "Orders {0, plural, one{# beer} other{# beers}}.", -1,
61 			"Orders -1 beer."},
62 		{"en_US", "Orders {0, plural, one{a lizard} other{more lizards}}.", 1,
63 			"Orders a lizard."},
64 		{"en_US", "Orders {0, plural, one{a lizard} other{more lizards}}.", 2,
65 			"Orders more lizards."},
66 		{"en_US", "Orders {0, plural, one{# \x8A} other{# \x02}}.", 2,
67 			"Orders 2 \x02."},
68 		{"fr_FR", "Commande {0, plural, one{# bière} other{# bières}}.",
69 			99999999, "Commande 99 999 999 bières."},
70 		{"pl_PL", polishTemplate, 1, "Wybrano 1 obiekt"},
71 		{"pl_PL", polishTemplate, 3, "Wybrano 3 obiekty"},
72 		{"pl_PL", polishTemplate, 5, "Wybrano 5 obiektów"},
73 		{"pl_PL", polishTemplate, 23, "Wybrano 23 obiekty"},
74 		{"ru_RU", russianTemplate, 1, "1 объект"},
75 		{"ru_RU", russianTemplate, 2, "2 объекта"},
76 		{"ru_RU", russianTemplate, 5, "5 объектов"},
77 		{NULL, NULL, 0, NULL}
78 	};
79 
80 	for (int i = 0; tests[i].pattern != NULL; i++) {
81 		status_t result;
82 		NextSubTest();
83 		output.Truncate(0);
84 		BLanguage language(tests[i].locale);
85 		BStringFormat formatter(language, tests[i].pattern);
86 
87 		result = formatter.Format(output, tests[i].number);
88 		CPPUNIT_ASSERT_EQUAL(B_OK, result);
89 		CPPUNIT_ASSERT_EQUAL(BString(tests[i].expected), output);
90 	}
91 }
92 
93 
94 void
95 StringFormatTest::TestBogus()
96 {
97 	struct Test {
98 		const char* pattern;
99 	};
100 
101 	static const Test tests[] = {
102 		{ "{0, plural, one{# dog} other{# dogs}" }, // Missing closing brace
103 		{ "{0, plural, one{# dog}, other{# dogs}}" }, // Extra comma
104 		{ "{0, plural, one{# dog}" }, // Missing "other"
105 		//{ "{4099, plural, one{# dog} other{# dogs}}" }, // Out of bounds arg
106 		{ "{0, invalid, one{# dog} other{# dogs}}" }, // Invalid rule
107 		{ NULL }
108 	};
109 
110 	for (int i = 0; tests[i].pattern != NULL; i++) {
111 		NextSubTest();
112 
113 		status_t result;
114 		BString output;
115 
116 		BStringFormat formatter(tests[i].pattern);
117 		CPPUNIT_ASSERT(formatter.InitCheck() != B_OK);
118 
119 		result = formatter.Format(output, 1);
120 		CPPUNIT_ASSERT(result != B_OK);
121 
122 		result = formatter.Format(output, 2);
123 		CPPUNIT_ASSERT(result != B_OK);
124 	}
125 }
126 
127 
128 /*static*/ void
129 StringFormatTest::AddTests(BTestSuite& parent)
130 {
131 	CppUnit::TestSuite& suite = *new CppUnit::TestSuite("StringFormatTest");
132 
133 	suite.addTest(new CppUnit::TestCaller<StringFormatTest>(
134 		"StringFormatTest::TestFormat", &StringFormatTest::TestFormat));
135 	suite.addTest(new CppUnit::TestCaller<StringFormatTest>(
136 		"StringFormatTest::TestBogus", &StringFormatTest::TestBogus));
137 
138 	parent.addTest("StringFormatTest", &suite);
139 }
140