⛏️ index : haiku.git

/*
 * Copyright 2014 Haiku, Inc.
 * Distributed under the terms of the MIT License.
 */


#include "StringFormatTest.h"

#include <Locale.h>
#include <StringFormat.h>

#include <cppunit/TestCaller.h>
#include <cppunit/TestSuite.h>


StringFormatTest::StringFormatTest()
{
}


StringFormatTest::~StringFormatTest()
{
}


void
StringFormatTest::TestFormat()
{
	BString output;

	struct Test {
		const char* locale;
		const char* pattern;
		int32 number;
		const char* expected;
	};

	static const char* polishTemplate = "{0, plural, one{Wybrano # obiekt} "
		"few{Wybrano # obiekty} many{Wybrano # obiektΓ³w} "
		"other{Wybrano # obyektu}}";

	// There are 4 rules in russian: one (1, 21, ...), few (2-4, 22-24, ...),
	// many (anything else), and other (non-integer numbers). When formatting
	// integers only, either both many and other must be there (with other
	// not being used), or one/few/other must be used.
	static const char* russianTemplate = "{0, plural, one{# ΠΎΠ±ΡŠΠ΅ΠΊΡ‚} "
		"few{# ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°} other{# ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ²}}";

	static const Test tests[] = {
		{"en_US", "A QA engineer walks into a bar.", 0,
			"A QA engineer walks into a bar."},
		{"en_US", "Orders {0, plural, one{# beer} other{# beers}}.", 1,
			"Orders 1 beer."},
		{"en_US", "Orders {0, plural, one{# beer} other{# beers}}.", 0,
			"Orders 0 beers."},
		{"en_US", "Orders {0, plural, one{# beer} other{# beers}}.", 99999999,
			"Orders 99,999,999 beers."},
		{"en_US", "Orders {0, plural, one{# beer} other{# beers}}.", -INT_MAX,
			"Orders -2,147,483,647 beers."},
		{"en_US", "Orders {0, plural, one{# beer} other{# beers}}.", -1,
			"Orders -1 beer."},
		{"en_US", "Orders {0, plural, one{a lizard} other{more lizards}}.", 1,
			"Orders a lizard."},
		{"en_US", "Orders {0, plural, one{a lizard} other{more lizards}}.", 2,
			"Orders more lizards."},
		{"en_US", "Orders {0, plural, one{# \x8A} other{# \x02}}.", 2,
			"Orders 2 \x02."},
		{"fr_FR", "Commande {0, plural, one{# bière} other{# bières}}.",
			99999999, "Commande 99 999 999 bières."},
		{"pl_PL", polishTemplate, 1, "Wybrano 1 obiekt"},
		{"pl_PL", polishTemplate, 3, "Wybrano 3 obiekty"},
		{"pl_PL", polishTemplate, 5, "Wybrano 5 obiektΓ³w"},
		{"pl_PL", polishTemplate, 23, "Wybrano 23 obiekty"},
		{"ru_RU", russianTemplate, 1, "1 ΠΎΠ±ΡŠΠ΅ΠΊΡ‚"},
		{"ru_RU", russianTemplate, 2, "2 ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°"},
		{"ru_RU", russianTemplate, 5, "5 ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ²"},
		{NULL, NULL, 0, NULL}
	};

	for (int i = 0; tests[i].pattern != NULL; i++) {
		status_t result;
		NextSubTest();
		output.Truncate(0);
		BLanguage language(tests[i].locale);
		BStringFormat formatter(language, tests[i].pattern);

		result = formatter.Format(output, tests[i].number);
		CPPUNIT_ASSERT_EQUAL(B_OK, result);
		CPPUNIT_ASSERT_EQUAL(BString(tests[i].expected), output);
	}
}


void
StringFormatTest::TestBogus()
{
	struct Test {
		const char* pattern;
	};

	static const Test tests[] = {
		{ "{0, plural, one{# dog} other{# dogs}" }, // Missing closing brace
		{ "{0, plural, one{# dog}, other{# dogs}}" }, // Extra comma
		{ "{0, plural, one{# dog}" }, // Missing "other"
		//{ "{4099, plural, one{# dog} other{# dogs}}" }, // Out of bounds arg
		{ "{0, invalid, one{# dog} other{# dogs}}" }, // Invalid rule
		{ NULL }
	};

	for (int i = 0; tests[i].pattern != NULL; i++) {
		NextSubTest();

		status_t result;
		BString output;

		BStringFormat formatter(tests[i].pattern);
		CPPUNIT_ASSERT(formatter.InitCheck() != B_OK);

		result = formatter.Format(output, 1);
		CPPUNIT_ASSERT(result != B_OK);

		result = formatter.Format(output, 2);
		CPPUNIT_ASSERT(result != B_OK);
	}
}


/*static*/ void
StringFormatTest::AddTests(BTestSuite& parent)
{
	CppUnit::TestSuite& suite = *new CppUnit::TestSuite("StringFormatTest");

	suite.addTest(new CppUnit::TestCaller<StringFormatTest>(
		"StringFormatTest::TestFormat", &StringFormatTest::TestFormat));
	suite.addTest(new CppUnit::TestCaller<StringFormatTest>(
		"StringFormatTest::TestBogus", &StringFormatTest::TestBogus));

	parent.addTest("StringFormatTest", &suite);
}