summaryrefslogtreecommitdiffstats
path: root/modules/libpref/test/gtest
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--modules/libpref/test/gtest/Basics.cpp58
-rw-r--r--modules/libpref/test/gtest/Parser.cpp496
-rw-r--r--modules/libpref/test/gtest/moz.build23
3 files changed, 577 insertions, 0 deletions
diff --git a/modules/libpref/test/gtest/Basics.cpp b/modules/libpref/test/gtest/Basics.cpp
new file mode 100644
index 0000000000..1bf8561a0d
--- /dev/null
+++ b/modules/libpref/test/gtest/Basics.cpp
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "gtest/gtest.h"
+#include "mozilla/Preferences.h"
+
+using namespace mozilla;
+
+TEST(PrefsBasics, Errors)
+{
+ Preferences::SetBool("foo.bool", true, PrefValueKind::Default);
+ Preferences::SetBool("foo.bool", false, PrefValueKind::User);
+ ASSERT_EQ(Preferences::GetBool("foo.bool", false, PrefValueKind::Default),
+ true);
+ ASSERT_EQ(Preferences::GetBool("foo.bool", true, PrefValueKind::User), false);
+
+ Preferences::SetInt("foo.int", -66, PrefValueKind::Default);
+ Preferences::SetInt("foo.int", -77, PrefValueKind::User);
+ ASSERT_EQ(Preferences::GetInt("foo.int", 1, PrefValueKind::Default), -66);
+ ASSERT_EQ(Preferences::GetInt("foo.int", 1, PrefValueKind::User), -77);
+
+ Preferences::SetUint("foo.uint", 88, PrefValueKind::Default);
+ Preferences::SetUint("foo.uint", 99, PrefValueKind::User);
+ ASSERT_EQ(Preferences::GetUint("foo.uint", 1, PrefValueKind::Default), 88U);
+ ASSERT_EQ(Preferences::GetUint("foo.uint", 1, PrefValueKind::User), 99U);
+
+ Preferences::SetFloat("foo.float", 3.33f, PrefValueKind::Default);
+ Preferences::SetFloat("foo.float", 4.44f, PrefValueKind::User);
+ ASSERT_FLOAT_EQ(
+ Preferences::GetFloat("foo.float", 1.0f, PrefValueKind::Default), 3.33f);
+ ASSERT_FLOAT_EQ(Preferences::GetFloat("foo.float", 1.0f, PrefValueKind::User),
+ 4.44f);
+}
+
+TEST(PrefsBasics, Serialize)
+{
+ // Ensure that at least this one preference exists
+ Preferences::SetBool("foo.bool", true, PrefValueKind::Default);
+ ASSERT_EQ(Preferences::GetBool("foo.bool", false, PrefValueKind::Default),
+ true);
+
+ nsCString str;
+ Preferences::SerializePreferences(str, true);
+ fprintf(stderr, "%s\n", str.Data());
+ // Assert that some prefs were not sanitized
+ ASSERT_NE(nullptr, strstr(str.Data(), "B--:"));
+ ASSERT_NE(nullptr, strstr(str.Data(), "I--:"));
+ ASSERT_NE(nullptr, strstr(str.Data(), "S--:"));
+ // Assert that something was sanitized
+ ASSERT_NE(
+ nullptr,
+ strstr(
+ str.Data(),
+ "I-S:56/datareporting.policy.dataSubmissionPolicyAcceptedVersion"));
+}
diff --git a/modules/libpref/test/gtest/Parser.cpp b/modules/libpref/test/gtest/Parser.cpp
new file mode 100644
index 0000000000..972d32cfca
--- /dev/null
+++ b/modules/libpref/test/gtest/Parser.cpp
@@ -0,0 +1,496 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "gtest/gtest.h"
+#include "mozilla/ArrayUtils.h"
+#include "Preferences.h"
+
+using namespace mozilla;
+
+// Keep this in sync with the declaration in Preferences.cpp.
+//
+// It's declared here to avoid polluting Preferences.h with test-only stuff.
+void TestParseError(PrefValueKind aKind, const char* aText,
+ nsCString& aErrorMsg);
+
+TEST(PrefsParser, Errors)
+{
+ nsAutoCStringN<128> actualErrorMsg;
+
+// Use a macro rather than a function so that the line number reported by
+// gtest on failure is useful.
+#define P(kind_, text_, expectedErrorMsg_) \
+ do { \
+ TestParseError(kind_, text_, actualErrorMsg); \
+ ASSERT_STREQ(expectedErrorMsg_, actualErrorMsg.get()); \
+ } while (0)
+
+#define DEFAULT(text_, expectedErrorMsg_) \
+ P(PrefValueKind::Default, text_, expectedErrorMsg_)
+
+#define USER(text_, expectedErrorMsg_) \
+ P(PrefValueKind::User, text_, expectedErrorMsg_)
+
+ // clang-format off
+
+ //-------------------------------------------------------------------------
+ // Valid syntax. (Other testing of more typical valid syntax and semantics is
+ // done in modules/libpref/test/unit/test_parser.js.)
+ //-------------------------------------------------------------------------
+
+ // Normal prefs.
+ DEFAULT(R"(
+pref("bool", true);
+sticky_pref("int", 123);
+user_pref("string", "value");
+ )",
+ ""
+ );
+
+ // Totally empty input.
+ DEFAULT("", "");
+
+ // Whitespace-only input.
+ DEFAULT(R"(
+
+ )" "\v \t \v \f",
+ ""
+ );
+
+ // Comment-only inputs.
+ DEFAULT(R"(// blah)", "");
+ DEFAULT(R"(# blah)", "");
+ DEFAULT(R"(/* blah */)", "");
+
+ //-------------------------------------------------------------------------
+ // All the lexing errors. (To be pedantic, some of the integer literal
+ // overflows are triggered in the parser, but put them all here so they're all
+ // in the one spot.)
+ //-------------------------------------------------------------------------
+
+ // Integer overflow errors.
+ DEFAULT(R"(
+pref("int.ok", 2147483647);
+pref("int.overflow", 2147483648);
+pref("int.ok", +2147483647);
+pref("int.overflow", +2147483648);
+pref("int.ok", -2147483648);
+pref("int.overflow", -2147483649);
+pref("int.overflow", 4294967296);
+pref("int.overflow", +4294967296);
+pref("int.overflow", -4294967296);
+pref("int.overflow", 4294967297);
+pref("int.overflow", 1234567890987654321);
+ )",
+ "test:3: prefs parse error: integer literal overflowed\n"
+ "test:5: prefs parse error: integer literal overflowed\n"
+ "test:7: prefs parse error: integer literal overflowed\n"
+ "test:8: prefs parse error: integer literal overflowed\n"
+ "test:9: prefs parse error: integer literal overflowed\n"
+ "test:10: prefs parse error: integer literal overflowed\n"
+ "test:11: prefs parse error: integer literal overflowed\n"
+ "test:12: prefs parse error: integer literal overflowed\n"
+ );
+
+ // Other integer errors.
+ DEFAULT(R"(
+pref("int.unexpected", 100foo);
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: unexpected character in integer literal\n"
+ );
+
+ // \x00 is not allowed.
+ DEFAULT(R"(
+pref("string.bad-x-escape", "foo\x00bar");
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: \\x00 is not allowed\n"
+ );
+
+ // Various bad things after \x: end of string, punctuation, space, newline,
+ // EOF.
+ DEFAULT(R"(
+pref("string.bad-x-escape", "foo\x");
+pref("string.bad-x-escape", "foo\x,bar");
+pref("string.bad-x-escape", "foo\x 12");
+pref("string.bad-x-escape", "foo\x
+12");
+pref("string.bad-x-escape", "foo\x)",
+ "test:2: prefs parse error: malformed \\x escape sequence\n"
+ "test:3: prefs parse error: malformed \\x escape sequence\n"
+ "test:4: prefs parse error: malformed \\x escape sequence\n"
+ "test:5: prefs parse error: malformed \\x escape sequence\n"
+ "test:7: prefs parse error: malformed \\x escape sequence\n"
+ );
+
+ // Not enough hex digits.
+ DEFAULT(R"(
+pref("string.bad-x-escape", "foo\x1");
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: malformed \\x escape sequence\n"
+ );
+
+ // Invalid hex digit.
+ DEFAULT(R"(
+pref("string.bad-x-escape", "foo\x1G");
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: malformed \\x escape sequence\n"
+ );
+
+ // \u0000 is not allowed.
+ // (The string literal is broken in two so that MSVC doesn't complain about
+ // an invalid universal-character-name.)
+ DEFAULT(R"(
+pref("string.bad-u-escape", "foo\)" R"(u0000 bar");
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: \\u0000 is not allowed\n"
+ );
+
+ // Various bad things after \u: end of string, punctuation, space, newline,
+ // EOF.
+ DEFAULT(R"(
+pref("string.bad-u-escape", "foo\u");
+pref("string.bad-u-escape", "foo\u,bar");
+pref("string.bad-u-escape", "foo\u 1234");
+pref("string.bad-u-escape", "foo\u
+1234");
+pref("string.bad-u-escape", "foo\u)",
+ "test:2: prefs parse error: malformed \\u escape sequence\n"
+ "test:3: prefs parse error: malformed \\u escape sequence\n"
+ "test:4: prefs parse error: malformed \\u escape sequence\n"
+ "test:5: prefs parse error: malformed \\u escape sequence\n"
+ "test:7: prefs parse error: malformed \\u escape sequence\n"
+ );
+
+ // Not enough hex digits.
+ DEFAULT(R"(
+pref("string.bad-u-escape", "foo\u1");
+pref("string.bad-u-escape", "foo\u12");
+pref("string.bad-u-escape", "foo\u123");
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: malformed \\u escape sequence\n"
+ "test:3: prefs parse error: malformed \\u escape sequence\n"
+ "test:4: prefs parse error: malformed \\u escape sequence\n"
+ );
+
+ // Invalid hex digit.
+ DEFAULT(R"(
+pref("string.bad-u-escape", "foo\u1G34");
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: malformed \\u escape sequence\n"
+ );
+
+ // High surrogate not followed by low surrogate.
+ // (The string literal is broken in two so that MSVC doesn't complain about
+ // an invalid universal-character-name.)
+ DEFAULT(R"(
+pref("string.bad-u-surrogate", "foo\)" R"(ud83c,blah");
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: expected low surrogate after high surrogate\n"
+ );
+
+ // High surrogate followed by invalid low surrogate.
+ // (The string literal is broken in two so that MSVC doesn't complain about
+ // an invalid universal-character-name.)
+ DEFAULT(R"(
+pref("string.bad-u-surrogate", "foo\)" R"(ud83c\u1234");
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: invalid low surrogate after high surrogate\n"
+ );
+
+ // Low surrogate not preceded by high surrogate.
+ // (The string literal is broken in two so that MSVC doesn't complain about
+ // an invalid universal-character-name.)
+ DEFAULT(R"(
+pref("string.bad-u-surrogate", "foo\)" R"(udc00");
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: expected high surrogate before low surrogate\n"
+ );
+
+ // Unlike in JavaScript, \b, \f, \t, \v aren't allowed.
+ DEFAULT(R"(
+pref("string.bad-escape", "foo\b");
+pref("string.bad-escape", "foo\f");
+pref("string.bad-escape", "foo\t");
+pref("string.bad-escape", "foo\v");
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: unexpected escape sequence character after '\\'\n"
+ "test:3: prefs parse error: unexpected escape sequence character after '\\'\n"
+ "test:4: prefs parse error: unexpected escape sequence character after '\\'\n"
+ "test:5: prefs parse error: unexpected escape sequence character after '\\'\n"
+ );
+
+ // Various bad things after \: non-special letter, number, punctuation,
+ // space, newline, EOF.
+ DEFAULT(R"(
+pref("string.bad-escape", "foo\Q");
+pref("string.bad-escape", "foo\1");
+pref("string.bad-escape", "foo\,");
+pref("string.bad-escape", "foo\ n");
+pref("string.bad-escape", "foo\
+n");
+pref("string.bad-escape", "foo\)",
+ "test:2: prefs parse error: unexpected escape sequence character after '\\'\n"
+ "test:3: prefs parse error: unexpected escape sequence character after '\\'\n"
+ "test:4: prefs parse error: unexpected escape sequence character after '\\'\n"
+ "test:5: prefs parse error: unexpected escape sequence character after '\\'\n"
+ "test:6: prefs parse error: unexpected escape sequence character after '\\'\n"
+ "test:8: prefs parse error: unexpected escape sequence character after '\\'\n"
+ );
+
+ // Unterminated string literals.
+
+ // Simple case.
+ DEFAULT(R"(
+pref("string.unterminated-string", "foo
+ )",
+ "test:3: prefs parse error: unterminated string literal\n"
+ );
+
+ // Alternative case; `int` comes after the string and is seen as a keyword.
+ // The parser then skips to the ';', so no error about the unterminated
+ // string is issued.
+ DEFAULT(R"(
+pref("string.unterminated-string", "foo);
+pref("int.ok", 0);
+ )",
+ "test:3: prefs parse error: unknown keyword\n"
+ );
+
+ // Mismatched quotes (1).
+ DEFAULT(R"(
+pref("string.unterminated-string", "foo');
+ )",
+ "test:3: prefs parse error: unterminated string literal\n"
+ );
+
+ // Mismatched quotes (2).
+ DEFAULT(R"(
+pref("string.unterminated-string", 'foo");
+ )",
+ "test:3: prefs parse error: unterminated string literal\n"
+ );
+
+ // Unknown keywords.
+ DEFAULT(R"(
+foo;
+preff("string.bad-keyword", true);
+ticky_pref("string.bad-keyword", true);
+User_pref("string.bad-keyword", true);
+pref("string.bad-keyword", TRUE);
+ )",
+ "test:2: prefs parse error: unknown keyword\n"
+ "test:3: prefs parse error: unknown keyword\n"
+ "test:4: prefs parse error: unknown keyword\n"
+ "test:5: prefs parse error: unknown keyword\n"
+ "test:6: prefs parse error: unknown keyword\n"
+ );
+
+ // Unterminated C-style comment.
+ DEFAULT(R"(
+/* comment
+ )",
+ "test:3: prefs parse error: unterminated /* comment\n"
+ );
+
+ // Malformed comments (single slashes), followed by whitespace, newline, EOF.
+ DEFAULT(R"(
+/ comment;
+/
+; /)",
+ "test:2: prefs parse error: expected '/' or '*' after '/'\n"
+ "test:3: prefs parse error: expected '/' or '*' after '/'\n"
+ "test:4: prefs parse error: expected '/' or '*' after '/'\n"
+ );
+
+ // C++-style comment ending in EOF (1).
+ DEFAULT(R"(
+// comment)",
+ ""
+ );
+
+ // C++-style comment ending in EOF (2).
+ DEFAULT(R"(
+//)",
+ ""
+ );
+
+ // Various unexpected characters.
+ DEFAULT(R"(
+pref("unexpected.chars", &true);
+pref("unexpected.chars" : true);
+@pref("unexpected.chars", true);
+pref["unexpected.chars": true];
+ )",
+ "test:2: prefs parse error: unexpected character\n"
+ "test:3: prefs parse error: unexpected character\n"
+ "test:4: prefs parse error: unexpected character\n"
+ "test:5: prefs parse error: unexpected character\n"
+ );
+
+ //-------------------------------------------------------------------------
+ // All the parsing errors.
+ //-------------------------------------------------------------------------
+
+ DEFAULT(R"(
+"pref"("parse.error": true);
+pref1("parse.error": true);
+pref(123: true);
+pref("parse.error" true);
+pref("parse.error", pref);
+pref("parse.error", -true);
+pref("parse.error", +"value");
+pref("parse.error", true,);
+pref("parse.error", true;
+pref("parse.error", true, sticky, locked;
+pref("parse.error", true)
+pref("int.ok", 1);
+pref("parse.error", true))",
+ "test:2: prefs parse error: expected pref specifier at start of pref definition\n"
+ "test:3: prefs parse error: expected '(' after pref specifier\n"
+ "test:4: prefs parse error: expected pref name after '('\n"
+ "test:5: prefs parse error: expected ',' after pref name\n"
+ "test:6: prefs parse error: expected pref value after ','\n"
+ "test:7: prefs parse error: expected integer literal after '-'\n"
+ "test:8: prefs parse error: expected integer literal after '+'\n"
+ "test:9: prefs parse error: expected pref attribute after ','\n"
+ "test:10: prefs parse error: expected ',' or ')' after pref value\n"
+ "test:11: prefs parse error: expected ',' or ')' after pref attribute\n"
+ "test:13: prefs parse error: expected ';' after ')'\n"
+ "test:14: prefs parse error: expected ';' after ')'\n"
+ );
+
+ USER(R"(
+pref("parse.error", true);
+sticky_pref("parse.error", true);
+user_pref("int.ok", 1);
+ )",
+ "test:2: prefs parse error: expected 'user_pref' at start of pref definition\n"
+ "test:3: prefs parse error: expected 'user_pref' at start of pref definition\n"
+ );
+
+ USER(R"(
+user_pref("parse.error", true;
+user_pref("int.ok", 1);
+ )",
+ "test:2: prefs parse error: expected ')' after pref value\n"
+ );
+
+ // Parse errors involving unexpected EOF.
+
+ DEFAULT(R"(
+pref)",
+ "test:2: prefs parse error: expected '(' after pref specifier\n"
+ );
+
+ DEFAULT(R"(
+pref()",
+ "test:2: prefs parse error: expected pref name after '('\n"
+ );
+
+ DEFAULT(R"(
+pref("parse.error")",
+ "test:2: prefs parse error: expected ',' after pref name\n"
+ );
+
+ DEFAULT(R"(
+pref("parse.error",)",
+ "test:2: prefs parse error: expected pref value after ','\n"
+ );
+
+ DEFAULT(R"(
+pref("parse.error", -)",
+ "test:2: prefs parse error: expected integer literal after '-'\n"
+ );
+
+ DEFAULT(R"(
+pref("parse.error", +)",
+ "test:2: prefs parse error: expected integer literal after '+'\n"
+ );
+
+ DEFAULT(R"(
+pref("parse.error", true)",
+ "test:2: prefs parse error: expected ',' or ')' after pref value\n"
+ );
+
+ USER(R"(
+user_pref("parse.error", true)",
+ "test:2: prefs parse error: expected ')' after pref value\n"
+ );
+
+ DEFAULT(R"(
+pref("parse.error", true,)",
+ "test:2: prefs parse error: expected pref attribute after ','\n"
+ );
+
+ DEFAULT(R"(
+pref("parse.error", true, sticky)",
+ "test:2: prefs parse error: expected ',' or ')' after pref attribute\n"
+ );
+
+ DEFAULT(R"(
+pref("parse.error", true))",
+ "test:2: prefs parse error: expected ';' after ')'\n"
+ );
+
+ // This is something we saw in practice with the old parser, which allowed
+ // repeated semicolons.
+ DEFAULT(R"(
+pref("parse.error", true);;
+pref("parse.error", true, locked);;;
+pref("parse.error", true, sticky, locked);;;;
+pref("int.ok", 0);
+ )",
+ "test:2: prefs parse error: expected pref specifier at start of pref definition\n"
+ "test:3: prefs parse error: expected pref specifier at start of pref definition\n"
+ "test:3: prefs parse error: expected pref specifier at start of pref definition\n"
+ "test:4: prefs parse error: expected pref specifier at start of pref definition\n"
+ "test:4: prefs parse error: expected pref specifier at start of pref definition\n"
+ "test:4: prefs parse error: expected pref specifier at start of pref definition\n"
+ );
+
+ //-------------------------------------------------------------------------
+ // Invalid syntax after various newline combinations, for the purpose of
+ // testing that line numbers are correct.
+ //-------------------------------------------------------------------------
+
+ // In all of the following we have a \n, a \r, a \r\n, and then an error, so
+ // the error is on line 4. (Note: these ones don't use raw string literals
+ // because MSVC somehow swallows any \r that appears in them.)
+
+ DEFAULT("\n \r \r\n bad",
+ "test:4: prefs parse error: unknown keyword\n"
+ );
+
+ DEFAULT("#\n#\r#\r\n bad",
+ "test:4: prefs parse error: unknown keyword\n"
+ );
+
+ DEFAULT("//\n//\r//\r\n bad",
+ "test:4: prefs parse error: unknown keyword\n"
+ );
+
+ DEFAULT("/*\n \r \r\n*/ bad",
+ "test:4: prefs parse error: unknown keyword\n"
+ );
+
+ // Note: the escape sequences do *not* affect the line number.
+ DEFAULT("pref(\"foo\\n\n foo\\r\r foo\\r\\n\r\n foo\", bad);",
+ "test:4: prefs parse error: unknown keyword\n"
+ );
+
+ // clang-format on
+}
diff --git a/modules/libpref/test/gtest/moz.build b/modules/libpref/test/gtest/moz.build
new file mode 100644
index 0000000000..d689b382f8
--- /dev/null
+++ b/modules/libpref/test/gtest/moz.build
@@ -0,0 +1,23 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Library("libpreftests")
+
+LOCAL_INCLUDES += [
+ "../..",
+]
+
+UNIFIED_SOURCES = [
+ "Basics.cpp",
+ "Parser.cpp",
+]
+
+# THE MOCK_METHOD2 macro from gtest triggers this clang warning and it's hard
+# to work around, so we just ignore it.
+if CONFIG["CC_TYPE"] == "clang":
+ CXXFLAGS += ["-Wno-inconsistent-missing-override"]
+
+FINAL_LIBRARY = "xul-gtest"