blob: 47c5d77223fd5715a1f29488b6773bf8d3f93799 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/feedback/crashpad_agent/inspect_manager.h"
#include <lib/inspect/cpp/hierarchy.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/inspect/cpp/reader.h>
#include <lib/timekeeper/test_clock.h>
#include <lib/zx/time.h>
#include <memory>
#include "sdk/lib/inspect/testing/cpp/inspect.h"
#include "src/developer/feedback/crashpad_agent/config.h"
#include "src/developer/feedback/crashpad_agent/constants.h"
#include "src/developer/feedback/crashpad_agent/settings.h"
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/test/test_settings.h"
#include "src/lib/syslog/cpp/logger.h"
#include "third_party/googletest/googlemock/include/gmock/gmock.h"
#include "third_party/googletest/googletest/include/gtest/gtest.h"
namespace feedback {
namespace {
using inspect::testing::ChildrenMatch;
using inspect::testing::NameMatches;
using inspect::testing::NodeMatches;
using inspect::testing::PropertyList;
using inspect::testing::StringIs;
using inspect::testing::UintIs;
using testing::Contains;
using testing::ElementsAre;
using testing::IsEmpty;
using testing::Not;
using testing::UnorderedElementsAreArray;
constexpr zx::time_utc kTime1(0);
constexpr zx::time_utc kTime2((zx::hour(7) + zx::min(14) + zx::sec(52)).get());
constexpr zx::time_utc kTime3((zx::hour(3) * 24 + zx::hour(15) + zx::min(33) + zx::sec(17)).get());
constexpr char kTime1Str[] = "1970-01-01 00:00:00 GMT";
constexpr char kTime2Str[] = "1970-01-01 07:14:52 GMT";
constexpr char kTime3Str[] = "1970-01-04 15:33:17 GMT";
constexpr CrashServerConfig::UploadPolicy kConfigDisabled =
CrashServerConfig::UploadPolicy::DISABLED;
constexpr CrashServerConfig::UploadPolicy kConfigEnabled = CrashServerConfig::UploadPolicy::ENABLED;
constexpr CrashServerConfig::UploadPolicy kConfigReadFromPrivacySettings =
CrashServerConfig::UploadPolicy::READ_FROM_PRIVACY_SETTINGS;
constexpr Settings::UploadPolicy kSettingsDisabled = Settings::UploadPolicy::DISABLED;
constexpr Settings::UploadPolicy kSettingsEnabled = Settings::UploadPolicy::ENABLED;
constexpr Settings::UploadPolicy kSettingsLimbo = Settings::UploadPolicy::LIMBO;
class InspectManagerTest : public testing::Test {
public:
void SetUp() override {
inspector_ = std::make_unique<inspect::Inspector>();
clock_ = std::make_unique<timekeeper::TestClock>();
inspect_manager_ = std::make_unique<InspectManager>(&inspector_->GetRoot(), clock_.get());
}
protected:
inspect::Hierarchy InspectTree() {
auto result = inspect::ReadFromVmo(inspector_->DuplicateVmo());
FXL_CHECK(result.is_ok());
return result.take_value();
}
std::unique_ptr<timekeeper::TestClock> clock_;
std::unique_ptr<InspectManager> inspect_manager_;
private:
std::unique_ptr<inspect::Inspector> inspector_;
};
TEST_F(InspectManagerTest, InitialInspectTree) {
EXPECT_THAT(InspectTree(), ChildrenMatch(UnorderedElementsAreArray({
NodeMatches(NameMatches(kInspectConfigName)),
NodeMatches(NameMatches(kInspectSettingsName)),
NodeMatches(NameMatches(kInspectReportsName)),
})));
}
TEST_F(InspectManagerTest, Succeed_AddReport_UniqueReports) {
clock_->Set(kTime1);
EXPECT_TRUE(inspect_manager_->AddReport("program_1", "local_report_id_1"));
EXPECT_THAT(
InspectTree(),
ChildrenMatch(Contains(
AllOf(NodeMatches(NameMatches(kInspectReportsName)),
ChildrenMatch(ElementsAre(AllOf(
NodeMatches(NameMatches("program_1")),
ChildrenMatch(ElementsAre(NodeMatches(AllOf(
NameMatches("local_report_id_1"),
PropertyList(ElementsAre(StringIs("creation_time", kTime1Str))))))))))))));
clock_->Set(kTime2);
EXPECT_TRUE(inspect_manager_->AddReport("program_1", "local_report_id_2"));
EXPECT_THAT(
InspectTree(),
ChildrenMatch(Contains(AllOf(
NodeMatches(NameMatches(kInspectReportsName)),
ChildrenMatch(ElementsAre(AllOf(NodeMatches(NameMatches("program_1")),
ChildrenMatch(UnorderedElementsAreArray({
NodeMatches(AllOf(NameMatches("local_report_id_1"),
PropertyList(ElementsAre(StringIs(
"creation_time", kTime1Str))))),
NodeMatches(AllOf(NameMatches("local_report_id_2"),
PropertyList(ElementsAre(StringIs(
"creation_time", kTime2Str))))),
})))))))));
clock_->Set(kTime3);
EXPECT_TRUE(inspect_manager_->AddReport("program_2", "local_report_id_3"));
EXPECT_TRUE(inspect_manager_->AddReport("program_2", "local_report_id_4"));
EXPECT_TRUE(inspect_manager_->AddReport("program_2", "local_report_id_5"));
EXPECT_THAT(
InspectTree(),
ChildrenMatch(Contains(AllOf(
NodeMatches(NameMatches(kInspectReportsName)),
ChildrenMatch(UnorderedElementsAreArray({
AllOf(NodeMatches(NameMatches("program_1")),
ChildrenMatch(UnorderedElementsAreArray({
NodeMatches(
AllOf(NameMatches("local_report_id_1"),
PropertyList(ElementsAre(StringIs("creation_time", kTime1Str))))),
NodeMatches(
AllOf(NameMatches("local_report_id_2"),
PropertyList(ElementsAre(StringIs("creation_time", kTime2Str))))),
}))),
AllOf(NodeMatches(NameMatches("program_2")),
ChildrenMatch(UnorderedElementsAreArray({
NodeMatches(
AllOf(NameMatches("local_report_id_3"),
PropertyList(ElementsAre(StringIs("creation_time", kTime3Str))))),
NodeMatches(
AllOf(NameMatches("local_report_id_4"),
PropertyList(ElementsAre(StringIs("creation_time", kTime3Str))))),
NodeMatches(
AllOf(NameMatches("local_report_id_5"),
PropertyList(ElementsAre(StringIs("creation_time", kTime3Str))))),
}))),
}))))));
}
TEST_F(InspectManagerTest, Fail_AddReport_DuplicateReport) {
clock_->Set(kTime2);
EXPECT_TRUE(inspect_manager_->AddReport("program", "local_report_id"));
clock_->Set(kTime3);
EXPECT_FALSE(inspect_manager_->AddReport("program", "local_report_id"));
EXPECT_THAT(
InspectTree(),
ChildrenMatch(Contains(
AllOf(NodeMatches(NameMatches(kInspectReportsName)),
ChildrenMatch(ElementsAre(AllOf(
NodeMatches(NameMatches("program")),
ChildrenMatch(ElementsAre(NodeMatches(AllOf(
NameMatches("local_report_id"),
PropertyList(ElementsAre(StringIs("creation_time", kTime2Str))))))))))))));
}
TEST_F(InspectManagerTest, Succeed_MarkReportAsUploaded) {
clock_->Set(kTime2);
EXPECT_TRUE(inspect_manager_->AddReport("program", "local_report_id"));
clock_->Set(kTime3);
EXPECT_TRUE(inspect_manager_->MarkReportAsUploaded("local_report_id", "server_report_id"));
EXPECT_THAT(InspectTree(),
ChildrenMatch(Contains(AllOf(
NodeMatches(NameMatches(kInspectReportsName)),
ChildrenMatch(ElementsAre(AllOf(
NodeMatches(NameMatches("program")),
ChildrenMatch(ElementsAre(AllOf(
NodeMatches(AllOf(
NameMatches("local_report_id"),
PropertyList(ElementsAre(StringIs("creation_time", kTime2Str))))),
ChildrenMatch(ElementsAre(NodeMatches(AllOf(
NameMatches("crash_server"), PropertyList(UnorderedElementsAreArray({
StringIs("creation_time", kTime3Str),
StringIs("id", "server_report_id"),
}))))))))))))))));
}
TEST_F(InspectManagerTest, Fail_MarkReportAsUploaded_UnknownReport) {
EXPECT_FALSE(inspect_manager_->MarkReportAsUploaded("unknown_report", "server_report_id"));
EXPECT_THAT(InspectTree(),
ChildrenMatch(Contains(
AllOf(NodeMatches(NameMatches(kInspectReportsName)), ChildrenMatch(IsEmpty())))));
}
TEST_F(InspectManagerTest, ExposeConfig_UploadEnabled) {
inspect_manager_->ExposeConfig(Config{
/*crashpad_database=*/
{
/*max_size_in_kb=*/1234,
},
/*crash_server=*/
{
/*upload_policy=*/kConfigEnabled,
/*url=*/std::make_unique<std::string>("http://localhost:1234"),
}});
EXPECT_THAT(
InspectTree(),
ChildrenMatch(Contains(AllOf(
NodeMatches(NameMatches(kInspectConfigName)),
ChildrenMatch(UnorderedElementsAreArray({
NodeMatches(AllOf(NameMatches(kCrashpadDatabaseKey),
PropertyList(UnorderedElementsAreArray({
UintIs(kCrashpadDatabaseMaxSizeInKbKey, 1234),
})))),
NodeMatches(AllOf(NameMatches(kCrashServerKey),
PropertyList(UnorderedElementsAreArray({
StringIs(kCrashServerUploadPolicyKey, ToString(kConfigEnabled)),
StringIs(kCrashServerUrlKey, "http://localhost:1234"),
})))),
}))))));
}
TEST_F(InspectManagerTest, ExposeConfig_UploadDisabled) {
inspect_manager_->ExposeConfig(Config{/*crashpad_database=*/
{
/*max_size_in_kb=*/1234,
},
/*crash_server=*/
{
/*upload_policy=*/kConfigDisabled,
/*url=*/nullptr,
}});
EXPECT_THAT(
InspectTree(),
ChildrenMatch(Contains(AllOf(
NodeMatches(NameMatches(kInspectConfigName)),
ChildrenMatch(UnorderedElementsAreArray({
NodeMatches(AllOf(NameMatches(kCrashpadDatabaseKey),
PropertyList(UnorderedElementsAreArray({
UintIs(kCrashpadDatabaseMaxSizeInKbKey, 1234),
})))),
NodeMatches(AllOf(NameMatches(kCrashServerKey),
PropertyList(ElementsAre(StringIs(kCrashServerUploadPolicyKey,
ToString(kConfigDisabled)))))),
}))))));
}
TEST_F(InspectManagerTest, ExposeConfig_UploadReadFromPrivacySettings) {
inspect_manager_->ExposeConfig(Config{/*crashpad_database=*/
{
/*max_size_in_kb=*/1234,
},
/*crash_server=*/
{
/*upload_policy=*/kConfigReadFromPrivacySettings,
/*url=*/nullptr,
}});
EXPECT_THAT(
InspectTree(),
ChildrenMatch(Contains(AllOf(
NodeMatches(NameMatches(kInspectConfigName)),
ChildrenMatch(UnorderedElementsAreArray({
NodeMatches(AllOf(NameMatches(kCrashpadDatabaseKey),
PropertyList(UnorderedElementsAreArray({
UintIs(kCrashpadDatabaseMaxSizeInKbKey, 1234),
})))),
NodeMatches(AllOf(
NameMatches(kCrashServerKey),
PropertyList(ElementsAre(StringIs(kCrashServerUploadPolicyKey,
ToString(kConfigReadFromPrivacySettings)))))),
}))))));
}
TEST_F(InspectManagerTest, ExposeSettings_TrackUploadPolicyChanges) {
Settings settings;
settings.set_upload_policy(kSettingsEnabled);
inspect_manager_->ExposeSettings(&settings);
EXPECT_THAT(
InspectTree(),
ChildrenMatch(Contains(NodeMatches(AllOf(
NameMatches(kInspectSettingsName),
PropertyList(ElementsAre(StringIs("upload_policy", ToString(kSettingsEnabled)))))))));
settings.set_upload_policy(kSettingsDisabled);
EXPECT_THAT(
InspectTree(),
ChildrenMatch(Contains(NodeMatches(AllOf(
NameMatches(kInspectSettingsName),
PropertyList(ElementsAre(StringIs("upload_policy", ToString(kSettingsDisabled)))))))));
settings.set_upload_policy(kSettingsLimbo);
EXPECT_THAT(
InspectTree(),
ChildrenMatch(Contains(NodeMatches(
AllOf(NameMatches(kInspectSettingsName),
PropertyList(ElementsAre(StringIs("upload_policy", ToString(kSettingsLimbo)))))))));
settings.set_upload_policy(kSettingsEnabled);
EXPECT_THAT(
InspectTree(),
ChildrenMatch(Contains(NodeMatches(AllOf(
NameMatches(kInspectSettingsName),
PropertyList(ElementsAre(StringIs("upload_policy", ToString(kSettingsEnabled)))))))));
}
} // namespace
} // namespace feedback
int main(int argc, char** argv) {
if (!fxl::SetTestSettings(argc, argv)) {
return EXIT_FAILURE;
}
testing::InitGoogleTest(&argc, argv);
syslog::InitLogger({"feedback", "test"});
return RUN_ALL_TESTS();
}