###################################################################
# HttpTestCase.py -- a library for testing HTTP-based servers
# Copyright (C) 2003  Chris Curvey
#
#This program is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public License
#as published by the Free Software Foundation; either version 2
#of the License, or (at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
###################################################################
import unittest
import urllib
import urllib2
import urlparse
from string import *
import ClientCookie

ClientCookie.CLIENTCOOKIE_DEBUG = 0

class HttpTestCase(unittest.TestCase):
    """
    This defines a bunch of useful functions that are used for 
    web-based testing.  I've made a moderate effort to implement
    the same interfaces that are in the Java version of HttpTestCase.
    """
    def __init__(self, *args):
        unittest.TestCase.__init__(self, *args)
	self.lastScheme = ""
	self.lastNetworkLocation = ""
	self.newServer = None
	self.opener = ClientCookie.build_opener(ClientCookie.SeekableProcessor)

    #########################################################
    def setWebServerReplacement(self, newServer):
        self.newServer = newServer

    ########################################################
    def replaceURL(self, url):
        """
	A function to "fix up" our urls by adding/replacing web
	server names, etc.
	"""

	(scheme, networkLocation, path, \
	parameters, query, fragmentId) = urlparse.urlparse(url)

	if scheme == "":
	    scheme = self.lastScheme

        if networkLocation == "":
	    networkLocation = self.lastNetworkLocation

        if path[0] != "/":
	    path = self.lastDir + path

        if self.newServer != None:
	    networkLocation = self.newServer

        self.lastScheme = scheme
	self.lastNetworkLocation = networkLocation
	self.lastUrl = url
	
	self.lastDir = path[0:path.rfind("/")+1]
	
	url = urlparse.urlunparse( (scheme, networkLocation, path, parameters,\
	                            query, fragmentId))
        
	return url

    #########################################################
    def get(self, url, params=None):

        url = self.replaceURL(url)

	if params != None:
            params = urllib.urlencode(params)
	    url = url + "?%s" % params

	try:
	    #self.response = ClientCookie.urlopen(url)
	    self.response = self.opener.open(url)
        except urllib2.HTTPError, e:
	    self.status = e.code
        else:
	    self.status = 200
            self.data = self.response.read()
	    self.info = self.response.info()

    ########################################################
    def post(self, url, params=None):
	
        url = self.replaceURL(url)

        self.request = urllib2.Request(url)

        if params != None:
	    params = urllib.urlencode(params)
	    self.request.add_data(params)

	try:
            self.response = self.opener.open(self.request)
        except urllib2.HTTPError, e:
	    self.status = e.code
        else:
	    self.status = 200
	    self.data = self.response.read()
	    self.info = self.response.info()

    #####################################################
    def postMultiPart(self, url, data, len, args=None):
	pass

    def acceptCookie(self, cookie, req, resp):
        pass

    def sendCookie(self, cookie, req):
        pass

    def responseOK(self):
        pass

    def responseContainsURI(self, uri):
        """
	this should move into HtmlTestCase
	"""
        pass

    def responseContainsString(self, string):
        """
	Searches the raw data of the response for a string.
	"""
	if find(self.data, string) == -1:
	    return 0

	else:
	    return 1

    def responseContainsHeader(self, header, value):
        """
	Would be nice to have a plural version that takes a dictionary
	""" 
	try:
	    if self.info[header] == value:
	         return 1
            else:
	         return 0
	except KeyError:
	    return 0

    def printResponse(self):
	# this should break down the response and show it
	# nicely
        pass

###############################################################
if __name__ == "__main__":
    class PythonHomePageTest(HttpTestCase):
        def setUp(self):
            self.get("http://www.python.org")
    
        def testBasicPage(self):
            self.failUnless(self.responseContainsString("pythonHi.gif"))
            self.failIf(self.responseContainsString("Guido"))

        def testHeaders(self):
	    self.failUnless(self.responseContainsHeader("Content-Type", "text/html"))
	    self.failUnless(self.responseContainsHeader("Connection" , "close"))
	    self.failIf(self.responseContainsHeader("muppet", "bert-is-evil"))

    ##########################################################
    class PostTest(HttpTestCase):
        def setUp(self):
    	    params = { "type_of_search" : "soft",
	               "words" : "pyunit" }

            self.post("http://sourceforge.net/search", params)
    
        def testBasicSearch(self):
	    print self.response.read()
    	    self.failUnless(self.status == 200)
    	    self.failUnless(self.responseContainsString("/projects/pyunit"))

    ####################################################
    # run the tests
    unittest.main()


