2 # Copyright 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
8 from appengine_wrappers
import GetAppVersion
9 from app_yaml_helper
import AppYamlHelper
10 from cron_servlet
import CronServlet
11 from empty_dir_file_system
import EmptyDirFileSystem
12 from extensions_paths
import (
13 APP_YAML
, CONTENT_PROVIDERS
, EXTENSIONS
, PUBLIC_TEMPLATES
, SERVER2
,
15 from github_file_system_provider
import GithubFileSystemProvider
16 from host_file_system_provider
import HostFileSystemProvider
17 from local_file_system
import LocalFileSystem
18 from mock_file_system
import MockFileSystem
19 from servlet
import Request
20 from test_branch_utility
import TestBranchUtility
21 from test_file_system
import MoveTo
, TestFileSystem
22 from test_util
import EnableLogging
, ReadFile
25 # NOTE(kalman): The ObjectStore created by the CronServlet is backed onto our
26 # fake AppEngine memcache/datastore, so the tests aren't isolated. Of course,
27 # if the host file systems have different identities, they will be, sort of.
28 class _TestDelegate(CronServlet
.Delegate
):
29 def __init__(self
, create_file_system
):
30 self
.file_systems
= []
31 # A callback taking a revision and returning a file system.
32 self
._create
_file
_system
= create_file_system
33 self
._app
_version
= GetAppVersion()
35 def CreateBranchUtility(self
, object_store_creator
):
36 return TestBranchUtility
.CreateWithCannedData()
38 def CreateHostFileSystemProvider(self
,
40 max_trunk_revision
=None):
41 def constructor(branch
=None, revision
=None):
42 file_system
= self
._create
_file
_system
(revision
)
43 self
.file_systems
.append(file_system
)
45 return HostFileSystemProvider(object_store_creator
,
46 max_trunk_revision
=max_trunk_revision
,
47 constructor_for_test
=constructor
)
49 def CreateGithubFileSystemProvider(self
, object_store_creator
):
50 return GithubFileSystemProvider
.ForEmpty()
52 def GetAppVersion(self
):
53 return self
._app
_version
55 # (non-Delegate method).
56 def SetAppVersion(self
, app_version
):
57 self
._app
_version
= app_version
59 class CronServletTest(unittest
.TestCase
):
60 @EnableLogging('info')
61 def testEverything(self
):
62 # All these tests are dependent (see above comment) so lump everything in
64 delegate
= _TestDelegate(lambda _
: MockFileSystem(LocalFileSystem
.Create()))
66 # Test that the cron runs successfully.
67 response
= CronServlet(Request
.ForTest('trunk'),
68 delegate_for_test
=delegate
).Get()
69 self
.assertEqual(200, response
.status
)
71 # Save the file systems created, start with a fresh set for the next run.
72 first_run_file_systems
= delegate
.file_systems
[:]
73 delegate
.file_systems
[:] = []
75 # When re-running, all file systems should be Stat()d the same number of
76 # times, but the second round shouldn't have been re-Read() since the
77 # Stats haven't changed.
78 response
= CronServlet(Request
.ForTest('trunk'),
79 delegate_for_test
=delegate
).Get()
80 self
.assertEqual(200, response
.status
)
82 self
.assertEqual(len(first_run_file_systems
), len(delegate
.file_systems
))
83 for i
, second_run_file_system
in enumerate(delegate
.file_systems
):
84 self
.assertTrue(*second_run_file_system
.CheckAndReset(
86 stat_count
=first_run_file_systems
[i
].GetStatCount()))
88 def testSafeRevision(self
):
91 '_api_features.json': '{}',
92 '_manifest_features.json': '{}',
93 '_permission_features.json': '{}',
97 'examples.txt': 'examples.txt contents'
100 'app.yaml': AppYamlHelper
.GenerateAppYaml('2-0-8')
103 'static.txt': 'static.txt contents'
107 'table_of_contents.html': 'table_of_contents.html contents',
111 'storage.html': '<h1>storage.html</h1> contents'
114 'storage.html': '<h1>storage.html</h1> contents'
118 'chrome_sidenav.json': '{}',
119 'content_providers.json': ReadFile(CONTENT_PROVIDERS
),
120 'manifest.json': '{}',
121 'permissions.json': '{}',
122 'strings.json': '{}',
130 def app_yaml_update(version
):
131 return MoveTo(SERVER2
, {
132 'app.yaml': AppYamlHelper
.GenerateAppYaml(version
)
134 def storage_html_update(update
):
135 return MoveTo(PUBLIC_TEMPLATES
, {
136 'apps': {'storage.html': update
}
138 def static_txt_update(update
):
139 return MoveTo(STATIC_DOCS
, {
143 storage_html_path
= '%s/apps/storage.html' % PUBLIC_TEMPLATES
144 static_txt_path
= '%s/static.txt' % STATIC_DOCS
146 def create_file_system(revision
=None):
147 '''Creates a MockFileSystem at |revision| by applying that many |updates|
150 mock_file_system
= MockFileSystem(
151 TestFileSystem(test_data
, relative_to
=EXTENSIONS
))
152 updates_for_revision
= (
153 updates
if revision
is None else updates
[:int(revision
)])
154 for update
in updates_for_revision
:
155 mock_file_system
.Update(update
)
156 return mock_file_system
158 delegate
= _TestDelegate(create_file_system
)
159 delegate
.SetAppVersion('2-0-8')
161 file_systems
= delegate
.file_systems
163 # No updates applied yet.
164 CronServlet(Request
.ForTest('trunk'), delegate_for_test
=delegate
).Get()
165 self
.assertEqual(AppYamlHelper
.GenerateAppYaml('2-0-8'),
166 file_systems
[-1].ReadSingle(APP_YAML
).Get())
167 self
.assertEqual('<h1>storage.html</h1> contents',
168 file_systems
[-1].ReadSingle(storage_html_path
).Get())
170 # Apply updates to storage.html.
171 updates
.append(storage_html_update('interim contents'))
172 updates
.append(storage_html_update('<h1>new</h1> contents'))
174 CronServlet(Request
.ForTest('trunk'), delegate_for_test
=delegate
).Get()
175 self
.assertEqual(AppYamlHelper
.GenerateAppYaml('2-0-8'),
176 file_systems
[-1].ReadSingle(APP_YAML
).Get())
177 self
.assertEqual('<h1>new</h1> contents',
178 file_systems
[-1].ReadSingle(storage_html_path
).Get())
180 # Apply several updates to storage.html and app.yaml. The file system
181 # should be pinned at the version before app.yaml changed.
182 updates
.append(storage_html_update('<h1>stuck here</h1> contents'))
184 double_update
= storage_html_update('<h1>newer</h1> contents')
185 double_update
.update(app_yaml_update('2-0-10'))
186 updates
.append(double_update
)
188 updates
.append(storage_html_update('never gonna reach here'))
190 CronServlet(Request
.ForTest('trunk'), delegate_for_test
=delegate
).Get()
191 self
.assertEqual(AppYamlHelper
.GenerateAppYaml('2-0-8'),
192 file_systems
[-1].ReadSingle(APP_YAML
).Get())
193 self
.assertEqual('<h1>stuck here</h1> contents',
194 file_systems
[-1].ReadSingle(storage_html_path
).Get())
196 # Further pushes to storage.html will keep it pinned.
197 updates
.append(storage_html_update('<h1>y</h1> u not update!'))
199 CronServlet(Request
.ForTest('trunk'), delegate_for_test
=delegate
).Get()
200 self
.assertEqual(AppYamlHelper
.GenerateAppYaml('2-0-8'),
201 file_systems
[-1].ReadSingle(APP_YAML
).Get())
202 self
.assertEqual('<h1>stuck here</h1> contents',
203 file_systems
[-1].ReadSingle(storage_html_path
).Get())
206 updates
.append(app_yaml_update('2-1-0'))
208 CronServlet(Request
.ForTest('trunk'), delegate_for_test
=delegate
).Get()
209 self
.assertEqual(AppYamlHelper
.GenerateAppYaml('2-0-8'),
210 file_systems
[-1].ReadSingle(APP_YAML
).Get())
211 self
.assertEqual('<h1>stuck here</h1> contents',
212 file_systems
[-1].ReadSingle(storage_html_path
).Get())
214 # And updates to other content won't happen either.
215 updates
.append(static_txt_update('important content!'))
217 CronServlet(Request
.ForTest('trunk'), delegate_for_test
=delegate
).Get()
218 self
.assertEqual(AppYamlHelper
.GenerateAppYaml('2-0-8'),
219 file_systems
[-1].ReadSingle(APP_YAML
).Get())
220 self
.assertEqual('<h1>stuck here</h1> contents',
221 file_systems
[-1].ReadSingle(storage_html_path
).Get())
222 self
.assertEqual('static.txt contents',
223 file_systems
[-1].ReadSingle(static_txt_path
).Get())
225 # Lastly - when the app version changes, everything should no longer be
227 delegate
.SetAppVersion('2-1-0')
228 CronServlet(Request
.ForTest('trunk'), delegate_for_test
=delegate
).Get()
229 self
.assertEqual(AppYamlHelper
.GenerateAppYaml('2-1-0'),
230 file_systems
[-1].ReadSingle(APP_YAML
).Get())
231 self
.assertEqual('<h1>y</h1> u not update!',
232 file_systems
[-1].ReadSingle(storage_html_path
).Get())
233 self
.assertEqual('important content!',
234 file_systems
[-1].ReadSingle(static_txt_path
).Get())
236 if __name__
== '__main__':