#!/usr/bin/python
"""
$Id: caching.py,v 1.4 2006/11/24 11:53:43 dom Exp $

The CachingTestCase implements the validator.testcase.TestCase
interface for the tests related to the following BP:
Provide caching information in HTTP responses.

License
-------
Copyright (c) 2006 World Wide Web Consortium, (Massachusetts
Institute of Technology, European Research Consortium for Informatics
and Mathematics, Keio University). All Rights Reserved. This work is
distributed under the W3C Software License [1] 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.

[1] http://www.w3.org/Consortium/Legal/copyright-software

"""


from  validator import testcase 

# Tests regarding the CACHING BP
class CachingTestCase(testcase.URIBasedTestCase):
    BpId=["CACHING"]

    # This is only done on the main page
    # it should probably be applied to each of the embedded resources, shouldn't it? @@@
    def run(self,uri,profile=None):
        from validator.testcase import Observation, Location, TestResults
        self._observations = TestResults()
        headers,content = self._http_request(uri,"HEAD")
        if not(headers.has_key("expires") or headers.has_key("cache-control")):
            self.addObservation(Observation("CA1",Location(uri)))
        validable_headers = {"Last-Modified":"If-Modified-Since","ETag":"If-None-Match"}
        validable = ""
        for h,v in validable_headers.iteritems():
            if headers.has_key(h.lower()):
                validator = headers[h.lower()]
                # we validate the header with a conditional request
                req_head = {"cache-control":"",v.lower():validator}
                headers2,content = self._http_request(uri,"HEAD",req_head)
                if headers2.has_key(h.lower()) and headers2[h.lower()]==validator:
                    if headers2.status!=304:
                        self.addObservation(Observation("CA2",Location(uri),{"validator":h}))
                    else:
                        # This breaks localization @@@ 
                        validable = " and does cache validation"
                        break
        if not "CA1" in self._observations and not "CA2" in self._observations:
            self.addObservation(Observation("CA3",Location(uri),{"validable":validable}))
        return self._observations


# -------------------------
# Unit tests for this module
import unittest

from validator.testcase import TestResults, Observation, Location
class Tests(unittest.TestCase):
    def _test(self,inp,res):
        a = CachingTestCase()
        self.assertEqual(a.run(inp),res)
        
    def testWithCompleteCaching(self):
        # we assume www.w3.org will be kept on the good side of force
        inp = "http://www.w3.org/"
        res = TestResults(
            [Observation('CA3',Location(inp),{'validable': ' and does cache validation'})]
            )
        self._test(inp,res)

    def testWithNoExpiresHeader(self):
        # we assume dev.w3.org will be kept on the grey side of force
        inp = "http://dev.w3.org/cvsweb/"
        res = TestResults(
            [Observation('CA1',Location(inp))]
            )
        self._test(inp,res)

    def testWithNonValidableLastModifiedHeader(self):
        inp = "http://www.w3.org/2006/09/non-validable-last-modified-header"
        res = TestResults(
            [Observation('CA2',Location(inp),{"validator":"Last-Modified"})]
            )
        self._test(inp,res)

def _test():
    unittest.main()

if __name__ == '__main__':
    _test()



