1781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard#!/usr/bin/python -u
2781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardimport string, sys, time
32cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillardtry:
42cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillard    from _thread import get_ident
52cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillardexcept:
62cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillard    from thread import get_ident
7781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardfrom threading import Thread, Lock
8781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
9781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardimport libxml2
10781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
11781ac8b19bfc10635a8bb83158f874116fd7559eDaniel VeillardTHREADS_COUNT = 15
12781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
13781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardfailed = 0
14781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
15781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardclass ErrorHandler:
16781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
17781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    def __init__(self):
18781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard        self.errors = []
19781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard        self.lock = Lock()
20781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
21781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    def handler(self,ctx,str):
22781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard        self.lock.acquire()
23781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard        self.errors.append(str)
24781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard        self.lock.release()
25781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
26781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillarddef getLineNumbersDefault():
27781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    old = libxml2.lineNumbersDefault(0)
28781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    libxml2.lineNumbersDefault(old)
29781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    return old
30781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
31781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillarddef test(expectedLineNumbersDefault):
32781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    time.sleep(1)
33781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    global failed
34781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    # check a per thread-global
35781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    if expectedLineNumbersDefault != getLineNumbersDefault():
36781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard        failed = 1
372cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillard        print("FAILED to obtain correct value for " \
382cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillard              "lineNumbersDefault in thread %d" % get_ident())
39781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    # check ther global error handler
40781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    # (which is NOT per-thread in the python bindings)
41781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    try:
42781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard        doc = libxml2.parseFile("bad.xml")
43781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    except:
44781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard        pass
45781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    else:
46781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard        assert "failed"
47781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
48781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard# global error handler
49781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardeh = ErrorHandler()
50781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardlibxml2.registerErrorHandler(eh.handler,"")
51781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
52781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard# set on the main thread only
53781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardlibxml2.lineNumbersDefault(1)
54781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardtest(1)
55781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardec = len(eh.errors)
56781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardif ec == 0:
572cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillard    print("FAILED: should have obtained errors")
58781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    sys.exit(1)
59781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
60781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardts = []
61781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardfor i in range(THREADS_COUNT):
62781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    # expect 0 for lineNumbersDefault because
63781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    # the new value has been set on the main thread only
64781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    ts.append(Thread(target=test,args=(0,)))
65781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardfor t in ts:
66781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    t.start()
67781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardfor t in ts:
68781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    t.join()
69781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
70781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardif len(eh.errors) != ec+THREADS_COUNT*ec:
712cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillard    print("FAILED: did not obtain the correct number of errors")
72781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    sys.exit(1)
73781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
74781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard# set lineNumbersDefault for future new threads
75781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardlibxml2.thrDefLineNumbersDefaultValue(1)
76781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardts = []
77781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardfor i in range(THREADS_COUNT):
78781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    # expect 1 for lineNumbersDefault
79781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    ts.append(Thread(target=test,args=(1,)))
80781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardfor t in ts:
81781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    t.start()
82781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardfor t in ts:
83781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    t.join()
84781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
85781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardif len(eh.errors) != ec+THREADS_COUNT*ec*2:
862cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillard    print("FAILED: did not obtain the correct number of errors")
87781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    sys.exit(1)
88781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
89781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardif failed:
902cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillard    print("FAILED")
91781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    sys.exit(1)
92781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard
93781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard# Memory debug specific
94781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardlibxml2.cleanupParser()
95781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardif libxml2.debugMemory(1) == 0:
962cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillard    print("OK")
97781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillardelse:
982cb6bf8eb019cc88578093abee3e37a78e7b3020Daniel Veillard    print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
99781ac8b19bfc10635a8bb83158f874116fd7559eDaniel Veillard    libxml2.dumpMemory()
100