1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Keep this file in sync with the .proto files in this directory.
7 #include "sync/protocol/proto_value_conversions.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/time/time.h"
12 #include "base/values.h"
13 #include "sync/internal_api/public/base/model_type.h"
14 #include "sync/protocol/app_notification_specifics.pb.h"
15 #include "sync/protocol/app_setting_specifics.pb.h"
16 #include "sync/protocol/app_specifics.pb.h"
17 #include "sync/protocol/autofill_specifics.pb.h"
18 #include "sync/protocol/bookmark_specifics.pb.h"
19 #include "sync/protocol/device_info_specifics.pb.h"
20 #include "sync/protocol/encryption.pb.h"
21 #include "sync/protocol/experiments_specifics.pb.h"
22 #include "sync/protocol/extension_setting_specifics.pb.h"
23 #include "sync/protocol/extension_specifics.pb.h"
24 #include "sync/protocol/favicon_image_specifics.pb.h"
25 #include "sync/protocol/favicon_tracking_specifics.pb.h"
26 #include "sync/protocol/managed_user_setting_specifics.pb.h"
27 #include "sync/protocol/managed_user_shared_setting_specifics.pb.h"
28 #include "sync/protocol/managed_user_specifics.pb.h"
29 #include "sync/protocol/managed_user_whitelist_specifics.pb.h"
30 #include "sync/protocol/nigori_specifics.pb.h"
31 #include "sync/protocol/password_specifics.pb.h"
32 #include "sync/protocol/preference_specifics.pb.h"
33 #include "sync/protocol/priority_preference_specifics.pb.h"
34 #include "sync/protocol/search_engine_specifics.pb.h"
35 #include "sync/protocol/session_specifics.pb.h"
36 #include "sync/protocol/sync.pb.h"
37 #include "sync/protocol/theme_specifics.pb.h"
38 #include "sync/protocol/typed_url_specifics.pb.h"
39 #include "sync/protocol/wifi_credential_specifics.pb.h"
40 #include "testing/gtest/include/gtest/gtest.h"
45 class ProtoValueConversionsTest
: public testing::Test
{
48 void TestSpecificsToValue(
49 scoped_ptr
<base::DictionaryValue
>(*specifics_to_value
)(const T
&)) {
50 const T
& specifics(T::default_instance());
51 scoped_ptr
<base::DictionaryValue
> value
= specifics_to_value(specifics
);
52 // We can't do much but make sure that this doesn't crash.
56 TEST_F(ProtoValueConversionsTest
, ProtoChangeCheck
) {
57 // If this number changes, that means we added or removed a data
58 // type. Don't forget to add a unit test for {New
59 // type}SpecificsToValue below.
60 EXPECT_EQ(36, MODEL_TYPE_COUNT
);
62 // We'd also like to check if we changed any field in our messages.
63 // However, that's hard to do: sizeof could work, but it's
64 // platform-dependent. default_instance().ByteSize() won't change
65 // for most changes, since most of our fields are optional. So we
66 // just settle for comments in the proto files.
69 TEST_F(ProtoValueConversionsTest
, EncryptedDataToValue
) {
70 TestSpecificsToValue(EncryptedDataToValue
);
73 TEST_F(ProtoValueConversionsTest
, SessionHeaderToValue
) {
74 TestSpecificsToValue(SessionHeaderToValue
);
77 TEST_F(ProtoValueConversionsTest
, SessionTabToValue
) {
78 TestSpecificsToValue(SessionTabToValue
);
81 TEST_F(ProtoValueConversionsTest
, SessionWindowToValue
) {
82 TestSpecificsToValue(SessionWindowToValue
);
85 TEST_F(ProtoValueConversionsTest
, TabNavigationToValue
) {
86 TestSpecificsToValue(TabNavigationToValue
);
89 TEST_F(ProtoValueConversionsTest
, NavigationRedirectToValue
) {
90 TestSpecificsToValue(NavigationRedirectToValue
);
93 TEST_F(ProtoValueConversionsTest
, PasswordSpecificsData
) {
94 sync_pb::PasswordSpecificsData specifics
;
95 specifics
.set_password_value("secret");
96 scoped_ptr
<base::DictionaryValue
> value(
97 PasswordSpecificsDataToValue(specifics
));
98 EXPECT_FALSE(value
->empty());
99 std::string password_value
;
100 EXPECT_TRUE(value
->GetString("password_value", &password_value
));
101 EXPECT_EQ("<redacted>", password_value
);
104 TEST_F(ProtoValueConversionsTest
, AppListSpecificsToValue
) {
105 TestSpecificsToValue(AppListSpecificsToValue
);
108 TEST_F(ProtoValueConversionsTest
, AppNotificationToValue
) {
109 TestSpecificsToValue(AppNotificationToValue
);
112 TEST_F(ProtoValueConversionsTest
, AppSettingSpecificsToValue
) {
113 sync_pb::AppNotificationSettings specifics
;
114 specifics
.set_disabled(true);
115 specifics
.set_oauth_client_id("some_id_value");
116 scoped_ptr
<base::DictionaryValue
> value(AppSettingsToValue(specifics
));
117 EXPECT_FALSE(value
->empty());
118 bool disabled_value
= false;
119 std::string oauth_client_id_value
;
120 EXPECT_TRUE(value
->GetBoolean("disabled", &disabled_value
));
121 EXPECT_EQ(true, disabled_value
);
122 EXPECT_TRUE(value
->GetString("oauth_client_id", &oauth_client_id_value
));
123 EXPECT_EQ("some_id_value", oauth_client_id_value
);
126 TEST_F(ProtoValueConversionsTest
, AppSpecificsToValue
) {
127 TestSpecificsToValue(AppSpecificsToValue
);
130 TEST_F(ProtoValueConversionsTest
, AutofillSpecificsToValue
) {
131 TestSpecificsToValue(AutofillSpecificsToValue
);
134 TEST_F(ProtoValueConversionsTest
, AutofillProfileSpecificsToValue
) {
135 TestSpecificsToValue(AutofillProfileSpecificsToValue
);
138 TEST_F(ProtoValueConversionsTest
, AutofillWalletSpecificsToValue
) {
139 TestSpecificsToValue(AutofillWalletSpecificsToValue
);
142 TEST_F(ProtoValueConversionsTest
, WalletMetadataSpecificsToValue
) {
143 TestSpecificsToValue(WalletMetadataSpecificsToValue
);
146 TEST_F(ProtoValueConversionsTest
, BookmarkSpecificsToValue
) {
147 TestSpecificsToValue(BookmarkSpecificsToValue
);
150 TEST_F(ProtoValueConversionsTest
, BookmarkSpecificsData
) {
151 const base::Time
creation_time(base::Time::Now());
152 const std::string icon_url
= "http://www.google.com/favicon.ico";
153 sync_pb::BookmarkSpecifics specifics
;
154 specifics
.set_creation_time_us(creation_time
.ToInternalValue());
155 specifics
.set_icon_url(icon_url
);
156 sync_pb::MetaInfo
* meta_1
= specifics
.add_meta_info();
157 meta_1
->set_key("key1");
158 meta_1
->set_value("value1");
159 sync_pb::MetaInfo
* meta_2
= specifics
.add_meta_info();
160 meta_2
->set_key("key2");
161 meta_2
->set_value("value2");
163 scoped_ptr
<base::DictionaryValue
> value(BookmarkSpecificsToValue(specifics
));
164 EXPECT_FALSE(value
->empty());
165 std::string encoded_time
;
166 EXPECT_TRUE(value
->GetString("creation_time_us", &encoded_time
));
167 EXPECT_EQ(base::Int64ToString(creation_time
.ToInternalValue()), encoded_time
);
168 std::string encoded_icon_url
;
169 EXPECT_TRUE(value
->GetString("icon_url", &encoded_icon_url
));
170 EXPECT_EQ(icon_url
, encoded_icon_url
);
171 base::ListValue
* meta_info_list
;
172 ASSERT_TRUE(value
->GetList("meta_info", &meta_info_list
));
173 EXPECT_EQ(2u, meta_info_list
->GetSize());
174 base::DictionaryValue
* meta_info
;
175 std::string meta_key
;
176 std::string meta_value
;
177 ASSERT_TRUE(meta_info_list
->GetDictionary(0, &meta_info
));
178 EXPECT_TRUE(meta_info
->GetString("key", &meta_key
));
179 EXPECT_TRUE(meta_info
->GetString("value", &meta_value
));
180 EXPECT_EQ("key1", meta_key
);
181 EXPECT_EQ("value1", meta_value
);
182 ASSERT_TRUE(meta_info_list
->GetDictionary(1, &meta_info
));
183 EXPECT_TRUE(meta_info
->GetString("key", &meta_key
));
184 EXPECT_TRUE(meta_info
->GetString("value", &meta_value
));
185 EXPECT_EQ("key2", meta_key
);
186 EXPECT_EQ("value2", meta_value
);
189 TEST_F(ProtoValueConversionsTest
, LinkedAppIconInfoToValue
) {
190 TestSpecificsToValue(LinkedAppIconInfoToValue
);
193 TEST_F(ProtoValueConversionsTest
, PriorityPreferenceSpecificsToValue
) {
194 TestSpecificsToValue(PriorityPreferenceSpecificsToValue
);
197 TEST_F(ProtoValueConversionsTest
, DeviceInfoSpecificsToValue
) {
198 TestSpecificsToValue(DeviceInfoSpecificsToValue
);
201 TEST_F(ProtoValueConversionsTest
, ExperimentsSpecificsToValue
) {
202 TestSpecificsToValue(ExperimentsSpecificsToValue
);
205 TEST_F(ProtoValueConversionsTest
, ExtensionSettingSpecificsToValue
) {
206 TestSpecificsToValue(ExtensionSettingSpecificsToValue
);
209 TEST_F(ProtoValueConversionsTest
, ExtensionSpecificsToValue
) {
210 TestSpecificsToValue(ExtensionSpecificsToValue
);
213 TEST_F(ProtoValueConversionsTest
, FaviconImageSpecificsToValue
) {
214 TestSpecificsToValue(FaviconImageSpecificsToValue
);
217 TEST_F(ProtoValueConversionsTest
, FaviconTrackingSpecificsToValue
) {
218 TestSpecificsToValue(FaviconTrackingSpecificsToValue
);
221 TEST_F(ProtoValueConversionsTest
, HistoryDeleteDirectiveSpecificsToValue
) {
222 TestSpecificsToValue(HistoryDeleteDirectiveSpecificsToValue
);
225 TEST_F(ProtoValueConversionsTest
, ManagedUserSettingSpecificsToValue
) {
226 TestSpecificsToValue(ManagedUserSettingSpecificsToValue
);
229 TEST_F(ProtoValueConversionsTest
, ManagedUserSpecificsToValue
) {
230 TestSpecificsToValue(ManagedUserSpecificsToValue
);
233 TEST_F(ProtoValueConversionsTest
, ManagedUserSharedSettingSpecificsToValue
) {
234 TestSpecificsToValue(ManagedUserSharedSettingSpecificsToValue
);
237 TEST_F(ProtoValueConversionsTest
, ManagedUserWhitelistSpecificsToValue
) {
238 TestSpecificsToValue(ManagedUserWhitelistSpecificsToValue
);
241 TEST_F(ProtoValueConversionsTest
, NigoriSpecificsToValue
) {
242 TestSpecificsToValue(NigoriSpecificsToValue
);
245 TEST_F(ProtoValueConversionsTest
, PasswordSpecificsToValue
) {
246 TestSpecificsToValue(PasswordSpecificsToValue
);
249 TEST_F(ProtoValueConversionsTest
, PreferenceSpecificsToValue
) {
250 TestSpecificsToValue(PreferenceSpecificsToValue
);
253 TEST_F(ProtoValueConversionsTest
, SearchEngineSpecificsToValue
) {
254 TestSpecificsToValue(SearchEngineSpecificsToValue
);
257 TEST_F(ProtoValueConversionsTest
, SessionSpecificsToValue
) {
258 TestSpecificsToValue(SessionSpecificsToValue
);
261 TEST_F(ProtoValueConversionsTest
, SyncedNotificationAppInfoSpecificsToValue
) {
262 TestSpecificsToValue(SyncedNotificationAppInfoSpecificsToValue
);
265 TEST_F(ProtoValueConversionsTest
, SyncedNotificationSpecificsToValue
) {
266 TestSpecificsToValue(SyncedNotificationSpecificsToValue
);
269 TEST_F(ProtoValueConversionsTest
, ThemeSpecificsToValue
) {
270 TestSpecificsToValue(ThemeSpecificsToValue
);
273 TEST_F(ProtoValueConversionsTest
, TypedUrlSpecificsToValue
) {
274 TestSpecificsToValue(TypedUrlSpecificsToValue
);
277 TEST_F(ProtoValueConversionsTest
, DictionarySpecificsToValue
) {
278 TestSpecificsToValue(DictionarySpecificsToValue
);
281 TEST_F(ProtoValueConversionsTest
, ArticleSpecificsToValue
) {
282 TestSpecificsToValue(ArticleSpecificsToValue
);
285 TEST_F(ProtoValueConversionsTest
, WifiCredentialSpecificsToValue
) {
286 TestSpecificsToValue(WifiCredentialSpecificsToValue
);
289 // TODO(akalin): Figure out how to better test EntitySpecificsToValue.
291 TEST_F(ProtoValueConversionsTest
, EntitySpecificsToValue
) {
292 sync_pb::EntitySpecifics specifics
;
293 // Touch the extensions to make sure it shows up in the generated
295 #define SET_FIELD(key) (void)specifics.mutable_##key()
299 SET_FIELD(app_notification
);
300 SET_FIELD(app_setting
);
303 SET_FIELD(autofill_profile
);
305 SET_FIELD(device_info
);
306 SET_FIELD(dictionary
);
307 SET_FIELD(experiments
);
308 SET_FIELD(extension
);
309 SET_FIELD(extension_setting
);
310 SET_FIELD(favicon_image
);
311 SET_FIELD(favicon_tracking
);
312 SET_FIELD(history_delete_directive
);
313 SET_FIELD(managed_user_setting
);
314 SET_FIELD(managed_user_shared_setting
);
315 SET_FIELD(managed_user_whitelist
);
316 SET_FIELD(managed_user
);
319 SET_FIELD(preference
);
320 SET_FIELD(priority_preference
);
321 SET_FIELD(search_engine
);
323 SET_FIELD(synced_notification
);
324 SET_FIELD(synced_notification_app_info
);
326 SET_FIELD(typed_url
);
327 SET_FIELD(wifi_credential
);
328 SET_FIELD(autofill_wallet
);
329 SET_FIELD(wallet_metadata
);
333 scoped_ptr
<base::DictionaryValue
> value(EntitySpecificsToValue(specifics
));
334 EXPECT_EQ(MODEL_TYPE_COUNT
- FIRST_REAL_MODEL_TYPE
-
335 (LAST_PROXY_TYPE
- FIRST_PROXY_TYPE
+ 1),
336 static_cast<int>(value
->size()));
340 // Returns whether the given value has specifics under the entries in the given
342 bool ValueHasSpecifics(const base::DictionaryValue
& value
,
343 const std::string
& path
) {
344 const base::ListValue
* entities_list
= NULL
;
345 const base::DictionaryValue
* entry_dictionary
= NULL
;
346 const base::DictionaryValue
* specifics_dictionary
= NULL
;
348 if (!value
.GetList(path
, &entities_list
))
351 if (!entities_list
->GetDictionary(0, &entry_dictionary
))
354 return entry_dictionary
->GetDictionary("specifics",
355 &specifics_dictionary
);
359 // Create a ClientToServerMessage with an EntitySpecifics. Converting it to
360 // a value should respect the |include_specifics| flag.
361 TEST_F(ProtoValueConversionsTest
, ClientToServerMessageToValue
) {
362 sync_pb::ClientToServerMessage message
;
363 sync_pb::CommitMessage
* commit_message
= message
.mutable_commit();
364 sync_pb::SyncEntity
* entity
= commit_message
->add_entries();
365 entity
->mutable_specifics();
367 scoped_ptr
<base::DictionaryValue
> value_with_specifics(
368 ClientToServerMessageToValue(message
, true /* include_specifics */));
369 EXPECT_FALSE(value_with_specifics
->empty());
370 EXPECT_TRUE(ValueHasSpecifics(*(value_with_specifics
.get()),
373 scoped_ptr
<base::DictionaryValue
> value_without_specifics(
374 ClientToServerMessageToValue(message
, false /* include_specifics */));
375 EXPECT_FALSE(value_without_specifics
->empty());
376 EXPECT_FALSE(ValueHasSpecifics(*(value_without_specifics
.get()),
380 // Create a ClientToServerResponse with an EntitySpecifics. Converting it to
381 // a value should respect the |include_specifics| flag.
382 TEST_F(ProtoValueConversionsTest
, ClientToServerResponseToValue
) {
383 sync_pb::ClientToServerResponse message
;
384 sync_pb::GetUpdatesResponse
* response
= message
.mutable_get_updates();
385 sync_pb::SyncEntity
* entity
= response
->add_entries();
386 entity
->mutable_specifics();
388 scoped_ptr
<base::DictionaryValue
> value_with_specifics(
389 ClientToServerResponseToValue(message
, true /* include_specifics */));
390 EXPECT_FALSE(value_with_specifics
->empty());
391 EXPECT_TRUE(ValueHasSpecifics(*(value_with_specifics
.get()),
392 "get_updates.entries"));
394 scoped_ptr
<base::DictionaryValue
> value_without_specifics(
395 ClientToServerResponseToValue(message
, false /* include_specifics */));
396 EXPECT_FALSE(value_without_specifics
->empty());
397 EXPECT_FALSE(ValueHasSpecifics(*(value_without_specifics
.get()),
398 "get_updates.entries"));
401 TEST_F(ProtoValueConversionsTest
, AttachmentIdProtoToValue
) {
402 TestSpecificsToValue(AttachmentIdProtoToValue
);
406 } // namespace syncer