| 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 |