blob: 41b4fff065338076e11f7af13316d757673e306d [file] [log] [blame]
// Copyright 2015 The Chromium 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 "components/sync_wifi/wifi_credential_syncable_service.h"
#include <stdint.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "base/tracked_objects.h"
#include "components/sync/model/attachments/attachment_id.h"
#include "components/sync/model/attachments/attachment_service_proxy_for_test.h"
#include "components/sync/model/fake_sync_change_processor.h"
#include "components/sync/model/sync_change.h"
#include "components/sync/model/sync_data.h"
#include "components/sync/model/sync_error.h"
#include "components/sync/model/sync_error_factory_mock.h"
#include "components/sync/protocol/sync.pb.h"
#include "components/sync_wifi/wifi_config_delegate.h"
#include "components/sync_wifi/wifi_credential.h"
#include "components/sync_wifi/wifi_security_class.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace sync_wifi {
using syncer::FakeSyncChangeProcessor;
using syncer::SyncErrorFactoryMock;
namespace {
const char kSsid[] = "fake-ssid";
const char kSsidNonUtf8[] = "\xc0";
// Fake implementation of WifiConfigDelegate, which provides the
// ability to check how many times a WifiConfigDelegate method has
// been called.
class FakeWifiConfigDelegate : public WifiConfigDelegate {
public:
FakeWifiConfigDelegate() : add_count_(0) {}
~FakeWifiConfigDelegate() override {}
// WifiConfigDelegate implementation.
void AddToLocalNetworks(const WifiCredential& network_credential) override {
++add_count_;
}
// Returns the number of times the AddToLocalNetworks method has
// been called.
unsigned int add_count() const { return add_count_; }
private:
// The number of times AddToLocalNetworks has been called on this fake.
unsigned int add_count_;
DISALLOW_COPY_AND_ASSIGN(FakeWifiConfigDelegate);
};
// Unit tests for WifiCredentialSyncableService.
class WifiCredentialSyncableServiceTest : public testing::Test {
protected:
WifiCredentialSyncableServiceTest()
: config_delegate_(new FakeWifiConfigDelegate()),
change_processor_(nullptr) {
syncable_service_.reset(
new WifiCredentialSyncableService(base::WrapUnique(config_delegate_)));
}
// Wrappers for methods in WifiCredentialSyncableService.
syncer::SyncError ProcessSyncChanges(
const syncer::SyncChangeList& change_list) {
return syncable_service_->ProcessSyncChanges(FROM_HERE, change_list);
}
bool AddToSyncedNetworks(const std::string& item_id,
const WifiCredential& credential) {
return syncable_service_->AddToSyncedNetworks(item_id, credential);
}
// Returns the number of change requests received by
// |change_processor_|.
int change_processor_changes_size() {
CHECK(change_processor_);
return change_processor_->changes().size();
}
// Returns the number of times AddToLocalNetworks has been called on
// |config_delegate_|.
unsigned int config_delegate_add_count() {
return config_delegate_->add_count();
}
// Returns a new WifiCredential constructed from the given parameters.
WifiCredential MakeCredential(const std::string& ssid,
WifiSecurityClass security_class,
const std::string& passphrase) {
std::unique_ptr<WifiCredential> credential = WifiCredential::Create(
WifiCredential::MakeSsidBytesForTest(ssid), security_class, passphrase);
CHECK(credential);
return *credential;
}
// Returns a new EntitySpecifics protobuf, with the
// wifi_credential_specifics fields populated with the given
// parameters.
sync_pb::EntitySpecifics MakeWifiCredentialSpecifics(
const std::string& ssid,
sync_pb::WifiCredentialSpecifics_SecurityClass security_class,
const std::string* passphrase) {
const std::vector<uint8_t> ssid_bytes(ssid.begin(), ssid.end());
sync_pb::EntitySpecifics sync_entity_specifics;
sync_pb::WifiCredentialSpecifics* wifi_credential_specifics =
sync_entity_specifics.mutable_wifi_credential();
CHECK(wifi_credential_specifics);
wifi_credential_specifics->set_ssid(ssid_bytes.data(), ssid_bytes.size());
wifi_credential_specifics->set_security_class(security_class);
if (passphrase) {
wifi_credential_specifics->set_passphrase(passphrase->data(),
passphrase->size());
}
return sync_entity_specifics;
}
syncer::SyncChange MakeActionAdd(
int sync_item_id,
const std::string& ssid,
sync_pb::WifiCredentialSpecifics_SecurityClass security_class,
const std::string* passphrase) {
return syncer::SyncChange(
FROM_HERE, syncer::SyncChange::ACTION_ADD,
syncer::SyncData::CreateRemoteData(
sync_item_id,
MakeWifiCredentialSpecifics(ssid, security_class, passphrase),
base::Time(), syncer::AttachmentIdList(),
syncer::AttachmentServiceProxyForTest::Create()));
}
void StartSyncing() {
std::unique_ptr<FakeSyncChangeProcessor> change_processor(
new FakeSyncChangeProcessor());
change_processor_ = change_processor.get();
syncable_service_->MergeDataAndStartSyncing(
syncer::WIFI_CREDENTIALS, syncer::SyncDataList(),
std::move(change_processor), base::MakeUnique<SyncErrorFactoryMock>());
}
private:
std::unique_ptr<WifiCredentialSyncableService> syncable_service_;
FakeWifiConfigDelegate* config_delegate_; // Owned by |syncable_service_|
FakeSyncChangeProcessor* change_processor_; // Owned by |syncable_service_|
DISALLOW_COPY_AND_ASSIGN(WifiCredentialSyncableServiceTest);
};
} // namespace
TEST_F(WifiCredentialSyncableServiceTest, ProcessSyncChangesNotStarted) {
syncer::SyncError sync_error(ProcessSyncChanges(syncer::SyncChangeList()));
ASSERT_TRUE(sync_error.IsSet());
EXPECT_EQ(syncer::SyncError::UNREADY_ERROR, sync_error.error_type());
EXPECT_EQ(0U, config_delegate_add_count());
}
TEST_F(WifiCredentialSyncableServiceTest,
ProcessSyncChangesActionAddSecurityClassInvalid) {
syncer::SyncChangeList changes;
const int sync_item_id = 1;
changes.push_back(MakeActionAdd(
sync_item_id, kSsidNonUtf8,
sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_INVALID, nullptr));
StartSyncing();
syncer::SyncError sync_error = ProcessSyncChanges(changes);
EXPECT_FALSE(sync_error.IsSet()); // Bad items are ignored.
EXPECT_EQ(0U, config_delegate_add_count());
}
TEST_F(WifiCredentialSyncableServiceTest,
ProcessSyncChangesActionAddSecurityClassNoneSuccess) {
syncer::SyncChangeList changes;
const int sync_item_id = 1;
changes.push_back(MakeActionAdd(
sync_item_id, kSsidNonUtf8,
sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_NONE, nullptr));
StartSyncing();
syncer::SyncError sync_error = ProcessSyncChanges(changes);
EXPECT_FALSE(sync_error.IsSet());
EXPECT_EQ(1U, config_delegate_add_count());
}
TEST_F(WifiCredentialSyncableServiceTest,
ProcessSyncChangesActionAddSecurityClassWepMissingPassphrase) {
syncer::SyncChangeList changes;
const int sync_item_id = 1;
changes.push_back(MakeActionAdd(
sync_item_id, kSsidNonUtf8,
sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_WEP, nullptr));
StartSyncing();
syncer::SyncError sync_error = ProcessSyncChanges(changes);
EXPECT_FALSE(sync_error.IsSet()); // Bad items are ignored.
EXPECT_EQ(0U, config_delegate_add_count());
}
TEST_F(WifiCredentialSyncableServiceTest,
ProcessSyncChangesActionAddSecurityClassWepSuccess) {
syncer::SyncChangeList changes;
const int sync_item_id = 1;
const std::string passphrase("abcde");
changes.push_back(MakeActionAdd(
sync_item_id, kSsidNonUtf8,
sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_WEP, &passphrase));
StartSyncing();
syncer::SyncError sync_error = ProcessSyncChanges(changes);
EXPECT_FALSE(sync_error.IsSet());
EXPECT_EQ(1U, config_delegate_add_count());
}
TEST_F(WifiCredentialSyncableServiceTest,
ProcessSyncChangesActionAddSecurityClassPskMissingPassphrase) {
syncer::SyncChangeList changes;
const int sync_item_id = 1;
changes.push_back(MakeActionAdd(
sync_item_id, kSsidNonUtf8,
sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_PSK, nullptr));
StartSyncing();
syncer::SyncError sync_error = ProcessSyncChanges(changes);
EXPECT_FALSE(sync_error.IsSet()); // Bad items are ignored.
EXPECT_EQ(0U, config_delegate_add_count());
}
TEST_F(WifiCredentialSyncableServiceTest,
ProcessSyncChangesActionAddSecurityClassPskSuccess) {
syncer::SyncChangeList changes;
const int sync_item_id = 1;
const std::string passphrase("psk-passphrase");
changes.push_back(MakeActionAdd(
sync_item_id, kSsidNonUtf8,
sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_PSK, &passphrase));
StartSyncing();
syncer::SyncError sync_error = ProcessSyncChanges(changes);
EXPECT_FALSE(sync_error.IsSet());
EXPECT_EQ(1U, config_delegate_add_count());
}
TEST_F(WifiCredentialSyncableServiceTest,
ProcessSyncChangesContinuesAfterSecurityClassInvalid) {
syncer::SyncChangeList changes;
changes.push_back(MakeActionAdd(
1 /* sync item id */, kSsidNonUtf8,
sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_INVALID, nullptr));
changes.push_back(MakeActionAdd(
2 /* sync item id */, kSsidNonUtf8,
sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_NONE, nullptr));
StartSyncing();
syncer::SyncError sync_error = ProcessSyncChanges(changes);
EXPECT_FALSE(sync_error.IsSet()); // Bad items are ignored.
EXPECT_EQ(1U, config_delegate_add_count());
}
TEST_F(WifiCredentialSyncableServiceTest,
ProcessSyncChangesContinuesAfterMissingPassphrase) {
syncer::SyncChangeList changes;
changes.push_back(MakeActionAdd(
1 /* sync item id */, kSsidNonUtf8,
sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_WEP, nullptr));
changes.push_back(MakeActionAdd(
2 /* sync item id */, kSsidNonUtf8,
sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_NONE, nullptr));
StartSyncing();
syncer::SyncError sync_error = ProcessSyncChanges(changes);
EXPECT_FALSE(sync_error.IsSet()); // Bad items are ignored.
EXPECT_EQ(1U, config_delegate_add_count());
}
TEST_F(WifiCredentialSyncableServiceTest, AddToSyncedNetworksNotStarted) {
EXPECT_FALSE(AddToSyncedNetworks(
"fake-item-id", MakeCredential(kSsidNonUtf8, SECURITY_CLASS_NONE, "")));
}
TEST_F(WifiCredentialSyncableServiceTest, AddToSyncedNetworksSuccess) {
StartSyncing();
EXPECT_TRUE(AddToSyncedNetworks(
"fake-item-id", MakeCredential(kSsidNonUtf8, SECURITY_CLASS_NONE, "")));
EXPECT_EQ(1, change_processor_changes_size());
}
TEST_F(WifiCredentialSyncableServiceTest,
AddToSyncedNetworksDifferentSecurityClassesSuccess) {
StartSyncing();
EXPECT_TRUE(AddToSyncedNetworks(
"fake-item-id", MakeCredential(kSsidNonUtf8, SECURITY_CLASS_NONE, "")));
EXPECT_TRUE(AddToSyncedNetworks(
"fake-item-id-2", MakeCredential(kSsidNonUtf8, SECURITY_CLASS_WEP, "")));
EXPECT_EQ(2, change_processor_changes_size());
}
TEST_F(WifiCredentialSyncableServiceTest,
AddToSyncedNetworksDifferentSsidsSuccess) {
StartSyncing();
EXPECT_TRUE(AddToSyncedNetworks(
"fake-item-id", MakeCredential(kSsidNonUtf8, SECURITY_CLASS_NONE, "")));
EXPECT_TRUE(AddToSyncedNetworks(
"fake-item-id-2", MakeCredential(kSsid, SECURITY_CLASS_NONE, "")));
EXPECT_EQ(2, change_processor_changes_size());
}
TEST_F(WifiCredentialSyncableServiceTest,
AddToSyncedNetworksDuplicateAddPskNetwork) {
const std::string passphrase("psk-passphrase");
StartSyncing();
EXPECT_TRUE(AddToSyncedNetworks(
"fake-item-id",
MakeCredential(kSsidNonUtf8, SECURITY_CLASS_PSK, passphrase)));
EXPECT_EQ(1, change_processor_changes_size());
EXPECT_FALSE(AddToSyncedNetworks(
"fake-item-id",
MakeCredential(kSsidNonUtf8, SECURITY_CLASS_PSK, passphrase)));
EXPECT_EQ(1, change_processor_changes_size());
}
TEST_F(WifiCredentialSyncableServiceTest,
AddToSyncedNetworksDuplicateAddOpenNetwork) {
StartSyncing();
EXPECT_TRUE(AddToSyncedNetworks(
"fake-item-id", MakeCredential(kSsidNonUtf8, SECURITY_CLASS_NONE, "")));
EXPECT_EQ(1, change_processor_changes_size());
EXPECT_FALSE(AddToSyncedNetworks(
"fake-item-id", MakeCredential(kSsidNonUtf8, SECURITY_CLASS_NONE, "")));
EXPECT_EQ(1, change_processor_changes_size());
}
} // namespace sync_wifi