blob: 500a9207f52f02d714d938a219e0260319d96036 [file] [log] [blame]
// Copyright 2017 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 "peridot/bin/ledger/cloud_sync/impl/user_sync_impl.h"
#include <utility>
#include <lib/backoff/backoff.h>
#include <lib/backoff/testing/test_backoff.h>
#include <lib/fxl/files/file.h>
#include <lib/fxl/macros.h>
#include <lib/gtest/test_loop_fixture.h>
#include "peridot/bin/ledger/cloud_sync/impl/testing/test_cloud_provider.h"
#include "peridot/bin/ledger/encryption/fake/fake_encryption_service.h"
#include "peridot/bin/ledger/testing/test_with_environment.h"
#include "peridot/lib/scoped_tmpfs/scoped_tmpfs.h"
namespace cloud_sync {
namespace {
class TestSyncStateWatcher : public SyncStateWatcher {
public:
TestSyncStateWatcher() {}
~TestSyncStateWatcher() override{};
void Notify(SyncStateContainer /*sync_state*/) override {}
};
class UserSyncImplTest : public ledger::TestWithEnvironment {
public:
UserSyncImplTest()
: cloud_provider_(cloud_provider_ptr_.NewRequest()),
encryption_service_(dispatcher()) {
UserConfig user_config;
user_config.user_directory = ledger::DetachedPath(tmpfs_.root_fd());
user_config.cloud_provider = std::move(cloud_provider_ptr_);
auto backoff = std::make_unique<backoff::TestBackoff>();
backoff->SetOnGetNext([this] {
// Make RunLoopUntilIdle() return once a backoff is requested, to avoid an
// infinite loop.
QuitLoop();
});
user_sync_ = std::make_unique<UserSyncImpl>(
&environment_, std::move(user_config), std::move(backoff),
[this] { on_version_mismatch_calls_++; });
user_sync_->SetSyncWatcher(&sync_state_watcher_);
}
~UserSyncImplTest() override {}
protected:
bool SetFingerprintFile(std::string content) {
ledger::DetachedPath fingerprint_path = user_sync_->GetFingerprintPath();
return files::WriteFileAt(fingerprint_path.root_fd(),
fingerprint_path.path(), content.data(),
content.size());
}
scoped_tmpfs::ScopedTmpFS tmpfs_;
cloud_provider::CloudProviderPtr cloud_provider_ptr_;
TestCloudProvider cloud_provider_;
std::unique_ptr<UserSyncImpl> user_sync_;
encryption::FakeEncryptionService encryption_service_;
TestSyncStateWatcher sync_state_watcher_;
int on_version_mismatch_calls_ = 0;
private:
FXL_DISALLOW_COPY_AND_ASSIGN(UserSyncImplTest);
};
// Verifies that the mismatch callback is called if the fingerprint appears to
// be erased from the cloud.
TEST_F(UserSyncImplTest, CloudCheckErased) {
ASSERT_TRUE(SetFingerprintFile("some-value"));
cloud_provider_.device_set.status_to_return =
cloud_provider::Status::NOT_FOUND;
EXPECT_EQ(0, on_version_mismatch_calls_);
user_sync_->Start();
RunLoopUntilIdle();
EXPECT_EQ(1, on_version_mismatch_calls_);
}
// Verifies that if the version checker reports that cloud is compatible, upload
// is enabled in LedgerSync.
TEST_F(UserSyncImplTest, CloudCheckOk) {
ASSERT_TRUE(SetFingerprintFile("some-value"));
cloud_provider_.device_set.status_to_return = cloud_provider::Status::OK;
EXPECT_EQ(0, on_version_mismatch_calls_);
user_sync_->Start();
auto ledger_a = user_sync_->CreateLedgerSync("app-id", &encryption_service_);
auto ledger_a_ptr = static_cast<LedgerSyncImpl*>(ledger_a.get());
EXPECT_FALSE(ledger_a_ptr->IsUploadEnabled());
RunLoopUntilIdle();
EXPECT_TRUE(ledger_a_ptr->IsUploadEnabled());
EXPECT_EQ(0, on_version_mismatch_calls_);
EXPECT_EQ("some-value", cloud_provider_.device_set.checked_fingerprint);
// Verify that newly created LedgerSyncs also have the upload enabled.
auto ledger_b = user_sync_->CreateLedgerSync("app-id", &encryption_service_);
auto ledger_b_ptr = static_cast<LedgerSyncImpl*>(ledger_b.get());
EXPECT_TRUE(ledger_b_ptr->IsUploadEnabled());
}
// Verifies that if there is no fingerprint file, it is created and set in the
// cloud.
TEST_F(UserSyncImplTest, CloudCheckSet) {
auto fingerprint_path = user_sync_->GetFingerprintPath();
EXPECT_FALSE(
files::IsFileAt(fingerprint_path.root_fd(), fingerprint_path.path()));
cloud_provider_.device_set.status_to_return = cloud_provider::Status::OK;
EXPECT_EQ(0, on_version_mismatch_calls_);
user_sync_->Start();
auto ledger = user_sync_->CreateLedgerSync("app-id", &encryption_service_);
auto ledger_ptr = static_cast<LedgerSyncImpl*>(ledger.get());
EXPECT_FALSE(ledger_ptr->IsUploadEnabled());
RunLoopUntilIdle();
EXPECT_TRUE(ledger_ptr->IsUploadEnabled());
EXPECT_EQ(0, on_version_mismatch_calls_);
EXPECT_FALSE(cloud_provider_.device_set.set_fingerprint.empty());
// Verify that the fingerprint file was created.
EXPECT_TRUE(
files::IsFileAt(fingerprint_path.root_fd(), fingerprint_path.path()));
}
// Verifies that the cloud watcher for the fingerprint is set and triggers the
// mismatch callback when cloud erase is detected.
TEST_F(UserSyncImplTest, WatchErase) {
ASSERT_TRUE(SetFingerprintFile("some-value"));
cloud_provider_.device_set.status_to_return = cloud_provider::Status::OK;
user_sync_->Start();
RunLoopUntilIdle();
EXPECT_TRUE(cloud_provider_.device_set.set_watcher.is_bound());
EXPECT_EQ("some-value", cloud_provider_.device_set.watched_fingerprint);
EXPECT_EQ(0, on_version_mismatch_calls_);
cloud_provider_.device_set.set_watcher->OnCloudErased();
RunLoopUntilIdle();
EXPECT_EQ(1, on_version_mismatch_calls_);
}
// Verifies that setting the cloud watcher for is retried on network errors.
TEST_F(UserSyncImplTest, WatchRetry) {
ASSERT_TRUE(SetFingerprintFile("some-value"));
cloud_provider_.device_set.set_watcher_status_to_return =
cloud_provider::Status::NETWORK_ERROR;
user_sync_->Start();
RunLoopUntilIdle();
EXPECT_EQ(1, cloud_provider_.device_set.set_watcher_calls);
}
} // namespace
} // namespace cloud_sync