Subversion Repositories Kolibri OS

Rev

Rev 9326 | Rev 9328 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
9249 Boppan 1
#!/usr/bin/python3
9312 Boppan 2
# Copyright 2021 Magomed Kostoev
9249 Boppan 3
# Published under MIT License
4
 
5
import os
6
import sys
9314 Boppan 7
import urllib
9249 Boppan 8
from importlib.machinery import SourceFileLoader
9310 Boppan 9
from shutil import which
9249 Boppan 10
import timeit
11
import urllib.request
12
import subprocess
9322 Boppan 13
from threading import Thread
9249 Boppan 14
 
15
sys.path.append('test')
16
import common
17
 
9326 Boppan 18
enable_umka = False
19
 
9249 Boppan 20
def log(s, end = "\n"):
21
    print(s, end = end, flush = True)
22
 
23
def execute(s, mute = False):
24
    mute = ">/dev/null" if mute else ""
25
    code = os.system(f"{s}{mute}")
26
    if code:
27
        print(f"Command returned {code}: \"{s}\"")
28
        exit(-1)
29
 
30
def stage(name, command, mute = False):
31
    print(f"{name}... ", end = "")
32
    execute(command, mute = mute)
33
    print("Done.")
34
 
9314 Boppan 35
def download(link, path):
36
    log(f"Downloading {path}... ", end = "")
9315 Boppan 37
    urllib.request.urlretrieve(link, path)
9314 Boppan 38
    log("Done.")
39
 
9310 Boppan 40
def tool_exists(name):
41
    assert(type(name) == str)
42
    return which(name) != None
43
 
44
def check_tools(tools):
45
    assert(type(tools) == tuple)
46
    for name_package_pair in tools:
47
        assert(type(name_package_pair) == tuple)
48
        assert(len(name_package_pair) == 2)
49
        assert(type(name_package_pair[0]) == str)
50
        assert(type(name_package_pair[1]) == str)
51
 
52
    not_exists = []
53
    for name, package in tools:
54
        if not tool_exists(name):
55
            not_exists.append((name, package))
56
    if len(not_exists) != 0:
57
        log("Sorry, I can't find some tools:")
9311 Boppan 58
 
59
        header_name = "Name"
60
        header_package = "Package (probably)"
61
 
62
        max_name_len = len(header_name)
63
        max_package_name_len = len(header_package)
9310 Boppan 64
        for name, package in not_exists:
65
            if len(package) > max_package_name_len:
66
                max_package_name_len = len(package)
67
            if len(name) > max_name_len:
68
                max_name_len = len(name)
69
 
70
        def draw_row(name, package):
71
            log(f" | {name.ljust(max_name_len)} | {package.ljust(max_package_name_len)} |")
72
 
73
        def draw_line():
74
            log(f" +-{'-' * max_name_len}-+-{'-' * max_package_name_len}-+")
75
 
76
        draw_line()
9311 Boppan 77
        draw_row(header_name, header_package)
9310 Boppan 78
        draw_line()
79
        for name, package in not_exists:
80
            draw_row(name, package)
81
        draw_line()
82
        exit()
83
 
9321 Boppan 84
def prepare_test_img():
85
    # TODO: Always recompile the kernel (after build system is done?)
9313 Boppan 86
    # Get IMG
87
    if not os.path.exists("kolibri_test.img"):
88
        if len(sys.argv) == 1:
9314 Boppan 89
            download("http://builds.kolibrios.org/eng/data/data/kolibri.img", "kolibri_test.img")
9313 Boppan 90
        else:
91
            builds_eng = sys.argv[1]
92
            execute(f"cp {builds_eng}/data/data/kolibri.img kolibri_test.img")
93
 
9316 Boppan 94
    # Open the IMG
95
    with open("kolibri_test.img", "rb") as img:
96
        img_data = img.read()
97
    img = common.Floppy(img_data)
9321 Boppan 98
 
9316 Boppan 99
    # Remove unuseful folders
100
    img.delete_path("GAMES")
101
    img.delete_path("DEMOS")
102
    img.delete_path("3D")
9313 Boppan 103
 
104
    # Get test kernel
105
    if not os.path.exists("kernel.mnt.pretest"):
106
        if len(sys.argv) == 1:
107
            with open("lang.inc", "w") as lang_inc:
108
                lang_inc.write("lang fix en\n")
109
            execute("fasm bootbios.asm bootbios.bin.pretest -dpretest_build=1")
110
            execute("fasm -m 65536 kernel.asm kernel.mnt.pretest -dpretest_build=1 -ddebug_com_base=0xe9")
111
        else:
112
            builds_eng = sys.argv[1]
