1b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#!/usr/bin/env python 2b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 3b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 4b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# found in the LICENSE file. 5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 6b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)import unittest 7b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)from extensions_paths import EXAMPLES, PUBLIC_TEMPLATES, STATIC_DOCS 9b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from local_file_system import LocalFileSystem 10b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from render_servlet import RenderServlet 11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from server_instance import ServerInstance 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochfrom servlet import Request, Response 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from test_util import ReadFile 14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class _RenderServletDelegate(RenderServlet.Delegate): 17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch def CreateServerInstance(self): 18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return ServerInstance.ForTest(LocalFileSystem.Create()) 19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 21b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class RenderServletTest(unittest.TestCase): 2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) def _Render(self, path, headers=None, host=None): 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return RenderServlet(Request.ForTest(path, headers=headers, host=host), 240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) _RenderServletDelegate()).Get() 250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 26b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def testExtensionAppRedirect(self): 27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch self.assertEqual( 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Response.Redirect('/apps/storage', permanent=False), 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._Render('storage')) 30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch def testChannelRedirect(self): 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for channel in ('stable', 'beta', 'dev', 'master'): 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.assertEqual( 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Response.Redirect('/extensions/storage', permanent=True), 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._Render('%s/extensions/storage' % channel)) 36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) def testOldHostsRedirect(self): 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) self.assertEqual( 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Response.Redirect('https://developer.chrome.com/extensions', 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) permanent=False), 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) self._Render('/chrome/extensions', host='http://code.google.com')) 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) self.assertEqual( 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Response.Redirect('https://developer.chrome.com/extensions', 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) permanent=False), 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) self._Render('/chrome/extensions', host='https://code.google.com')) 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def testNotFound(self): 480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) def create_404_response(real_path): 490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) real_404 = self._Render(real_path) 500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) self.assertEqual(200, real_404.status) 510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) real_404.status = 404 520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return real_404 530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) root_404 = create_404_response('404') 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions_404 = create_404_response('extensions/404') 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps_404 = create_404_response('apps/404') 570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.assertEqual(root_404, self._Render('not_found')) 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.assertEqual(root_404, self._Render('not_found/not_found')) 600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.assertEqual(extensions_404, self._Render('extensions/not_found')) 620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) self.assertEqual( 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions_404, self._Render('extensions/manifest/not_found')) 640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) self.assertEqual( 650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) extensions_404, 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._Render('extensions/manifest/not_found/not_found')) 670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.assertEqual(apps_404, self._Render('apps/not_found')) 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.assertEqual(apps_404, self._Render('apps/manifest/not_found')) 700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) self.assertEqual( 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps_404, self._Render('apps/manifest/not_found/not_found')) 72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def testSampleFile(self): 74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sample_file = 'extensions/talking_alarm_clock/background.js' 750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) response = self._Render('extensions/examples/%s' % sample_file) 76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.assertEqual(200, response.status) 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self.assertTrue(response.headers['Content-Type'] in ( 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 'application/javascript; charset=utf-8', 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 'application/x-javascript; charset=utf-8')) 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.assertEqual(ReadFile('%s%s' % (EXAMPLES, sample_file)), 81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) response.content.ToString()) 82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def testSampleZip(self): 84b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sample_dir = 'extensions/talking_alarm_clock' 850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) response = self._Render('extensions/examples/%s.zip' % sample_dir) 86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.assertEqual(200, response.status) 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self.assertEqual('application/zip', response.headers['Content-Type']) 88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def testStaticFile(self): 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_file = 'css/out/site.css' 910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) response = self._Render('static/%s' % static_file) 92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.assertEqual(200, response.status) 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self.assertEqual('text/css; charset=utf-8', 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) response.headers['Content-Type']) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.assertEqual(ReadFile('%s%s' % (STATIC_DOCS, static_file)), 96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) response.content.ToString()) 97b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def testHtmlTemplate(self): 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) html_file = 'extensions/storage' 1000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) response = self._Render(html_file) 101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.assertEqual(200, response.status) 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self.assertEqual('text/html; charset=utf-8', 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) response.headers.get('Content-Type')) 104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # Can't really test rendering all that well. 105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.assertTrue(len(response.content) > 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) len(ReadFile('%s%s.html' % (PUBLIC_TEMPLATES, html_file)))) 107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch def testIndexRender(self): 1090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) response = self._Render('extensions') 1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch self.assertEqual(200, response.status) 1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch self.assertEqual(self._Render('extensions/index').content.ToString(), 1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch response.content.ToString()) 1130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) def testOtherRedirectsJsonRedirect(self): 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) response = self._Render('apps/webview_tag') 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.assertEqual(('/apps/tags/webview', False), 1170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) response.GetRedirect()) 1180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) def testDirectories(self): 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) # Directories should be redirected to a URL that doesn't end in a '/' 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) # whether or not that exists. 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) self.assertEqual(('/dir', False), self._Render('dir/').GetRedirect()) 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch def testEtags(self): 125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch def test_path(path, content_type): 126e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch # Render without etag. 127e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response = self._Render(path) 128e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch self.assertEqual(200, response.status) 129e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch etag = response.headers.get('ETag') 130e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch self.assertTrue(etag is not None) 131e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 132e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch # Render with an If-None-Match which doesn't match. 133e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response = self._Render(path, headers={ 134e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 'If-None-Match': '"fake etag"', 135e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch }) 136e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch self.assertEqual(200, response.status) 137e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch self.assertEqual(content_type, response.headers.get('Content-Type')) 138e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch self.assertEqual(etag, response.headers.get('ETag')) 139e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 140e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch # Render with the correct matching If-None-Match. 141e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch response = self._Render(path, headers={ 142e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 'If-None-Match': etag, 143e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch }) 144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch self.assertEqual(304, response.status) 145e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch self.assertEqual('Not Modified', response.content.ToString()) 146e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch self.assertEqual(content_type, response.headers.get('Content-Type')) 147e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch self.assertEqual(etag, response.headers.get('ETag')) 148e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 149e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch # Test with a static path and a dynamic path. 150e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch test_path('static/css/out/site.css', 'text/css; charset=utf-8') 151e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch test_path('extensions/storage', 'text/html; charset=utf-8') 152e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 1530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)if __name__ == '__main__': 155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) unittest.main() 156