OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "sync/test/fake_server/fake_server_verifier.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include <map> | |
10 #include <memory> | |
11 #include <set> | |
12 #include <vector> | |
13 | |
14 #include "base/json/json_writer.h" | |
15 #include "base/values.h" | |
16 #include "sync/internal_api/public/base/model_type.h" | |
17 #include "sync/test/fake_server/fake_server.h" | |
18 #include "sync/test/fake_server/sessions_hierarchy.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | |
20 | |
21 using base::JSONWriter; | |
22 using std::string; | |
23 using testing::AssertionFailure; | |
24 using testing::AssertionResult; | |
25 using testing::AssertionSuccess; | |
26 | |
27 namespace fake_server { | |
28 | |
29 namespace { | |
30 | |
31 AssertionResult DictionaryCreationAssertionFailure() { | |
32 return AssertionFailure() << "FakeServer failed to create an entities " | |
33 << "dictionary."; | |
34 } | |
35 | |
36 AssertionResult VerificationCountAssertionFailure(size_t actual_count, | |
37 size_t expected_count) { | |
38 return AssertionFailure() << "Actual count: " << actual_count << "; " | |
39 << "Expected count: " << expected_count; | |
40 } | |
41 | |
42 AssertionResult UnknownTypeAssertionFailure(const string& model_type) { | |
43 return AssertionFailure() << "Verification not attempted. Unknown ModelType: " | |
44 << model_type; | |
45 } | |
46 | |
47 AssertionResult VerifySessionsHierarchyEquality( | |
48 const SessionsHierarchy& expected, | |
49 const SessionsHierarchy& actual) { | |
50 if (expected.Equals(actual)) | |
51 return AssertionSuccess() << "Sessions hierarchies are equal."; | |
52 | |
53 return AssertionFailure() << "Sessions hierarchies are not equal. " | |
54 << "FakeServer contents: " << actual.ToString() | |
55 << "; Expected contents: " << expected.ToString(); | |
56 } | |
57 | |
58 // Caller maintains ownership of |entities|. | |
59 string ConvertFakeServerContentsToString( | |
60 const base::DictionaryValue& entities) { | |
61 string entities_str; | |
62 if (!JSONWriter::WriteWithOptions(entities, JSONWriter::OPTIONS_PRETTY_PRINT, | |
63 &entities_str)) { | |
64 entities_str = "Could not convert FakeServer contents to string."; | |
65 } | |
66 return "FakeServer contents:\n" + entities_str; | |
67 } | |
68 | |
69 } // namespace | |
70 | |
71 FakeServerVerifier::FakeServerVerifier(FakeServer* fake_server) | |
72 : fake_server_(fake_server) { } | |
73 | |
74 FakeServerVerifier::~FakeServerVerifier() {} | |
75 | |
76 AssertionResult FakeServerVerifier::VerifyEntityCountByType( | |
77 size_t expected_count, | |
78 syncer::ModelType model_type) const { | |
79 std::unique_ptr<base::DictionaryValue> entities = | |
80 fake_server_->GetEntitiesAsDictionaryValue(); | |
81 if (!entities.get()) { | |
82 return DictionaryCreationAssertionFailure(); | |
83 } | |
84 | |
85 string model_type_string = ModelTypeToString(model_type); | |
86 base::ListValue* entity_list = NULL; | |
87 if (!entities->GetList(model_type_string, &entity_list)) { | |
88 return UnknownTypeAssertionFailure(model_type_string); | |
89 } else if (expected_count != entity_list->GetSize()) { | |
90 return VerificationCountAssertionFailure(entity_list->GetSize(), | |
91 expected_count) | |
92 << "\n\n" | |
93 << ConvertFakeServerContentsToString(*entities); | |
94 } | |
95 | |
96 return AssertionSuccess(); | |
97 } | |
98 | |
99 AssertionResult FakeServerVerifier::VerifyEntityCountByTypeAndName( | |
100 size_t expected_count, | |
101 syncer::ModelType model_type, | |
102 const string& name) const { | |
103 std::unique_ptr<base::DictionaryValue> entities = | |
104 fake_server_->GetEntitiesAsDictionaryValue(); | |
105 if (!entities.get()) { | |
106 return DictionaryCreationAssertionFailure(); | |
107 } | |
108 | |
109 string model_type_string = ModelTypeToString(model_type); | |
110 base::ListValue* entity_list = NULL; | |
111 size_t actual_count = 0; | |
112 if (entities->GetList(model_type_string, &entity_list)) { | |
113 base::StringValue name_value(name); | |
114 for (const auto& entity : *entity_list) { | |
115 if (name_value.Equals(entity.get())) | |
116 actual_count++; | |
117 } | |
118 } | |
119 | |
120 if (!entity_list) { | |
121 return UnknownTypeAssertionFailure(model_type_string); | |
122 } else if (actual_count != expected_count) { | |
123 return VerificationCountAssertionFailure(actual_count, expected_count) | |
124 << "; Name: " | |
125 << name | |
126 << "\n\n" | |
127 << ConvertFakeServerContentsToString(*entities); | |
128 } | |
129 | |
130 return AssertionSuccess(); | |
131 } | |
132 | |
133 AssertionResult FakeServerVerifier::VerifySessions( | |
134 const SessionsHierarchy& expected_sessions) { | |
135 std::vector<sync_pb::SyncEntity> sessions = | |
136 fake_server_->GetSyncEntitiesByModelType(syncer::SESSIONS); | |
137 // Look for the sessions entity containing a SessionHeader and cache all tab | |
138 // IDs/URLs. These will be used later to construct a SessionsHierarchy. | |
139 sync_pb::SessionHeader session_header; | |
140 std::map<int, int> tab_ids_to_window_ids; | |
141 std::map<int, std::string> tab_ids_to_urls; | |
142 std::string session_tag; | |
143 for (std::vector<sync_pb::SyncEntity>::const_iterator it = sessions.begin(); | |
144 it != sessions.end(); ++it) { | |
145 sync_pb::SyncEntity entity = *it; | |
146 sync_pb::SessionSpecifics session_specifics = entity.specifics().session(); | |
147 | |
148 // Ensure that all session tags match the first entity. Only one session is | |
149 // supported for verification at this time. | |
150 if (it == sessions.begin()) | |
151 session_tag = session_specifics.session_tag(); | |
152 else if (session_specifics.session_tag() != session_tag) | |
153 return AssertionFailure() << "Multiple session tags found."; | |
154 | |
155 if (session_specifics.has_header()) { | |
156 session_header = session_specifics.header(); | |
157 } else if (session_specifics.has_tab()) { | |
158 sync_pb::SessionTab tab = session_specifics.tab(); | |
159 tab_ids_to_window_ids[tab.tab_id()] = tab.window_id(); | |
160 tab_ids_to_urls[tab.tab_id()] = | |
161 tab.navigation(tab.current_navigation_index()).virtual_url(); | |
162 } | |
163 } | |
164 | |
165 // Create a SessionsHierarchy from the cached SyncEntity data. This loop over | |
166 // the SessionHeader also ensures its data corresponds to the data stored in | |
167 // each SessionTab. | |
168 SessionsHierarchy actual_sessions; | |
169 ::google::protobuf::RepeatedPtrField<sync_pb::SessionWindow>::const_iterator | |
170 window_it; | |
171 for (window_it = session_header.window().begin(); | |
172 window_it != session_header.window().end(); ++window_it) { | |
173 sync_pb::SessionWindow window = *window_it; | |
174 std::multiset<std::string> tab_urls; | |
175 ::google::protobuf::RepeatedField<int>::const_iterator tab_it; | |
176 for (tab_it = window.tab().begin(); tab_it != window.tab().end(); | |
177 ++tab_it) { | |
178 int tab_id = *tab_it; | |
179 if (tab_ids_to_window_ids.find(tab_id) == tab_ids_to_window_ids.end()) { | |
180 return AssertionFailure() << "Malformed data: Tab entity not found."; | |
181 } | |
182 tab_urls.insert(tab_ids_to_urls[tab_id]); | |
183 } | |
184 actual_sessions.AddWindow(tab_urls); | |
185 } | |
186 return VerifySessionsHierarchyEquality(expected_sessions, actual_sessions); | |
187 } | |
188 | |
189 } // namespace fake_server | |
OLD | NEW |