Bug 1674968 - UniqueJSONStrings unit tests - r=gregtatum

`UniqueJSONStrings` constructors now accept a `JSONWriter::CollectionStyle` to pass to the internal JSON writer.
The default won't change how the unique string list is output (with friendly indented lines), but tests can use `JSONWriter::SingleLineStyle` to make comparison strings more readable and maintainable.

Differential Revision: https://phabricator.services.mozilla.com/D95832
This commit is contained in:
Gerald Squelart 2020-11-06 01:35:36 +00:00
Родитель ac6be32a0a
Коммит 896ddd992a
3 изменённых файлов: 202 добавлений и 5 удалений

Просмотреть файл

@ -8,10 +8,13 @@
namespace mozilla::baseprofiler {
UniqueJSONStrings::UniqueJSONStrings() { mStringTableWriter.StartBareList(); }
UniqueJSONStrings::UniqueJSONStrings(JSONWriter::CollectionStyle aStyle) {
mStringTableWriter.StartBareList(aStyle);
}
UniqueJSONStrings::UniqueJSONStrings(const UniqueJSONStrings& aOther) {
mStringTableWriter.StartBareList();
UniqueJSONStrings::UniqueJSONStrings(const UniqueJSONStrings& aOther,
JSONWriter::CollectionStyle aStyle) {
mStringTableWriter.StartBareList(aStyle);
uint32_t count = mStringHashToIndexMap.count();
if (count != 0) {
MOZ_RELEASE_ASSERT(mStringHashToIndexMap.reserve(count));

Просмотреть файл

@ -297,10 +297,13 @@ class JSONSchemaWriter {
class UniqueJSONStrings {
public:
// Start an empty list of unique strings.
MFBT_API UniqueJSONStrings();
MFBT_API explicit UniqueJSONStrings(
JSONWriter::CollectionStyle aStyle = JSONWriter::MultiLineStyle);
// Start with a copy of the strings from another list.
MFBT_API explicit UniqueJSONStrings(const UniqueJSONStrings& aOther);
MFBT_API explicit UniqueJSONStrings(
const UniqueJSONStrings& aOther,
JSONWriter::CollectionStyle aStyle = JSONWriter::MultiLineStyle);
MFBT_API ~UniqueJSONStrings();

Просмотреть файл

@ -3555,6 +3555,196 @@ void TestProfiler() {
printf("TestProfiler done\n");
}
// Minimal string escaping, similar to how C++ stringliterals should be entered,
// to help update comparison strings in tests below.
void printEscaped(std::string_view aString) {
for (const char c : aString) {
switch (c) {
case '\n':
fprintf(stderr, "\\n\n");
break;
case '"':
fprintf(stderr, "\\\"");
break;
case '\\':
fprintf(stderr, "\\\\");
break;
default:
if (c >= ' ' && c <= '~') {
fprintf(stderr, "%c", c);
} else {
fprintf(stderr, "\\x%02x", unsigned(c));
}
break;
}
}
}
// Run aF(SpliceableChunkedJSONWriter&, UniqueJSONStrings&) from inside a JSON
// array, then output the string table, and compare the full output to
// aExpected.
template <typename F>
static void VerifyUniqueStringContents(
F&& aF, std::string_view aExpectedData,
std::string_view aExpectedUniqueStrings,
mozilla::baseprofiler::UniqueJSONStrings* aUniqueStringsOrNull = nullptr) {
mozilla::baseprofiler::SpliceableChunkedJSONWriter writer;
// By default use a local UniqueJSONStrings, otherwise use the one provided.
mozilla::baseprofiler::UniqueJSONStrings localUniqueStrings(
mozilla::JSONWriter::SingleLineStyle);
mozilla::baseprofiler::UniqueJSONStrings& uniqueStrings =
aUniqueStringsOrNull ? *aUniqueStringsOrNull : localUniqueStrings;
writer.Start(mozilla::JSONWriter::SingleLineStyle);
{
writer.StartArrayProperty("data", mozilla::JSONWriter::SingleLineStyle);
{ std::forward<F>(aF)(writer, uniqueStrings); }
writer.EndArray();
writer.StartArrayProperty("stringTable",
mozilla::JSONWriter::SingleLineStyle);
{ uniqueStrings.SpliceStringTableElements(writer); }
writer.EndArray();
}
writer.End();
UniquePtr<char[]> jsonString = writer.ChunkedWriteFunc().CopyData();
MOZ_RELEASE_ASSERT(jsonString);
std::string_view jsonStringView(jsonString.get());
std::string expected = "{\"data\": [";
expected += aExpectedData;
expected += "], \"stringTable\": [";
expected += aExpectedUniqueStrings;
expected += "]}\n";
if (jsonStringView != expected) {
fprintf(stderr,
"Expected:\n"
"------\n");
printEscaped(expected);
fprintf(stderr,
"\n"
"------\n"
"Actual:\n"
"------\n");
printEscaped(jsonStringView);
fprintf(stderr,
"\n"
"------\n");
}
MOZ_RELEASE_ASSERT(jsonStringView == expected);
}
void TestUniqueJSONStrings() {
printf("TestUniqueJSONStrings...\n");
using SCJW = mozilla::baseprofiler::SpliceableChunkedJSONWriter;
using UJS = mozilla::baseprofiler::UniqueJSONStrings;
// Empty everything.
VerifyUniqueStringContents([](SCJW& aWriter, UJS& aUniqueStrings) {}, "", "");
// Empty unique strings.
VerifyUniqueStringContents(
[](SCJW& aWriter, UJS& aUniqueStrings) {
aWriter.StringElement("string");
},
R"("string")", "");
// One unique string.
VerifyUniqueStringContents(
[](SCJW& aWriter, UJS& aUniqueStrings) {
aUniqueStrings.WriteElement(aWriter, "string");
},
"0", R"("string")");
// One unique string twice.
VerifyUniqueStringContents(
[](SCJW& aWriter, UJS& aUniqueStrings) {
aUniqueStrings.WriteElement(aWriter, "string");
aUniqueStrings.WriteElement(aWriter, "string");
},
"0, 0", R"("string")");
// Two single unique strings.
VerifyUniqueStringContents(
[](SCJW& aWriter, UJS& aUniqueStrings) {
aUniqueStrings.WriteElement(aWriter, "string0");
aUniqueStrings.WriteElement(aWriter, "string1");
},
"0, 1", R"("string0", "string1")");
// Two unique strings with repetition.
VerifyUniqueStringContents(
[](SCJW& aWriter, UJS& aUniqueStrings) {
aUniqueStrings.WriteElement(aWriter, "string0");
aUniqueStrings.WriteElement(aWriter, "string1");
aUniqueStrings.WriteElement(aWriter, "string0");
},
"0, 1, 0", R"("string0", "string1")");
// Mix some object properties, for coverage.
VerifyUniqueStringContents(
[](SCJW& aWriter, UJS& aUniqueStrings) {
aUniqueStrings.WriteElement(aWriter, "string0");
aWriter.StartObjectElement(mozilla::JSONWriter::SingleLineStyle);
{
aUniqueStrings.WriteProperty(aWriter, "p0", "prop");
aUniqueStrings.WriteProperty(aWriter, "p1", "string0");
aUniqueStrings.WriteProperty(aWriter, "p2", "prop");
}
aWriter.EndObject();
aUniqueStrings.WriteElement(aWriter, "string1");
aUniqueStrings.WriteElement(aWriter, "string0");
aUniqueStrings.WriteElement(aWriter, "prop");
},
R"(0, {"p0": 1, "p1": 0, "p2": 1}, 2, 0, 1)",
R"("string0", "prop", "string1")");
// Unique string table with pre-existing data.
{
UJS ujs(mozilla::JSONWriter::SingleLineStyle);
{
SCJW writer;
ujs.WriteElement(writer, "external0");
ujs.WriteElement(writer, "external1");
ujs.WriteElement(writer, "external0");
}
VerifyUniqueStringContents(
[](SCJW& aWriter, UJS& aUniqueStrings) {
aUniqueStrings.WriteElement(aWriter, "string0");
aUniqueStrings.WriteElement(aWriter, "string1");
aUniqueStrings.WriteElement(aWriter, "string0");
},
"2, 3, 2", R"("external0", "external1", "string0", "string1")", &ujs);
}
// This currently fails, demonstrating the regression from bug 1520104, to be
// fixed in the next patch in bug 1674968.
# if 0
// Unique string table with pre-existing data from another table.
{
UJS ujs(mozilla::JSONWriter::SingleLineStyle);
{
SCJW writer;
ujs.WriteElement(writer, "external0");
ujs.WriteElement(writer, "external1");
ujs.WriteElement(writer, "external0");
}
UJS ujsCopy(ujs, mozilla::JSONWriter::SingleLineStyle);
VerifyUniqueStringContents(
[](SCJW& aWriter, UJS& aUniqueStrings) {
aUniqueStrings.WriteElement(aWriter, "string0");
aUniqueStrings.WriteElement(aWriter, "string1");
aUniqueStrings.WriteElement(aWriter, "string0");
},
"2, 3, 2", R"("external0", "external1", "string0", "string1")", &ujs);
}
# endif
printf("TestUniqueJSONStrings done\n");
}
void StreamMarkers(const mozilla::ProfileChunkedBuffer& aBuffer,
mozilla::JSONWriter& aWriter) {
aWriter.Start();
@ -3872,6 +4062,7 @@ void TestProfilerMarkers() {
mozilla::baseprofiler::profiler_current_thread_id());
// ::SleepMilli(10000);
TestUniqueJSONStrings();
TestMarkerCategory();
TestMarkerThreadId();
TestMarkerNoPayload();