blob: 3e599f63bafbd848422371e3f4ec8281fee043db [file] [log] [blame]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <optional>
#include <string>
#include <base/functional/callback.h>
#include <base/json/json_reader.h>
#include <base/test/task_environment.h>
#include <base/test/test_future.h>
#include <base/values.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "runtime_probe/probe_function.h"
#include "runtime_probe/probe_statement.h"
namespace runtime_probe {
namespace {
using ::testing::ByMove;
using ::testing::Return;
class MockProbeFunction : public ProbeFunction {
using ProbeFunction::ProbeFunction;
public:
NAME_PROBE_FUNCTION("mock_function");
MOCK_METHOD(DataType, EvalImpl, (), (const, override));
};
class ProbeStatementTest : public testing::Test {
private:
base::test::SingleThreadTaskEnvironment task_environment_;
};
TEST_F(ProbeStatementTest, FromValue) {
auto dict_value = base::JSONReader::Read(R"({
"eval": {
"memory": {}
}
})");
auto probe_statement = ProbeStatement::FromValue("component", *dict_value);
EXPECT_NE(probe_statement, nullptr);
}
TEST_F(ProbeStatementTest, FromValueWithNonDictValue) {
auto non_dict_value = base::JSONReader::Read("[]");
auto probe_statement =
ProbeStatement::FromValue("component", *non_dict_value);
EXPECT_EQ(probe_statement, nullptr);
}
TEST_F(ProbeStatementTest, FromValueWithoutEval) {
// No required field "eval".
auto dict_value = base::JSONReader::Read("{}");
auto probe_statement = ProbeStatement::FromValue("component", *dict_value);
EXPECT_EQ(probe_statement, nullptr);
}
TEST_F(ProbeStatementTest, FromValueWithInvalidFunction) {
// The probe function is not defined.
auto dict_value = base::JSONReader::Read(R"({
"eval": {
"invalid_function": {}
}
})");
auto probe_statement = ProbeStatement::FromValue("component", *dict_value);
EXPECT_EQ(probe_statement, nullptr);
}
TEST_F(ProbeStatementTest, Eval) {
// Set a valid probe function and mock it later.
auto dict_value = base::JSONReader::Read(R"({
"eval": {
"memory": {}
}
})");
auto probe_statement = ProbeStatement::FromValue("component", *dict_value);
auto ans = std::move(base::JSONReader::Read(R"([
{
"field": "value"
}
])")
->GetList());
auto probe_function = std::make_unique<MockProbeFunction>();
EXPECT_CALL(*probe_function, EvalImpl())
.WillOnce(Return(ByMove(ans.Clone())));
probe_statement->SetProbeFunctionForTesting(std::move(probe_function));
base::test::TestFuture<ProbeFunction::DataType> future;
probe_statement->Eval(future.GetCallback());
EXPECT_EQ(future.Get(), ans);
}
TEST_F(ProbeStatementTest, EvalWithFilteredKeys) {
// Set a valid probe function and mock it later.
auto dict_value = base::JSONReader::Read(R"({
"eval": {
"memory": {}
},
"keys": ["field_1", "field_2"]
})");
auto probe_statement = ProbeStatement::FromValue("component", *dict_value);
auto eval_result = std::move(base::JSONReader::Read(R"([
{
"field_1": "value_1",
"field_2": "value_2",
"field_3": "value_3"
}
])")
->GetList());
auto probe_function = std::make_unique<MockProbeFunction>();
EXPECT_CALL(*probe_function, EvalImpl())
.WillOnce(Return(ByMove(std::move(eval_result))));
probe_statement->SetProbeFunctionForTesting(std::move(probe_function));
// Should only get fields defined in "keys".
auto ans = std::move(base::JSONReader::Read(R"([
{
"field_1": "value_1",
"field_2": "value_2"
}
])")
->GetList());
base::test::TestFuture<ProbeFunction::DataType> future;
probe_statement->Eval(future.GetCallback());
EXPECT_EQ(future.Get(), ans);
}
TEST_F(ProbeStatementTest, EvalWithExpectValue) {
// Set a valid probe function and mock it later.
auto dict_value = base::JSONReader::Read(R"({
"eval": {
"memory": {}
}
})");
auto probe_statement = ProbeStatement::FromValue("component", *dict_value);
auto eval_result = std::move(base::JSONReader::Read(R"([
{
"field_1": "value_1"
},
{
"field_2": "value_2"
}
])")
->GetList());
auto probe_function = std::make_unique<MockProbeFunction>();
EXPECT_CALL(*probe_function, EvalImpl())
.WillOnce(Return(ByMove(std::move(eval_result))));
auto expect_value = base::JSONReader::Read(R"([
{
"field_2": [true, "str"]
}
])");
probe_statement->SetProbeFunctionForTesting(std::move(probe_function));
probe_statement->SetExpectForTesting(std::move(*expect_value));
// Should only get results that pass the check.
auto ans = std::move(base::JSONReader::Read(R"([
{
"field_2": "value_2"
}
])")
->GetList());
base::test::TestFuture<ProbeFunction::DataType> future;
probe_statement->Eval(future.GetCallback());
EXPECT_EQ(future.Get(), ans);
}
TEST_F(ProbeStatementTest, GetInformation) {
auto dict_value = base::JSONReader::Read(R"({
"eval": {
"memory": {}
},
"information": {
"field": "value"
}
})");
auto probe_statement = ProbeStatement::FromValue("component", *dict_value);
auto ans = base::JSONReader::Read(R"({
"field": "value"
})");
auto res = probe_statement->GetInformation();
EXPECT_EQ(res, ans);
}
TEST_F(ProbeStatementTest, GetInformationWithoutInformation) {
auto dict_value = base::JSONReader::Read(R"({
"eval": {
"memory": {}
}
})");
auto probe_statement = ProbeStatement::FromValue("component", *dict_value);
auto res = probe_statement->GetInformation();
EXPECT_EQ(res, std::nullopt);
}
} // namespace
} // namespace runtime_probe