cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / chrome / common / extensions / docs / server2 / patch_servlet_test.py
blob214cbf2ccf5c670967ac3d0be95e8b7f8efd1a86
1 #!/usr/bin/env python
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.
6 from HTMLParser import HTMLParser
7 import unittest
9 from fake_fetchers import ConfigureFakeFetchers
10 from host_file_system_provider import HostFileSystemProvider
11 from patch_servlet import PatchServlet
12 from render_servlet import RenderServlet
13 from server_instance import ServerInstance
14 from servlet import Request
15 from test_branch_utility import TestBranchUtility
16 from test_util import DisableLogging
20 _ALLOWED_HOST = 'chrome-apps-doc.appspot.com'
23 def _CheckURLsArePatched(content, patch_servlet_path):
24 errors = []
25 class LinkChecker(HTMLParser):
26 def handle_starttag(self, tag, attrs):
27 if tag != 'a':
28 return
29 tag_description = '<a %s .../>' % ' '.join('%s="%s"' % (key, val)
30 for key, val in attrs)
31 attrs = dict(attrs)
32 if ('href' in attrs and
33 attrs['href'].startswith('/') and
34 not attrs['href'].startswith('/%s/' % patch_servlet_path)):
35 errors.append('%s has an unqualified href' % tag_description)
36 LinkChecker().feed(content)
37 return errors
40 class _RenderServletDelegate(RenderServlet.Delegate):
41 def CreateServerInstance(self):
42 return ServerInstance.ForLocal()
44 class _PatchServletDelegate(RenderServlet.Delegate):
45 def CreateBranchUtility(self, object_store_creator):
46 return TestBranchUtility.CreateWithCannedData()
48 def CreateHostFileSystemProvider(self, object_store_creator, **optargs):
49 return HostFileSystemProvider.ForLocal(object_store_creator, **optargs)
51 def CreateGithubFileSystemProvider(self, object_store_creator):
52 return GithubFileSystemProvider.ForEmpty()
55 class PatchServletTest(unittest.TestCase):
56 def setUp(self):
57 ConfigureFakeFetchers()
59 def _RenderWithPatch(self, path, issue):
60 path_with_issue = '%s/%s' % (issue, path)
61 return PatchServlet(Request.ForTest(path_with_issue, host=_ALLOWED_HOST),
62 _PatchServletDelegate()).Get()
64 def _RenderWithoutPatch(self, path):
65 return RenderServlet(Request.ForTest(path, host=_ALLOWED_HOST),
66 _RenderServletDelegate()).Get()
68 def _RenderAndCheck(self, path, issue, expected_equal):
69 '''Renders |path| with |issue| patched in and asserts that the result is
70 the same as |expected_equal| modulo any links that get rewritten to
71 "_patch/issue".
72 '''
73 patched_response = self._RenderWithPatch(path, issue)
74 unpatched_response = self._RenderWithoutPatch(path)
75 for header in ('Cache-Control', 'ETag'):
76 patched_response.headers.pop(header, None)
77 unpatched_response.headers.pop(header, None)
78 unpatched_content = unpatched_response.content.ToString()
80 # Check that all links in the patched content are qualified with
81 # the patch URL, then strip them out for checking (in)equality.
82 patched_content = patched_response.content.ToString()
83 patch_servlet_path = '_patch/%s' % issue
84 errors = _CheckURLsArePatched(patched_content, patch_servlet_path)
85 self.assertFalse(errors,
86 '%s\nFound errors:\n * %s' % (patched_content, '\n * '.join(errors)))
87 patched_content = patched_content.replace('/%s' % patch_servlet_path, '')
89 self.assertEqual(patched_response.status, unpatched_response.status)
90 self.assertEqual(patched_response.headers, unpatched_response.headers)
91 if expected_equal:
92 self.assertEqual(patched_content, unpatched_content)
93 else:
94 self.assertNotEqual(patched_content, unpatched_content)
96 def _RenderAndAssertEqual(self, path, issue):
97 self._RenderAndCheck(path, issue, True)
99 def _RenderAndAssertNotEqual(self, path, issue):
100 self._RenderAndCheck(path, issue, False)
102 @DisableLogging('warning')
103 def _AssertNotFound(self, path, issue):
104 response = self._RenderWithPatch(path, issue)
105 self.assertEqual(response.status, 404,
106 'Path %s with issue %s should have been removed for %s.' % (
107 path, issue, response))
109 def _AssertOk(self, path, issue):
110 response = self._RenderWithPatch(path, issue)
111 self.assertEqual(response.status, 200,
112 'Failed to render path %s with issue %s.' % (path, issue))
113 self.assertTrue(len(response.content.ToString()) > 0,
114 'Rendered result for path %s with issue %s should not be empty.' %
115 (path, issue))
117 def _AssertRedirect(self, path, issue, redirect_path):
118 response = self._RenderWithPatch(path, issue)
119 self.assertEqual(302, response.status)
120 self.assertEqual('/_patch/%s/%s' % (issue, redirect_path),
121 response.headers['Location'])
123 def testRender(self):
124 # '_patch' is not included in paths below because it's stripped by Handler.
125 issue = '14096030'
127 # TODO(kalman): Test with chrome_sidenav.json once the sidenav logic has
128 # stabilised.
130 # extensions/runtime.html is removed in the patch, should redirect to the
131 # apps version.
132 self._AssertRedirect('extensions/runtime', issue, 'apps/runtime')
134 # apps/runtime.html is not removed.
135 self._RenderAndAssertEqual('apps/runtime', issue)
137 # test_foo.html is added in the patch.
138 self._AssertOk('extensions/test_foo', issue)
140 # Invalid issue number results in a 404.
141 self._AssertNotFound('extensions/index', '11111')
143 def testXssRedirect(self):
144 def is_redirect(from_host, from_path, to_url):
145 response = PatchServlet(Request.ForTest(from_path, host=from_host),
146 _PatchServletDelegate()).Get()
147 redirect_url, _ = response.GetRedirect()
148 if redirect_url is None:
149 return (False, '%s/%s did not cause a redirect' % (
150 from_host, from_path))
151 if redirect_url != to_url:
152 return (False, '%s/%s redirected to %s not %s' % (
153 from_host, from_path, redirect_url, to_url))
154 return (True, '%s/%s redirected to %s' % (
155 from_host, from_path, redirect_url))
156 self.assertTrue(*is_redirect('developer.chrome.com', '12345',
157 'https://%s/_patch/12345' % _ALLOWED_HOST))
158 self.assertTrue(*is_redirect('developers.google.com', '12345',
159 'https://%s/_patch/12345' % _ALLOWED_HOST))
160 self.assertFalse(*is_redirect('chrome-apps-doc.appspot.com', '12345',
161 None))
162 self.assertFalse(*is_redirect('some-other-app.appspot.com', '12345',
163 None))
165 if __name__ == '__main__':
166 unittest.main()