File: testctl

package info (click to toggle)
ghc 9.6.6-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 158,216 kB
  • sloc: haskell: 648,228; ansic: 81,656; cpp: 11,808; javascript: 8,444; sh: 5,831; fortran: 3,527; python: 3,277; asm: 2,523; makefile: 2,298; yacc: 1,570; lisp: 532; xml: 196; perl: 145; csh: 2
file content (130 lines) | stat: -rwxr-xr-x 3,772 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env python
import glob, os, re, sys

USAGE = """
Usage:

    {program} add NAME

        Add a new test with the given NAME in the test directory and then
        update the list of tests in Main.hs (warning: discards manual edits).

    {program} update

        Update the list of tests in Main.hs (warning: discards manual edits).

"""[1:]

TEST_DIR = "tests"
TEST_EXT = ".hs"
TEST_TEMPLATE = """
{{-# LANGUAGE CPP #-}}
module {name} where
#include "util.inl"

main :: TestEnv -> IO ()
main _t = do

"""[1:]
MAIN_NAME = "Main"
MAIN_TEMPLATE = """
module Main (main) where
import qualified Util as T
{imports}
main :: IO ()
main = T.testMain $ \ _t -> do
{runs}
"""[1:-1]
MAIN_IMPORT_TEMPLATE = "import qualified {name}\n"
MAIN_RUN_TEMPLATE = '  T.isolatedRun _t "{name}" {name}.main\n'
BLACKLIST = "^(Main|.*Util.*)$"

CABAL_FILE = glob.glob("*.cabal")[0]
CABAL_SECTION_PATTERN = """(?s)
( *)-- test-modules-begin
.*?-- test-modules-end
"""
CABAL_SECTION_TEMPLATE = """
{0}-- test-modules-begin
{1}{0}-- test-modules-end
"""

program = os.path.basename(sys.argv[0])

def rename(src, dest):
    '''Rename a file (allows overwrites on Windows).'''
    import os
    if os.name == "nt":
        import ctypes, ctypes.wintypes
        MoveFileExW = ctypes.windll.kernel32.MoveFileExW
        MoveFileExW.restype = ctypes.wintypes.BOOL
        MOVEFILE_REPLACE_EXISTING = ctypes.wintypes.DWORD(0x1)
        success = MoveFileExW(ctypes.wintypes.LPCWSTR(src),
                              ctypes.wintypes.LPCWSTR(dest),
                              MOVEFILE_REPLACE_EXISTING)
        if not success:
            raise ctypes.WinError()
    else:
        os.rename(src, dest)

def usage():
    sys.stderr.write(USAGE.format(program=program))
    sys.exit(2)

def add(name):
    if not name[0].isupper():
        sys.stderr.write("{0}: must start with a capital letter: {1}\n"
                         .format(program, name))
        sys.exit(1)
    filename = os.path.join(TEST_DIR, name + TEST_EXT)
    if os.path.exists(filename):
        sys.stderr.write("{0}: test already exists: {1}\n"
                         .format(program, filename))
        sys.exit(1)
    with open(filename, "wb") as file:
        file.write(TEST_TEMPLATE.format(name=name)
                   .encode("utf8"))
    update()
    print("{0}: test added: {1}".format(program, filename))

def update():
    tests = []
    for basename in os.listdir(TEST_DIR):
        name, ext = os.path.splitext(basename)
        if (ext == TEST_EXT and
            len(name) > 0 and
            not re.search(BLACKLIST, name) and
            name[0].isupper()):
            tests.append(name)
    tests.sort()
    with open(os.path.join(TEST_DIR, MAIN_NAME + TEST_EXT), "wb") as file:
        file.write(MAIN_TEMPLATE.format(
            imports="".join(MAIN_IMPORT_TEMPLATE.format(name=name)
                            for name in tests),
            runs="".join(MAIN_RUN_TEMPLATE.format(name=name)
                         for name in tests),
        ).encode("utf8"))
    with open(CABAL_FILE, "rb") as file:
        cabal_file = file.read().decode("utf8")
    with open(CABAL_FILE + ".tmp", "wb") as file:
        indent, = re.search(CABAL_SECTION_PATTERN, cabal_file).groups()
        repl = CABAL_SECTION_TEMPLATE.format(
            indent,
            "".join("{0}{1}\n".format(indent, name) for name in tests)
        )
        file.write(re.sub(CABAL_SECTION_PATTERN, repl, cabal_file)
                   .encode("utf8"))
    rename(CABAL_FILE + ".tmp", CABAL_FILE)

if len(sys.argv) < 2:
    usage()

command = sys.argv[1]
if command == "add":
    if len(sys.argv) > 3:
        usage()
    add(sys.argv[2])
elif command == "update":
    if len(sys.argv) > 2:
        usage()
    update()