15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2011 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)"""This functional test spawns a web server, and runs chrome to point
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)at that web server.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)The content served contains prefetch requests, and the tests assert that the
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)webserver logs reflect that.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Run like any functional test:
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$ python chrome/test/functional/prefetch.py
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)in a repo with a built pyautolib
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)The import of multiprocessing implies python 2.6 is required
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import time
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import multiprocessing
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import Queue
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import string
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import pyauto_functional  # Must be imported before pyauto
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import pyauto
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# this class handles IPC retrieving server "logs" from our integral
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# server.  Each test should clear() the log, and then run asserts on
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# the retrieval list.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# at startup, the server puts an int in the queue which is its port,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# we store that for subsequent tests
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ServerLog:
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def clear(self):
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.log = {}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self,queue):
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.clear()
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.port = None
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.queue = queue
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _readQueue(self):
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while True:
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        queueval = self.queue.get(False)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if isinstance(queueval,int):
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          self.port = queueval
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         self.log[queueval] = True
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    except Queue.Empty:
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def getPort(self):
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not self.port:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._readQueue()
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self.port
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def isRetrieved(self,path):
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._readQueue()
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return self.log[path]
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    except KeyError:
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return None
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# The next few classes run a simple web server that returns log information
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# via a multiprocessing.Queue.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AbstractPrefetchServerHandler(BaseHTTPRequestHandler):
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content = {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "prefetch-origin.html":
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (200, """<html><head>
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)<link rel="prefetch" href="static-prefetch-target.html">
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)<script type="text/javascript">
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function changeParagraph()
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var newPara = document.createElement("p");
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  newPara.innerHTML =
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "<link rel=\\"prefetch\\" href=\\"dynamic-prefetch-target.html\\">" +
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       "<p>This paragraph contains a dynamic link prefetch.  " +
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       "The target of this prefetch is " +
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       "<a href=\\"dynamic-prefetch-target.html\\">this document.</a>";
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var para = document.getElementById("p1");
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  document.body.insertBefore(newPara,para);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)</script>
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)</head>
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)<body onload="changeParagraph()">
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)<p id="p1">This is a document that contains a link prefetch.  The target of
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)that prefetch is <a href="static-prefetch-target.html">this document.</a>
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)</body>"""),
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "static-prefetch-target.html":
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (200, "<html><head></head><body>empty</body>"),
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "dynamic-prefetch-target.html":
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (200, "<html><head></head><body>empty</body>")}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def do_GET(self):
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.queue.put(self.path[1:])
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try:
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_code, response = self.content[self.path[1:]]
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.send_response(response_code)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.end_headers()
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.wfile.write(response)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    except KeyError:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.send_response(404)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.end_headers()
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def run_web_server(queue_arg):
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class PrefetchServerHandler(AbstractPrefetchServerHandler):
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    queue = queue_arg
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server = HTTPServer(('',0), PrefetchServerHandler)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue.put(server.server_port)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server.serve_forever()
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Here's the test itself
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)queue = multiprocessing.Queue()
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)server_log = ServerLog(queue)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PrefetchTest(pyauto.PyUITest):
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Testcase for Prefetching"""
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testBasic(self):
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_log.clear()
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url = "http://localhost:%d/prefetch-origin.html" % server_log.getPort()
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.NavigateToURL(url)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(True, server_log.isRetrieved("prefetch-origin.html"))
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    time.sleep(0.1)  # required since prefetches occur after onload
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(True, server_log.isRetrieved(
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "static-prefetch-target.html"))
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(True, server_log.isRetrieved(
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "dynamic-prefetch-target.html"))
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_server = multiprocessing.Process(target=run_web_server,args=(queue,))
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_server.daemon = True
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_server.start()
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pyauto_functional.Main()
142