--- a/xpcom/tests/gtest/TestTextFormatter.cpp
+++ b/xpcom/tests/gtest/TestTextFormatter.cpp
@@ -1,17 +1,35 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsTextFormatter.h"
#include "nsString.h"
+
+#ifdef MOZ_CRASHREPORTER
+#include "nsCOMPtr.h"
+#include "nsICrashReporter.h"
+#include "nsServiceManagerUtils.h"
+#endif
+
#include "gtest/gtest.h"
+void DisableCrashReporterForTextFormatter()
+{
+#ifdef MOZ_CRASHREPORTER
+ nsCOMPtr<nsICrashReporter> crashreporter =
+ do_GetService("@mozilla.org/toolkit/crash-reporter;1");
+ if (crashreporter) {
+ crashreporter->SetEnabled(false);
+ }
+#endif
+}
+
TEST(TextFormatter, Tests)
{
nsAutoString fmt(NS_LITERAL_STRING("%3$s %4$S %1$d %2$d %2$d %3$s"));
char utf8[] = "Hello";
char16_t ucs2[]={'W', 'o', 'r', 'l', 'd', 0x4e00, 0xAc00, 0xFF45, 0x0103, 0x00};
int d=3;
char16_t buf[256];
@@ -27,8 +45,177 @@ TEST(TextFormatter, Tests)
0x33, 0x33, 0x20, 0x48, 0x65, 0x6C,
0x6C, 0x6F};
for (uint32_t i=0; i<out.Length(); i++) {
ASSERT_EQ(uout[i], expected[i]);
}
}
+/*
+ * The tests below validate checks we run on localizations against the
+ * implementation of the nsTextFormatter.
+ * If they need fixing, please CC l10n@mozilla.com to the bug,
+ * to evaluate the necessary changes to the l10n ecosystem and checks.
+ *
+ * EXPECT_STRNE cases need checks in compare-locales, and of course
+ * EXPECT_DEATH, too.
+ */
+
+/*
+ * Check misordered parameters
+ */
+
+TEST(TextFormatterOrdering, orders)
+{
+ nsString out;
+
+ // plain list
+ out.Adopt(nsTextFormatter::smprintf(u"%S %S %S", u"1", u"2", u"3"));
+ EXPECT_STREQ("1 2 3", NS_ConvertUTF16toUTF8(out).get());
+
+ // ordered list
+ out.Adopt(nsTextFormatter::smprintf(u"%2$S %3$S %1$S", u"1", u"2", u"3"));
+ EXPECT_STREQ("2 3 1", NS_ConvertUTF16toUTF8(out).get());
+
+ // mixed ordered list and non-ordered
+ // This hits an MOZ_ASSERT. TODO
+ out.Adopt(nsTextFormatter::smprintf(u"%2S %S %1$S", u"1", u"2", u"3"));
+ EXPECT_STRNE("2 3 1", NS_ConvertUTF16toUTF8(out).get());
+
+ // Referencing an extra param returns empty strings
+ out.Adopt(nsTextFormatter::smprintf(u" %2$S ", u"1"));
+ EXPECT_STRNE(" 1 ", NS_ConvertUTF16toUTF8(out).get());
+
+ // Double referencing existing argument works
+ out.Adopt(nsTextFormatter::smprintf(u"%1$S %1$S", u"1"));
+ EXPECT_STREQ("1 1", NS_ConvertUTF16toUTF8(out).get());
+
+ // Dropping trailing argument works
+ out.Adopt(nsTextFormatter::smprintf(u" %1$S ", u"1", u"2"));
+ EXPECT_STREQ(" 1 ", NS_ConvertUTF16toUTF8(out).get());
+
+ // Dropping leading arguments doesn't
+ out.Adopt(nsTextFormatter::smprintf(u" %2$S ", u"1", u"2"));
+ EXPECT_STRNE(" 2 ", NS_ConvertUTF16toUTF8(out).get());
+
+ // Dropping middle arguments doesn't
+ out.Adopt(nsTextFormatter::smprintf(u" %3$S %1$S ", u"1", u"2", u"3"));
+ EXPECT_STRNE(" 3 1 ", NS_ConvertUTF16toUTF8(out).get());
+}
+
+/*
+ * Tests to validate that horrible things happen if the passed-in
+ * variable and the formatter don't match.
+ */
+TEST(TextFormatterTestMismatch, format_d)
+{
+ DisableCrashReporterForTextFormatter();
+ NS_NAMED_LITERAL_STRING(fmt, "%d");
+ nsString out;
+ // just for completeness, this is our format, and works
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), int(-1)));
+ EXPECT_STREQ("-1", NS_ConvertUTF16toUTF8(out).get());
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), (uint32_t)-1));
+ EXPECT_STRNE("360999", NS_ConvertUTF16toUTF8(out).get());
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), float(3.5)));
+ EXPECT_STRNE("3.5", NS_ConvertUTF16toUTF8(out).get());
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), "foo"));
+ EXPECT_STRNE("foo", NS_ConvertUTF16toUTF8(out).get());
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), u"foo"));
+ EXPECT_STRNE("foo", NS_ConvertUTF16toUTF8(out).get());
+}
+
+TEST(TextFormatterTestMismatch, format_u)
+{
+ DisableCrashReporterForTextFormatter();
+ NS_NAMED_LITERAL_STRING(fmt, "%u");
+ nsString out;
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), int(-1)));
+ EXPECT_STRNE("-1", NS_ConvertUTF16toUTF8(out).get());
+ // just for completeness, this is our format, and works
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), (uint32_t)-1));
+ EXPECT_STREQ("4294967295", NS_ConvertUTF16toUTF8(out).get());
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), float(3.5)));
+ EXPECT_STRNE("3.5", NS_ConvertUTF16toUTF8(out).get());
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), "foo"));
+ EXPECT_STRNE("foo", NS_ConvertUTF16toUTF8(out).get());
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), u"foo"));
+ EXPECT_STRNE("foo", NS_ConvertUTF16toUTF8(out).get());
+}
+
+TEST(TextFormatterTestMismatch, format_x)
+{
+ DisableCrashReporterForTextFormatter();
+ NS_NAMED_LITERAL_STRING(fmt, "%x");
+ nsString out;
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), int(-1)));
+ // not clear if this is intended or not, but it's not completely garbage
+ EXPECT_STREQ("ffffffff", NS_ConvertUTF16toUTF8(out).get());
+ // just for completeness, this is our format, and works
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), (uint32_t)-1));
+ EXPECT_STREQ("ffffffff", NS_ConvertUTF16toUTF8(out).get());
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), float(3.5)));
+ EXPECT_STRNE("3.5", NS_ConvertUTF16toUTF8(out).get());
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), "foo"));
+ EXPECT_STRNE("foo", NS_ConvertUTF16toUTF8(out).get());
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), u"foo"));
+ EXPECT_STRNE("foo", NS_ConvertUTF16toUTF8(out).get());
+}
+
+TEST(TextFormatterTestMismatch, format_s)
+{
+ DisableCrashReporterForTextFormatter();
+ NS_NAMED_LITERAL_STRING(fmt, "%s");
+ nsString out;
+ EXPECT_DEATH_IF_SUPPORTED(nsTextFormatter::smprintf(fmt.get(), int(-1)), "");
+ EXPECT_DEATH_IF_SUPPORTED(nsTextFormatter::smprintf(fmt.get(), (uint32_t)-1), "");
+ EXPECT_DEATH_IF_SUPPORTED(nsTextFormatter::smprintf(fmt.get(), float(3.5)), "");
+ // just for completeness, this is our format, and works
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), "foo"));
+ EXPECT_STREQ("foo", NS_ConvertUTF16toUTF8(out).get());
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), u"foo"));
+ EXPECT_STRNE("foo", NS_LossyConvertUTF16toASCII(out).get());
+}
+
+TEST(TextFormatterTestMismatch, format_S)
+{
+ DisableCrashReporterForTextFormatter();
+ NS_NAMED_LITERAL_STRING(fmt, "%S");
+ nsString out;
+ EXPECT_DEATH_IF_SUPPORTED(nsTextFormatter::smprintf(fmt.get(), int32_t(-1)), "");
+ EXPECT_DEATH_IF_SUPPORTED(nsTextFormatter::smprintf(fmt.get(), (uint32_t)-1), "");
+ EXPECT_DEATH_IF_SUPPORTED(nsTextFormatter::smprintf(fmt.get(), float(3.5)), "");
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), "foo"));
+ EXPECT_STRNE("foo", NS_ConvertUTF16toUTF8(out).get());
+ // just for completeness, this is our format, and works
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), u"foo"));
+ EXPECT_STREQ("foo", NS_ConvertUTF16toUTF8(out).get());
+}
+
+TEST(TextFormatterTestMismatch, format_c)
+{
+ DisableCrashReporterForTextFormatter();
+ NS_NAMED_LITERAL_STRING(fmt, "%c");
+ nsString out;
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), int32_t(-1)));
+ EXPECT_EQ(1u, out.Length());
+ EXPECT_EQ((uint16_t)-1, out.CharAt(0)); // not useful for humans :-/
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), (uint32_t)-1));
+ EXPECT_EQ(1u, out.Length());
+ EXPECT_EQ((uint16_t)-1, out.CharAt(0)); // not useful for humans :-/
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), float(3.5)));
+ EXPECT_NE(1u, out.Length()); // not even the length works here :-?
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), "foo"));
+ EXPECT_EQ(1u, out.Length());
+ EXPECT_NE(u'f', out.CharAt(0));
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), u"foo"));
+ EXPECT_EQ(1u, out.Length());
+ EXPECT_NE(u'f', out.CharAt(0));
+
+ // just for completeness, this is our format, and works
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), 'c'));
+ EXPECT_EQ(1u, out.Length());
+ EXPECT_EQ(u'c', out.CharAt(0));
+ out.Adopt(nsTextFormatter::smprintf(fmt.get(), u'c'));
+ EXPECT_EQ(1u, out.Length());
+ EXPECT_EQ(u'c', out.CharAt(0));
+}