Home | History | Annotate | Download | only in functional
      1 #!/usr/bin/env python
      2 # Copyright (c) 2011 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 """This functional test spawns a web server, and runs chrome to point
      7 at that web server.
      8 
      9 The content served contains prefetch requests, and the tests assert that the
     10 webserver logs reflect that.
     11 
     12 Run like any functional test:
     13 $ python chrome/test/functional/prefetch.py
     14 in a repo with a built pyautolib
     15 
     16 The import of multiprocessing implies python 2.6 is required
     17 """
     18 
     19 import os
     20 import time
     21 import multiprocessing
     22 import Queue
     23 import string
     24 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
     25 
     26 import pyauto_functional  # Must be imported before pyauto
     27 import pyauto
     28 
     29 # this class handles IPC retrieving server "logs" from our integral
     30 # server.  Each test should clear() the log, and then run asserts on
     31 # the retrieval list.
     32 
     33 # at startup, the server puts an int in the queue which is its port,
     34 # we store that for subsequent tests
     35 
     36 class ServerLog:
     37   def clear(self):
     38     self.log = {}
     39 
     40   def __init__(self,queue):
     41     self.clear()
     42     self.port = None
     43     self.queue = queue
     44 
     45   def _readQueue(self):
     46     try:
     47       while True:
     48         queueval = self.queue.get(False)
     49         if isinstance(queueval,int):
     50           self.port = queueval
     51         else:
     52          self.log[queueval] = True
     53     except Queue.Empty:
     54       return
     55 
     56   def getPort(self):
     57     if not self.port:
     58       self._readQueue()
     59     return self.port
     60 
     61   def isRetrieved(self,path):
     62     self._readQueue()
     63     try:
     64       return self.log[path]
     65     except KeyError:
     66       return None
     67 
     68 #
     69 # The next few classes run a simple web server that returns log information
     70 # via a multiprocessing.Queue.
     71 #
     72 class AbstractPrefetchServerHandler(BaseHTTPRequestHandler):
     73   content = {
     74       "prefetch-origin.html":
     75         (200, """<html><head>
     76 <link rel="prefetch" href="static-prefetch-target.html">
     77 <script type="text/javascript">
     78 function changeParagraph()
     79 {
     80   var newPara = document.createElement("p");
     81   newPara.innerHTML =
     82         "<link rel=\\"prefetch\\" href=\\"dynamic-prefetch-target.html\\">" +
     83        "<p>This paragraph contains a dynamic link prefetch.  " +
     84        "The target of this prefetch is " +
     85        "<a href=\\"dynamic-prefetch-target.html\\">this document.</a>";
     86   var para = document.getElementById("p1");
     87   document.body.insertBefore(newPara,para);
     88 }
     89 </script>
     90 </head>
     91 <body onload="changeParagraph()">
     92 <p id="p1">This is a document that contains a link prefetch.  The target of
     93 that prefetch is <a href="static-prefetch-target.html">this document.</a>
     94 </body>"""),
     95       "static-prefetch-target.html":
     96         (200, "<html><head></head><body>empty</body>"),
     97       "dynamic-prefetch-target.html":
     98         (200, "<html><head></head><body>empty</body>")}
     99 
    100   def do_GET(self):
    101     self.queue.put(self.path[1:])
    102     try:
    103       response_code, response = self.content[self.path[1:]]
    104       self.send_response(response_code)
    105       self.end_headers()
    106       self.wfile.write(response)
    107     except KeyError:
    108       self.send_response(404)
    109       self.end_headers()
    110 
    111 def run_web_server(queue_arg):
    112   class PrefetchServerHandler(AbstractPrefetchServerHandler):
    113     queue = queue_arg
    114   server = HTTPServer(('',0), PrefetchServerHandler)
    115   queue.put(server.server_port)
    116   server.serve_forever()
    117 
    118 #
    119 # Here's the test itself
    120 #
    121 queue = multiprocessing.Queue()
    122 server_log = ServerLog(queue)
    123 
    124 class PrefetchTest(pyauto.PyUITest):
    125   """Testcase for Prefetching"""
    126   def testBasic(self):
    127     server_log.clear()
    128     url = "http://localhost:%d/prefetch-origin.html" % server_log.getPort()
    129     self.NavigateToURL(url)
    130     self.assertEqual(True, server_log.isRetrieved("prefetch-origin.html"))
    131     time.sleep(0.1)  # required since prefetches occur after onload
    132     self.assertEqual(True, server_log.isRetrieved(
    133         "static-prefetch-target.html"))
    134     self.assertEqual(True, server_log.isRetrieved(
    135         "dynamic-prefetch-target.html"))
    136 
    137 if __name__ == '__main__':
    138   web_server = multiprocessing.Process(target=run_web_server,args=(queue,))
    139   web_server.daemon = True
    140   web_server.start()
    141   pyauto_functional.Main()
    142