1 // Copyright 2014 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 #include "sync/test/fake_server/fake_server_verifier.h"
7 #include "base/json/json_writer.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/values.h"
10 #include "sync/internal_api/public/base/model_type.h"
11 #include "sync/test/fake_server/fake_server.h"
12 #include "sync/test/fake_server/sessions_hierarchy.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 using base::JSONWriter
;
17 using testing::AssertionFailure
;
18 using testing::AssertionResult
;
19 using testing::AssertionSuccess
;
21 namespace fake_server
{
25 AssertionResult
DictionaryCreationAssertionFailure() {
26 return AssertionFailure() << "FakeServer failed to create an entities "
30 AssertionResult
VerificationCountAssertionFailure(size_t actual_count
,
31 size_t expected_count
) {
32 return AssertionFailure() << "Actual count: " << actual_count
<< "; "
33 << "Expected count: " << expected_count
;
36 AssertionResult
UnknownTypeAssertionFailure(const string
& model_type
) {
37 return AssertionFailure() << "Verification not attempted. Unknown ModelType: "
41 AssertionResult
VerifySessionsHierarchyEquality(
42 const SessionsHierarchy
& expected
,
43 const SessionsHierarchy
& actual
) {
44 if (expected
.Equals(actual
))
45 return AssertionSuccess() << "Sessions hierarchies are equal.";
47 return AssertionFailure() << "Sessions hierarchies are not equal. "
48 << "FakeServer contents: " << actual
.ToString()
49 << "; Expected contents: " << expected
.ToString();
52 // Caller maintains ownership of |entities|.
53 string
ConvertFakeServerContentsToString(
54 const base::DictionaryValue
& entities
) {
56 if (!JSONWriter::WriteWithOptions(&entities
,
57 JSONWriter::OPTIONS_PRETTY_PRINT
,
59 entities_str
= "Could not convert FakeServer contents to string.";
61 return "FakeServer contents:\n" + entities_str
;
66 FakeServerVerifier::FakeServerVerifier(FakeServer
* fake_server
)
67 : fake_server_(fake_server
) { }
69 FakeServerVerifier::~FakeServerVerifier() {}
71 AssertionResult
FakeServerVerifier::VerifyEntityCountByType(
72 size_t expected_count
,
73 syncer::ModelType model_type
) const {
74 scoped_ptr
<base::DictionaryValue
> entities
=
75 fake_server_
->GetEntitiesAsDictionaryValue();
76 if (!entities
.get()) {
77 return DictionaryCreationAssertionFailure();
80 string model_type_string
= ModelTypeToString(model_type
);
81 base::ListValue
* entity_list
= NULL
;
82 if (!entities
->GetList(model_type_string
, &entity_list
)) {
83 return UnknownTypeAssertionFailure(model_type_string
);
84 } else if (expected_count
!= entity_list
->GetSize()) {
85 return VerificationCountAssertionFailure(entity_list
->GetSize(),
88 << ConvertFakeServerContentsToString(*entities
);
91 return AssertionSuccess();
94 AssertionResult
FakeServerVerifier::VerifyEntityCountByTypeAndName(
95 size_t expected_count
,
96 syncer::ModelType model_type
,
97 const string
& name
) const {
98 scoped_ptr
<base::DictionaryValue
> entities
=
99 fake_server_
->GetEntitiesAsDictionaryValue();
100 if (!entities
.get()) {
101 return DictionaryCreationAssertionFailure();
104 string model_type_string
= ModelTypeToString(model_type
);
105 base::ListValue
* entity_list
= NULL
;
106 size_t actual_count
= 0;
107 if (entities
->GetList(model_type_string
, &entity_list
)) {
108 scoped_ptr
<base::Value
> name_value(new base::StringValue(name
));
109 for (base::ListValue::const_iterator it
= entity_list
->begin();
110 it
!= entity_list
->end(); ++it
) {
111 if (name_value
->Equals(*it
)) {
118 return UnknownTypeAssertionFailure(model_type_string
);
119 } else if (actual_count
!= expected_count
) {
120 return VerificationCountAssertionFailure(actual_count
, expected_count
)
124 << ConvertFakeServerContentsToString(*entities
);
127 return AssertionSuccess();
130 AssertionResult
FakeServerVerifier::VerifySessions(
131 const SessionsHierarchy
& expected_sessions
) {
132 std::vector
<sync_pb::SyncEntity
> sessions
=
133 fake_server_
->GetSyncEntitiesByModelType(syncer::SESSIONS
);
134 // Look for the sessions entity containing a SessionHeader and cache all tab
135 // IDs/URLs. These will be used later to construct a SessionsHierarchy.
136 sync_pb::SessionHeader session_header
;
137 std::map
<int, int> tab_ids_to_window_ids
;
138 std::map
<int, std::string
> tab_ids_to_urls
;
139 std::string session_tag
;
140 for (std::vector
<sync_pb::SyncEntity
>::const_iterator it
= sessions
.begin();
141 it
!= sessions
.end(); ++it
) {
142 sync_pb::SyncEntity entity
= *it
;
143 sync_pb::SessionSpecifics session_specifics
= entity
.specifics().session();
145 // Ensure that all session tags match the first entity. Only one session is
146 // supported for verification at this time.
147 if (it
== sessions
.begin())
148 session_tag
= session_specifics
.session_tag();
149 else if (session_specifics
.session_tag() != session_tag
)
150 return AssertionFailure() << "Multiple session tags found.";
152 if (session_specifics
.has_header()) {
153 session_header
= session_specifics
.header();
154 } else if (session_specifics
.has_tab()) {
155 sync_pb::SessionTab tab
= session_specifics
.tab();
156 tab_ids_to_window_ids
[tab
.tab_id()] = tab
.window_id();
157 tab_ids_to_urls
[tab
.tab_id()] =
158 tab
.navigation(tab
.current_navigation_index()).virtual_url();
162 // Create a SessionsHierarchy from the cached SyncEntity data. This loop over
163 // the SessionHeader also ensures its data corresponds to the data stored in
165 SessionsHierarchy actual_sessions
;
166 ::google::protobuf::RepeatedPtrField
<sync_pb::SessionWindow
>::const_iterator
168 for (window_it
= session_header
.window().begin();
169 window_it
!= session_header
.window().end(); ++window_it
) {
170 sync_pb::SessionWindow window
= *window_it
;
171 std::multiset
<std::string
> tab_urls
;
172 ::google::protobuf::RepeatedField
<int>::const_iterator tab_it
;
173 for (tab_it
= window
.tab().begin(); tab_it
!= window
.tab().end();
175 int tab_id
= *tab_it
;
176 if (tab_ids_to_window_ids
.find(tab_id
) == tab_ids_to_window_ids
.end()) {
177 return AssertionFailure() << "Malformed data: Tab entity not found.";
179 tab_urls
.insert(tab_ids_to_urls
[tab_id
]);
181 actual_sessions
.AddWindow(tab_urls
);
183 return VerifySessionsHierarchyEquality(expected_sessions
, actual_sessions
);
186 } // namespace fake_server