blob: 22a3885bc400538dffad842f2e50427646e85202 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "src/trace_processor/importers/json/json_trace_tokenizer.h"
#include <json/value.h>
#include "src/trace_processor/importers/json/json_utils.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
namespace trace_processor {
namespace {
TEST(JsonTraceTokenizerTest, ReadDictSuccess) {
const char* start = R"({ "foo": "bar" })";
const char* end = start + strlen(start);
const char* next = nullptr;
base::StringView value;
ReadDictRes result = ReadOneJsonDict(start, end, &value, &next);
ASSERT_EQ(result, ReadDictRes::kFoundDict);
ASSERT_EQ(next, end);
Json::Value parsed = *json::ParseJsonString(value);
ASSERT_EQ(parsed["foo"].asString(), "bar");
}
TEST(JsonTraceTokenizerTest, ReadDictQuotedBraces) {
const char* start = R"({ "foo": "}\"bar{\\" })";
const char* end = start + strlen(start);
const char* next = nullptr;
base::StringView value;
ReadDictRes result = ReadOneJsonDict(start, end, &value, &next);
ASSERT_EQ(result, ReadDictRes::kFoundDict);
ASSERT_EQ(next, end);
Json::Value parsed = *json::ParseJsonString(value);
ASSERT_EQ(parsed["foo"].asString(), "}\"bar{\\");
}
TEST(JsonTraceTokenizerTest, ReadDictTwoDicts) {
const char* start = R"({"foo": 1}, {"bar": 2})";
const char* middle = start + strlen(R"({"foo": 1})");
const char* end = start + strlen(start);
const char* next = nullptr;
base::StringView value;
ASSERT_EQ(ReadOneJsonDict(start, end, &value, &next),
ReadDictRes::kFoundDict);
ASSERT_EQ(next, middle);
Json::Value parsed = *json::ParseJsonString(value);
ASSERT_EQ(parsed["foo"].asInt(), 1);
ASSERT_EQ(ReadOneJsonDict(next, end, &value, &next), ReadDictRes::kFoundDict);
ASSERT_EQ(next, end);
parsed = *json::ParseJsonString(value);
ASSERT_EQ(parsed["bar"].asInt(), 2);
}
TEST(JsonTraceTokenizerTest, ReadDictNeedMoreData) {
const char* start = R"({"foo": 1)";
const char* end = start + strlen(start);
const char* next = nullptr;
base::StringView value;
ASSERT_EQ(ReadOneJsonDict(start, end, &value, &next),
ReadDictRes::kNeedsMoreData);
ASSERT_EQ(next, nullptr);
}
TEST(JsonTraceTokenizerTest, ReadKeyIntValue) {
const char* start = R"("Test": 01234, )";
const char* middle = start + strlen(R"("Test": )");
const char* end = start + strlen(start);
const char* next = nullptr;
std::string key;
ASSERT_EQ(ReadOneJsonKey(start, end, &key, &next), ReadKeyRes::kFoundKey);
ASSERT_EQ(next, middle);
ASSERT_EQ(key, "Test");
}
TEST(JsonTraceTokenizerTest, ReadKeyArrayValue) {
const char* start = R"(, "key": [test], )";
const char* middle = start + strlen(R"(, "key": )");
const char* end = start + strlen(start);
const char* next = nullptr;
std::string key;
ASSERT_EQ(ReadOneJsonKey(start, end, &key, &next), ReadKeyRes::kFoundKey);
ASSERT_EQ(next, middle);
ASSERT_EQ(key, "key");
}
TEST(JsonTraceTokenizerTest, ReadKeyDictValue) {
const char* start = R"("key2": {}})";
const char* middle = start + strlen(R"("key2": )");
const char* end = start + strlen(start);
const char* next = nullptr;
std::string key;
ASSERT_EQ(ReadOneJsonKey(start, end, &key, &next), ReadKeyRes::kFoundKey);
ASSERT_EQ(next, middle);
ASSERT_EQ(key, "key2");
}
TEST(JsonTraceTokenizerTest, ReadKeyEscaped) {
const char* start = R"("key\n2": {}})";
const char* middle = start + strlen(R"("key\n2": )");
const char* end = start + strlen(start);
const char* next = nullptr;
std::string key;
ASSERT_EQ(ReadOneJsonKey(start, end, &key, &next), ReadKeyRes::kFoundKey);
ASSERT_EQ(next, middle);
ASSERT_EQ(key, "key\n2");
}
TEST(JsonTraceTokenizerTest, ReadKeyNeedMoreDataStartString) {
const char* start = R"(")";
const char* end = start + strlen(start);
const char* next = nullptr;
std::string key;
ASSERT_EQ(ReadOneJsonKey(start, end, &key, &next),
ReadKeyRes::kNeedsMoreData);
ASSERT_EQ(next, nullptr);
}
TEST(JsonTraceTokenizerTest, ReadKeyNeedMoreDataMiddleString) {
const char* start = R"("key)";
const char* end = start + strlen(start);
const char* next = nullptr;
std::string key;
ASSERT_EQ(ReadOneJsonKey(start, end, &key, &next),
ReadKeyRes::kNeedsMoreData);
ASSERT_EQ(next, nullptr);
}
TEST(JsonTraceTokenizerTest, ReadKeyNeedMoreDataNoValue) {
const char* start = R"("key": )";
const char* end = start + strlen(start);
const char* next = nullptr;
std::string key;
ASSERT_EQ(ReadOneJsonKey(start, end, &key, &next),
ReadKeyRes::kNeedsMoreData);
ASSERT_EQ(next, nullptr);
}
TEST(JsonTraceTokenizerTest, ReadKeyEndOfDict) {
const char* start = R"( })";
const char* end = start + strlen(start);
const char* next = nullptr;
std::string key;
ASSERT_EQ(ReadOneJsonKey(start, end, &key, &next),
ReadKeyRes::kEndOfDictionary);
ASSERT_EQ(next, end);
}
TEST(JsonTraceTokenizerTest, ReadSystraceLine) {
const char* start = R"(test one two\n test again\n)";
const char* middle = start + strlen(R"(test one two\n)");
const char* end = start + strlen(start);
const char* next = nullptr;
std::string line;
ASSERT_EQ(ReadOneSystemTraceLine(start, end, &line, &next),
ReadSystemLineRes::kFoundLine);
ASSERT_EQ(next, middle);
ASSERT_EQ(line, "test one two");
}
TEST(JsonTraceTokenizerTest, ReadSystraceLineEscaped) {
const char* start = R"(test\t one two\n test again\n)";
const char* middle = start + strlen(R"(test\t one two\n)");
const char* end = start + strlen(start);
const char* next = nullptr;
std::string line;
ASSERT_EQ(ReadOneSystemTraceLine(start, end, &line, &next),
ReadSystemLineRes::kFoundLine);
ASSERT_EQ(next, middle);
ASSERT_EQ(line, "test\t one two");
}
TEST(JsonTraceTokenizerTest, ReadSystraceNeedMoreDataOnlyEscape) {
const char* start = R"(test one two\)";
const char* end = start + strlen(start);
const char* next = nullptr;
std::string line;
ASSERT_EQ(ReadOneSystemTraceLine(start, end, &line, &next),
ReadSystemLineRes::kNeedsMoreData);
ASSERT_EQ(next, nullptr);
}
TEST(JsonTraceTokenizerTest, ReadSystraceEndOfData) {
const char* start = R"(")";
const char* end = start + strlen(start);
const char* next = nullptr;
std::string line;
ASSERT_EQ(ReadOneSystemTraceLine(start, end, &line, &next),
ReadSystemLineRes::kEndOfSystemTrace);
ASSERT_EQ(next, end);
}
TEST(JsonTraceTokenizerTest, ExtractValueForJsonKey) {
std::optional<std::string> line;
ASSERT_TRUE(ExtractValueForJsonKey(R"({"ts": 149029})", "ts", &line).ok());
ASSERT_EQ(*line, "149029");
ASSERT_TRUE(ExtractValueForJsonKey(R"(
{
"lots_of": "whitespace"
}
)",
"lots_of", &line)
.ok());
ASSERT_EQ(*line, "whitespace");
ASSERT_TRUE(ExtractValueForJsonKey(R"(
{
"lots_of": "whitespace" ,
"other": "value"
}
)",
"other", &line)
.ok());
ASSERT_EQ(*line, "value");
ASSERT_TRUE(ExtractValueForJsonKey(R"({
"ts": 149029, "foo": "bar"
})",
"ts", &line)
.ok());
ASSERT_EQ(*line, "149029");
ASSERT_TRUE(ExtractValueForJsonKey(R"({
"ts": 149029, "foo": "bar"
})",
"foo", &line)
.ok());
ASSERT_EQ(*line, "bar");
ASSERT_TRUE(ExtractValueForJsonKey(R"({
"nested": {"ts": 149029, "foo": "bar"}
})",
"nested", &line)
.ok());
ASSERT_EQ(*line, R"({"ts": 149029, "foo": "bar"})");
}
} // namespace
} // namespace trace_processor
} // namespace perfetto