blob: 789e354ac3f039e1a0a0e176b14d3ecd0db9afb7 [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/crash_reports/privacy_settings_ptr.h"
#include <fuchsia/settings/cpp/fidl.h>
#include <lib/fit/result.h>
#include <lib/fostr/fidl/fuchsia/settings/formatting.h>
#include <zircon/errors.h>
#include <memory>
#include <optional>
#include <gtest/gtest.h>
#include "src/developer/feedback/crash_reports/settings.h"
#include "src/developer/feedback/testing/fakes/privacy_settings.h"
#include "src/developer/feedback/testing/unit_test_fixture.h"
#include "src/lib/fxl/logging.h"
namespace feedback {
namespace {
using fuchsia::settings::Error;
using fuchsia::settings::PrivacySettings;
constexpr Settings::UploadPolicy kDisabled = Settings::UploadPolicy::DISABLED;
constexpr Settings::UploadPolicy kEnabled = Settings::UploadPolicy::ENABLED;
constexpr Settings::UploadPolicy kLimbo = Settings::UploadPolicy::LIMBO;
constexpr bool kUserOptIn = true;
constexpr bool kUserOptOut = false;
constexpr std::optional<bool> kNotSet = std::nullopt;
PrivacySettings MakePrivacySettings(const std::optional<bool> user_data_sharing_consent) {
PrivacySettings settings;
if (user_data_sharing_consent.has_value()) {
settings.set_user_data_sharing_consent(user_data_sharing_consent.value());
}
return settings;
}
class PrivacySettingsWatcherTest : public UnitTestFixture,
public testing::WithParamInterface<Settings::UploadPolicy> {
public:
PrivacySettingsWatcherTest() : watcher_(dispatcher(), services(), &crash_reporter_settings_) {}
protected:
void SetUpPrivacySettingsServer(std::unique_ptr<fakes::PrivacySettings> server) {
privacy_settings_server_ = std::move(server);
if (privacy_settings_server_) {
InjectServiceProvider(privacy_settings_server_.get());
}
}
void SetPrivacySettings(std::optional<bool> user_data_sharing_consent) {
::fit::result<void, Error> set_result;
privacy_settings_server_->Set(
MakePrivacySettings(user_data_sharing_consent),
[&set_result](::fit::result<void, Error> result) { set_result = std::move(result); });
EXPECT_TRUE(set_result.is_ok());
}
void SetInitialUploadPolicy(const Settings::UploadPolicy upload_policy) {
crash_reporter_settings_.set_upload_policy(upload_policy);
}
protected:
Settings crash_reporter_settings_;
PrivacySettingsWatcher watcher_;
private:
std::unique_ptr<fakes::PrivacySettings> privacy_settings_server_;
};
TEST_F(PrivacySettingsWatcherTest, SetUp) {
EXPECT_TRUE(watcher_.privacy_settings().IsEmpty());
EXPECT_FALSE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
}
// This allows us to see meaningful names rather than /0, /1 and /2 in the parameterized test case
// names.
std::string PrettyPrintUploadPolicyUploadsEnabledValue(
const testing::TestParamInfo<Settings::UploadPolicy>& info) {
switch (info.param) {
case Settings::UploadPolicy::DISABLED:
return "DisabledInitially";
case Settings::UploadPolicy::ENABLED:
return "EnabledInitially";
case Settings::UploadPolicy::LIMBO:
return "LimboInitially";
}
};
// We want to make sure that regardless of the state in which the crash reporter's upload policy
// started in, the expectations are always the same. In particular that failure paths always end up
// setting the upload policy to LIMBO.
//
// We use a parameterized gTest where the 3 values represent the 3 possible UploadPolicy.
INSTANTIATE_TEST_SUITE_P(WithVariousInitialUploadPolicies, PrivacySettingsWatcherTest,
::testing::ValuesIn(std::vector<Settings::UploadPolicy>({
Settings::UploadPolicy::DISABLED,
Settings::UploadPolicy::ENABLED,
Settings::UploadPolicy::LIMBO,
})),
&PrettyPrintUploadPolicyUploadsEnabledValue);
TEST_P(PrivacySettingsWatcherTest, UploadPolicyDefaultToDisabledIfServerNotAvailable) {
SetInitialUploadPolicy(GetParam());
SetUpPrivacySettingsServer(nullptr);
watcher_.StartWatching();
RunLoopUntilIdle();
EXPECT_FALSE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_TRUE(watcher_.privacy_settings().IsEmpty());
}
TEST_P(PrivacySettingsWatcherTest, UploadPolicyDefaultToDisabledIfServerClosesConnection) {
SetInitialUploadPolicy(GetParam());
SetUpPrivacySettingsServer(std::make_unique<fakes::PrivacySettingsClosesConnectionOnWatch>());
watcher_.StartWatching();
RunLoopUntilIdle();
EXPECT_FALSE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_TRUE(watcher_.privacy_settings().IsEmpty());
}
TEST_P(PrivacySettingsWatcherTest, UploadPolicyDefaultToDisabledIfNoCallToSet) {
SetInitialUploadPolicy(GetParam());
SetUpPrivacySettingsServer(std::make_unique<fakes::PrivacySettings>());
watcher_.StartWatching();
RunLoopUntilIdle();
EXPECT_TRUE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_FALSE(watcher_.privacy_settings().has_user_data_sharing_consent());
}
TEST_P(PrivacySettingsWatcherTest, UploadPolicySwitchesToSetValueOnRetry) {
SetInitialUploadPolicy(GetParam());
SetUpPrivacySettingsServer(
std::make_unique<fakes::PrivacySettingsClosesConnectionOnFirstWatch>());
SetPrivacySettings(kUserOptIn);
// The connection will be closed on the first call to Watch().
watcher_.StartWatching();
RunLoopUntilIdle();
EXPECT_FALSE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_TRUE(watcher_.privacy_settings().IsEmpty());
// We then retry to connect 5 minutes later and succeed.
// We run the loop longer than the delay to account for the nondeterminism of
// backoff::ExponentialBackoff.
RunLoopFor(zx::min(5));
EXPECT_TRUE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kEnabled);
EXPECT_TRUE(watcher_.privacy_settings().has_user_data_sharing_consent());
}
TEST_P(PrivacySettingsWatcherTest, UploadPolicySwitchesToSetValueOnFirstWatch_OptIn) {
SetInitialUploadPolicy(GetParam());
SetUpPrivacySettingsServer(std::make_unique<fakes::PrivacySettings>());
SetPrivacySettings(kUserOptIn);
watcher_.StartWatching();
RunLoopUntilIdle();
EXPECT_TRUE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kEnabled);
EXPECT_TRUE(watcher_.privacy_settings().has_user_data_sharing_consent());
}
TEST_P(PrivacySettingsWatcherTest, UploadPolicySwitchesToSetValueOnFirstWatch_OptOut) {
SetInitialUploadPolicy(GetParam());
SetUpPrivacySettingsServer(std::make_unique<fakes::PrivacySettings>());
SetPrivacySettings(kUserOptOut);
watcher_.StartWatching();
RunLoopUntilIdle();
EXPECT_TRUE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kDisabled);
EXPECT_TRUE(watcher_.privacy_settings().has_user_data_sharing_consent());
}
TEST_P(PrivacySettingsWatcherTest, UploadPolicySwitchesToSetValueOnFirstWatch_NotSet) {
SetInitialUploadPolicy(GetParam());
SetUpPrivacySettingsServer(std::make_unique<fakes::PrivacySettings>());
SetPrivacySettings(kNotSet);
watcher_.StartWatching();
RunLoopUntilIdle();
EXPECT_TRUE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_FALSE(watcher_.privacy_settings().has_user_data_sharing_consent());
}
TEST_P(PrivacySettingsWatcherTest, UploadPolicySwitchesToSetValueOnSecondWatch_OptIn) {
SetInitialUploadPolicy(GetParam());
SetUpPrivacySettingsServer(std::make_unique<fakes::PrivacySettings>());
watcher_.StartWatching();
RunLoopUntilIdle();
EXPECT_TRUE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_FALSE(watcher_.privacy_settings().has_user_data_sharing_consent());
SetPrivacySettings(kUserOptIn);
RunLoopUntilIdle();
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kEnabled);
EXPECT_TRUE(watcher_.privacy_settings().has_user_data_sharing_consent());
}
TEST_P(PrivacySettingsWatcherTest, UploadPolicySwitchesToSetValueOnSecondWatch_OptOut) {
SetInitialUploadPolicy(GetParam());
SetUpPrivacySettingsServer(std::make_unique<fakes::PrivacySettings>());
watcher_.StartWatching();
RunLoopUntilIdle();
EXPECT_TRUE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_FALSE(watcher_.privacy_settings().has_user_data_sharing_consent());
SetPrivacySettings(kUserOptOut);
RunLoopUntilIdle();
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kDisabled);
EXPECT_TRUE(watcher_.privacy_settings().has_user_data_sharing_consent());
}
TEST_P(PrivacySettingsWatcherTest, UploadPolicySwitchesToSetValueOnSecondWatch_NotSet) {
SetInitialUploadPolicy(GetParam());
SetUpPrivacySettingsServer(std::make_unique<fakes::PrivacySettings>());
watcher_.StartWatching();
RunLoopUntilIdle();
EXPECT_TRUE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_FALSE(watcher_.privacy_settings().has_user_data_sharing_consent());
SetPrivacySettings(kNotSet);
RunLoopUntilIdle();
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_FALSE(watcher_.privacy_settings().has_user_data_sharing_consent());
}
TEST_P(PrivacySettingsWatcherTest, UploadPolicySwitchesToSetValueOnEachWatch) {
SetInitialUploadPolicy(GetParam());
SetUpPrivacySettingsServer(std::make_unique<fakes::PrivacySettings>());
watcher_.StartWatching();
RunLoopUntilIdle();
EXPECT_TRUE(watcher_.IsConnected());
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_FALSE(watcher_.privacy_settings().has_user_data_sharing_consent());
SetPrivacySettings(kUserOptIn);
RunLoopUntilIdle();
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kEnabled);
EXPECT_TRUE(watcher_.privacy_settings().has_user_data_sharing_consent());
SetPrivacySettings(kUserOptOut);
RunLoopUntilIdle();
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kDisabled);
EXPECT_TRUE(watcher_.privacy_settings().has_user_data_sharing_consent());
SetPrivacySettings(kUserOptIn);
RunLoopUntilIdle();
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kEnabled);
EXPECT_TRUE(watcher_.privacy_settings().has_user_data_sharing_consent());
SetPrivacySettings(kUserOptIn);
RunLoopUntilIdle();
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kEnabled);
EXPECT_TRUE(watcher_.privacy_settings().has_user_data_sharing_consent());
SetPrivacySettings(kUserOptOut);
RunLoopUntilIdle();
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kDisabled);
EXPECT_TRUE(watcher_.privacy_settings().has_user_data_sharing_consent());
SetPrivacySettings(kNotSet);
RunLoopUntilIdle();
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_FALSE(watcher_.privacy_settings().has_user_data_sharing_consent());
SetPrivacySettings(kUserOptIn);
RunLoopUntilIdle();
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kEnabled);
EXPECT_TRUE(watcher_.privacy_settings().has_user_data_sharing_consent());
SetPrivacySettings(kNotSet);
RunLoopUntilIdle();
EXPECT_EQ(crash_reporter_settings_.upload_policy(), kLimbo);
EXPECT_FALSE(watcher_.privacy_settings().has_user_data_sharing_consent());
}
} // namespace
// Pretty-prints Settings::UploadPolicy in gTest matchers instead of the default byte
// string in case of failed expectations.
void PrintTo(const Settings::UploadPolicy& upload_policy, std::ostream* os) {
*os << ToString(upload_policy);
}
} // namespace feedback