blob: 6d0e99b45eb897542b4fda867853420d57272856 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001#!/usr/bin/env python
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002# Copyright 2013 The Chromium Authors. All rights reserved.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003# 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)58218062012-11-14 11:43:16 +00006# Run build_server so that files needed by tests are copied to the local
7# third_party directory.
8import build_server
9build_server.main()
10
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010011import optparse
12import os
Ben Murdochca12bfa2013-07-23 11:17:05 +010013import posixpath
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010014import sys
15import time
16import unittest
Torne (Richard Coles)58218062012-11-14 11:43:16 +000017
Ben Murdochca12bfa2013-07-23 11:17:05 +010018from branch_utility import BranchUtility
Ben Murdochbb1529c2013-08-08 10:24:53 +010019from link_error_detector import LinkErrorDetector, StringifyBrokenLinks
Ben Murdochca12bfa2013-07-23 11:17:05 +010020from local_file_system import LocalFileSystem
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010021from local_renderer import LocalRenderer
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010022from fake_fetchers import ConfigureFakeFetchers
23from handler import Handler
24from servlet import Request
25from test_util import EnableLogging, DisableLogging
Torne (Richard Coles)58218062012-11-14 11:43:16 +000026
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010027# Arguments set up if __main__ specifies them.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010028_EXPLICIT_TEST_FILES = None
Torne (Richard Coles)58218062012-11-14 11:43:16 +000029
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010030def _ToPosixPath(os_path):
31 return os_path.replace(os.sep, '/')
32
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010033def _GetPublicFiles():
34 '''Gets all public files mapped to their contents.
35 '''
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010036 public_path = os.path.join(sys.path[0], os.pardir, 'templates', 'public')
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010037 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)a93a17c2013-05-15 11:34:50 +010040 relative_posix_path = _ToPosixPath(path[len(public_path):])
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010041 for filename in files:
42 with open(os.path.join(path, filename), 'r') as f:
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010043 public_files['/'.join((relative_posix_path, filename))] = f.read()
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010044 return public_files
Torne (Richard Coles)58218062012-11-14 11:43:16 +000045
46class IntegrationTest(unittest.TestCase):
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010047 def setUp(self):
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010048 ConfigureFakeFetchers()
Torne (Richard Coles)58218062012-11-14 11:43:16 +000049
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010050 @EnableLogging('info')
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010051 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)58218062012-11-14 11:43:16 +000056 return
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010057
58 print('Running cron...')
59 start_time = time.time()
Torne (Richard Coles)58218062012-11-14 11:43:16 +000060 try:
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010061 response = Handler(Request.ForTest('/_cron/stable')).Get()
Torne (Richard Coles)58218062012-11-14 11:43:16 +000062 self.assertEqual(200, response.status)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010063 self.assertEqual('Success', response.content.ToString())
Torne (Richard Coles)58218062012-11-14 11:43:16 +000064 finally:
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010065 print('Took %s seconds' % (time.time() - start_time))
66
Ben Murdochca12bfa2013-07-23 11:17:05 +010067 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 Murdoch558790d2013-07-30 15:19:42 +010075 broken_links = link_error_detector.GetBrokenLinks()
76 if broken_links:
Ben Murdochca12bfa2013-07-23 11:17:05 +010077 # TODO(jshumway): Test should fail when broken links are detected.
78 print('Warning: Found %d broken links:' % (
Ben Murdoch558790d2013-07-30 15:19:42 +010079 len(broken_links)))
Ben Murdochbb1529c2013-08-08 10:24:53 +010080 print(StringifyBrokenLinks(broken_links))
Ben Murdochca12bfa2013-07-23 11:17:05 +010081
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)c2e0dbd2013-05-09 18:35:53 +010094 public_files = _GetPublicFiles()
95
96 print('Rendering %s public files...' % len(public_files.keys()))
97 start_time = time.time()
98 try:
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010099 for path, content in public_files.iteritems():
Ben Murdocheb525c52013-07-10 11:40:50 +0100100 if path.endswith('redirects.json'):
101 continue
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100102 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 Murdochca12bfa2013-07-23 11:17:05 +0100109
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100110 check_result(Handler(Request.ForTest(path)).Get())
Ben Murdochca12bfa2013-07-23 11:17:05 +0100111
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)c2e0dbd2013-05-09 18:35:53 +0100126 # Samples are internationalized, test some locales.
127 if path.endswith('/samples.html'):
128 for lang in ['en-US', 'es', 'ar']:
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100129 check_result(Handler(Request.ForTest(
130 path,
131 headers={'Accept-Language': '%s;q=0.8' % lang})).Get())
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100132 finally:
133 print('Took %s seconds' % (time.time() - start_time))
134
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100135 # TODO(kalman): Move this test elsewhere, it's not an integration test.
136 # Perhaps like "presubmit_tests" or something.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100137 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)a93a17c2013-05-15 11:34:50 +0100146 response = LocalRenderer.Render(_ToPosixPath(filename))
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100147 self.assertEqual(200, response.status)
148 self.assertTrue(response.content != '')
149 finally:
150 print('Took %s seconds' % (time.time() - start_time))
151
Ben Murdochca12bfa2013-07-23 11:17:05 +0100152 # TODO(jshumway): Check page for broken links (currently prohibited by the
153 # time it takes to render the pages).
154
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100155 @DisableLogging('warning')
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100156 def testFileNotFound(self):
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100157 response = Handler(Request.ForTest('/extensions/notfound.html')).Get()
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100158 self.assertEqual(404, response.status)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000159
160if __name__ == '__main__':
161 parser = optparse.OptionParser()
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100162 parser.add_option('-a', '--all', action='store_true', default=False)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000163 (opts, args) = parser.parse_args()
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000164 if not opts.all:
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100165 _EXPLICIT_TEST_FILES = args
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100166 # Kill sys.argv because we have our own flags.
167 sys.argv = [sys.argv[0]]
168 unittest.main()