[commits-cosmo] (mikeal) [1759] Big Big Big Update:

Mikeal Rogers mikeal at osafoundation.org
Fri Apr 7 17:14:43 PDT 2006


Forgot one more thing.

Added feature to TestObject. TestObject.teststart(testname)

This method is really useful for tracking issues, it sets self.test  
to the current test name string. If debug is set it will print the  
test at the beginning of each test. Simple but useful.

-Mikeal

On Apr 7, 2006, at 5:09 PM, svncheckin at osafoundation.org wrote:

> Revision
> 1759
> Author
> mikeal
> Date
> 2006-04-07 17:09:17 -0700 (Fri, 07 Apr 2006)
> Log Message
>
> Big Big Big Update:
>
> Moved non-HTTP testing functionality from HTTPTest in to TestObject  
> for reuse, HTTPTest now inherits from TestObject.
>
> Created DAVTest, an object for WebDAV and CalDAV testing which  
> inherits form HTTPTest.
> The DAVTest object has a magic method that removed the necessity of  
> those huge nested if statements in all my cosmo REPORTS tests.
>
> Ported cosmo_timerangequery.py to DAVTest.
> Added bkirsh's new tests to cosmo_timerangequery.py, last 3 are  
> blocked by known bug.
> Modified Paths
>
> cosmo/trunk/src/test/functional/HTTPTest/HTTPTest.py
> cosmo/trunk/src/test/functional/HTTPTest/cosmo_timerangequery.py
> Added Paths
>
> cosmo/trunk/src/test/functional/HTTPTest/DAVTest.py
> cosmo/trunk/src/test/functional/HTTPTest/TestObject.py
> cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC1.xml
> cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC2.xml
> cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC3.xml
> cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC4.xml
> cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC5.xml
> cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC6.xml
> cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_01.xml
> cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_02.xml
> cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_03.xml
> Diff
>
> Added: cosmo/trunk/src/test/functional/HTTPTest/DAVTest.py (1758 =>  
> 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/DAVTest.py	2006-04-07  
> 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/DAVTest.py	2006-04-08  
> 00:09:17 UTC (rev 1759)
> @@ -0,0 +1,157 @@
> +from HTTPTest import HTTPTest
> +
> +class DAVTest(HTTPTest):
> +
> +    def verifyitems(self, *args, **keyargs):
> +        """
> +        Method to verify elements exist and, if specified, verify  
> that all strings in dict are in inelement.
> +
> +        Required Attributes;
> +        args = single strings representing all the expected items  
> in the response url
> +
> +        Optional attributes;
> +        test = overwrite self.test
> +        comment = overwrite self.comment
> +        inelement = string represent find within each response  
> element to search for positive list strings
> +            Optional attributes if inelement and positive are  
> specified;
> +            positive = list of strings to search for in inelement
> +            negative = list of strings to search for not existing  
> in inelement
> +            inelementexpectedcount = amount of inelement items,  
> used if elements in response are greater than elements matching  
> inelement
> +        """
> +
> +        self.xmlparse()
> +
> +        # ----- Set all necessary counts and attributes
> +
> +        responseelementcount = 0
> +        itemexpectedcount = 0
> +        itemreturnedcount = 0
> +        positiveexpectedcount = 0
> +        positivepasscount = 0
> +        negativeexpectedcount = 0
> +        negativepasscount = 0
> +        inelementcount = 0
> +        inelementexpectedcount = 0
> +
> +        try:
> +            test = keyargs['test']
> +        except KeyError:
> +            test = self.test
> +
> +        for arg in args:
> +            itemexpectedcount = itemexpectedcount+1
> +
> +        try:
> +            positive = keyargs['positive']
> +            for p in positive:
> +                positiveexpectedcount = positiveexpectedcount+1
> +            positiveexpectedcount =  
> (positiveexpectedcount*itemexpectedcount)
> +        except KeyError:
> +            positive = None
> +
> +        try:
> +            negative = keyargs['negative']
> +            for p in negative:
> +                negativeexpectedcount = negativeexpectedcount+1
> +            negativeexpectedcount =  
> (negativeexpectedcount*itemexpectedcount)
> +        except KeyError:
> +            negative = None
> +
> +        try:
> +            comment = keyargs['comment']
> +        except KeyError:
> +            comment = None
> +
> +        try:
> +            inelement = keyargs['inelement']
> +        except KeyError:
> +            inelement = None
> +
> +        # ------ Super magic logic to verify all counts and matches
> +
> +        rtest = self.xml_doc.findall('.//{DAV:}response')
> +        for t in rtest:
> +            responseelementcount = responseelementcount+1
> +            # -- For every arg match response url
> +            for item in args:
> +                if t[0].text.find('%s' % item) != -1:
> +                    itemreturnedcount = itemreturnedcount+1
> +                    # -- For each element matcing inelement
> +                    if inelement != None:
> +                        ctest = t.find('.//%s' % inelement)
> +                        inelementcount = inelementcount+1
> +                        # -- For each element matching inelement  
> verify text contains strings in positive list
> +                        if positive != None:
> +                            for p in positive:
> +                                if ctest.text.find(p) != -1:
> +                                    positivepasscount =  
> positivepasscount+1
> +                                else:
> +                                    self.printout('FAILED to get % 
> s in %s' % (p, t[0].text))
> +                        if negative != None:
> +                            for p in negative:
> +                                if ctest.text.find(p) == -1:
> +                                    negativepasscount =  
> negativepasscount+1
> +                                else:
> +                                    self.printout('FAILED to get % 
> s in %s' % (p, t[0].text))
> +
> +        try:
> +            inelementexpectedcount = keyargs 
> ['inelementexpectedcount']
> +        except KeyError:
> +            inelementexpectedcount = inelementcount
> +        except:
> +            inelementexpectedcount = 0
> +
> +        if responseelementcount == itemexpectedcount ==  
> itemreturnedcount \
> +                           and positiveexpectedcount ==  
> positivepasscount \
> +                           and negativeexpectedcount ==  
> negativepasscount \
> +                           and inelementcount ==  
> inelementexpectedcount:
> +            self.report(True, test='VerifyItems :: %s' % test ,  
> comment=comment)
> +        else:
> +            self.report(False, test='VerifyItems :: %s' % test,  
> comment='Response_elements :: %s; Expected_item_matches :: %s;  
> Returned_item_matches :: %s; Positive_expected_count :: %s;  
> Positive_passed_count :: %s; Negative_expected_count :: %s;  
> Negative_passed_count :: %s; InElement_expected_count :: %s;  
> InElement_passed_count :: %s;' %
> +                                                                      
>        (responseelementcount, itemexpectedcount, itemreturnedcount,
> +                                                                      
>          positiveexpectedcount, positivepasscount,
> +                                                                      
>          negativeexpectedcount, negativepasscount,
> +                                                                      
>          inelementexpectedcount, inelementcount))
> +
> +
> +    def verifyinelement(self, response, inelement, positive,  
> negative=None, test=None, comment=None):
> +        """
> +        Method to verify positive and negative string list exists  
> in single response.element match
> +        """
> +
> +        itemreturnedcount = 0
> +        positivepasscount = 0
> +        negativepasscount = 0
> +        inelementcount = 0
> +
> +        if test == None:
> +            test = self.test
> +
> +        rtest = self.xml_doc.findall('.//{DAV:}response')
> +        for t in rtest:
> +            if t[0].text.find('%s' % response) != -1:
> +                itemreturnedcount = itemreturnedcount+1
> +                # -- For each element matcing inelement
> +                ctest = t.find('.//%s' % inelement)
> +                inelementcount = inelementcount+1
> +                # -- For each element matching inelement verify  
> text contains strings in positive list
> +                for p in positive:
> +                    if ctest.text.find(p) != -1:
> +                        positivepasscount = positivepasscount+1
> +                    else:
> +                        self.printout('FAILED to get %s in %s' %  
> (p, t[0].text))
> +                if negative != None:
> +                    for p in negative:
> +                        if ctest.text.find(p) == -1:
> +                            negativepasscount = negativepasscount+1
> +                        else:
> +                            self.printout('FAILED to get %s in %s'  
> % (p, t[0].text))
> +
> +        if itemreturnedcount == inelementcount == 1 and  
> positivepasscount == len(positive) and negativepasscount == len 
> (negative):
> +            self.report(True, test='VerifyItemsInElement :: %s; %s  
> in %s;' % (test, inelement, response), comment=comment)
> +        else:
> +            self.report(False, test='VerifyItemsInElement :: %s; % 
> s in %s;' % (test, inelement, response),  
> comment='Positive_expected_count :: %s; Positive_passed_count :: % 
> s; Negative_expected_count :: %s; Negative_passed_count :: %s;  
> Item_returned_count :: %s; InElement_returned_count :: %s' %
> +                                                                      
>        (len(positive), positivepasscount,
> +                                                                      
>         len(negative), negativepasscount,
> +                                                                      
>         itemreturnedcount, inelementcount))
> +
> Modified: cosmo/trunk/src/test/functional/HTTPTest/HTTPTest.py  
> (1758 => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/HTTPTest.py	2006-04-07  
> 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/HTTPTest.py	2006-04-08  
> 00:09:17 UTC (rev 1759)
> @@ -3,10 +3,16 @@
>
>  from elementtree import ElementTree
>
> -class HTTPTest:
> +from TestObject import TestObject
> +
> +class HTTPTest(TestObject):
>
>      def __init__(self, host, port, path, debug=0, headers=None,  
> tls=False, mask=0):
>
> +        self.debug = debug
> +        self.mask = mask
> +        TestObject.__init__(self, debug=debug, mask=mask)
> +
>          if headers == None:
>              self.headers = {'Host' : "localhost:8080",
>                               'User-Agent': "Mozilla/5.0  
> (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.0.1) Gecko/ 
> 20060111 Firefox/1.5.0.1",
> @@ -15,13 +21,10 @@
>              self.headers = headers
>
>          self.connection = {"host" : host, "port" : port, "path" :  
> path, "tls" : tls}
> -        self.debug = debug
> -        self.results = []
> -        self.resultnames = []
> -        self.resultcomments = []
> +
>          self.request('OPTIONS', path, body=None,  
> headers=self.headers)
> -        self.mask = mask
>
> +
>      def headeradd(self, headers):
>          """
>          Method to return dict copy of self.headers with header added
> @@ -54,48 +57,14 @@
>          else:
>              self.report(False, test='Status Code Check on %s' %  
> status, comment='expected %s ; received %s' % (status, out))
>              return False
> -
> -    def printout(self, string):
> -
> -        if self.mask == 0:
> -            print string
> -
> -    def end(self):
> -
> -        count = 0
> -        failures = 0
> -        passes = 0
> -        for result in self.results:
> -            if result == False:
> -                failures = failures + 1
> -            elif result == True:
> -                passes = passes +1
>
> -            count = count + 1
> -
> -        print("Failures :: %s" % failures)
> -        print("Passes :: %s" % passes)
> -        print("Total tests run :: %s" % count)
> -
>      def xmlparse(self):
>          """
>          Get xml in body
>          """
>
>          self.xml_doc = ElementTree.XML(self.test_response.read())
> -
> -    def report(self, result, test=None, comment=None):
> -
> -        self.results.append(result)
> -        self.resultnames.append(test)
> -        self.resultcomments.append(comment)
> -        if result == True:
> -            if self.debug > 0:
> -                self.printout("Passed :: Test %s :: %s" % (test,  
> comment))
> -        if result == False:
> -            self.printout("Failure :: Test %s :: %s" % (test,  
> comment))
>
> -
>      def request(self, method, url, body=None, headers={},
>                  autoheaders=('Content-Length', 'Content-Type',  
> 'User-Agent',
>                                'Host'),
> Added: cosmo/trunk/src/test/functional/HTTPTest/TestObject.py (1758  
> => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/TestObject.py	 
> 2006-04-07 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/TestObject.py	 
> 2006-04-08 00:09:17 UTC (rev 1759)
> @@ -0,0 +1,57 @@
> +
> +
> +class TestObject:
> +
> +    def __init__(self, debug=0, mask=0):
> +
> +        self.debug = debug
> +        self.mask = mask
> +        self.results = []
> +        self.resultnames = []
> +        self.resultcomments = []
> +
> +    def printout(self, string):
> +
> +        if self.mask == 0:
> +            print string
> +
> +    def teststart(self, testname):
> +        """
> +        Set test name
> +        """
> +
> +        self.test = testname
> +        if self.debug > 0 and self.mask == 0:
> +            print 'Starting New Test :: %s' % self.test
> +
> +    def report(self, result, test=None, comment=None):
> +
> +        self.results.append(result)
> +        self.resultnames.append(test)
> +        self.resultcomments.append(comment)
> +        if result == True:
> +            if self.debug > 0:
> +                self.printout("Passed :: Test %s :: %s" % (test,  
> comment))
> +        if result == False:
> +            self.printout("Failure :: Test %s :: %s" % (test,  
> comment))
> +
> +
> +
> +    def end(self):
> +
> +        count = 0
> +        failures = 0
> +        passes = 0
> +        for result in self.results:
> +            if result == False:
> +                failures = failures + 1
> +            elif result == True:
> +                passes = passes +1
> +
> +            count = count + 1
> +
> +        print("Failures :: %s" % failures)
> +        print("Passes :: %s" % passes)
> +        print("Total tests run :: %s" % count)
> +
> +
> \ No newline at end of file
> Modified: cosmo/trunk/src/test/functional/HTTPTest/ 
> cosmo_timerangequery.py (1758 => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/ 
> cosmo_timerangequery.py	2006-04-07 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/ 
> cosmo_timerangequery.py	2006-04-08 00:09:17 UTC (rev 1759)
> @@ -1,6 +1,7 @@
> -from HTTPTest import HTTPTest
> +#from HTTPTest import HTTPTest
> +from DAVTest import DAVTest
>
> -class CosmoTimeRangeQuery(HTTPTest):
> +class CosmoTimeRangeQuery(DAVTest):
>
>      def startRun(self):
>
> @@ -9,6 +10,8 @@
>          #Create Headers for CMP
>
>          # ------- Test Create Account ------- #
> +
> +        self.teststart('Setup Account')
>
>          cmpheaders = self.headeradd({'Content-Type' : "text/xml;  
> charset=UTF-8"})
>          cmpheaders = self.headeraddauth("root", "cosmo",  
> headers=cmpheaders)
> @@ -32,6 +35,8 @@
>
>          # ------- Test Create Calendar ------- #
>
> +        self.teststart('Create Calendar')
> +
>          #Add auth to global headers
>          self.headers = self.headeraddauth("cosmo- 
> timerangequeryTestAccount", "cosmo-timerange")
>
> @@ -42,6 +47,8 @@
>
>          # ------- Test Creation of events view ICS ------- #
>
> +        self.teststart('Put 1-7.ics')
> +
>          #Construct headers & body
>          puticsheaders = self.headeradd({'Content-Type' : 'text/ 
> calendar'})
>          put1icspath = self.pathbuilder('/home/cosmo- 
> timerangequeryTestAccount/calendar/1.ics')
> @@ -83,175 +90,71 @@
>
>          # --------- Test 1.xml query for VEVENTs within time range
>
> +        self.teststart('Test 1.xml query for VEVENTs within time  
> range')
> +
>          #Setup request
>          f = open('files/reports/timerangequery/1.xml')
>          report1body = f.read()
>          self.request('REPORT', calpath, body=report1body,  
> headers=self.headers)
> -
> -        #Set all success counters
> -        elementcount = 0
> -        etagcount = 0
> -        icscount = 0
> -
> -        #Verify correct number of calendar-data elements
> -        self.xmlparse()
> -        test = self.xml_doc.findall('.// 
> {urn:ietf:params:xml:ns:caldav}calendar-data')
> -        for t in test:
> -            elementcount = elementcount + 1
> -
> -        #Verify correct number of etags
> -        test = self.xml_doc.findall('.//{DAV:}getetag')
> -        for t in test:
> -            etagcount = etagcount + 1
>
>          vcalitems = ['BEGIN:VCALENDAR', 'CALSCALE:GREGORIAN',  
> 'PRODID', 'VERSION:2.0',
>                        'BEGIN:VTIMEZONE', 'LAST-MODIFIED:', 'TZID',  
> 'BEGIN:DAYLIGHT',
>                        'DTSTART:', 'RRULE:', 'TZNAME:',  
> 'TZOFFSETFROM:', 'TZOFFSETTO:',
>                        'END:', 'BEGIN:STANDARD', 'END:STANDARD',  
> 'END:VTIMEZONE', 'END:VCALENDAR',
>                        'BEGIN:VEVENT', 'SUMMARY:event', 'END:VEVENT']
> +
> +        self.verifyitems('5.ics', '6.ics', '7.ics',  
> inelement='{urn:ietf:params:xml:ns:caldav}calendar-data',  
> positive=vcalitems)
>
> -        #Check response elements for each response and verify the  
> calendar-data element has the proper info
> -        test = self.xml_doc.findall('.//{DAV:}response')
> -        for t in test:
> -            if t[0].text.find('.ics') != -1:
> -                if t[0].text.find('5.ics') != -1 & t[0].text.find 
> ('6.ics') != -1 & t[0].text.find('7.ics') != -1:
> -                    self.printout('FAILED - element is not 5,6, or  
> 7.ics')
> -                    icscount = icscount -1
> -                    break
> -                ctest = t.find('.//{urn:ietf:params:xml:ns:caldav} 
> calendar-data')
> -                icscount = icscount + 1
> -                for x in vcalitems:
> -                    if ctest.text.find(x) == -1:
> -                        self.printout('FAILED to get %s in %s' %  
> (x, t[0].text))
> -                        icscount = icscount - 100
> -
> -
> -
> -        #Run through all the elemenet and etag counts and make  
> sure they match
> -        if elementcount == 3 & icscount == 3 & etagcount == 3:
> -            self.report(True, test='report/timerangequery/1.xml  
> REPORT return 3 caldata elements query for VEVENTs within time  
> range', comment=None)
> -        else:
> -            self.report(False, test='report/timerangequery/1.xml  
> REPORT return 3 caldata elements query for VEVENTs within time  
> range', comment='Returned %s elements & %s ics matches' %  
> (elementcount, icscount))
> -
>          # --------- Test 2.xml query for VEVENTs that have a  
> DTSTART within time range
>
> +        self.teststart('Test 2.xml query for VEVENTs that have a  
> DTSTART within time range')
> +
>          #Setup request
>          f = open('files/reports/timerangequery/2.xml')
>          report2body = f.read()
>          self.request('REPORT', calpath, body=report2body,  
> headers=self.headers)
> -
> -        #Set all success counters
> -        elementcount = 0
> -        etagcount = 0
> -        icscount = 0
> -
> -        #Verify correct number of calendar-data elements
> -        self.xmlparse()
> -        test = self.xml_doc.findall('.// 
> {urn:ietf:params:xml:ns:caldav}calendar-data')
> -        for t in test:
> -            elementcount = elementcount + 1
> -
> -        #Verify correct number of etags
> -        test = self.xml_doc.findall('.//{DAV:}getetag')
> -        for t in test:
> -            etagcount = etagcount + 1
> -
> -        vcalitems = ['BEGIN:VCALENDAR', 'CALSCALE:GREGORIAN',  
> 'PRODID', 'VERSION:2.0',
> -                      'BEGIN:VTIMEZONE', 'LAST-MODIFIED:', 'TZID',  
> 'BEGIN:DAYLIGHT',
> -                      'DTSTART:', 'RRULE:', 'TZNAME:',  
> 'TZOFFSETFROM:', 'TZOFFSETTO:',
> -                      'END:', 'BEGIN:STANDARD', 'END:STANDARD',  
> 'END:VTIMEZONE', 'END:VCALENDAR',
> -                      'BEGIN:VEVENT', 'SUMMARY:event', 'END:VEVENT']
> -
> -        #Check response elements for each response and verify the  
> calendar-data element has the proper info
> -        test = self.xml_doc.findall('.//{DAV:}response')
> -        for t in test:
> -            if t[0].text.find('.ics') != -1:
> -                if t[0].text.find('1.ics') != -1 & t[0].text.find 
> ('2.ics') != -1 & t[0].text.find('3.ics') != -1 & t[0].text.find 
> ('4.ics'):
> -                    self.printout('FAILED - element is not 1,2,3  
> or 4.ics')
> -                    icscount = icscount -1
> -                    break
> -                ctest = t.find('.//{urn:ietf:params:xml:ns:caldav} 
> calendar-data')
> -                icscount = icscount + 1
> -                for x in vcalitems:
> -                    if ctest.text.find(x) == -1:
> -                        self.printout('FAILED to get %s in %s' %  
> (x, t[0].text))
> -                        icscount = icscount - 100
>
> -
> -
> -        #Run through all the elemenet and etag counts and make  
> sure they match
> -        if elementcount == 4 & icscount == 4 & etagcount == 4:
> -            self.report(True, test='report/timerangequery/2.xml  
> REPORT return 4 caldata elements query for VEVENTs that have a  
> DTSTART within time range', comment=None)
> -        else:
> -            self.report(False, test='report/timerangequery/2.xml  
> REPORT return 4 caldata elements query for VEVENTs that have a  
> DTSTART within time range', comment='Returned %s elements & %s ics  
> matches' % (elementcount, icscount))
> -
> -
> +        self.verifyitems('1.ics', '2.ics', '3.ics', '4.ics',  
> positive=vcalitems, inelement='{urn:ietf:params:xml:ns:caldav} 
> calendar-data')
> +
>          # --------- Test 3.xml query for VALARMS within time range
>
> +        self.teststart('Test 3.xml query for VALARMS within time  
> range')
> +
>          #Setup request
>          f = open('files/reports/timerangequery/3.xml')
>          report3body = f.read()
>          self.request('REPORT', calpath, body=report3body,  
> headers=self.headers)
> -
> -        #Set all success counters
> -        elementcount = 0
> -        etagcount = 0
> -        icscount = 0
> -
> -        #Verify correct number of calendar-data elements
> -        self.xmlparse()
> -        test = self.xml_doc.findall('.// 
> {urn:ietf:params:xml:ns:caldav}calendar-data')
> -        for t in test:
> -            elementcount = elementcount + 1
> -
> -        #Verify correct number of etags
> -        test = self.xml_doc.findall('.//{DAV:}getetag')
> -        for t in test:
> -            etagcount = etagcount + 1
>
> -        vcalitems = ['BEGIN:VCALENDAR', 'CALSCALE:GREGORIAN',  
> 'PRODID', 'VERSION:2.0',
> -                      'BEGIN:VTIMEZONE', 'LAST-MODIFIED:', 'TZID',  
> 'BEGIN:DAYLIGHT',
> -                      'DTSTART:', 'RRULE:', 'TZNAME:',  
> 'TZOFFSETFROM:', 'TZOFFSETTO:',
> -                      'END:', 'BEGIN:STANDARD', 'END:STANDARD',  
> 'END:VTIMEZONE', 'END:VCALENDAR',
> -                      'BEGIN:VEVENT', 'SUMMARY:event', 'END:VEVENT']
> +        self.verifyitems('4.ics', positive=vcalitems,  
> inelement='{urn:ietf:params:xml:ns:caldav}calendar-data')
> +
> +        # --------- Test 4.xml
>
> -        #Check response elements for each response and verify the  
> calendar-data element has the proper info
> -        test = self.xml_doc.findall('.//{DAV:}response')
> -        for t in test:
> -            if t[0].text.find('4.ics') != -1:
> -                ctest = t.find('.//{urn:ietf:params:xml:ns:caldav} 
> calendar-data')
> -                icscount = icscount + 1
> -                for x in vcalitems:
> -                    if ctest.text.find(x) == -1:
> -                        self.printout('FAILED to get %s in %s' %  
> (x, t[0].text))
> -                        icscount = icscount - 100
> -
> -        #Run through all the elemenet and etag counts and make  
> sure they match
> -        if elementcount == 1 & icscount == 1 & etagcount == 1:
> -            self.report(True, test='report/timerangequery/3.xml  
> REPORT return 1 caldata elements query for VALARMS within time  
> range', comment=None)
> -        else:
> -            self.report(False, test='report/timerangequery/3.xml  
> REPORT return 1 caldata elements query for VALARMS within time  
> range', comment='Returned %s elements & %s ics matches' %  
> (elementcount, icscount))
> +        self.teststart('Test 4.xml')
>
> -        # --------- Test 4.xml
> -
>          #Setup request
>          f = open('files/reports/timerangequery/4.xml')
>          report4body = f.read()
>          self.request('REPORT', calpath, body=report4body,  
> headers=self.headers)
>
> -        ##Blocked by bug 5551
> +        self.verifyitems('1.ics', '2.ics', '3.ics', '4.ics',  
> '5.ics', '6.ics', '7.ics', positive=vcalitems,  
> inelement='{urn:ietf:params:xml:ns:caldav}calendar-data')
>
>          # --------- Test 5.xml
>
> +        self.teststart('Test 5.xml')
> +
>          #Setup request
>          f = open('files/reports/timerangequery/5.xml')
>          report5body = f.read()
>          self.request('REPORT', calpath, body=report5body,  
> headers=self.headers)
>
> +        self.verifyitems('1.ics', '2.ics', '3.ics', '4.ics',  
> '5.ics', '6.ics', '7.ics', positive=vcalitems,  
> inelement='{urn:ietf:params:xml:ns:caldav}calendar-data')
> +
>          ##Blocked by bug 5551
>
>          # -------------- More time range tests
>
> +        self.teststart('Uploading Float Events')
> +
>          # Put all float cals
>          putfloat1icspath = self.pathbuilder('/home/cosmo- 
> timerangequeryTestAccount/calendar/float1.ics')
>          putfloat2icspath = self.pathbuilder('/home/cosmo- 
> timerangequeryTestAccount/calendar/float2.ics')
> @@ -270,25 +173,186 @@
>
>          # ---------------- oneInHonolulu.xml test
>
> +        self.teststart('oneInHonolulu.xml')
> +
>          #Build request
>          f = open('files/reports/timerangequery/oneInHonolulu.xml')
>          reportoneInHonolulubody = f.read()
>          self.request('REPORT', calpath,  
> body=reportoneInHonolulubody, headers=self.headers)
>
> +        vcalitems = ['BEGIN:VCALENDAR', 'CALSCALE:GREGORIAN',  
> 'PRODID:-//Cyrusoft International\, Inc.//Mulberry v4.0//EN',
> +                      'VERSION:2.0', 'BEGIN:VEVENT', 'DTSTART: 
> 20060330T120000', 'DTEND:20060330T130000', 'SUMMARY:Floating Event  
> One',
> +                      'DESCRIPTION: This event should appear in  
> Honolulu, Mountain, and Eastern', 'UID: 
> 54E181BC7CCC373042B21884211 at ninevah.local',
> +                      'END:VEVENT', 'END:VCALENDAR']
> +
> +        negcalitems = ['LAST-MODIFIED:', 'TZID',  
> 'BEGIN:DAYLIGHT','RRULE:', 'TZNAME:',
> +                        'TZOFFSETFROM:', 'TZOFFSETTO:']
> +
> +        self.verifyitems('float1.ics', positive=vcalitems,  
> negative=negcalitems, inelement='{urn:ietf:params:xml:ns:caldav} 
> calendar-data')
> +
>          # ---------------- twoInMountain.xml test
>
> +        self.teststart('twoInMountain.xml')
> +
>          f = open('files/reports/timerangequery/twoInMountain.xml')
>          reporttwoInMountainbody = f.read()
>          self.request('REPORT', calpath,  
> body=reporttwoInMountainbody, headers=self.headers)
>
> +        self.verifyitems('float1.ics','float2.ics',  
> inelement='{urn:ietf:params:xml:ns:caldav}calendar-data',  
> inelementexpectedcount=2)
> +        self.verifyinelement('float1.ics',  
> '{urn:ietf:params:xml:ns:caldav}calendar-data', positive=vcalitems,  
> negative=negcalitems)
> +
> +        vcalitems = ['BEGIN:VCALENDAR', 'CALSCALE:GREGORIAN',  
> 'PRODID:-//Cyrusoft International\, Inc.//Mulberry v4.0//EN',
> +                      'VERSION:2.0', 'BEGIN:VEVENT', 'DTSTART: 
> 20060330T150000', 'DTEND:20060330T160000', 'SUMMARY:Floating Event  
> Two',
> +                      'DESCRIPTION: This event should appear in  
> Honolulu and Mountain', 'UID: 
> 54E181BC7CCC373042B218842112 at ninevah.local',
> +                      'END:VEVENT', 'END:VCALENDAR']
> +
> +        self.verifyinelement('float2.ics',  
> '{urn:ietf:params:xml:ns:caldav}calendar-data', positive=vcalitems,  
> negative=negcalitems)
> +
>          # ----------------- threeInEastern.xml test
> +
> +        self.teststart('threeInEastern.xml')
>
>          f = open('files/reports/timerangequery/threeInEastern.xml')
>          reportthreeInEasternbody = f.read()
>          self.request('REPORT', calpath,  
> body=reportthreeInEasternbody, headers=self.headers)
>
> +        vcalitems = ['BEGIN:VCALENDAR', 'CALSCALE:GREGORIAN',  
> 'PRODID:-//Cyrusoft International\, Inc.//Mulberry v4.0//EN',
> +                      'VERSION:2.0', 'BEGIN:VEVENT', 'DTSTART: 
> 20060330T120000', 'DTEND:20060330T130000', 'SUMMARY:Floating Event  
> One',
> +                      'DESCRIPTION: This event should appear in  
> Honolulu, Mountain, and Eastern', 'UID: 
> 54E181BC7CCC373042B21884211 at ninevah.local',
> +                      'END:VEVENT', 'END:VCALENDAR']
> +
> +        negcalitems = ['LAST-MODIFIED:', 'TZID',  
> 'BEGIN:DAYLIGHT','RRULE:', 'TZNAME:',
> +                        'TZOFFSETFROM:', 'TZOFFSETTO:']
> +
> +        self.verifyitems('float1.ics','float2.ics', 'float3.ics',  
> inelement='{urn:ietf:params:xml:ns:caldav}calendar-data',  
> inelementexpectedcount=3)
> +        self.verifyinelement('float1.ics',  
> '{urn:ietf:params:xml:ns:caldav}calendar-data', positive=vcalitems,  
> negative=negcalitems)
>
> +        vcalitems = ['BEGIN:VCALENDAR', 'CALSCALE:GREGORIAN',  
> 'PRODID:-//Cyrusoft International\, Inc.//Mulberry v4.0//EN',
> +                      'VERSION:2.0', 'BEGIN:VEVENT', 'DTSTART: 
> 20060330T150000', 'DTEND:20060330T160000', 'SUMMARY:Floating Event  
> Two',
> +                      'DESCRIPTION: This event should appear in  
> Honolulu and Mountain', 'UID: 
> 54E181BC7CCC373042B218842112 at ninevah.local',
> +                      'END:VEVENT', 'END:VCALENDAR']
>
> +        self.verifyinelement('float2.ics',  
> '{urn:ietf:params:xml:ns:caldav}calendar-data', positive=vcalitems,  
> negative=negcalitems)
> +
> +        vcalitems = ['BEGIN:VCALENDAR', 'CALSCALE:GREGORIAN',  
> 'PRODID:-//Cyrusoft International\, Inc.//Mulberry v4.0//EN',
> +                      'VERSION:2.0', 'BEGIN:VEVENT', 'DTSTART: 
> 20060330T170000', 'DTEND:20060330T180000', 'SUMMARY:Floating Event  
> Three',
> +                      'DESCRIPTION: This event should appear in  
> Honolulu', 'UID:54E181BC7CCC373042B218842113 at ninevah.local',
> +                      'END:VEVENT', 'END:VCALENDAR']
> +
> +        self.verifyinelement('float3.ics',  
> '{urn:ietf:params:xml:ns:caldav}calendar-data', positive=vcalitems,  
> negative=negcalitems)
> +
> +        # ----------------- invalid_nonUTC1 ---- specified by  
> bkirsh via email on 4/5/2006
> +
> +        self.teststart('invalid_nonUTC1')
> +
> +        #Setup request
> +        f = open('files/reports/timerangequery/invalid_nonUTC1.xml')
> +        report_invalid_nonUTC1body = f.read()
> +        self.request('REPORT', calpath,  
> body=report_invalid_nonUTC1body, headers=self.headers)
> +
> +        #Check Status = 400
> +        self.checkStatus(400)
> +
> +        # ----------------- invalid_nonUTC2 ---- specified by  
> bkirsh via email on 4/5/2006
> +
> +        self.teststart('invalid_nonUTC2')
> +
> +        #Setup request
> +        f = open('files/reports/timerangequery/invalid_nonUTC2.xml')
> +        report_invalid_nonUTC2body = f.read()
> +        self.request('REPORT', calpath,  
> body=report_invalid_nonUTC2body, headers=self.headers)
> +
> +        #Check Status = 400
> +        self.checkStatus(400)
> +
> +        # ----------------- invalid_nonUTC3 ---- specified by  
> bkirsh via email on 4/5/2006
> +
> +        self.teststart('invalid_nonUTC3')
> +
> +        #Setup request
> +        f = open('files/reports/timerangequery/invalid_nonUTC3.xml')
> +        report_invalid_nonUTC3body = f.read()
> +        self.request('REPORT', calpath,  
> body=report_invalid_nonUTC3body, headers=self.headers)
> +
> +        #Check Status = 400
> +        self.checkStatus(400)
> +
> +        # ----------------- invalid_nonUTC4 ---- specified by  
> bkirsh via email on 4/5/2006
> +
> +        self.teststart('invalid_nonUTC4')
> +
> +        #Setup request
> +        f = open('files/reports/timerangequery/invalid_nonUTC4.xml')
> +        report_invalid_nonUTC4body = f.read()
> +        self.request('REPORT', calpath,  
> body=report_invalid_nonUTC4body, headers=self.headers)
> +
> +        #Check Status = 400
> +        self.checkStatus(400)
> +
> +        # ----------------- invalid_nonUTC5 ---- specified by  
> bkirsh via email on 4/5/2006
> +
> +        self.teststart('invalid_nonUTC5')
> +
> +        #Setup request
> +        f = open('files/reports/timerangequery/invalid_nonUTC5.xml')
> +        report_invalid_nonUTC5body = f.read()
> +        self.request('REPORT', calpath,  
> body=report_invalid_nonUTC5body, headers=self.headers)
> +
> +        #Check Status = 400
> +        self.checkStatus(400)
> +
> +        # ----------------- invalid_nonUTC6 ---- specified by  
> bkirsh via email on 4/5/2006
> +
> +        self.teststart('invalid_nonUTC6')
> +
> +        #Setup request
> +        f = open('files/reports/timerangequery/invalid_nonUTC6.xml')
> +        report_invalid_nonUTC6body = f.read()
> +        self.request('REPORT', calpath,  
> body=report_invalid_nonUTC6body, headers=self.headers)
> +
> +        #Check Status = 400
> +        self.checkStatus(400)
> +
> +        # ----------------- timerange_01 ---- specified by bkirsh  
> via email on 4/5/2006
> +
> +        self.teststart('timerange_01')
> +
> +        #Setup request
> +        f = open('files/reports/timerangequery/timerange_01.xml')
> +        report_timerange_01body = f.read()
> +        self.request('REPORT', calpath,  
> body=report_timerange_01body, headers=self.headers)
> +
> +        #Check Status = 207 Multistatus
> +        self.checkStatus(207)
> +
> +        # ----------------- timerange_02 ---- specified by bkirsh  
> via email on 4/5/2006
> +
> +        self.teststart('timerange_02')
> +
> +        #Setup request
> +        f = open('files/reports/timerangequery/timerange_02.xml')
> +        report_timerange_02body = f.read()
> +        self.request('REPORT', calpath,  
> body=report_timerange_02body, headers=self.headers)
> +
> +        #Check Status = 207 Multistatus
> +        self.checkStatus(207)
> +
> +        # ----------------- timerange_03 ---- specified by bkirsh  
> via email on 4/5/2006
> +
> +        self.teststart('timerange_03')
> +
> +        #Setup request
> +        f = open('files/reports/timerangequery/timerange_03.xml')
> +        report_timerange_03body = f.read()
> +        self.request('REPORT', calpath,  
> body=report_timerange_03body, headers=self.headers)
> +
> +        #Check Status = 207 Multistatus
> +        self.checkStatus(207)
> +
> +
> +
> +
> +
>  if __name__ == "__main__":
>
>      import sys
> Added: cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC1.xml (1758 => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC1.xml	2006-04-07 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC1.xml	2006-04-08 00:09:17 UTC (rev 1759)
> @@ -0,0 +1,13 @@
> +<?xml version="1.0" encoding="utf-8" ?>
> +<C:calendar-query xmlns:D="DAV:"  
> xmlns:C="urn:ietf:params:xml:ns:caldav">
> +  <D:prop>
> +    <D:getetag/>
> +  </D:prop>
> +  <C:filter>
> +    <C:comp-filter name="VCALENDAR">
> +      <C:comp-filter name="VEVENT">
> +        <C:time-range start="20060102T000000Z" end="20060103T00000"/>
> +      </C:comp-filter>
> +    </C:comp-filter>
> +  </C:filter>
> +</C:calendar-query>
> Added: cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC2.xml (1758 => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC2.xml	2006-04-07 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC2.xml	2006-04-08 00:09:17 UTC (rev 1759)
> @@ -0,0 +1,13 @@
> +<?xml version="1.0" encoding="utf-8" ?>
> +<C:calendar-query xmlns:D="DAV:"  
> xmlns:C="urn:ietf:params:xml:ns:caldav">
> +  <D:prop>
> +    <D:getetag/>
> +  </D:prop>
> +  <C:filter>
> +    <C:comp-filter name="VCALENDAR">
> +      <C:comp-filter name="VEVENT">
> +        <C:time-range start="20060102T00000" end="20060103T000000Z"/>
> +      </C:comp-filter>
> +    </C:comp-filter>
> +  </C:filter>
> +</C:calendar-query>
> Added: cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC3.xml (1758 => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC3.xml	2006-04-07 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC3.xml	2006-04-08 00:09:17 UTC (rev 1759)
> @@ -0,0 +1,16 @@
> +<?xml version="1.0" encoding="utf-8" ?>
> +<C:calendar-query xmlns:D="DAV:"  
> xmlns:C="urn:ietf:params:xml:ns:caldav">
> +  <D:prop>
> +    <D:getetag/>
> +    <C:calendar-data>
> +      <C:expand start="20060102T000000" end="20060105T000000Z"/>
> +    </C:calendar-data>
> +  </D:prop>
> +  <C:filter>
> +    <C:comp-filter name="VCALENDAR">
> +      <C:comp-filter name="VEVENT">
> +        <C:time-range start="20060102T000000Z"  
> end="20060105T000000Z"/>
> +      </C:comp-filter>
> +    </C:comp-filter>
> +  </C:filter>
> +</C:calendar-query>
> Added: cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC4.xml (1758 => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC4.xml	2006-04-07 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC4.xml	2006-04-08 00:09:17 UTC (rev 1759)
> @@ -0,0 +1,16 @@
> +<?xml version="1.0" encoding="utf-8" ?>
> +<C:calendar-query xmlns:D="DAV:"  
> xmlns:C="urn:ietf:params:xml:ns:caldav">
> +  <D:prop>
> +    <D:getetag/>
> +    <C:calendar-data>
> +      <C:expand start="20060102T000000Z" end="20060105T000000"/>
> +    </C:calendar-data>
> +  </D:prop>
> +  <C:filter>
> +    <C:comp-filter name="VCALENDAR">
> +      <C:comp-filter name="VEVENT">
> +        <C:time-range start="20060102T000000Z"  
> end="20060105T000000Z"/>
> +      </C:comp-filter>
> +    </C:comp-filter>
> +  </C:filter>
> +</C:calendar-query>
> Added: cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC5.xml (1758 => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC5.xml	2006-04-07 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC5.xml	2006-04-08 00:09:17 UTC (rev 1759)
> @@ -0,0 +1,15 @@
> +<C:calendar-query xmlns:D="DAV:"  
> xmlns:C="urn:ietf:params:xml:ns:caldav">
> +  <D:prop>
> +    <D:getetag/>
> +    <C:calendar-data>
> +      <C:limit-recurrence-set start="20060102T00000"  
> end="20060103T000000Z"/>
> +    </C:calendar-data>
> +  </D:prop>
> +  <C:filter>
> +    <C:comp-filter name="VCALENDAR">
> +      <C:comp-filter name="VEVENT">
> +        <C:time-range start="20060102T000000Z"  
> end="20060103T000000Z"/>
> +      </C:comp-filter>
> +    </C:comp-filter>
> +  </C:filter>
> +</C:calendar-query>
> Added: cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC6.xml (1758 => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC6.xml	2006-04-07 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/invalid_nonUTC6.xml	2006-04-08 00:09:17 UTC (rev 1759)
> @@ -0,0 +1,16 @@
> +<?xml version="1.0" encoding="utf-8" ?>
> +<C:calendar-query xmlns:D="DAV:"  
> xmlns:C="urn:ietf:params:xml:ns:caldav">
> +  <D:prop>
> +    <D:getetag/>
> +    <C:calendar-data>
> +      <C:limit-recurrence-set start="20060102T000000Z"  
> end="20060103T000000"/>
> +    </C:calendar-data>
> +  </D:prop>
> +  <C:filter>
> +    <C:comp-filter name="VCALENDAR">
> +      <C:comp-filter name="VEVENT">
> +        <C:time-range start="20060102T000000Z"  
> end="20060103T000000Z"/>
> +      </C:comp-filter>
> +    </C:comp-filter>
> +  </C:filter>
> +</C:calendar-query>
> Added: cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_01.xml (1758 => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_01.xml	2006-04-07 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_01.xml	2006-04-08 00:09:17 UTC (rev 1759)
> @@ -0,0 +1,16 @@
> +<?xml version="1.0" encoding="utf-8" ?>
> + <C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav">
> +  <D:prop xmlns:D="DAV:">
> +    <D:getetag/>
> +    <C:calendar-data/>
> +  </D:prop>
> +  <C:filter>
> +    <C:comp-filter name="VCALENDAR">
> +      <C:comp-filter name="VTODO">
> +        <C:comp-filter name="VALARM">
> +           <C:time-range start="20060106T100000Z"  
> end="20060107T100000Z"/>
> +        </C:comp-filter>
> +      </C:comp-filter>
> +     </C:comp-filter>
> +   </C:filter>
> +</C:calendar-query>
> Added: cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_02.xml (1758 => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_02.xml	2006-04-07 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_02.xml	2006-04-08 00:09:17 UTC (rev 1759)
> @@ -0,0 +1,13 @@
> +<?xml version="1.0" encoding="utf-8" ?>
> +<C:calendar-query xmlns:D="DAV:"  
> xmlns:C="urn:ietf:params:xml:ns:caldav">
> +  <D:prop>
> +    <D:getcontenttype/>
> +  </D:prop>
> +  <C:filter>
> +    <C:comp-filter name="VCALENDAR">
> +      <C:comp-filter name="VEVENT">
> +        <C:time-range start="20060102T000000Z"  
> end="20060103T000000Z"/>
> +      </C:comp-filter>
> +    </C:comp-filter>
> +  </C:filter>
> +</C:calendar-query>
> Added: cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_03.xml (1758 => 1759)
>
> --- cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_03.xml	2006-04-07 23:09:57 UTC (rev 1758)
> +++ cosmo/trunk/src/test/functional/HTTPTest/files/reports/ 
> timerangequery/timerange_03.xml	2006-04-08 00:09:17 UTC (rev 1759)
> @@ -0,0 +1,16 @@
> +<?xml version="1.0" encoding="utf-8" ?>
> +  <C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav">
> +    <D:prop xmlns:D="DAV:">
> +       <D:getetag/>
> +       <C:calendar-data/>
> +    </D:prop>
> +     <C:filter>
> +          <C:comp-filter name="VCALENDAR">
> +                 <C:comp-filter name="VEVENT">
> +                      <C:prop-filter name="SUMMARY">
> +                        <C:text-match>event 3</C:text-match>
> +                      </C:prop-filter>
> +           </C:comp-filter>
> +    </C:comp-filter>
> +    </C:filter>
> +</C:calendar-query>
>
> _______________________________________________
> Commits-Cosmo mailing list
> Commits-Cosmo at osafoundation.org
> http://lists.osafoundation.org/cgi-bin/mailman/listinfo/commits-cosmo

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osafoundation.org/pipermail/commits-cosmo/attachments/20060407/8a4edd6e/attachment.html


More information about the Commits-Cosmo mailing list