#!/usr/bin/python

"""Regression test harness for new versions of RDF Calendar tools

Originally a regression test harness written by Tim Berners-Lee for cwm.
Adjustments were made to adopt the harness to round-trip test 
  http://www.w3.org/2000/10/swap/pim/toIcal.py and 
  http://www.w3.org/2002/12/cal/ical2rdf.py.

Options:

--testsFrom=uri -f uri  Take test definitions from these files (in RDF/XML or N3 format)
--start=13      -s 13   Skip the first 12 tests
--verbose       -v      Print what you are doing as you go
--ignoreErrors  -i      Print error message but plough on though more tests if errors found
                        (Summary error still raised when all tests ahve been tried)
--help          -h      Print this message and exit

You must specify some test definitions, and normal or proofs or both,
or nothing will happen.

Example:    python cal-retest.py -f regression.n3

 $Id: cal-retest.py,v 1.3 2005/02/26 03:20:47 connolly Exp $
This is or was http://www.w3.org/2002/12/cal/cal-retest.py
This was adopted from http://www.w3.org/2000/10/swap/test/retest.py
W3C open source license <http://www.w3.org/Consortium/Legal/copyright-software.html>.

"""
from os import system
import os
import sys
import urllib

# From PYTHONPATH equivalent to http://www.w3.org/2000/10/swap

import llyn
from myStore import load, loadMany, Namespace

RDF = Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
TEST = Namespace("http://www.w3.org/2002/12/cal/caltest.n3#")
#rdft = Namespace("http://www.w3.org/2000/10/rdf-tests/rdfcore/testSchema#")
#triage = Namespace("http://www.w3.org/2000/10/swap/test/triage#")
GC = Namespace("http://www.w3.org/2002/12/cal/test/graphCompare.n3#")

import getopt
import sys

CP = "cp"
PYTHON = "python"
PERL = "perl"
CAL = ".."
SWAP = "../../../../2000/10/swap"
#ICAL2RDF = CAL + "/ical2rdf.pl"
FROMICAL="../fromIcal.py"
TOICAL = SWAP + "/pim/toIcal.py"
CWM = SWAP + "/cwm.py"
CALTEST = 'http://www.w3.org/2002/12/cal/test'

def localize(uri):
    """Get URI relative to where this lives"""
    import uripath
    return uripath.refTo("http://www.w3.org/2000/10/swap/test/retest.py", uri)

def problem(str):
    global ploughOn
    global problems
    sys.stderr.write(str + "\n")
    problems = problems + 1
    if not ploughOn:
        sys.exit(-1)

def usage():
    print __doc__

def execute(cmd1):
    global verbose
    global ploughOn
    if verbose: print "    "+cmd1
    result = system(cmd1)
    if result != 0:
        if ploughOn:
            problem("Error %i executing %s" %(result, cmd1))
        else: 
            raise RuntimeError("Error %i executing %s" %(result, cmd1))

def diff(case):
    global verbose
    # perform graph comparison
    diffcmd ="""PYTHONPATH=%s %s %s graphCompare.n3 --think --purge-rules --with %s.rdf ,temp/%s,.rdf > ,compare/%s-compare.n3 """ % (SWAP, PYTHON, CWM, case, case, case) 
    execute(diffcmd)        
    sts = load(",compare/%s-compare.n3" % case)
    if not sts:
        problem("Unable to load %s-compare.n3!" % case)
    success = sts.statementsMatching(subj = GC.thisTest, obj = GC.Success)
    if not success:
        sys.stderr.write("Comparison fails: executing %s" % diffcmd + "\n")
        return 1
    return 0

def main():
    testFiles = []
    start = 1
    normal = 0
    chatty = 0
    proofs = 0
    global ploughOn # even if error
    ploughOn = 0
    global verbose
    verbose = 0
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hs:if:v",
            ["help", "start=", "testsFrom=", "ignoreErrors", "verbose"])
    except getopt.GetoptError:
        # print help information and exit:
        usage()
        sys.exit(2)
    output = None
    for o, a in opts:
        if o in ("-h", "--help"):
            usage()
            sys.exit()
        if o in ("-v", "--verbose"):
            verbose = 1
        if o in ("-i", "--ignoreErrors"):
            ploughOn = 1
        if o in ("-s", "--start"):
            start = int(a)
        if o in ("-f", "--testsFrom"):
            testFiles.append(a)

    if not testFiles:
        usage()
        sys.exit(2)

    assert system("mkdir -p ,temp") == 0
    assert system("mkdir -p ,compare") == 0
    
    tests=0
    passes=0
    global problems
    problems = 0
    
    # REFWD="file:/devel/WWW/2002/12/cal/test"
    WD = "file:" + os.getcwd()
    
    kb = loadMany(testFiles)
    testData = []
    RDFTestData  = []
    
    for t in kb.each(pred=RDF.type, obj=TEST.CalTest):
        case = str(kb.the(t, TEST.shortFileName))
        description = str(kb.the(t, TEST.description))
        initrdf = str(kb.the(t, TEST.initRDF))
        testData.append((t.uriref(), case, description, initrdf))

    testData.sort()
    if verbose: print "RDF Calendar tests: %i" % len(testData)

    for u, case, description, initrdf in testData:
        tests = tests + 1
        if tests < start: continue
    
        print "######### %3i)  %s" %(tests, description)
        assert case and description 
        # cleanup = """sed -e 's/\$[I]d.*\$//g' -e "s;%s;%s;g" -e '/@prefix run/d'""" % (WD, REFWD)
        
        # generate or copy existing initial RDF file
        if initrdf == "yes":
            #@@ dead code
            cmd = """%s %s %s.ics > ,temp/%s.rdf""" % (PERL, ICAL2RDF, case, case)
            execute(cmd)
        else:
            pass
            #cmd = """%s %s.rdf ,temp/%s.rdf""" % (CP, case, case)
            #execute(cmd)
        # trip to iCal
        cmd = """PYTHONPATH=%s:.. %s %s %s.rdf > ,temp/%s,.ics """ % \
              (SWAP, PYTHON, TOICAL, case, case)
        execute(cmd)        
        # trip to RDF
        cmd = """%s %s --base %s/%s ,temp/%s,.ics > ,temp/%s,.rdf """ % \
              (PYTHON, FROMICAL, CALTEST, case, case, case)
        execute(cmd)        
        # perform comparison 
        if diff(case):
            problem("#########   test case failed: %s" % (case))
            continue

        passes = passes + 1

    if problems > 0:
        raise RuntimeError("Total %i errors in %i tests." % (problems, tests))
    else:
        print "No errors in %i tests." % tests

if __name__ == "__main__":
    main()


# ends
