blob: b75a74d19c78fb1ab6ca05d924e2c415034afd5f [file] [log] [blame]
// Copyright 2015 The Chromium OS 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 "settingsd/settings_document_manager.h"
#include <algorithm>
#include <deque>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <base/files/scoped_temp_dir.h>
#include <gtest/gtest.h>
#include "settingsd/mock_locked_settings.h"
#include "settingsd/mock_settings_document.h"
#include "settingsd/settings_keys.h"
#include "settingsd/simple_settings_map.h"
#include "settingsd/source.h"
#include "settingsd/source_delegate.h"
#include "settingsd/test_helpers.h"
#include "settingsd/version_stamp.h"
namespace settingsd {
namespace {
// Test constants.
const char kTestSource0[] = "source0";
const char kTestSource1[] = "source1";
const char kTestSource2[] = "source2";
const char kSharedKey[] = "shared";
// A mock settings blob parser that returns staged LockedSettingsContainer
// instances.
class MockSettingsBlobParser {
public:
MockSettingsBlobParser() = default;
// Parse a blob. The corresponding LockedSettingsContainer instance must have
// been registered with the parser via Register().
std::unique_ptr<LockedSettingsContainer> operator()(const std::string& format,
BlobRef data) {
if (!data.valid())
return std::unique_ptr<LockedSettingsContainer>();
auto entry = containers_.find(data.ToString());
if (entry != containers_.end())
return entry->second->Clone();
return std::unique_ptr<LockedSettingsContainer>();
}
// Registers a LockedSettingsContainer with the parser. Returns the BlobRef
// that'll make the parser return the container.
BlobRef Register(MockLockedSettingsContainer* container) {
const std::string blob_id = "blob_" + std::to_string(next_blob_id_++);
containers_[blob_id] = container;
return BlobRef(&containers_.find(blob_id)->first);
}
// Unregisters a LockedSettingsContainer with the parser.
void Unregister(MockLockedSettingsContainer* container) {
for (auto it = containers_.cbegin(); it != containers_.cend();) {
if (it->second == container) {
containers_.erase(it++);
} else {
++it;
}
}
}
private:
int next_blob_id_ = 0;
std::unordered_map<std::string, MockLockedSettingsContainer*> containers_;
DISALLOW_COPY_AND_ASSIGN(MockSettingsBlobParser);
};
// A SourceDelegate implementation with behavior configurable at construction
// time.
class MockSourceDelegate : public SourceDelegate {
public:
MockSourceDelegate() {}
~MockSourceDelegate() override = default;
// SourceDelegate:
bool ValidateVersionComponent(
const LockedVersionComponent& version_component) const override {
return static_cast<const MockLockedVersionComponent&>(version_component)
.is_valid();
}
bool ValidateContainer(
const LockedSettingsContainer& container) const override {
return static_cast<const MockLockedSettingsContainer&>(container)
.is_valid();
}
// This function is suitable as a SourceDelegateFactoryFunction.
static std::unique_ptr<SourceDelegate> Create(
const std::string& source_id,
const SettingsService& settings) {
return std::unique_ptr<SourceDelegate>(new MockSourceDelegate);
}
private:
DISALLOW_COPY_AND_ASSIGN(MockSourceDelegate);
};
// A SettingsObserver implementation that verifies expectations.
class SettingsChangeVerifier : public SettingsObserver {
public:
SettingsChangeVerifier(SettingsDocumentManager* manager,
const std::deque<std::set<Key>>& expectations)
: manager_(manager), expectations_(expectations) {
manager_->AddSettingsObserver(this);
}
~SettingsChangeVerifier() {
EXPECT_TRUE(expectations_.empty());
manager_->RemoveSettingsObserver(this);
}
void OnSettingsChanged(const std::set<Key>& keys) override {
ASSERT_FALSE(expectations_.empty());
EXPECT_TRUE(std::includes(keys.begin(), keys.end(),
expectations_.front().begin(),
expectations_.front().end()));
expectations_.pop_front();
}
private:
SettingsDocumentManager* manager_;
std::deque<std::set<Key>> expectations_;
DISALLOW_COPY_AND_ASSIGN(SettingsChangeVerifier);
};
// Add trust configuration for |source_id| to |doc|.
static void ConfigureSource(MockSettingsDocument* doc,
const std::string& source_id,
SettingStatus status,
const std::map<Key, SettingStatus> access_rules) {
doc->SetKey(MakeSourceKey(source_id).Extend({keys::sources::kStatus}),
SettingStatusToString(status));
doc->SetKey(MakeSourceKey(source_id).Extend({keys::sources::kName}),
source_id);
doc->SetKey(MakeSourceKey(source_id).Extend({keys::sources::kType}),
source_id);
for (auto& access_rule : access_rules) {
doc->SetKey(MakeSourceKey(source_id)
.Extend({keys::sources::kAccess})
.Append(access_rule.first),
SettingStatusToString(access_rule.second));
}
}
// Create the initial trusted settings document for bootstrapping
// SettingsDocumentManager. This configures a source that has access to its
// sentinel value as well as the trust configuration for other sources.
std::unique_ptr<const SettingsDocument> CreateInitialTrustedSettingsDocument() {
// No version stamp is fine, since the initial document can't collide with
// anything and doesn't have an associated source for which it'd need to
// supply a unique version component.
std::unique_ptr<MockSettingsDocument> document(
new MockSettingsDocument(VersionStamp()));
ConfigureSource(document.get(), kTestSource0, kSettingStatusActive,
{{Key(kTestSource0), kSettingStatusActive},
{MakeSourceKey(kTestSource1), kSettingStatusActive},
{MakeSourceKey(kTestSource2), kSettingStatusActive}});
return std::move(document);
}
} // namespace
class SettingsDocumentManagerTest : public testing::Test {
public:
SettingsDocumentManagerTest() {
// Create permissive source delegates for the test sources.
for (auto& source : {kTestSource0, kTestSource1, kTestSource2}) {
source_delegate_factory_.RegisterFunction(source,
MockSourceDelegate::Create);
}
}
void SetUp() override {
ASSERT_TRUE(tmpdir_.CreateUniqueTempDir());
ReinitializeSettingsDocumentManager();
}
void ReinitializeSettingsDocumentManager() {
manager_.reset(new SettingsDocumentManager(
std::ref(parser_), std::ref(source_delegate_factory_),
tmpdir_.path().value(),
std::unique_ptr<SettingsMap>(new SimpleSettingsMap()),
CreateInitialTrustedSettingsDocument()));
manager_->Init();
}
// Creates a container and moves |payload| inside.
MockLockedSettingsContainer* MakeContainer(
std::unique_ptr<MockSettingsDocument> payload) {
std::unique_ptr<MockLockedSettingsContainer> container(
new MockLockedSettingsContainer(std::move(payload)));
MockLockedSettingsContainer* container_ptr = container.get();
containers_.push_back(std::move(container));
return container_ptr;
}
SettingsDocumentManager::InsertionStatus InsertBlob(
const std::string& source_id,
BlobRef blob,
const std::deque<std::set<Key>>& expected_changes) {
SettingsChangeVerifier verifier(manager_.get(), expected_changes);
return manager_->InsertBlob(source_id, blob);
}
// Creates a settings document with a bumped version stamp.
std::unique_ptr<MockSettingsDocument> MakeDocument(
const std::string& source_id) {
current_version_.Set(source_id, current_version_.Get(source_id) + 1);
return std::unique_ptr<MockSettingsDocument>(
new MockSettingsDocument(current_version_));
}
// Convenience wrapper for SettingsDocumentManager::InsertBlob, which wraps
// the given |document| in a MockLockedSettingsContainer, registers the
// container with the parser, and inserts the resulting blob. This also makes
// sure that the parser can re-load the document for re-validation. This
// function is useful for test cases that just want to insert a document -
// call InsertBlob directly for test cases that exercise blob insertion logic.
SettingsDocumentManager::InsertionStatus InsertDocument(
std::unique_ptr<MockSettingsDocument> document,
const std::string& source_id,
const std::deque<std::set<Key>>& expected_changes) {
SettingsChangeVerifier verifier(manager_.get(), expected_changes);
return manager_->InsertBlob(
source_id, parser_.Register(MakeContainer(std::move(document))));
}
// A helper to configure a trusted source.
void ConfigureTrustedSource(const std::string& added_source) {
SCOPED_TRACE("Configuring source " + added_source);
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource0));
ConfigureSource(document.get(), added_source, kSettingStatusActive,
{{Key(added_source), kSettingStatusActive},
{Key(kSharedKey), kSettingStatusActive}});
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource0, {{}}));
}
// A helper that sets a settings key serving as the sentinel value for whether
// the source it originates from is still valid.
MockLockedSettingsContainer* AddSentinelValue(const std::string& source_id) {
SCOPED_TRACE("Adding sentinel value for " + source_id);
std::unique_ptr<MockSettingsDocument> document(MakeDocument(source_id));
document->SetKey(Key(source_id), source_id);
std::unique_ptr<MockLockedSettingsContainer> container(
new MockLockedSettingsContainer(std::move(document)));
MockLockedSettingsContainer* container_ptr = container.get();
containers_.push_back(std::move(container));
BlobRef blob_ref = parser_.Register(container_ptr);
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertBlob(source_id, blob_ref, {{}}));
return container_ptr;
}
// Checks presence of the correct sentinel values.
void CheckSentinelValues(std::initializer_list<std::string> present,
std::initializer_list<std::string> absent) {
for (auto& source : present) {
BlobRef value = manager_->GetValue(Key(source));
EXPECT_TRUE(value.valid()) << "Sentinel value " << source << " missing.";
EXPECT_EQ(source, value.ToString()) << "Sentinel value " << source
<< " has wrong value.";
}
for (auto& source : absent) {
BlobRef value = manager_->GetValue(Key(source));
EXPECT_FALSE(value.valid()) << "Sentinel value " << source << " present.";
}
}
// Changes the trust of |source_id|'s sentinel value for |source_id| to
// |status|.
void SetTrustForSentinelKey(const std::string& source_id,
SettingStatus status) {
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource0));
document->SetKey(MakeSourceKey(source_id)
.Extend({keys::sources::kAccess})
.Append(Key(source_id)),
SettingStatusToString(status));
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource0, {{}}));
}
base::ScopedTempDir tmpdir_;
std::vector<std::unique_ptr<LockedSettingsContainer>> containers_;
MockSettingsBlobParser parser_;
SourceDelegateFactory source_delegate_factory_;
VersionStamp current_version_;
std::unique_ptr<SettingsDocumentManager> manager_;
};
TEST_F(SettingsDocumentManagerTest, ValueInsertionAndRemoval) {
ConfigureTrustedSource(kTestSource1);
const Key kTestKey(kTestSource1);
// Insert a document with a fresh key.
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource1));
document->SetKey(kTestKey, "42");
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource1, {{kTestKey}}));
BlobRef value = manager_->GetValue(kTestKey);
EXPECT_TRUE(value.valid());
EXPECT_EQ("42", value.ToString());
// Update the value.
document = MakeDocument(kTestSource1);
document->SetKey(kTestKey, "string");
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource1, {{kTestKey}}));
BlobRef new_value = manager_->GetValue(kTestKey);
EXPECT_TRUE(new_value.valid());
EXPECT_EQ("string", new_value.ToString());
// Clear the value.
document = MakeDocument(kTestSource1);
document->SetDeletion(kTestKey);
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource1, {{kTestKey}}));
BlobRef newer_value = manager_->GetValue(kTestKey);
EXPECT_FALSE(newer_value.valid());
}
TEST_F(SettingsDocumentManagerTest, TrustChange) {
ConfigureTrustedSource(kTestSource1);
AddSentinelValue(kTestSource1);
// Check whether the sentinel for the inserted source is present.
CheckSentinelValues({kTestSource1}, {});
// Remove trust, which should make the sentinel value disappear.
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource0));
ConfigureSource(document.get(), kTestSource1, kSettingStatusInvalid, {});
EXPECT_EQ(
SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource0, {{Key(kTestSource1)}}));
CheckSentinelValues({}, {kTestSource1});
}
TEST_F(SettingsDocumentManagerTest, CascadingRemoval) {
// Have source0 add source1 and grant it access to source2.
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource0));
ConfigureSource(document.get(), kTestSource1, kSettingStatusActive,
{{Key(kTestSource1), kSettingStatusActive},
{MakeSourceKey(kTestSource2), kSettingStatusActive}});
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource0, {{}}));
AddSentinelValue(kTestSource1);
// Have source1 extend trust to source2.
document = MakeDocument(kTestSource1);
ConfigureSource(document.get(), kTestSource2, kSettingStatusActive,
{{Key(kTestSource2), kSettingStatusActive}});
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource1, {{}}));
AddSentinelValue(kTestSource2);
// Both sentinels should be present.
CheckSentinelValues({kTestSource1, kTestSource2}, {});
// Revoke trust from kTestSource1. kTestSource2 becomes invalid as well.
document = MakeDocument(kTestSource0);
ConfigureSource(document.get(), kTestSource1, kSettingStatusInvalid, {});
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource0,
{{Key(kTestSource1), Key(kTestSource2)}}));
CheckSentinelValues({}, {kTestSource1, kTestSource2});
}
TEST_F(SettingsDocumentManagerTest, TrustChangeDeletion) {
ConfigureTrustedSource(kTestSource1);
AddSentinelValue(kTestSource1);
CheckSentinelValues({kTestSource1}, {});
// Remove trust via a deletion. The sentinel value should disappear.
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource0));
document->SetDeletion(Key(MakeSourceKey(kTestSource1)));
EXPECT_EQ(
SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource0, {{Key(kTestSource1)}}));
CheckSentinelValues({}, {kTestSource1});
}
TEST_F(SettingsDocumentManagerTest, TrustChangeAccessRules) {
ConfigureTrustedSource(kTestSource1);
AddSentinelValue(kTestSource1);
CheckSentinelValues({kTestSource1}, {});
// Revoke source1's ability to write its sentinel.
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource0));
document->SetKey(
MakeSourceKey(kTestSource1)
.Extend({keys::sources::kAccess, kTestSource1}),
SettingStatusToString(kSettingStatusInvalid));
EXPECT_EQ(
SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource0, {{Key(kTestSource1)}}));
CheckSentinelValues({}, {kTestSource1});
}
TEST_F(SettingsDocumentManagerTest, TrustChangeWithdrawnSource) {
ConfigureTrustedSource(kTestSource1);
AddSentinelValue(kTestSource1);
CheckSentinelValues({kTestSource1}, {});
// Switch the source to withdrawn state.
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource0));
ConfigureSource(document.get(), kTestSource1, kSettingStatusWithdrawn, {});
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource0, {{}}));
// The value should still remain present.
CheckSentinelValues({kTestSource1}, {});
// source1 may no longer change the value.
document = MakeDocument(kTestSource1);
document->SetKey(Key(kTestSource1), "change");
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusAccessViolation,
InsertDocument(std::move(document), kTestSource1, {}));
}
TEST_F(SettingsDocumentManagerTest, TrustChangeWithdrawnAccessRules) {
ConfigureTrustedSource(kTestSource1);
AddSentinelValue(kTestSource1);
CheckSentinelValues({kTestSource1}, {});
// Change access rule for the sentinel key to withdrawn.
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource0));
ConfigureSource(document.get(), kTestSource1, kSettingStatusActive,
{{Key(kTestSource1), kSettingStatusWithdrawn}});
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource0, {{}}));
// The value should still remain present.
CheckSentinelValues({kTestSource1}, {});
// source1 may no longer change the value.
document = MakeDocument(kTestSource1);
document->SetKey(Key(kTestSource1), "change");
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusAccessViolation,
InsertDocument(std::move(document), kTestSource1, {}));
}
TEST_F(SettingsDocumentManagerTest, InsertionFailureStatus) {
// Configure source1, but in invalid state.
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource0));
ConfigureSource(document.get(), kTestSource1, kSettingStatusInvalid,
{{Key(kTestSource1), kSettingStatusActive}});
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource0, {{}}));
// Inserting a document should fail.
document = MakeDocument(kTestSource1);
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusAccessViolation,
InsertDocument(std::move(document), kTestSource1, {}));
}
TEST_F(SettingsDocumentManagerTest, InsertionFailureAccessRules) {
ConfigureTrustedSource(kTestSource1);
// Inserting a document with a key the source can't write to should fail.
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource1));
document->SetKey(Key("A"), "42");
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusAccessViolation,
InsertDocument(std::move(document), kTestSource1, {}));
}
TEST_F(SettingsDocumentManagerTest, InsertionFailureVersionClash) {
ConfigureTrustedSource(kTestSource1);
AddSentinelValue(kTestSource1);
// Inserting a document with an already-used version stamp component for the
// issuing source should fail, even if there is no collision.
VersionStamp version_stamp = current_version_;
version_stamp.Set(kTestSource2, current_version_.Get(kTestSource2) + 1);
EXPECT_TRUE(version_stamp.IsAfter(current_version_));
std::unique_ptr<MockSettingsDocument> document(
new MockSettingsDocument(version_stamp));
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusVersionClash,
InsertDocument(std::move(document), kTestSource1, {}));
}
TEST_F(SettingsDocumentManagerTest, InsertionFailureVersionCollision) {
ConfigureTrustedSource(kTestSource1);
ConfigureTrustedSource(kTestSource2);
VersionStamp initial_version = current_version_;
// Insert a value for |kSharedKey|.
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource1));
document->SetKey(Key(kSharedKey), "42");
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertDocument(std::move(document), kTestSource1, {{}}));
// Construct a colliding document, which should fail insertion.
VersionStamp previous_version(current_version_);
current_version_ = initial_version;
document = MakeDocument(kTestSource2);
document->SetKey(Key(kSharedKey), "0");
EXPECT_TRUE(previous_version.IsConcurrent(current_version_));
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusCollision,
InsertDocument(std::move(document), kTestSource2, {}));
}
TEST_F(SettingsDocumentManagerTest, InsertBlobSuccess) {
ConfigureTrustedSource(kTestSource1);
std::unique_ptr<MockSettingsDocument> document(MakeDocument(kTestSource1));
document->SetKey(Key(kTestSource1), kTestSource1);
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusSuccess,
InsertBlob(kTestSource1,
parser_.Register(MakeContainer(std::move(document))),
{{Key(kTestSource1)}}));
CheckSentinelValues({kTestSource1}, {});
}
TEST_F(SettingsDocumentManagerTest, InsertBlobUnknownSource) {
EXPECT_EQ(
SettingsDocumentManager::kInsertionStatusUnknownSource,
InsertBlob(kTestSource1,
parser_.Register(MakeContainer(MakeDocument(kTestSource1))),
{}));
}
TEST_F(SettingsDocumentManagerTest, InsertBlobParseError) {
ConfigureTrustedSource(kTestSource1);
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusParseError,
InsertBlob(kTestSource1, BlobRef(nullptr, 0), {}));
}
TEST_F(SettingsDocumentManagerTest, InsertBlobValidationErrorNoDelegate) {
source_delegate_factory_.RegisterFunction(
kTestSource1,
[](const std::string& source_id, const SettingsService& settings) {
return std::unique_ptr<SourceDelegate>();
});
ConfigureTrustedSource(kTestSource1);
MockLockedSettingsContainer* container =
MakeContainer(MakeDocument(kTestSource1));
container->GetVersionComponent(kTestSource1)->SetSourceId(kTestSource1);
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusValidationError,
InsertBlob(kTestSource1, parser_.Register(container), {}));
}
TEST_F(SettingsDocumentManagerTest, InsertBlobValidationErrorSourceFailure) {
ConfigureTrustedSource(kTestSource1);
MockLockedSettingsContainer* container =
MakeContainer(MakeDocument(kTestSource1));
container->set_valid(false);
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusValidationError,
InsertBlob(kTestSource1, parser_.Register(container), {}));
}
TEST_F(SettingsDocumentManagerTest,
InsertBlobValidationErrorVersionStampFailure) {
ConfigureTrustedSource(kTestSource1);
MockLockedSettingsContainer* container =
MakeContainer(MakeDocument(kTestSource1));
container->GetVersionComponent(kTestSource1)->SetSourceId(kTestSource1);
container->GetVersionComponent(kTestSource1)->set_valid(false);
EXPECT_EQ(SettingsDocumentManager::kInsertionStatusValidationError,
InsertBlob(kTestSource1, parser_.Register(container), {}));
}
TEST_F(SettingsDocumentManagerTest, InsertBlobValidationErrorBadPayload) {
ConfigureTrustedSource(kTestSource1);
EXPECT_EQ(
SettingsDocumentManager::kInsertionStatusBadPayload,
InsertBlob(kTestSource1, parser_.Register(MakeContainer(nullptr)), {}));
}
TEST_F(SettingsDocumentManagerTest, InsertBlobOnStartUp) {
AddSentinelValue(kTestSource0);
ReinitializeSettingsDocumentManager();
CheckSentinelValues({kTestSource0}, {});
}
TEST_F(SettingsDocumentManagerTest, ContainerNotParseableOnRevalidation) {
ConfigureTrustedSource(kTestSource1);
MockLockedSettingsContainer* container = AddSentinelValue(kTestSource1);
parser_.Unregister(container);
SetTrustForSentinelKey(kTestSource1, kSettingStatusWithdrawn);
CheckSentinelValues({}, {kTestSource1});
}
TEST_F(SettingsDocumentManagerTest, ContainerValidationFailureOnRevalidation) {
ConfigureTrustedSource(kTestSource1);
MockLockedSettingsContainer* container = AddSentinelValue(kTestSource1);
container->set_valid(false);
SetTrustForSentinelKey(kTestSource1, kSettingStatusWithdrawn);
CheckSentinelValues({}, {kTestSource1});
}
TEST_F(SettingsDocumentManagerTest,
VersionComponentValidationFailureOnRevalidation) {
ConfigureTrustedSource(kTestSource1);
MockLockedSettingsContainer* container = AddSentinelValue(kTestSource1);
container->GetVersionComponent(kTestSource1)->set_valid(false);
SetTrustForSentinelKey(kTestSource1, kSettingStatusWithdrawn);
CheckSentinelValues({}, {kTestSource1});
}
} // namespace settingsd