100dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com#!/usr/bin/env python 28015dd83ae37147bb630d4751030868051ad0caereed@android.com# Copyright 2013 The Chromium Authors. All rights reserved. 38015dd83ae37147bb630d4751030868051ad0caereed@android.com# Use of this source code is governed by a BSD-style license that can be 48015dd83ae37147bb630d4751030868051ad0caereed@android.com# found in the LICENSE file. 500dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com 600dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.comimport unittest 700dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com 800dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.comfrom extensions_paths import EXAMPLES, PUBLIC_TEMPLATES, STATIC_DOCS 900dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.comfrom local_file_system import LocalFileSystem 1000dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.comfrom render_servlet import RenderServlet 1100dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.comfrom server_instance import ServerInstance 1200dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.comfrom servlet import Request, Response 1300dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.comfrom test_util import ReadFile 14dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com 1500dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com 1600dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.comclass _RenderServletDelegate(RenderServlet.Delegate): 17dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com def CreateServerInstance(self): 1800dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com return ServerInstance.ForTest(LocalFileSystem.Create()) 19dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com 2000dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com 21dd0ac281e920b01a63789893cc3e7422789658ddreed@android.comclass RenderServletTest(unittest.TestCase): 2200dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com def _Render(self, path, headers=None, host=None): 2300dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com return RenderServlet(Request.ForTest(path, headers=headers, host=host), 2400dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com _RenderServletDelegate()).Get() 2500dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com 2600dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com def testExtensionAppRedirect(self): 27dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com self.assertEqual( 2800dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com Response.Redirect('/apps/storage', permanent=False), 2900dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self._Render('storage')) 3000dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com 3100dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com def testChannelRedirect(self): 3200dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com for channel in ('stable', 'beta', 'dev', 'master'): 3300dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual( 3400dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com Response.Redirect('/extensions/storage', permanent=True), 3500dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self._Render('%s/extensions/storage' % channel)) 3600dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com 3700dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com def testOldHostsRedirect(self): 3800dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual( 3900dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com Response.Redirect('https://developer.chrome.com/extensions', 408015dd83ae37147bb630d4751030868051ad0caereed@android.com permanent=False), 418015dd83ae37147bb630d4751030868051ad0caereed@android.com self._Render('/chrome/extensions', host='http://code.google.com')) 428015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertEqual( 438015dd83ae37147bb630d4751030868051ad0caereed@android.com Response.Redirect('https://developer.chrome.com/extensions', 448015dd83ae37147bb630d4751030868051ad0caereed@android.com permanent=False), 458015dd83ae37147bb630d4751030868051ad0caereed@android.com self._Render('/chrome/extensions', host='https://code.google.com')) 468015dd83ae37147bb630d4751030868051ad0caereed@android.com 478015dd83ae37147bb630d4751030868051ad0caereed@android.com def testNotFound(self): 488015dd83ae37147bb630d4751030868051ad0caereed@android.com def create_404_response(real_path): 498015dd83ae37147bb630d4751030868051ad0caereed@android.com real_404 = self._Render(real_path) 5000dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual(200, real_404.status) 518015dd83ae37147bb630d4751030868051ad0caereed@android.com real_404.status = 404 528015dd83ae37147bb630d4751030868051ad0caereed@android.com return real_404 538015dd83ae37147bb630d4751030868051ad0caereed@android.com 548015dd83ae37147bb630d4751030868051ad0caereed@android.com root_404 = create_404_response('404') 558015dd83ae37147bb630d4751030868051ad0caereed@android.com extensions_404 = create_404_response('extensions/404') 568015dd83ae37147bb630d4751030868051ad0caereed@android.com apps_404 = create_404_response('apps/404') 578015dd83ae37147bb630d4751030868051ad0caereed@android.com 5800dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual(root_404, self._Render('not_found')) 5900dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual(root_404, self._Render('not_found/not_found')) 6000dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com 6100dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual(extensions_404, self._Render('extensions/not_found')) 6200dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual( 6300dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com extensions_404, self._Render('extensions/manifest/not_found')) 6400dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual( 6500dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com extensions_404, 6600dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self._Render('extensions/manifest/not_found/not_found')) 6700dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com 6800dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual(apps_404, self._Render('apps/not_found')) 6900dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual(apps_404, self._Render('apps/manifest/not_found')) 7000dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual( 7100dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com apps_404, self._Render('apps/manifest/not_found/not_found')) 7200dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com 738015dd83ae37147bb630d4751030868051ad0caereed@android.com def testSampleFile(self): 748015dd83ae37147bb630d4751030868051ad0caereed@android.com sample_file = 'extensions/talking_alarm_clock/background.js' 758015dd83ae37147bb630d4751030868051ad0caereed@android.com response = self._Render('extensions/examples/%s' % sample_file) 768015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertEqual(200, response.status) 778015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertTrue(response.headers['Content-Type'] in ( 788015dd83ae37147bb630d4751030868051ad0caereed@android.com 'application/javascript; charset=utf-8', 798015dd83ae37147bb630d4751030868051ad0caereed@android.com 'application/x-javascript; charset=utf-8')) 808015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertEqual(ReadFile('%s%s' % (EXAMPLES, sample_file)), 818015dd83ae37147bb630d4751030868051ad0caereed@android.com response.content.ToString()) 828015dd83ae37147bb630d4751030868051ad0caereed@android.com 838015dd83ae37147bb630d4751030868051ad0caereed@android.com def testSampleZip(self): 848015dd83ae37147bb630d4751030868051ad0caereed@android.com sample_dir = 'extensions/talking_alarm_clock' 858015dd83ae37147bb630d4751030868051ad0caereed@android.com response = self._Render('extensions/examples/%s.zip' % sample_dir) 868015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertEqual(200, response.status) 878015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertEqual('application/zip', response.headers['Content-Type']) 888015dd83ae37147bb630d4751030868051ad0caereed@android.com 898015dd83ae37147bb630d4751030868051ad0caereed@android.com def testStaticFile(self): 908015dd83ae37147bb630d4751030868051ad0caereed@android.com static_file = 'css/out/site.css' 9100dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com response = self._Render('static/%s' % static_file) 9200dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual(200, response.status) 938015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertEqual('text/css; charset=utf-8', 9400dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com response.headers['Content-Type']) 9500dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual(ReadFile('%s%s' % (STATIC_DOCS, static_file)), 968015dd83ae37147bb630d4751030868051ad0caereed@android.com response.content.ToString()) 978015dd83ae37147bb630d4751030868051ad0caereed@android.com 988015dd83ae37147bb630d4751030868051ad0caereed@android.com def testHtmlTemplate(self): 9900dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com html_file = 'extensions/storage' 100dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com response = self._Render(html_file) 10100dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual(200, response.status) 10200dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertEqual('text/html; charset=utf-8', 10300dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com response.headers.get('Content-Type')) 10400dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com # Can't really test rendering all that well. 10500dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertTrue(len(response.content) > 10600dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com len(ReadFile('%s%s.html' % (PUBLIC_TEMPLATES, html_file)))) 1078015dd83ae37147bb630d4751030868051ad0caereed@android.com 1088015dd83ae37147bb630d4751030868051ad0caereed@android.com def testIndexRender(self): 1098015dd83ae37147bb630d4751030868051ad0caereed@android.com response = self._Render('extensions') 1108015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertEqual(200, response.status) 1118015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertEqual(self._Render('extensions/index').content.ToString(), 1128015dd83ae37147bb630d4751030868051ad0caereed@android.com response.content.ToString()) 1138015dd83ae37147bb630d4751030868051ad0caereed@android.com 1148015dd83ae37147bb630d4751030868051ad0caereed@android.com def testOtherRedirectsJsonRedirect(self): 1158015dd83ae37147bb630d4751030868051ad0caereed@android.com response = self._Render('apps/webview_tag') 1168015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertEqual(('/apps/tags/webview', False), 1178015dd83ae37147bb630d4751030868051ad0caereed@android.com response.GetRedirect()) 1188015dd83ae37147bb630d4751030868051ad0caereed@android.com 1198015dd83ae37147bb630d4751030868051ad0caereed@android.com def testDirectories(self): 1208015dd83ae37147bb630d4751030868051ad0caereed@android.com # Directories should be redirected to a URL that doesn't end in a '/' 1218015dd83ae37147bb630d4751030868051ad0caereed@android.com # whether or not that exists. 1228015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertEqual(('/dir', False), self._Render('dir/').GetRedirect()) 1238015dd83ae37147bb630d4751030868051ad0caereed@android.com 1248015dd83ae37147bb630d4751030868051ad0caereed@android.com def testEtags(self): 1258015dd83ae37147bb630d4751030868051ad0caereed@android.com def test_path(path, content_type): 1268015dd83ae37147bb630d4751030868051ad0caereed@android.com # Render without etag. 1278015dd83ae37147bb630d4751030868051ad0caereed@android.com response = self._Render(path) 1288015dd83ae37147bb630d4751030868051ad0caereed@android.com self.assertEqual(200, response.status) 12900dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com etag = response.headers.get('ETag') 13000dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com self.assertTrue(etag is not None) 13100dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com 13200dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com # Render with an If-None-Match which doesn't match. 13300dae86f5872b60927b28a32b375bc01cd7c61c9reed@android.com response = self._Render(path, headers={ 134dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com 'If-None-Match': '"fake etag"', 135dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com }) 136dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com self.assertEqual(200, response.status) 137dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com self.assertEqual(content_type, response.headers.get('Content-Type')) 138dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com self.assertEqual(etag, response.headers.get('ETag')) 139dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com 140dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com # Render with the correct matching If-None-Match. 141dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com response = self._Render(path, headers={ 142dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com 'If-None-Match': etag, 143dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com }) 144dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com self.assertEqual(304, response.status) 145dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com self.assertEqual('Not Modified', response.content.ToString()) 146dd0ac281e920b01a63789893cc3e7422789658ddreed@android.com self.assertEqual(content_type, response.headers.get('Content-Type')) 147 self.assertEqual(etag, response.headers.get('ETag')) 148 149 # Test with a static path and a dynamic path. 150 test_path('static/css/out/site.css', 'text/css; charset=utf-8') 151 test_path('extensions/storage', 'text/html; charset=utf-8') 152 153 154if __name__ == '__main__': 155 unittest.main() 156