113
            execute(f"cp {builds_eng}/data/kernel/trunk/kernel.mnt.pretest kernel.mnt.pretest", mute = True)
114
 
115
    # Put the kernel into IMG
9316 Boppan 116
    with open("kernel.mnt.pretest", "rb") as kernel_mnt_pretest:
117
        kernel_mnt_pretest_data = kernel_mnt_pretest.read()
9317 Boppan 118
    img.add_file_path("KERNEL.MNT", kernel_mnt_pretest_data)
9316 Boppan 119
    img.save("kolibri_test.img")
9321 Boppan 120
 
121
def collect_tests():
122
    tests = []
123
 
9313 Boppan 124
    # Collect tests from test folder (not recursively yet)
125
    for test_folder in os.listdir("test"):
126
        test_folder_path = f"test/{test_folder}"
127
        test_file = f"{test_folder_path}/test.py"
9321 Boppan 128
 
9313 Boppan 129
        if not os.path.isdir(test_folder_path):
130
            continue
9321 Boppan 131
 
9313 Boppan 132
        if os.path.exists(test_file):
133
            tests.append(test_folder_path)
9321 Boppan 134
    return tests
135
 
9327 Boppan 136
def collect_umka_tests():
137
    tests = []
138
 
139
    for test_file in os.listdir("umka/test"):
140
        test_file_path = f"umka/test/{test_file}"
141
        if not test_file.endswith(".t"):
142
            continue
143
        if not os.path.isfile(test_file_path):
144
            continue
145
        tests.append(test_file_path)
146
    return tests
147
 
9323 Boppan 148
def run_tests_serially_thread(test, root_dir):
9313 Boppan 149
    test_number = 1
150
    for test in tests:
151
        test_dir = f"{root_dir}/{test}"
152
 
153
        os.chdir(test_dir)
154
        print(f"[{test_number}/{len(tests)}] {test}... ", end = "", flush=True)
155
        start = timeit.default_timer()
156
        try:
157
            SourceFileLoader("test", "test.py").load_module().run()
158
        except common.TestTimeoutException:
159
            result = "TIMEOUT"
160
        except common.TestFailureException:
161
            result = "FAILURE"
162
        else:
163
            result = "SUCCESS"
164
        finish = timeit.default_timer()
165
        print(f"{result} ({finish - start:.2f} seconds)")
166
        os.chdir(root_dir)
167
 
168
        test_number += 1
9322 Boppan 169
 
9323 Boppan 170
def run_tests_serially(tests, root_dir):
171
    thread = Thread(target = run_tests_serially_thread, args = (tests, root_dir))
172
    thread.start()
173
    return thread
174
 
9326 Boppan 175
def gcc(fin, fout):
176
    command = f"gcc -m32 -std=c11 -g -O0 -D_FILE_OFFSET_BITS=64 -DNDEBUG -masm=intel -D_POSIX_C_SOURCE=200809L -Iumka -Iumka/linux -fno-pie -c {fin} -o {fout}"
177
    print(command)
178
    os.system(command)
179
 
180
def build_umka():
181
    if not enable_umka:
182
        return
183
    if os.path.exists("umka_shell"):
184
        return
185
    os.makedirs("umka/build", exist_ok = True)
186
    sources = ["umka_shell.c", "shell.c", "trace.c", "trace_lbr.c", "vdisk.c", "vnet.c", "lodepng.c", "linux/pci.c", "linux/thread.c", "util.c"]
187
    sources = [f"umka/{f}" for f in sources]
188
    for source in sources:
189
        gcc(source, f"{source}.o")
190
    objects = " ".join([ f"{s}.o" for s in sources ])
191
    os.system(f"INCLUDE=\"../../programs/develop/libraries/libcrash/hash\" fasm -dUEFI=1 -dextended_primary_loader=1 -dUMKA=1 umka/umka.asm umka/build/umka.o -s umka/build/umka.fas -m 2000000")
192
    objects += (" umka/build/umka.o")
193
    os.system(f"gcc -m32 -no-pie -o umka_shell -static -T umka/umka.ld {objects}")
194
 
9322 Boppan 195
if __name__ == "__main__":
196
    root_dir = os.getcwd()
197
 
198
    # Check available tools
199
    tools = (("qemu-system-i386", "qemu-system-x86"),
200
             ("fasm", "fasm"))
201
    check_tools(tools)
9313 Boppan 202
 
9322 Boppan 203
    prepare_test_img()
9326 Boppan 204
    build_umka()
9322 Boppan 205
    tests = collect_tests()
9327 Boppan 206
    print(collect_umka_tests)
9323 Boppan 207
    serial_executor_thread = run_tests_serially(tests, root_dir)
208
    serial_executor_thread.join()
209