Subversion Repositories Kolibri OS

Rev

Rev 9323 | Rev 9327 | 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
 
9323 Boppan 136
def run_tests_serially_thread(test, root_dir):
9313 Boppan 137
    test_number = 1
138
    for test in tests:
139
        test_dir = f"{root_dir}/{test}"
140
 
141
        os.chdir(test_dir)
142
        print(f"[{test_number}/{len(tests)}] {test}... ", end = "", flush=True)
143
        start = timeit.default_timer()
144
        try:
145
            SourceFileLoader("test", "test.py").load_module().run()
146
        except common.TestTimeoutException:
147
            result = "TIMEOUT"
148
        except common.TestFailureException:
149
            result = "FAILURE"
150
        else:
151
            result = "SUCCESS"
152
        finish = timeit.default_timer()
153
        print(f"{result} ({finish - start:.2f} seconds)")
154
        os.chdir(root_dir)
155
 
156
        test_number += 1
9322 Boppan 157
 
9323 Boppan 158
def run_tests_serially(tests, root_dir):
159
    thread = Thread(target = run_tests_serially_thread, args = (tests, root_dir))
160
    thread.start()
161
    return thread
162
 
9326 Boppan 163
def gcc(fin, fout):
164
    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}"
165
    print(command)
166
    os.system(command)
167
 
168
def build_umka():
169
    if not enable_umka:
170
        return
171
    if os.path.exists("umka_shell"):
172
        return
173
    os.makedirs("umka/build", exist_ok = True)
174
    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"]
175
    sources = [f"umka/{f}" for f in sources]
176
    for source in sources:
177
        gcc(source, f"{source}.o")
178
    objects = " ".join([ f"{s}.o" for s in sources ])
179
    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")
180
    objects += (" umka/build/umka.o")
181
    os.system(f"gcc -m32 -no-pie -o umka_shell -static -T umka/umka.ld {objects}")
182
 
9322 Boppan 183
if __name__ == "__main__":
184
    root_dir = os.getcwd()
185
 
186
    # Check available tools
187
    tools = (("qemu-system-i386", "qemu-system-x86"),
188
             ("fasm", "fasm"))
189
    check_tools(tools)
9313 Boppan 190
 
9322 Boppan 191
    prepare_test_img()
9326 Boppan 192
    build_umka()
9322 Boppan 193
    tests = collect_tests()
9323 Boppan 194
    serial_executor_thread = run_tests_serially(tests, root_dir)
195
    serial_executor_thread.join()
196