Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / docs / server2 / patch_servlet_test.py
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.
5
6 from HTMLParser import HTMLParser
7 import unittest
8
9 from fake_fetchers import ConfigureFakeFetchers
10 from github_file_system_provider import GithubFileSystemProvider
11 from host_file_system_provider import HostFileSystemProvider
12 from patch_servlet import PatchServlet
13 from render_servlet import RenderServlet
14 from server_instance import ServerInstance
15 from servlet import Request
16 from test_branch_utility import TestBranchUtility
17 from test_util import DisableLogging
18
19
20
21 _ALLOWED_HOST = 'https://chrome-apps-doc.appspot.com'
22
23
24 def _CheckURLsArePatched(content, patch_servlet_path):
25   errors = []
26   class LinkChecker(HTMLParser):
27     def handle_starttag(self, tag, attrs):
28       if tag != 'a':
29         return
30       tag_description = '<a %s .../>' % ' '.join('%s="%s"' % (key, val)
31                                                  for key, val in attrs)
32       attrs = dict(attrs)
33       if ('href' in attrs and
34            attrs['href'].startswith('/') and
35            not attrs['href'].startswith('/%s/' % patch_servlet_path)):
36         errors.append('%s has an unqualified href' % tag_description)
37   LinkChecker().feed(content)
38   return errors
39
40
41 class _RenderServletDelegate(RenderServlet.Delegate):
42   def CreateServerInstance(self):
43     return ServerInstance.ForLocal()
44
45 class _PatchServletDelegate(RenderServlet.Delegate):
46   def CreateBranchUtility(self, object_store_creator):
47     return TestBranchUtility.CreateWithCannedData()
48
49   def CreateHostFileSystemProvider(self, object_store_creator, **optargs):
50     return HostFileSystemProvider.ForLocal(object_store_creator, **optargs)
51
52   def CreateGithubFileSystemProvider(self, object_store_creator):
53     return GithubFileSystemProvider.ForEmpty()
54
55
56 class PatchServletTest(unittest.TestCase):
57   def setUp(self):
58     ConfigureFakeFetchers()
59
60   def _RenderWithPatch(self, path, issue):
61     path_with_issue = '%s/%s' % (issue, path)
62     return PatchServlet(Request.ForTest(path_with_issue, host=_ALLOWED_HOST),
63                         _PatchServletDelegate()).Get()
64
65   def _RenderWithoutPatch(self, path):
66     return RenderServlet(Request.ForTest(path, host=_ALLOWED_HOST),
67                          _RenderServletDelegate()).Get()
68
69   def _RenderAndCheck(self, path, issue, expected_equal):
70     '''Renders |path| with |issue| patched in and asserts that the result is
71     the same as |expected_equal| modulo any links that get rewritten to
72     "_patch/issue".
73     '''
74     patched_response = self._RenderWithPatch(path, issue)
75     unpatched_response = self._RenderWithoutPatch(path)
76     patched_response.headers.pop('cache-control', None)
77     unpatched_response.headers.pop('cache-control', None)
78     unpatched_content = unpatched_response.content.ToString()
79
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, '')
88
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)
95
96   def _RenderAndAssertEqual(self, path, issue):
97     self._RenderAndCheck(path, issue, True)
98
99   def _RenderAndAssertNotEqual(self, path, issue):
100     self._RenderAndCheck(path, issue, False)
101
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))
108
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))
116
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'])
122
123   def testRender(self):
124     # '_patch' is not included in paths below because it's stripped by Handler.
125     issue = '14096030'
126
127     # TODO(kalman): Test with chrome_sidenav.json once the sidenav logic has
128     # stabilised.
129
130     # extensions/runtime.html is removed in the patch, should redirect to the
131     # apps version.
132     self._AssertRedirect('extensions/runtime', issue, 'apps/runtime')
133
134     # apps/runtime.html is not removed.
135     self._RenderAndAssertEqual('apps/runtime', issue)
136
137     # test_foo.html is added in the patch.
138     self._AssertOk('extensions/test_foo', issue)
139
140     # Invalid issue number results in a 404.
141     self._AssertNotFound('extensions/index', '11111')
142
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('http://developer.chrome.com', '12345',
157                                  '%s/_patch/12345' % _ALLOWED_HOST))
158     self.assertTrue(*is_redirect('http://developers.google.com', '12345',
159                                  '%s/_patch/12345' % _ALLOWED_HOST))
160     self.assertFalse(*is_redirect('http://chrome-apps-doc.appspot.com', '12345',
161                                   None))
162     self.assertFalse(*is_redirect('http://some-other-app.appspot.com', '12345',
163                                   None))
164
165 if __name__ == '__main__':
166   unittest.main()