1#! /usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# file src/tex2lyx/test/runtests.py
5# This file is part of LyX, the document processor.
6# Licence details can be found in the file COPYING.
7
8# author Georg Baum
9
10# Full author contact details are available in file CREDITS
11
12# This script is a very basic test suite runner for tex2lyx
13# The defaults for optional command line arguments are tailored to the
14# standard use case of testing without special build settings like a version
15# suffix, since I don't know how to transport command line arguments through
16# the autotools "make check" mechanism.
17
18from __future__ import print_function
19
20import os, string, sys, time, difflib, filecmp, subprocess, re
21
22def usage(prog_name):
23  return "Usage: %s [uselyx2lyx] [<tex2lyx binary> [[<script dir>] [[<output dir>] [testfile]]]]" % prog_name
24
25pat_fl1 = re.compile(r'^#LyX file created by tex2lyx .*$')
26pat_fl2 = re.compile(r'^#LyX \d+\.\d+ created this file.*$')
27
28def compareLyx(lines1, lines2):
29    if lines1[1:] != lines2[1:]:
30        return False
31    if not pat_fl1.match(lines1[0]) and not pat_fl2.match(lines1[0]):
32        return False
33    if not pat_fl1.match(lines2[0]) and not pat_fl2.match(lines2[0]):
34        return False
35    return True
36
37def main(argv):
38    # Parse and manipulate the command line arguments.
39    skipcount = 0
40    uselyx2lyx = False
41    if len(argv) > 1:
42        if argv[1] == "uselyx2lyx":
43            uselyx2lyx = True
44            skipcount = 1
45    if len(argv) >= 3+skipcount:
46        sys.path.append(os.path.join(sys.argv[2+skipcount]))
47    else:
48        sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../lib/scripts'))
49
50    from lyxpreview_tools import error
51
52    if len(argv) < 2+skipcount:
53        tex2lyx = './tex2lyx'
54    elif len(argv) <= 5+skipcount:
55        tex2lyx = argv[1+skipcount]
56    else:
57        error(usage(argv[0]))
58
59    suffixre = re.search(r'\d+\.\d+$', tex2lyx)
60    if suffixre:
61        suffix = suffixre.group()
62    else:
63        suffix = ""
64    lyx = os.path.join(os.path.dirname(tex2lyx), "lyx" + suffix)
65    inputdir = os.path.realpath(os.path.dirname(argv[0]))
66    if len(argv) >= 4+skipcount:
67        outputdir = os.path.realpath(sys.argv[3+skipcount])
68    else:
69#        outputdir = inputdir
70        outputdir = os.path.realpath(os.path.join(os.path.dirname(tex2lyx), "test"))
71
72    if len(argv) >= 5+skipcount:
73        files = [sys.argv[4+skipcount]]
74    else:
75        files = ['test.ltx', \
76                 'algo2e.tex', \
77                 'beamer.tex', \
78                 'box-color-size-space-align.tex', \
79                 'CJK.tex', \
80                 'CJKutf8.tex', \
81                 'test-insets.tex', \
82                 'test-insets-basic.tex', \
83                 'test-memoir.tex', \
84                 'test-minted.tex', \
85                 'test-modules.tex', \
86                 'test-refstyle-theorems.tex', \
87                 'test-scr.tex', \
88                 'test-structure.tex', \
89                 'verbatim.tex', \
90                 'XeTeX-polyglossia.tex']
91
92    errors = []
93    overwrite = (outputdir == inputdir)
94    for f in files:
95        (base, ext) = os.path.splitext(f)
96        texfile = os.path.join(inputdir, f)
97        if overwrite:
98            # we are updating the test references, so use roundtrip to allow
99            # for checking the LyX export as well.
100            cmd = '%s -roundtrip -f %s' % (tex2lyx, texfile)
101        else:
102            lyxfile = os.path.join(outputdir, base + ".lyx")
103            cmd = '%s -roundtrip -copyfiles -f %s %s' % (tex2lyx, texfile, lyxfile)
104        print('Executing: ' + cmd + "\n")
105        proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
106        proc.wait()
107        err = proc.returncode
108        errorstring = proc.stderr.read()
109        if not errorstring is None:
110            print(errorstring)
111        if err != 0:
112            errors.append(f)
113        elif not overwrite:
114            lyxfile1 = getlyxinput(lyx,
115                        os.path.join(inputdir, base + ".lyx.lyx"),
116                        os.path.join(outputdir, base + ".lyx1.lyx") , uselyx2lyx)
117            if lyxfile1 is None:
118                errors.append(f)
119            else:
120                lyxfile2 = getlyxinput(lyx,
121                          os.path.join(outputdir, base + ".lyx"),
122                          os.path.join(outputdir, base + ".lyx2.lyx"), uselyx2lyx)
123                if lyxfile2 is None:
124                    errors.append(f)
125                else:
126                    t1 = time.ctime(os.path.getmtime(lyxfile1))
127                    t2 = time.ctime(os.path.getmtime(lyxfile2))
128                    f1 = open(lyxfile1, 'r')
129                    f2 = open(lyxfile2, 'r')
130                    lines1 = f1.readlines()
131                    i1 = 0
132                    for linex in lines1:
133                      if linex[:-1] == '\origin ' + inputdir + '/':
134                        lines1[i1] = '\origin ' + outputdir + '/' + "\n"
135                        break
136                      i1 = i1+1
137                    lines2 = f2.readlines()
138                    f1.close()
139                    f2.close()
140                    # ignore the first line e.g. the version of lyx
141                    if not compareLyx(lines1, lines2):
142                        diff = difflib.unified_diff(lines1, lines2, lyxfile1, lyxfile2, t1, t2)
143                        sys.stdout.writelines(diff)
144                        errors.append(f)
145
146
147    if len(errors) > 0:
148        error('Converting the following files failed: %s' % ', '.join(errors))
149
150def getlyxinput(lyx, lyxfx, lyxf, uselyx2lyx):
151    if uselyx2lyx:
152        cmd = '%s -E lyx %s %s' % (lyx, lyxf, lyxfx)
153        sys.stdout.writelines(cmd)
154        sys.stdout.writelines("\n")
155        if os.system(cmd) != 0:
156            return None
157        return lyxf
158    else:
159        return lyxfx
160
161if __name__ == "__main__":
162    main(sys.argv)
163
164