integration_test.py revision bb1529ce867d8845a77ec7cdf3e3003ef1771a40
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# 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
11import optparse
12import os
13import posixpath
14import sys
15import time
16import unittest
17
18from branch_utility import BranchUtility
19from link_error_detector import LinkErrorDetector, StringifyBrokenLinks
20from local_file_system import LocalFileSystem
21from local_renderer import LocalRenderer
22from fake_fetchers import ConfigureFakeFetchers
23from handler import Handler
24from servlet import Request
25from test_util import EnableLogging, DisableLogging
26
27# Arguments set up if __main__ specifies them.
28_EXPLICIT_TEST_FILES = None
29
30def _ToPosixPath(os_path):
31  return os_path.replace(os.sep, '/')
32
33def _GetPublicFiles():
34  '''Gets all public files mapped to their contents.
35  '''
36  public_path = os.path.join(sys.path[0], os.pardir, 'templates', 'public')
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']
40    relative_posix_path = _ToPosixPath(path[len(public_path):])
41    for filename in files:
42      with open(os.path.join(path, filename), 'r') as f:
43        public_files['/'.join((relative_posix_path, filename))] = f.read()
44  return public_files
45
46class IntegrationTest(unittest.TestCase):
47  def setUp(self):
48    ConfigureFakeFetchers()
49
50  @EnableLogging('info')
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:
56      return
57
58    print('Running cron...')
59    start_time = time.time()
60    try:
61      response = Handler(Request.ForTest('/_cron/stable')).Get()
62      self.assertEqual(200, response.status)
63      self.assertEqual('Success', response.content.ToString())
64    finally:
65      print('Took %s seconds' % (time.time() - start_time))
66
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
75    broken_links = link_error_detector.GetBrokenLinks()
76    if broken_links:
77      # TODO(jshumway): Test should fail when broken links are detected.
78      print('Warning: Found %d broken links:' % (
79        len(broken_links)))
80      print(StringifyBrokenLinks(broken_links))
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
94    public_files = _GetPublicFiles()
95
96    print('Rendering %s public files...' % len(public_files.keys()))
97    start_time = time.time()
98    try:
99      for path, content in public_files.iteritems():
100        if path.endswith('redirects.json'):
101          continue
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))
109
110        check_result(Handler(Request.ForTest(path)).Get())
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
126        # Samples are internationalized, test some locales.
127        if path.endswith('/samples.html'):
128          for lang in ['en-US', 'es', 'ar']:
129            check_result(Handler(Request.ForTest(
130                path,
131                headers={'Accept-Language': '%s;q=0.8' % lang})).Get())
132    finally:
133      print('Took %s seconds' % (time.time() - start_time))
134
135  # TODO(kalman): Move this test elsewhere, it's not an integration test.
136  # Perhaps like "presubmit_tests" or something.
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:
146        response = LocalRenderer.Render(_ToPosixPath(filename))
147        self.assertEqual(200, response.status)
148        self.assertTrue(response.content != '')
149      finally:
150        print('Took %s seconds' % (time.time() - start_time))
151
152    # TODO(jshumway): Check page for broken links (currently prohibited by the
153    # time it takes to render the pages).
154
155  @DisableLogging('warning')
156  def testFileNotFound(self):
157    response = Handler(Request.ForTest('/extensions/notfound.html')).Get()
158    self.assertEqual(404, response.status)
159
160if __name__ == '__main__':
161  parser = optparse.OptionParser()
162  parser.add_option('-a', '--all', action='store_true', default=False)
163  (opts, args) = parser.parse_args()
164  if not opts.all:
165    _EXPLICIT_TEST_FILES = args
166  # Kill sys.argv because we have our own flags.
167  sys.argv = [sys.argv[0]]
168  unittest.main()
169