OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 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 // TODO(rickcam): Bug 73183: Add unit tests for image loading | |
6 | |
7 #include <algorithm> | |
8 #include <cstdlib> | |
9 #include <map> | |
10 #include <set> | |
11 #include <vector> | |
12 | |
13 #include "chrome/browser/background_application_list_model.h" | |
14 | |
15 #include "base/command_line.h" | |
16 #include "base/file_path.h" | |
17 #include "base/file_util.h" | |
18 #include "base/message_loop.h" | |
19 #include "base/scoped_ptr.h" | |
20 #include "base/stl_util-inl.h" | |
21 #include "chrome/browser/browser_thread.h" | |
22 #include "chrome/browser/extensions/extension_service.h" | |
23 #include "chrome/common/extensions/extension.h" | |
24 #include "chrome/common/notification_registrar.h" | |
25 #include "chrome/common/notification_service.h" | |
26 #include "chrome/common/notification_type.h" | |
27 #include "chrome/test/testing_profile.h" | |
28 #include "testing/gtest/include/gtest/gtest.h" | |
29 | |
30 // This value is used to seed the PRNG at the beginning of a sequence of | |
31 // operations to produce a repeatable sequence. | |
32 #define RANDOM_SEED (0x33F7A7A7) | |
33 | |
34 // For ExtensionService interface when it requires a path that is not used. | |
35 FilePath bogus_file_path() { | |
36 #if defined(OS_WIN) | |
37 return FilePath(FILE_PATH_LITERAL("c:\\foo")); | |
Andrew T Wilson (Slow)
2011/02/16 18:45:46
To avoid having platform-dependent code here, can
The wrong rickcam account
2011/02/16 22:39:20
It must be absolute to avoid "Check failed: path.I
| |
38 #elif defined(OS_POSIX) | |
39 return FilePath(FILE_PATH_LITERAL("/foo")); | |
40 #endif | |
41 } | |
42 | |
43 class BackgroundApplicationListModelTest : public testing::Test { | |
44 public: | |
45 BackgroundApplicationListModelTest(); | |
46 ~BackgroundApplicationListModelTest(); | |
47 | |
48 virtual void InitializeEmptyExtensionService(); | |
49 | |
50 protected: | |
51 scoped_ptr<Profile> profile_; | |
52 scoped_refptr<ExtensionService> service_; | |
53 MessageLoop loop_; | |
54 BrowserThread ui_thread_; | |
55 }; | |
56 | |
57 // The message loop may be used in tests which require it to be an IO loop. | |
58 BackgroundApplicationListModelTest::BackgroundApplicationListModelTest() | |
59 : loop_(MessageLoop::TYPE_IO), | |
60 ui_thread_(BrowserThread::UI, &loop_) { | |
61 } | |
62 | |
63 BackgroundApplicationListModelTest::~BackgroundApplicationListModelTest() { | |
64 // Drop reference to ExtensionService and TestingProfile, so that they can be | |
65 // destroyed while BrowserThreads and MessageLoop are still around. They | |
66 // are used in the destruction process. | |
67 service_ = NULL; | |
68 profile_.reset(NULL); | |
69 MessageLoop::current()->RunAllPending(); | |
70 } | |
71 | |
72 // This is modeled on a similar routine in ExtensionServiceTestBase. | |
73 void BackgroundApplicationListModelTest::InitializeEmptyExtensionService() { | |
74 TestingProfile* profile = new TestingProfile(); | |
75 profile_.reset(profile); | |
76 service_ = profile->CreateExtensionService( | |
77 CommandLine::ForCurrentProcess(), | |
78 bogus_file_path()); | |
79 service_->set_extensions_enabled(true); | |
80 service_->set_show_extensions_prompts(false); | |
81 service_->OnLoadedInstalledExtensions(); /* Sends EXTENSIONS_READY */ | |
82 } | |
83 | |
84 // Returns a barebones test Extension object with the specified |name|. The | |
85 // returned extension will include background permission iff | |
86 // |background_permission| is true. | |
87 static scoped_refptr<Extension> CreateExtension(const std::string& name, | |
88 bool background_permission) { | |
89 DictionaryValue manifest; | |
90 manifest.SetString(extension_manifest_keys::kVersion, "1.0.0.0"); | |
91 manifest.SetString(extension_manifest_keys::kName, name); | |
92 if (background_permission) { | |
93 ListValue* permissions = new ListValue(); | |
94 manifest.Set(extension_manifest_keys::kPermissions, permissions); | |
95 permissions->Append(Value::CreateStringValue("background")); | |
96 } | |
97 std::string error; | |
98 scoped_refptr<Extension> extension = Extension::Create( | |
99 bogus_file_path().AppendASCII(name), Extension::INVALID, manifest, false, | |
100 &error); | |
101 EXPECT_TRUE(extension) << error; | |
Andrew T Wilson (Slow)
2011/02/16 18:45:46
Use an ASSERT here rather than EXPECT since you wa
The wrong rickcam account
2011/02/16 22:39:20
As discussed with you, I'm going to leave the code
| |
102 return extension; | |
103 } | |
104 | |
105 // With minimal test logic, verifies behavior over an explicit set of | |
106 // extensions, of which some are Background Apps and others are not. | |
107 TEST_F(BackgroundApplicationListModelTest, LoadExplicitExtensions) { | |
108 InitializeEmptyExtensionService(); | |
109 ExtensionService* service = profile_->GetExtensionService(); | |
110 ASSERT_TRUE(service); | |
111 ASSERT_TRUE(service->is_ready()); | |
112 ASSERT_TRUE(service->extensions()); | |
113 ASSERT_TRUE(service->extensions()->empty()); | |
114 scoped_ptr<BackgroundApplicationListModel> model( | |
115 new BackgroundApplicationListModel(profile_.get())); | |
116 ASSERT_FALSE(model->size()); | |
Andrew T Wilson (Slow)
2011/02/16 18:45:46
It's more readable and generates better error outp
The wrong rickcam account
2011/02/16 22:39:20
Done, but with 0U as size() returns an unsigned in
| |
117 | |
118 scoped_refptr<Extension> ext1 = CreateExtension("alpha", false); | |
119 scoped_refptr<Extension> ext2 = CreateExtension("bravo", false); | |
120 scoped_refptr<Extension> ext3 = CreateExtension("charlie", false); | |
121 scoped_refptr<Extension> bgapp1 = CreateExtension("delta", true); | |
122 scoped_refptr<Extension> bgapp2 = CreateExtension("echo", true); | |
123 ASSERT_TRUE(service->extensions()); | |
124 ASSERT_FALSE(service->extensions()->size()); | |
125 ASSERT_TRUE(model->size() == 0); | |
Andrew T Wilson (Slow)
2011/02/16 18:45:46
Use ASSERT_EQ here and elsewhere in the routine wh
The wrong rickcam account
2011/02/16 22:39:20
Done.
| |
126 // Add alternating Extensions and Background Apps | |
127 ASSERT_FALSE(BackgroundApplicationListModel::IsBackgroundApp(*ext1)); | |
128 service->AddExtension(ext1); | |
129 ASSERT_TRUE(service->extensions()->size() == 1); | |
130 ASSERT_TRUE(model->size() == 0); | |
131 ASSERT_TRUE(BackgroundApplicationListModel::IsBackgroundApp(*bgapp1)); | |
132 service->AddExtension(bgapp1); | |
133 ASSERT_TRUE(service->extensions()->size() == 2); | |
134 ASSERT_TRUE(model->size() == 1); | |
135 ASSERT_FALSE(BackgroundApplicationListModel::IsBackgroundApp(*ext2)); | |
136 service->AddExtension(ext2); | |
137 ASSERT_TRUE(service->extensions()->size() == 3); | |
138 ASSERT_TRUE(model->size() == 1); | |
139 ASSERT_TRUE(BackgroundApplicationListModel::IsBackgroundApp(*bgapp2)); | |
140 service->AddExtension(bgapp2); | |
141 ASSERT_TRUE(service->extensions()->size() == 4); | |
142 ASSERT_TRUE(model->size() == 2); | |
143 ASSERT_FALSE(BackgroundApplicationListModel::IsBackgroundApp(*ext3)); | |
144 service->AddExtension(ext3); | |
145 ASSERT_TRUE(service->extensions()->size() == 5); | |
146 ASSERT_TRUE(model->size() == 2); | |
147 // Remove in FIFO order. | |
148 ASSERT_FALSE(BackgroundApplicationListModel::IsBackgroundApp(*ext1)); | |
149 service->UninstallExtension(ext1->id(), false); | |
150 ASSERT_TRUE(service->extensions()->size() == 4); | |
151 ASSERT_TRUE(model->size() == 2); | |
152 ASSERT_TRUE(BackgroundApplicationListModel::IsBackgroundApp(*bgapp1)); | |
153 service->UninstallExtension(bgapp1->id(), false); | |
154 ASSERT_TRUE(service->extensions()->size() == 3); | |
155 ASSERT_TRUE(model->size() == 1); | |
156 ASSERT_FALSE(BackgroundApplicationListModel::IsBackgroundApp(*ext2)); | |
157 service->UninstallExtension(ext2->id(), false); | |
158 ASSERT_TRUE(service->extensions()->size() == 2); | |
159 ASSERT_TRUE(model->size() == 1); | |
160 ASSERT_TRUE(BackgroundApplicationListModel::IsBackgroundApp(*bgapp2)); | |
161 service->UninstallExtension(bgapp2->id(), false); | |
162 ASSERT_TRUE(service->extensions()->size() == 1); | |
163 ASSERT_TRUE(model->size() == 0); | |
164 ASSERT_FALSE(BackgroundApplicationListModel::IsBackgroundApp(*ext3)); | |
165 service->UninstallExtension(ext3->id(), false); | |
166 ASSERT_TRUE(service->extensions()->size() == 0); | |
167 ASSERT_TRUE(model->size() == 0); | |
168 } | |
169 | |
170 typedef std::map<std::string,scoped_refptr<Extension> > ExtensionTable; | |
Andrew T Wilson (Slow)
2011/02/16 18:45:46
Do you really need a map here? I don't think you a
The wrong rickcam account
2011/02/16 22:39:20
Done.
| |
171 | |
172 namespace { | |
173 std::string | |
174 GenerateRandomExtensionName() { | |
Andrew T Wilson (Slow)
2011/02/16 18:45:46
put return type and function name on same line.
The wrong rickcam account
2011/02/16 22:39:20
Done. FWIW, this is leftover from previous style
| |
175 static const char VALID[] = "ABCDEFGHIHJKMNOPabcdefghihjkmnop0123456789 "; | |
Andrew T Wilson (Slow)
2011/02/16 18:45:46
Should you put some non-ascii chars in here (unico
The wrong rickcam account
2011/02/16 22:39:20
No, but I need to change this! Your question made
| |
176 static const unsigned int VALID_COUNT = sizeof(VALID) - 1; | |
177 static const unsigned int MINIMUM_NAME_LENGTH = 10; | |
178 static const unsigned int MAXIMUM_NAME_LENGTH = 30; | |
179 | |
180 unsigned int length = MINIMUM_NAME_LENGTH + | |
181 random() % (MAXIMUM_NAME_LENGTH - MINIMUM_NAME_LENGTH); | |
182 char* characters = new char[length]; | |
183 for (unsigned int index = 0; index < length; ++index) | |
184 characters[index] = VALID[random() % VALID_COUNT]; | |
185 return std::string(characters, length); | |
186 } | |
187 } | |
188 | |
189 // Verifies behavior with a pseudo-randomly generated set of actions: Adding and | |
190 // removing extensions, of which some are Background Apps and others are not. | |
191 TEST_F(BackgroundApplicationListModelTest, LoadRandomExtension) { | |
192 InitializeEmptyExtensionService(); | |
193 ExtensionService* service = profile_->GetExtensionService(); | |
194 ASSERT_TRUE(service); | |
195 ASSERT_TRUE(service->is_ready()); | |
196 ASSERT_TRUE(service->extensions()); | |
197 ASSERT_TRUE(service->extensions()->empty()); | |
198 scoped_ptr<BackgroundApplicationListModel> model( | |
199 new BackgroundApplicationListModel(profile_.get())); | |
200 ASSERT_FALSE(model->size()); | |
201 | |
202 static const unsigned int iterations = 500; | |
Andrew T Wilson (Slow)
2011/02/16 18:45:46
nit: I think the style for contstants is of the fo
The wrong rickcam account
2011/02/16 22:39:20
Done.
| |
203 ExtensionTable extensions; | |
204 unsigned int count = 0; | |
205 unsigned int expected = 0; | |
206 srandom(RANDOM_SEED); | |
207 for (unsigned int index = 0; index < iterations; ++index) { | |
208 // Randomly select: Add Extension (25%), Add Bg App (25%), Remove (50%) | |
209 switch (random() % 4) { | |
210 case 0: { | |
211 // Add a non-Background-App extension | |
212 std::string name = GenerateRandomExtensionName(); | |
213 scoped_refptr<Extension> extension = CreateExtension(name, false); | |
214 ASSERT_FALSE( | |
215 BackgroundApplicationListModel::IsBackgroundApp(*extension)); | |
216 std::string id = extension->id(); | |
217 extensions[id] = extension; | |
218 ++count; | |
219 ASSERT_TRUE(extensions.size() == count); | |
220 service->AddExtension(extension); | |
221 ASSERT_TRUE(service->extensions()->size() == count); | |
222 ASSERT_TRUE(model->size() == expected); | |
223 break; | |
224 } | |
225 case 1: { | |
226 // Add a Background App | |
227 std::string name = GenerateRandomExtensionName(); | |
228 scoped_refptr<Extension> extension = CreateExtension(name, true); | |
229 ASSERT_TRUE( | |
230 BackgroundApplicationListModel::IsBackgroundApp(*extension)); | |
231 std::string id = extension->id(); | |
232 extensions[id] = extension; | |
233 ++expected; | |
234 ++count; | |
235 ASSERT_TRUE(extensions.size() == count); | |
236 service->AddExtension(extension); | |
237 ASSERT_TRUE(service->extensions()->size() == count); | |
Andrew T Wilson (Slow)
2011/02/16 18:45:46
I suspect you could combine case 0: and case 1: an
The wrong rickcam account
2011/02/16 22:39:20
It got a little funkier than that, but I've redone
| |
238 ASSERT_TRUE(model->size() == expected); | |
239 break; | |
240 } | |
241 case 2: // Intentional fall through | |
242 case 3: { | |
243 // Maybe remove an extension. | |
244 ExtensionTable::iterator cursor = extensions.begin(); | |
245 if (cursor == extensions.end()) { | |
246 // Nothing to remove. Just verify accounting. | |
247 ASSERT_TRUE(count == 0); | |
248 ASSERT_TRUE(expected == 0); | |
249 ASSERT_TRUE(service->extensions()->size() == 0); | |
250 ASSERT_TRUE(model->size() == 0); | |
251 } else { | |
252 // Randomly select an extension | |
253 if (extensions.size() > 1) { | |
254 unsigned int offset = random() % (extensions.size() - 1); | |
255 for (unsigned int index = 0; index < offset; ++index) | |
256 ++cursor; | |
257 } | |
258 scoped_refptr<Extension> extension = cursor->second.get(); | |
259 std::string id = extension->id(); | |
260 if (BackgroundApplicationListModel::IsBackgroundApp(*extension)) | |
261 --expected; | |
262 extensions.erase(cursor); | |
263 --count; | |
264 ASSERT_TRUE(extensions.size() == count); | |
265 service->UninstallExtension(extension->id(), false); | |
266 ASSERT_TRUE(service->extensions()->size() == count); | |
267 ASSERT_TRUE(model->size() == expected); | |
268 } | |
269 break; | |
270 } | |
271 default: | |
272 NOTREACHED(); | |
273 break; | |
274 } | |
275 } | |
276 } | |
OLD | NEW |