Index: components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc |
diff --git a/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc |
index de05b01f299f68c6e6ee03e167e1d7d42c521c44..596d67d1812fa2ca7eb1436a2ea8a8706f35ef85 100644 |
--- a/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc |
+++ b/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc |
@@ -4,7 +4,8 @@ |
#include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h" |
-#include <memory> |
+#include <map> |
+#include <vector> |
#include "base/bind.h" |
#include "base/files/scoped_temp_dir.h" |
@@ -21,10 +22,12 @@ |
#include "components/sync/model/fake_model_type_change_processor.h" |
#include "components/sync/model/metadata_batch.h" |
#include "components/webdata/common/web_database.h" |
-#include "net/base/escape.h" |
#include "testing/gtest/include/gtest/gtest.h" |
using sync_pb::AutofillSpecifics; |
+using sync_pb::EntitySpecifics; |
+using syncer::EntityDataPtr; |
+using syncer::EntityData; |
using syncer::SyncError; |
namespace autofill { |
@@ -60,6 +63,28 @@ CreateModelTypeChangeProcessor(syncer::ModelType type, |
return base::MakeUnique<syncer::FakeModelTypeChangeProcessor>(); |
} |
+AutofillEntry CreateAutofillEntry( |
+ const sync_pb::AutofillSpecifics& autofill_specifics) { |
+ AutofillKey key(base::UTF8ToUTF16(autofill_specifics.name()), |
+ base::UTF8ToUTF16(autofill_specifics.value())); |
+ base::Time date_created, date_last_used; |
+ const google::protobuf::RepeatedField<int64_t>& timestamps = |
+ autofill_specifics.usage_timestamp(); |
+ if (!timestamps.empty()) { |
+ date_created = base::Time::FromInternalValue(*timestamps.begin()); |
+ date_last_used = base::Time::FromInternalValue(*timestamps.rbegin()); |
+ } |
+ return AutofillEntry(key, date_created, date_last_used); |
+} |
+ |
+// Creates an EntityData/EntityDataPtr around a copy of the given specifics. |
+EntityDataPtr SpecificsToEntity(const AutofillSpecifics& specifics) { |
+ EntityData data; |
+ data.client_tag_hash = "ignored"; |
+ *data.specifics.mutable_autofill() = specifics; |
+ return data.PassToPtr(); |
+} |
+ |
class FakeAutofillBackend : public AutofillWebDataBackend { |
public: |
FakeAutofillBackend() {} |
@@ -101,8 +126,7 @@ class AutocompleteSyncBridgeTest : public testing::Test { |
const std::vector<AutofillSpecifics>& specifics_list) { |
std::vector<AutofillEntry> new_entries; |
for (const auto& specifics : specifics_list) { |
- new_entries.push_back( |
- AutocompleteSyncBridge::CreateAutofillEntry(specifics)); |
+ new_entries.push_back(CreateAutofillEntry(specifics)); |
} |
table_.UpdateAutofillEntries(new_entries); |
} |
@@ -116,8 +140,10 @@ class AutocompleteSyncBridgeTest : public testing::Test { |
} |
std::string GetStorageKey(const AutofillSpecifics& specifics) { |
- return net::EscapePath(specifics.name()) + "|" + |
- net::EscapePath(specifics.value()); |
+ std::string key = |
+ bridge()->GetStorageKey(SpecificsToEntity(specifics).value()); |
+ EXPECT_FALSE(key.empty()); |
+ return key; |
} |
private: |
@@ -131,6 +157,56 @@ class AutocompleteSyncBridgeTest : public testing::Test { |
DISALLOW_COPY_AND_ASSIGN(AutocompleteSyncBridgeTest); |
}; |
+TEST_F(AutocompleteSyncBridgeTest, GetClientTag) { |
+ // TODO(skym, crbug.com/675991): Implementation. |
+} |
+ |
+TEST_F(AutocompleteSyncBridgeTest, GetStorageKey) { |
+ std::string key = GetStorageKey(CreateSpecifics(1)); |
+ EXPECT_EQ(key, GetStorageKey(CreateSpecifics(1))); |
+ EXPECT_NE(key, GetStorageKey(CreateSpecifics(2))); |
+} |
+ |
+// Timestamps should not affect storage keys. |
+TEST_F(AutocompleteSyncBridgeTest, GetStorageKeyTimestamp) { |
+ AutofillSpecifics specifics = CreateSpecifics(1); |
+ std::string key = GetStorageKey(specifics); |
+ |
+ specifics.add_usage_timestamp(1); |
+ EXPECT_EQ(key, GetStorageKey(specifics)); |
+ |
+ specifics.add_usage_timestamp(0); |
+ EXPECT_EQ(key, GetStorageKey(specifics)); |
+ |
+ specifics.add_usage_timestamp(-1); |
+ EXPECT_EQ(key, GetStorageKey(specifics)); |
+} |
+ |
+// Verify that the \0 character is respected as a difference. |
+TEST_F(AutocompleteSyncBridgeTest, GetStorageKeyNull) { |
+ AutofillSpecifics specifics; |
+ std::string key = GetStorageKey(specifics); |
+ |
+ specifics.set_value(std::string("\0", 1)); |
+ EXPECT_NE(key, GetStorageKey(specifics)); |
+} |
+ |
+// The storage key should never accidentally change for existing data. This |
+// would cause lookups to fail and either lose or duplicate user data. It should |
+// be possible for the model type to migrate storage key formats, but doing so |
+// would need to be done very carefully. |
+TEST_F(AutocompleteSyncBridgeTest, GetStorageKeyFixed) { |
+ EXPECT_EQ("\n\x6name 1\x12\avalue 1", GetStorageKey(CreateSpecifics(1))); |
+ EXPECT_EQ("\n\x6name 2\x12\avalue 2", GetStorageKey(CreateSpecifics(2))); |
+ // This literal contains the null terminating character, which causes |
+ // std::string to stop copying early if we don't tell it how much to read. |
+ EXPECT_EQ(std::string("\n\0\x12\0", 4), GetStorageKey(AutofillSpecifics())); |
+ AutofillSpecifics specifics; |
+ specifics.set_name("\xEC\xA4\x91"); |
+ specifics.set_value("\xD0\x80"); |
+ EXPECT_EQ("\n\x3\xEC\xA4\x91\x12\x2\xD0\x80", GetStorageKey(specifics)); |
+} |
+ |
TEST_F(AutocompleteSyncBridgeTest, GetData) { |
const AutofillSpecifics specifics1 = CreateSpecifics(1); |
const AutofillSpecifics specifics2 = CreateSpecifics(2); |