Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / supervised_user / supervised_user_bookmarks_handler_unittest.cc
blobd259cf7766b0151a1bf260e663fd5c5af3548721
1 // Copyright 2015 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 <iostream>
6 #include <map>
7 #include <string>
8 #include <vector>
10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/values.h"
14 #include "chrome/browser/supervised_user/supervised_user_bookmarks_handler.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 using Folder = SupervisedUserBookmarksHandler::Folder;
18 using Link = SupervisedUserBookmarksHandler::Link;
20 namespace {
22 typedef std::pair<std::string, std::string> Setting;
24 // Settings representing the following tree:
25 // |--Folder1
26 // |--SubFolder
27 // |--Empty SubSubFolder
28 // |--Google(google.com)
29 // |--(www.theoatmeal.com)
30 // |--Test(www.test.de)
31 // |--Empty Folder
32 // |--XKCD(m.xkcd.com)
34 // Folder setting format: "<ID>", "<ParentID>:<Name>"
35 const Setting FOLDER_SETTINGS[] = {
36 Setting("5", "0:Folder1"),
37 Setting("9", "0:Empty Folder"),
38 Setting("3", "5:SubFolder"),
39 Setting("4", "3:Empty SubSubFolder"),
42 const Setting FOLDER_SETTINGS_INVALID_PARENT[] = {
43 Setting("5", "0:Folder1"),
44 Setting("9", "7:Empty Folder"), // Invalid parent id.
45 Setting("3", "5:SubFolder"),
46 Setting("4", "3:Empty SubSubFolder"),
49 const Setting FOLDER_SETTINGS_CIRCLE[] = {
50 Setting("5", "3:Folder1"),
51 Setting("9", "5:Empty Folder"),
52 Setting("3", "9:SubFolder"),
55 // Link setting format: "<ID>:<URL>", "<ParentID>:<Name>"
56 const Setting LINK_SETTINGS[] = {
57 Setting("4:www.theoatmeal.com", "3:"),
58 Setting("1:m.xkcd.com", "0:XKCD"),
59 Setting("2:www.test.de", "5:Test"),
60 Setting("3:google.com", "3:Google"),
63 const Setting LINK_SETTINGS_INVALID_PARENT[] = {
64 Setting("4:www.theoatmeal.com", "3:"),
65 Setting("1:m.xkcd.com", "7:XKCD"), // Invalid parent id.
66 Setting("2:www.test.de", "8:Test"), // Invalid parent id.
69 // Parsed data is sorted by ID (even though the parsed links don't actually
70 // contain their IDs!)
72 const Folder PARSED_FOLDERS[] = {
73 Folder(3, "SubFolder", 5), // Note: Forward reference.
74 Folder(4, "Empty SubSubFolder", 3),
75 Folder(5, "Folder1", 0),
76 Folder(9, "Empty Folder", 0),
79 const Link PARSED_LINKS[] = {
80 Link("m.xkcd.com", "XKCD", 0),
81 Link("www.test.de", "Test", 5),
82 Link("google.com", "Google", 3),
83 Link("www.theoatmeal.com", std::string(), 3),
86 const char BOOKMARKS_TREE_JSON[] =
87 "["
88 " {"
89 " \"id\":5,"
90 " \"name\":\"Folder1\","
91 " \"children\":["
92 " {"
93 " \"id\":3,"
94 " \"name\":\"SubFolder\","
95 " \"children\":["
96 " {"
97 " \"id\":4,"
98 " \"name\":\"Empty SubSubFolder\","
99 " \"children\":[]"
100 " },"
101 " {"
102 " \"name\":\"Google\","
103 " \"url\":\"http://google.com/\""
104 " },"
105 " {"
106 " \"name\":\"\","
107 " \"url\":\"http://www.theoatmeal.com/\""
108 " }"
109 " ]"
110 " },"
111 " {"
112 " \"name\":\"Test\","
113 " \"url\":\"http://www.test.de/\""
114 " }"
115 " ]"
116 " },"
117 " {"
118 " \"id\":9,"
119 " \"name\":\"Empty Folder\","
120 " \"children\":[]"
121 " },"
122 " {"
123 " \"name\":\"XKCD\","
124 " \"url\":\"http://m.xkcd.com/\""
125 " }"
126 "]";
128 const char BOOKMARKS_TREE_INVALID_PARENTS_JSON[] =
130 " {"
131 " \"id\":5,"
132 " \"name\":\"Folder1\","
133 " \"children\":["
134 " {"
135 " \"id\":3,"
136 " \"name\":\"SubFolder\","
137 " \"children\":["
138 " {"
139 " \"id\":4,"
140 " \"name\":\"Empty SubSubFolder\","
141 " \"children\":[]"
142 " },"
143 " {"
144 " \"name\":\"\","
145 " \"url\":\"http://www.theoatmeal.com/\""
146 " }"
147 " ]"
148 " }"
149 " ]"
150 " }"
151 "]";
153 // Builds the base::Values tree from a json string above.
154 scoped_ptr<base::ListValue> CreateTree(const char* json) {
155 base::Value* value = base::JSONReader::DeprecatedRead(json);
156 EXPECT_NE(value, nullptr);
157 base::ListValue* list;
158 EXPECT_TRUE(value->GetAsList(&list));
159 return make_scoped_ptr(list);
162 scoped_ptr<base::ListValue> CreateBookmarksTree() {
163 return CreateTree(BOOKMARKS_TREE_JSON);
166 scoped_ptr<base::ListValue> CreateBookmarksTreeWithInvalidParents() {
167 return CreateTree(BOOKMARKS_TREE_INVALID_PARENTS_JSON);
170 } // namespace
172 static bool operator==(const Folder& f1, const Folder& f2) {
173 return f1.id == f2.id && f1.name == f2.name && f1.parent_id == f2.parent_id;
176 static bool operator==(const Link& l1, const Link& l2) {
177 return l1.url == l2.url && l1.name == l2.name && l1.parent_id == l2.parent_id;
180 std::ostream& operator<<(std::ostream& str, const Folder& folder) {
181 str << folder.id << " " << folder.name << " " << folder.parent_id;
182 return str;
185 std::ostream& operator<<(std::ostream& str, const Link& link) {
186 str << link.url << " " << link.name << " " << link.parent_id;
187 return str;
190 class SupervisedUserBookmarksHandlerTest : public ::testing::Test {
191 protected:
192 static base::DictionaryValue* CreateSettings(base::DictionaryValue* links,
193 base::DictionaryValue* folders) {
194 base::DictionaryValue* settings = new base::DictionaryValue;
195 settings->SetStringWithoutPathExpansion("some_setting", "bleh");
196 settings->SetWithoutPathExpansion("SupervisedBookmarkLink", links);
197 settings->SetStringWithoutPathExpansion("some_other_setting", "foo");
198 settings->SetWithoutPathExpansion("SupervisedBookmarkFolder", folders);
199 settings->SetStringWithoutPathExpansion("another_one", "blurb");
200 return settings;
203 static base::DictionaryValue* CreateDictionary(const Setting* begin,
204 const Setting* end) {
205 base::DictionaryValue* dict = new base::DictionaryValue;
206 for (const Setting* setting = begin; setting != end; ++setting)
207 dict->SetStringWithoutPathExpansion(setting->first, setting->second);
208 return dict;
211 static base::DictionaryValue* CreateLinkDictionary() {
212 return CreateDictionary(LINK_SETTINGS,
213 LINK_SETTINGS + arraysize(LINK_SETTINGS));
216 static base::DictionaryValue* CreateLinkDictionaryWithInvalidParents() {
217 return CreateDictionary(
218 LINK_SETTINGS_INVALID_PARENT,
219 LINK_SETTINGS_INVALID_PARENT + arraysize(LINK_SETTINGS_INVALID_PARENT));
222 static base::DictionaryValue* CreateFolderDictionary() {
223 return CreateDictionary(FOLDER_SETTINGS,
224 FOLDER_SETTINGS + arraysize(FOLDER_SETTINGS));
227 static base::DictionaryValue* CreateFolderDictionaryWithInvalidParents() {
228 return CreateDictionary(
229 FOLDER_SETTINGS_INVALID_PARENT,
230 FOLDER_SETTINGS_INVALID_PARENT +
231 arraysize(FOLDER_SETTINGS_INVALID_PARENT));
234 static base::DictionaryValue* CreateFolderDictionaryWithCircle() {
235 return CreateDictionary(
236 FOLDER_SETTINGS_CIRCLE,
237 FOLDER_SETTINGS_CIRCLE + arraysize(FOLDER_SETTINGS_CIRCLE));
240 void ParseFolders(const base::DictionaryValue& folders) {
241 deserializer_.ParseFolders(folders);
244 void ParseLinks(const base::DictionaryValue& links) {
245 deserializer_.ParseLinks(links);
248 const std::vector<Folder>& GetFolders() const {
249 return deserializer_.folders_for_testing();
252 const std::vector<Link>& GetLinks() const {
253 return deserializer_.links_for_testing();
256 private:
257 SupervisedUserBookmarksHandler deserializer_;
260 TEST_F(SupervisedUserBookmarksHandlerTest, ParseSettings) {
261 scoped_ptr<base::DictionaryValue> link_dictionary(CreateLinkDictionary());
262 scoped_ptr<base::DictionaryValue> folder_dictionary(CreateFolderDictionary());
264 ParseLinks(*link_dictionary.get());
265 ParseFolders(*folder_dictionary.get());
267 const std::vector<Link>& links = GetLinks();
268 EXPECT_EQ(arraysize(PARSED_LINKS), links.size());
269 for (size_t i = 0; i < links.size(); ++i)
270 EXPECT_EQ(PARSED_LINKS[i], links[i]);
272 const std::vector<Folder>& folders = GetFolders();
273 EXPECT_EQ(arraysize(PARSED_FOLDERS), folders.size());
274 for (size_t i = 0; i < folders.size(); ++i)
275 EXPECT_EQ(PARSED_FOLDERS[i], folders[i]);
278 TEST_F(SupervisedUserBookmarksHandlerTest, BuildBookmarksTree) {
279 // Make some fake settings.
280 scoped_ptr<base::DictionaryValue> settings(
281 CreateSettings(CreateLinkDictionary(), CreateFolderDictionary()));
282 // Parse the settings into a bookmarks tree.
283 scoped_ptr<base::ListValue> bookmarks(
284 SupervisedUserBookmarksHandler::BuildBookmarksTree(*settings.get()));
286 // Check that the parsed tree matches the expected tree constructed directly
287 // from the hardcoded json above.
288 scoped_ptr<base::ListValue> expected_bookmarks(CreateBookmarksTree());
289 EXPECT_TRUE(bookmarks->Equals(expected_bookmarks.get()));
292 TEST_F(SupervisedUserBookmarksHandlerTest,
293 BuildBookmarksTreeWithInvalidParents) {
294 // Make some fake settings, including some entries with invalid parent
295 // references.
296 scoped_ptr<base::DictionaryValue> settings(
297 CreateSettings(CreateLinkDictionaryWithInvalidParents(),
298 CreateFolderDictionaryWithInvalidParents()));
299 // Parse the settings into a bookmarks tree.
300 scoped_ptr<base::ListValue> bookmarks(
301 SupervisedUserBookmarksHandler::BuildBookmarksTree(*settings.get()));
303 // Check that the parsed tree matches the expected tree constructed directly
304 // from the hardcoded json above (which does not contain the entries with
305 // invalid parents!).
306 scoped_ptr<base::ListValue> expected_bookmarks(
307 CreateBookmarksTreeWithInvalidParents());
308 EXPECT_TRUE(bookmarks->Equals(expected_bookmarks.get()));
311 TEST_F(SupervisedUserBookmarksHandlerTest, Circle) {
312 // Make some fake settings which include a circular reference in the folders.
313 scoped_ptr<base::DictionaryValue> settings(
314 CreateSettings(CreateLinkDictionary(),
315 CreateFolderDictionaryWithCircle()));
316 scoped_ptr<base::ListValue> bookmarks(
317 SupervisedUserBookmarksHandler::BuildBookmarksTree(*settings.get()));
318 // Don't care what exactly the result looks like, just that we don't run into
319 // an endless loop.