Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 2 | # Copyright 2013 The Chromium Authors. All rights reserved. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 6 | # Run build_server so that files needed by tests are copied to the local |
| 7 | # third_party directory. |
| 8 | import build_server |
| 9 | build_server.main() |
| 10 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 11 | import optparse |
| 12 | import os |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 13 | import posixpath |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 14 | import sys |
| 15 | import time |
| 16 | import unittest |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 17 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 18 | from branch_utility import BranchUtility |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 19 | from link_error_detector import LinkErrorDetector, StringifyBrokenLinks |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 20 | from local_file_system import LocalFileSystem |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 21 | from local_renderer import LocalRenderer |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 22 | from fake_fetchers import ConfigureFakeFetchers |
| 23 | from handler import Handler |
| 24 | from servlet import Request |
| 25 | from test_util import EnableLogging, DisableLogging |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 26 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 27 | # Arguments set up if __main__ specifies them. |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 28 | _EXPLICIT_TEST_FILES = None |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 29 | |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 30 | def _ToPosixPath(os_path): |
| 31 | return os_path.replace(os.sep, '/') |
| 32 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 33 | def _GetPublicFiles(): |
| 34 | '''Gets all public files mapped to their contents. |
| 35 | ''' |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 36 | public_path = os.path.join(sys.path[0], os.pardir, 'templates', 'public') |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 37 | public_files = {} |
| 38 | for path, dirs, files in os.walk(public_path, topdown=True): |
| 39 | dirs[:] = [d for d in dirs if d != '.svn'] |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 40 | relative_posix_path = _ToPosixPath(path[len(public_path):]) |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 41 | for filename in files: |
| 42 | with open(os.path.join(path, filename), 'r') as f: |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 43 | public_files['/'.join((relative_posix_path, filename))] = f.read() |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 44 | return public_files |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 45 | |
| 46 | class IntegrationTest(unittest.TestCase): |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 47 | def setUp(self): |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 48 | ConfigureFakeFetchers() |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 49 | |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 50 | @EnableLogging('info') |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 51 | def testCronAndPublicFiles(self): |
| 52 | '''Runs cron then requests every public file. Cron needs to be run first |
| 53 | because the public file requests are offline. |
| 54 | ''' |
| 55 | if _EXPLICIT_TEST_FILES is not None: |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 56 | return |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 57 | |
| 58 | print('Running cron...') |
| 59 | start_time = time.time() |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 60 | try: |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 61 | response = Handler(Request.ForTest('/_cron/stable')).Get() |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 62 | self.assertEqual(200, response.status) |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 63 | self.assertEqual('Success', response.content.ToString()) |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 64 | finally: |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 65 | print('Took %s seconds' % (time.time() - start_time)) |
| 66 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 67 | print("Checking for broken links...") |
| 68 | start_time = time.time() |
| 69 | link_error_detector = LinkErrorDetector( |
| 70 | LocalFileSystem(os.path.join(sys.path[0], os.pardir, os.pardir)), |
| 71 | lambda path: Handler(Request.ForTest(path)).Get(), |
| 72 | 'templates/public', |
| 73 | ('extensions/index.html', 'apps/about_apps.html')) |
| 74 | |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 75 | broken_links = link_error_detector.GetBrokenLinks() |
| 76 | if broken_links: |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 77 | # TODO(jshumway): Test should fail when broken links are detected. |
| 78 | print('Warning: Found %d broken links:' % ( |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 79 | len(broken_links))) |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 80 | print(StringifyBrokenLinks(broken_links)) |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 81 | |
| 82 | print('Took %s seconds.' % (time.time() - start_time)) |
| 83 | |
| 84 | print('Searching for orphaned pages...') |
| 85 | start_time = time.time() |
| 86 | orphaned_pages = link_error_detector.GetOrphanedPages() |
| 87 | if orphaned_pages: |
| 88 | # TODO(jshumway): Test should fail when orphaned pages are detected. |
| 89 | print('Warning: Found %d orphaned pages:' % len(orphaned_pages)) |
| 90 | for page in orphaned_pages: |
| 91 | print(page) |
| 92 | print('Took %s seconds.' % (time.time() - start_time)) |
| 93 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 94 | public_files = _GetPublicFiles() |
| 95 | |
| 96 | print('Rendering %s public files...' % len(public_files.keys())) |
| 97 | start_time = time.time() |
| 98 | try: |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 99 | for path, content in public_files.iteritems(): |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 100 | if path.endswith('redirects.json'): |
| 101 | continue |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 102 | def check_result(response): |
| 103 | self.assertEqual(200, response.status, |
| 104 | 'Got %s when rendering %s' % (response.status, path)) |
| 105 | # This is reaaaaally rough since usually these will be tiny templates |
| 106 | # that render large files. At least it'll catch zero-length responses. |
| 107 | self.assertTrue(len(response.content) >= len(content), |
| 108 | 'Content was "%s" when rendering %s' % (response.content, path)) |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 109 | |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 110 | check_result(Handler(Request.ForTest(path)).Get()) |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 111 | |
| 112 | # Make sure that leaving out the .html will temporarily redirect to the |
| 113 | # path with the .html. |
| 114 | if path != '/404.html': |
| 115 | redirect_result = Handler( |
| 116 | Request.ForTest(posixpath.splitext(path)[0])).Get() |
| 117 | self.assertEqual((path, False), redirect_result.GetRedirect()) |
| 118 | |
| 119 | # Make sure including a channel will permanently redirect to the same |
| 120 | # path without a channel. |
| 121 | for channel in BranchUtility.GetAllChannelNames(): |
| 122 | redirect_result = Handler( |
| 123 | Request.ForTest('%s/%s' % (channel, path))).Get() |
| 124 | self.assertEqual((path, True), redirect_result.GetRedirect()) |
| 125 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 126 | # Samples are internationalized, test some locales. |
| 127 | if path.endswith('/samples.html'): |
| 128 | for lang in ['en-US', 'es', 'ar']: |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 129 | check_result(Handler(Request.ForTest( |
| 130 | path, |
| 131 | headers={'Accept-Language': '%s;q=0.8' % lang})).Get()) |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 132 | finally: |
| 133 | print('Took %s seconds' % (time.time() - start_time)) |
| 134 | |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 135 | # TODO(kalman): Move this test elsewhere, it's not an integration test. |
| 136 | # Perhaps like "presubmit_tests" or something. |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 137 | def testExplicitFiles(self): |
| 138 | '''Tests just the files in _EXPLICIT_TEST_FILES. |
| 139 | ''' |
| 140 | if _EXPLICIT_TEST_FILES is None: |
| 141 | return |
| 142 | for filename in _EXPLICIT_TEST_FILES: |
| 143 | print('Rendering %s...' % filename) |
| 144 | start_time = time.time() |
| 145 | try: |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 146 | response = LocalRenderer.Render(_ToPosixPath(filename)) |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 147 | self.assertEqual(200, response.status) |
| 148 | self.assertTrue(response.content != '') |
| 149 | finally: |
| 150 | print('Took %s seconds' % (time.time() - start_time)) |
| 151 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 152 | # TODO(jshumway): Check page for broken links (currently prohibited by the |
| 153 | # time it takes to render the pages). |
| 154 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 155 | @DisableLogging('warning') |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 156 | def testFileNotFound(self): |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 157 | response = Handler(Request.ForTest('/extensions/notfound.html')).Get() |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 158 | self.assertEqual(404, response.status) |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 159 | |
| 160 | if __name__ == '__main__': |
| 161 | parser = optparse.OptionParser() |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 162 | parser.add_option('-a', '--all', action='store_true', default=False) |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 163 | (opts, args) = parser.parse_args() |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 164 | if not opts.all: |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 165 | _EXPLICIT_TEST_FILES = args |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 166 | # Kill sys.argv because we have our own flags. |
| 167 | sys.argv = [sys.argv[0]] |
| 168 | unittest.main() |