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