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
16StringFormatTest::StringFormatTest()
17{
18}
19
20
21StringFormatTest::~StringFormatTest()
22{
23}
24
25
26void
27StringFormatTest::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
94void
95StringFormatTest::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
129StringFormatTest::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