mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Update .editorconfig to reflect current style (#1571)
* Update .editorconfig to reflect current style * .editorconfig use tabs for python * update msvc_build_libraries.py from two-space to tab indent * update test/src/tester.py from 4-space to tab indent
This commit is contained in:
@@ -11,18 +11,15 @@ indent_style = space
|
|||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
|
||||||
[*.{c,cc,h}]
|
[*.{c,cc,h}]
|
||||||
indent_style = space
|
indent_style = tab
|
||||||
indent_size = 4
|
|
||||||
|
|
||||||
[*.{c3}]
|
[*.{c3}]
|
||||||
indent_style = space
|
indent_style = tab
|
||||||
indent_size = 4
|
|
||||||
|
|
||||||
[*.{json,toml,yml,gyp}]
|
[*.{json,toml,yml,gyp}]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
[*.{py,pyi}]
|
[*.{py,pyi}]
|
||||||
indent_style = space
|
indent_style = tab
|
||||||
indent_size = 2
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,55 +19,55 @@ import tempfile
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
if (platform.system() == "Windows"):
|
if (platform.system() == "Windows"):
|
||||||
print("Creating msvc_sdk for compilation without VS.")
|
print("Creating msvc_sdk for compilation without VS.")
|
||||||
else:
|
else:
|
||||||
print("Creating msvc_sdk for cross platform compilation to Windows.")
|
print("Creating msvc_sdk for cross platform compilation to Windows.")
|
||||||
|
|
||||||
OUTPUT = Path(tempfile.mkdtemp()) # output folder
|
OUTPUT = Path(tempfile.mkdtemp()) # output folder
|
||||||
SDK_OUTPUT = Path("msvc_sdk")
|
SDK_OUTPUT = Path("msvc_sdk")
|
||||||
|
|
||||||
if (not os.environ.get('PYTHONHTTPSVERIFY', '') and
|
if (not os.environ.get('PYTHONHTTPSVERIFY', '') and
|
||||||
getattr(ssl, '_create_unverified_context', None)):
|
getattr(ssl, '_create_unverified_context', None)):
|
||||||
ssl._create_default_https_context = ssl._create_unverified_context
|
ssl._create_default_https_context = ssl._create_unverified_context
|
||||||
|
|
||||||
MANIFEST_URL = "https://aka.ms/vs/17/release/channel"
|
MANIFEST_URL = "https://aka.ms/vs/17/release/channel"
|
||||||
|
|
||||||
def download(url):
|
def download(url):
|
||||||
with urllib.request.urlopen(url) as res:
|
with urllib.request.urlopen(url) as res:
|
||||||
return res.read()
|
return res.read()
|
||||||
|
|
||||||
def download_progress(url, check, name, f):
|
def download_progress(url, check, name, f):
|
||||||
data = io.BytesIO()
|
data = io.BytesIO()
|
||||||
with urllib.request.urlopen(url) as res:
|
with urllib.request.urlopen(url) as res:
|
||||||
total = int(res.headers["Content-Length"])
|
total = int(res.headers["Content-Length"])
|
||||||
size = 0
|
size = 0
|
||||||
while True:
|
while True:
|
||||||
block = res.read(1<<20)
|
block = res.read(1<<20)
|
||||||
if not block:
|
if not block:
|
||||||
break
|
break
|
||||||
f.write(block)
|
f.write(block)
|
||||||
data.write(block)
|
data.write(block)
|
||||||
size += len(block)
|
size += len(block)
|
||||||
perc = size * 100 // total
|
perc = size * 100 // total
|
||||||
print(f"\r{name} ... {perc}%", end="")
|
print(f"\r{name} ... {perc}%", end="")
|
||||||
print()
|
print()
|
||||||
data = data.getvalue()
|
data = data.getvalue()
|
||||||
digest = hashlib.sha256(data).hexdigest()
|
digest = hashlib.sha256(data).hexdigest()
|
||||||
if check.lower() != digest:
|
if check.lower() != digest:
|
||||||
exit(f"Hash mismatch for f{pkg}")
|
exit(f"Hash mismatch for f{pkg}")
|
||||||
return data
|
return data
|
||||||
|
|
||||||
# super crappy msi format parser just to find required .cab files
|
# super crappy msi format parser just to find required .cab files
|
||||||
def get_msi_cabs(msi):
|
def get_msi_cabs(msi):
|
||||||
index = 0
|
index = 0
|
||||||
while True:
|
while True:
|
||||||
index = msi.find(b".cab", index+4)
|
index = msi.find(b".cab", index+4)
|
||||||
if index < 0:
|
if index < 0:
|
||||||
return
|
return
|
||||||
yield msi[index-32:index+4].decode("ascii")
|
yield msi[index-32:index+4].decode("ascii")
|
||||||
|
|
||||||
def first(items, cond):
|
def first(items, cond):
|
||||||
return next(item for item in items if cond(item))
|
return next(item for item in items if cond(item))
|
||||||
|
|
||||||
### parse command-line arguments
|
### parse command-line arguments
|
||||||
|
|
||||||
@@ -96,40 +96,40 @@ vsmanifest = json.loads(download(payload))
|
|||||||
|
|
||||||
packages = {}
|
packages = {}
|
||||||
for p in vsmanifest["packages"]:
|
for p in vsmanifest["packages"]:
|
||||||
packages.setdefault(p["id"].lower(), []).append(p)
|
packages.setdefault(p["id"].lower(), []).append(p)
|
||||||
|
|
||||||
msvc = {}
|
msvc = {}
|
||||||
sdk_path = {}
|
sdk_path = {}
|
||||||
|
|
||||||
for pid,p in packages.items():
|
for pid,p in packages.items():
|
||||||
if pid.startswith("Microsoft.VisualStudio.Component.VC.".lower()) and pid.endswith(".x86.x64".lower()):
|
if pid.startswith("Microsoft.VisualStudio.Component.VC.".lower()) and pid.endswith(".x86.x64".lower()):
|
||||||
pver = ".".join(pid.split(".")[4:6])
|
pver = ".".join(pid.split(".")[4:6])
|
||||||
if pver[0].isnumeric():
|
if pver[0].isnumeric():
|
||||||
msvc[pver] = pid
|
msvc[pver] = pid
|
||||||
elif pid.startswith("Microsoft.VisualStudio.Component.Windows10SDK.".lower()) or \
|
elif pid.startswith("Microsoft.VisualStudio.Component.Windows10SDK.".lower()) or \
|
||||||
pid.startswith("Microsoft.VisualStudio.Component.Windows11SDK.".lower()):
|
pid.startswith("Microsoft.VisualStudio.Component.Windows11SDK.".lower()):
|
||||||
pver = pid.split(".")[-1]
|
pver = pid.split(".")[-1]
|
||||||
if pver.isnumeric():
|
if pver.isnumeric():
|
||||||
sdk_path[pver] = pid
|
sdk_path[pver] = pid
|
||||||
|
|
||||||
if args.show_versions:
|
if args.show_versions:
|
||||||
print("MSVC versions:", " ".join(sorted(msvc.keys())))
|
print("MSVC versions:", " ".join(sorted(msvc.keys())))
|
||||||
print("Windows SDK versions:", " ".join(sorted(sdk_path.keys())))
|
print("Windows SDK versions:", " ".join(sorted(sdk_path.keys())))
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
msvc_ver = args.msvc_version or max(sorted(msvc.keys()))
|
msvc_ver = args.msvc_version or max(sorted(msvc.keys()))
|
||||||
sdk_ver = args.sdk_version or max(sorted(sdk_path.keys()))
|
sdk_ver = args.sdk_version or max(sorted(sdk_path.keys()))
|
||||||
|
|
||||||
if msvc_ver in msvc:
|
if msvc_ver in msvc:
|
||||||
msvc_pid = msvc[msvc_ver]
|
msvc_pid = msvc[msvc_ver]
|
||||||
msvc_ver = ".".join(msvc_pid.split(".")[4:-2])
|
msvc_ver = ".".join(msvc_pid.split(".")[4:-2])
|
||||||
else:
|
else:
|
||||||
exit(f"Unknown MSVC version: f{args.msvc_version}")
|
exit(f"Unknown MSVC version: f{args.msvc_version}")
|
||||||
|
|
||||||
if sdk_ver in sdk_path:
|
if sdk_ver in sdk_path:
|
||||||
sdk_pid = sdk_path[sdk_ver]
|
sdk_pid = sdk_path[sdk_ver]
|
||||||
else:
|
else:
|
||||||
exit(f"Unknown Windows SDK version: f{args.sdk_version}")
|
exit(f"Unknown Windows SDK version: f{args.sdk_version}")
|
||||||
|
|
||||||
print(f"Downloading MSVC v{msvc_ver} and Windows SDK v{sdk_ver}")
|
print(f"Downloading MSVC v{msvc_ver} and Windows SDK v{sdk_ver}")
|
||||||
|
|
||||||
@@ -141,9 +141,9 @@ resource = first(tools["localizedResources"], lambda x: x["language"] == "en-us"
|
|||||||
license = resource["license"]
|
license = resource["license"]
|
||||||
|
|
||||||
if not args.accept_license:
|
if not args.accept_license:
|
||||||
accept = input(f"Do you accept Visual Studio license at {license}, and also confirm that you have a valid license Visual Studio license allowing you to download the VS Build Tools [Y/N] ?")
|
accept = input(f"Do you accept Visual Studio license at {license}, and also confirm that you have a valid license Visual Studio license allowing you to download the VS Build Tools [Y/N] ?")
|
||||||
if not accept or accept[0].lower() != "y":
|
if not accept or accept[0].lower() != "y":
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
shutil.rmtree(SDK_OUTPUT, ignore_errors = True)
|
shutil.rmtree(SDK_OUTPUT, ignore_errors = True)
|
||||||
total_download = 0
|
total_download = 0
|
||||||
@@ -151,82 +151,82 @@ total_download = 0
|
|||||||
### download Windows SDK
|
### download Windows SDK
|
||||||
|
|
||||||
archs = [
|
archs = [
|
||||||
#"arm",
|
#"arm",
|
||||||
#"arm64",
|
#"arm64",
|
||||||
"x64",
|
"x64",
|
||||||
#"x86"
|
#"x86"
|
||||||
]
|
]
|
||||||
|
|
||||||
msvc_packages = [
|
msvc_packages = [
|
||||||
f"microsoft.vc.{msvc_ver}.asan.headers.base",
|
f"microsoft.vc.{msvc_ver}.asan.headers.base",
|
||||||
]
|
]
|
||||||
|
|
||||||
for arch in archs:
|
for arch in archs:
|
||||||
msvc_packages.append(f"microsoft.vc.{msvc_ver}.crt.{arch}.desktop.base")
|
msvc_packages.append(f"microsoft.vc.{msvc_ver}.crt.{arch}.desktop.base")
|
||||||
msvc_packages.append(f"microsoft.vc.{msvc_ver}.crt.{arch}.store.base")
|
msvc_packages.append(f"microsoft.vc.{msvc_ver}.crt.{arch}.store.base")
|
||||||
msvc_packages.append(f"microsoft.vc.{msvc_ver}.asan.{arch}.base")
|
msvc_packages.append(f"microsoft.vc.{msvc_ver}.asan.{arch}.base")
|
||||||
|
|
||||||
for pkg in msvc_packages:
|
for pkg in msvc_packages:
|
||||||
p = first(packages[pkg], lambda p: p.get("language") in (None, "en-US"))
|
p = first(packages[pkg], lambda p: p.get("language") in (None, "en-US"))
|
||||||
for payload in p["payloads"]:
|
for payload in p["payloads"]:
|
||||||
with tempfile.TemporaryFile() as f:
|
with tempfile.TemporaryFile() as f:
|
||||||
data = download_progress(payload["url"], payload["sha256"], pkg, f)
|
data = download_progress(payload["url"], payload["sha256"], pkg, f)
|
||||||
total_download += len(data)
|
total_download += len(data)
|
||||||
with zipfile.ZipFile(f) as z:
|
with zipfile.ZipFile(f) as z:
|
||||||
for name in z.namelist():
|
for name in z.namelist():
|
||||||
if name.startswith("Contents/"):
|
if name.startswith("Contents/"):
|
||||||
out = OUTPUT / Path(name).relative_to("Contents")
|
out = OUTPUT / Path(name).relative_to("Contents")
|
||||||
out.parent.mkdir(parents=True, exist_ok=True)
|
out.parent.mkdir(parents=True, exist_ok=True)
|
||||||
out.write_bytes(z.read(name))
|
out.write_bytes(z.read(name))
|
||||||
|
|
||||||
sdk_packages = [
|
sdk_packages = [
|
||||||
# Windows SDK libs
|
# Windows SDK libs
|
||||||
"Windows SDK for Windows Store Apps Libs-x86_en-us.msi",
|
"Windows SDK for Windows Store Apps Libs-x86_en-us.msi",
|
||||||
"Windows SDK Desktop Libs x64-x86_en-us.msi",
|
"Windows SDK Desktop Libs x64-x86_en-us.msi",
|
||||||
# CRT headers & libs
|
# CRT headers & libs
|
||||||
"Universal CRT Headers Libraries and Sources-x86_en-us.msi",
|
"Universal CRT Headers Libraries and Sources-x86_en-us.msi",
|
||||||
]
|
]
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as d:
|
with tempfile.TemporaryDirectory() as d:
|
||||||
dst = Path(d)
|
dst = Path(d)
|
||||||
|
|
||||||
sdk_pkg = packages[sdk_pid][0]
|
sdk_pkg = packages[sdk_pid][0]
|
||||||
sdk_pkg = packages[first(sdk_pkg["dependencies"], lambda x: True).lower()][0]
|
sdk_pkg = packages[first(sdk_pkg["dependencies"], lambda x: True).lower()][0]
|
||||||
|
|
||||||
msi = []
|
msi = []
|
||||||
cabs = []
|
cabs = []
|
||||||
|
|
||||||
# download msi files
|
# download msi files
|
||||||
for pkg in sdk_packages:
|
for pkg in sdk_packages:
|
||||||
payload = first(sdk_pkg["payloads"], lambda p: p["fileName"] == f"Installers\\{pkg}")
|
payload = first(sdk_pkg["payloads"], lambda p: p["fileName"] == f"Installers\\{pkg}")
|
||||||
msi.append(dst / pkg)
|
msi.append(dst / pkg)
|
||||||
with open(dst / pkg, "wb") as f:
|
with open(dst / pkg, "wb") as f:
|
||||||
data = download_progress(payload["url"], payload["sha256"], pkg, f)
|
data = download_progress(payload["url"], payload["sha256"], pkg, f)
|
||||||
total_download += len(data)
|
total_download += len(data)
|
||||||
cabs += list(get_msi_cabs(data))
|
cabs += list(get_msi_cabs(data))
|
||||||
|
|
||||||
# download .cab files
|
# download .cab files
|
||||||
for pkg in cabs:
|
for pkg in cabs:
|
||||||
payload = first(sdk_pkg["payloads"], lambda p: p["fileName"] == f"Installers\\{pkg}")
|
payload = first(sdk_pkg["payloads"], lambda p: p["fileName"] == f"Installers\\{pkg}")
|
||||||
with open(dst / pkg, "wb") as f:
|
with open(dst / pkg, "wb") as f:
|
||||||
download_progress(payload["url"], payload["sha256"], pkg, f)
|
download_progress(payload["url"], payload["sha256"], pkg, f)
|
||||||
|
|
||||||
print("Unpacking msi files...")
|
print("Unpacking msi files...")
|
||||||
|
|
||||||
# run msi installers
|
# run msi installers
|
||||||
for m in msi:
|
for m in msi:
|
||||||
if (platform.system() == "Windows"):
|
if (platform.system() == "Windows"):
|
||||||
subprocess.check_call(["msiexec.exe", "/a", m, "/quiet", "/qn", f"TARGETDIR={OUTPUT.resolve()}"])
|
subprocess.check_call(["msiexec.exe", "/a", m, "/quiet", "/qn", f"TARGETDIR={OUTPUT.resolve()}"])
|
||||||
else:
|
else:
|
||||||
subprocess.check_call(["msiextract", m, '-C', OUTPUT.resolve()])
|
subprocess.check_call(["msiextract", m, '-C', OUTPUT.resolve()])
|
||||||
|
|
||||||
|
|
||||||
### versions
|
### versions
|
||||||
|
|
||||||
if (platform.system() == "Windows"):
|
if (platform.system() == "Windows"):
|
||||||
window_kit = OUTPUT / "Windows Kits/"
|
window_kit = OUTPUT / "Windows Kits/"
|
||||||
else:
|
else:
|
||||||
window_kit = OUTPUT / "Program Files/Windows Kits/"
|
window_kit = OUTPUT / "Program Files/Windows Kits/"
|
||||||
|
|
||||||
ucrt = list(window_kit.glob("*/Lib/*/ucrt"))[0]
|
ucrt = list(window_kit.glob("*/Lib/*/ucrt"))[0]
|
||||||
um = list(window_kit.glob("*/Lib/*/um"))[0]
|
um = list(window_kit.glob("*/Lib/*/um"))[0]
|
||||||
@@ -235,9 +235,9 @@ lib = list((OUTPUT / "VC/Tools/MSVC/").glob("*/lib"))[0]
|
|||||||
SDK_OUTPUT.mkdir(exist_ok=True)
|
SDK_OUTPUT.mkdir(exist_ok=True)
|
||||||
|
|
||||||
for arch in archs:
|
for arch in archs:
|
||||||
out_dir = SDK_OUTPUT / arch
|
out_dir = SDK_OUTPUT / arch
|
||||||
shutil.copytree(ucrt / arch, out_dir, dirs_exist_ok=True)
|
shutil.copytree(ucrt / arch, out_dir, dirs_exist_ok=True)
|
||||||
shutil.copytree(um / arch, out_dir, dirs_exist_ok=True)
|
shutil.copytree(um / arch, out_dir, dirs_exist_ok=True)
|
||||||
shutil.copytree(lib / arch, out_dir, dirs_exist_ok=True)
|
shutil.copytree(lib / arch, out_dir, dirs_exist_ok=True)
|
||||||
|
|
||||||
print("Congratulations! The 'msvc_sdk' directory was successfully generated.")
|
print("Congratulations! The 'msvc_sdk' directory was successfully generated.")
|
||||||
|
|||||||
@@ -9,355 +9,355 @@ TEST_DIR = tempfile.mkdtemp().replace('\\', '/') + '/c3test/'
|
|||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
run_skipped = False
|
run_skipped = False
|
||||||
cwd = "."
|
cwd = "."
|
||||||
numtests = 0
|
numtests = 0
|
||||||
numsuccess = 0
|
numsuccess = 0
|
||||||
numskipped = 0
|
numskipped = 0
|
||||||
|
|
||||||
|
|
||||||
class File:
|
class File:
|
||||||
def __init__(self, filepath):
|
def __init__(self, filepath):
|
||||||
with open(filepath, encoding='utf8') as reader:
|
with open(filepath, encoding='utf8') as reader:
|
||||||
self.content = reader.read().splitlines()
|
self.content = reader.read().splitlines()
|
||||||
self.filepath = filepath
|
self.filepath = filepath
|
||||||
self.filename = os.path.basename(filepath)
|
self.filename = os.path.basename(filepath)
|
||||||
|
|
||||||
|
|
||||||
class TargetFile:
|
class TargetFile:
|
||||||
def __init__(self, filepath, is_target, line_offset):
|
def __init__(self, filepath, is_target, line_offset):
|
||||||
self.is_target = is_target
|
self.is_target = is_target
|
||||||
self.line_offset = line_offset
|
self.line_offset = line_offset
|
||||||
if is_target:
|
if is_target:
|
||||||
self.file = open(filepath, mode="wb")
|
self.file = open(filepath, mode="wb")
|
||||||
else:
|
else:
|
||||||
self.expected_lines = []
|
self.expected_lines = []
|
||||||
self.file = None
|
self.file = None
|
||||||
self.filepath = filepath
|
self.filepath = filepath
|
||||||
self.filename = os.path.basename(filepath)
|
self.filename = os.path.basename(filepath)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.file:
|
if self.file:
|
||||||
self.file.close()
|
self.file.close()
|
||||||
self.file = None
|
self.file = None
|
||||||
|
|
||||||
def write(self, line):
|
def write(self, line):
|
||||||
if self.file:
|
if self.file:
|
||||||
self.file.write(bytearray(line, "utf-8"))
|
self.file.write(bytearray(line, "utf-8"))
|
||||||
self.file.write(b"\n")
|
self.file.write(b"\n")
|
||||||
else:
|
else:
|
||||||
self.expected_lines.append(line)
|
self.expected_lines.append(line)
|
||||||
|
|
||||||
|
|
||||||
class Issues:
|
class Issues:
|
||||||
def __init__(self, conf, file, single):
|
def __init__(self, conf, file, single):
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
self.sourcefile = file
|
self.sourcefile = file
|
||||||
self.single = single
|
self.single = single
|
||||||
self.line = 0
|
self.line = 0
|
||||||
self.file_start = 0
|
self.file_start = 0
|
||||||
self.line_offset = 0
|
self.line_offset = 0
|
||||||
self.has_errors = False
|
self.has_errors = False
|
||||||
self.error_message = "unknown"
|
self.error_message = "unknown"
|
||||||
self.skip = False
|
self.skip = False
|
||||||
self.cur = 0
|
self.cur = 0
|
||||||
self.debuginfo = False
|
self.debuginfo = False
|
||||||
self.safe = False
|
self.safe = False
|
||||||
self.arch = None
|
self.arch = None
|
||||||
self.current_file = None
|
self.current_file = None
|
||||||
self.files = []
|
self.files = []
|
||||||
self.errors = {}
|
self.errors = {}
|
||||||
self.warnings = {}
|
self.warnings = {}
|
||||||
self.opts = []
|
self.opts = []
|
||||||
|
|
||||||
def exit_error(self, message):
|
def exit_error(self, message):
|
||||||
print('Error in file ' + self.sourcefile.filepath + ': ' + message)
|
print('Error in file ' + self.sourcefile.filepath + ': ' + message)
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
def set_failed(self):
|
def set_failed(self):
|
||||||
if not self.has_errors:
|
if not self.has_errors:
|
||||||
print(" Failed.")
|
print(" Failed.")
|
||||||
self.has_errors = True
|
self.has_errors = True
|
||||||
|
|
||||||
def check_line(self, typ, file, line, col, message):
|
def check_line(self, typ, file, line, col, message):
|
||||||
map_ = {}
|
map_ = {}
|
||||||
if typ == 'Error':
|
if typ == 'Error':
|
||||||
map_ = self.errors
|
map_ = self.errors
|
||||||
elif typ == 'Warning':
|
elif typ == 'Warning':
|
||||||
map_ = self.warnings
|
map_ = self.warnings
|
||||||
else:
|
else:
|
||||||
self.exit_error("Unknown type: " + typ)
|
self.exit_error("Unknown type: " + typ)
|
||||||
file = os.path.basename(file)
|
file = os.path.basename(file)
|
||||||
key = file + ":" + line
|
key = file + ":" + line
|
||||||
value = map_.get(key)
|
value = map_.get(key)
|
||||||
if value is None:
|
if value is None:
|
||||||
return False
|
return False
|
||||||
if value in message:
|
if value in message:
|
||||||
del map_[key]
|
del map_[key]
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def parse_result(self, lines):
|
def parse_result(self, lines):
|
||||||
for line in lines:
|
for line in lines:
|
||||||
parts = line.split('|', maxsplit=5)
|
parts = line.split('|', maxsplit=5)
|
||||||
if len(parts) != 5:
|
if len(parts) != 5:
|
||||||
self.exit_error("Illegal error result: " + line)
|
self.exit_error("Illegal error result: " + line)
|
||||||
if not self.check_line(parts[0], parts[1], parts[2], parts[3], parts[4]):
|
if not self.check_line(parts[0], parts[1], parts[2], parts[3], parts[4]):
|
||||||
self.set_failed()
|
self.set_failed()
|
||||||
print("Unexpected " + parts[0].lower() + " in " + os.path.basename(parts[1]) + " line " + parts[2] + ":", end="")
|
print("Unexpected " + parts[0].lower() + " in " + os.path.basename(parts[1]) + " line " + parts[2] + ":", end="")
|
||||||
print('"' + parts[4] + '"')
|
print('"' + parts[4] + '"')
|
||||||
if len(self.errors) > 0:
|
if len(self.errors) > 0:
|
||||||
self.set_failed()
|
self.set_failed()
|
||||||
print("Expected errors that never occurred:")
|
print("Expected errors that never occurred:")
|
||||||
num = 1
|
num = 1
|
||||||
for key, value in self.errors.items():
|
for key, value in self.errors.items():
|
||||||
pos = key.split(":", 2)
|
pos = key.split(":", 2)
|
||||||
print(str(num) + ". " + pos[0] + " line: " + pos[1] + " expected: \"" + value + "\"")
|
print(str(num) + ". " + pos[0] + " line: " + pos[1] + " expected: \"" + value + "\"")
|
||||||
num += 1
|
num += 1
|
||||||
|
|
||||||
def compile(self, args):
|
def compile(self, args):
|
||||||
os.chdir(TEST_DIR)
|
os.chdir(TEST_DIR)
|
||||||
target = ""
|
target = ""
|
||||||
debug = "-g0 "
|
debug = "-g0 "
|
||||||
if self.arch:
|
if self.arch:
|
||||||
target = " --target " + self.arch
|
target = " --target " + self.arch
|
||||||
if self.debuginfo:
|
if self.debuginfo:
|
||||||
debug = "-g "
|
debug = "-g "
|
||||||
opts = ""
|
opts = ""
|
||||||
for opt in self.opts:
|
for opt in self.opts:
|
||||||
opts += ' ' + opt
|
opts += ' ' + opt
|
||||||
if self.safe:
|
if self.safe:
|
||||||
opts += " --safe=yes"
|
opts += " --safe=yes"
|
||||||
else:
|
else:
|
||||||
opts += " --safe=no"
|
opts += " --safe=no"
|
||||||
code = subprocess.run(self.conf.compiler + target + ' -O0 ' + opts + ' ' + debug + args,
|
code = subprocess.run(self.conf.compiler + target + ' -O0 ' + opts + ' ' + debug + args,
|
||||||
universal_newlines=True, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
universal_newlines=True, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
os.chdir(self.conf.cwd)
|
os.chdir(self.conf.cwd)
|
||||||
if code.returncode != 0 and code.returncode != 1:
|
if code.returncode != 0 and code.returncode != 1:
|
||||||
self.set_failed()
|
self.set_failed()
|
||||||
print("Error (" + str(code.returncode) + "): " + code.stderr)
|
print("Error (" + str(code.returncode) + "): " + code.stderr)
|
||||||
self.has_errors = True
|
self.has_errors = True
|
||||||
return
|
return
|
||||||
self.parse_result(code.stderr.splitlines(keepends=False))
|
self.parse_result(code.stderr.splitlines(keepends=False))
|
||||||
|
|
||||||
def parse_single(self):
|
def parse_single(self):
|
||||||
self.current_file = TargetFile(TEST_DIR + self.sourcefile.filename, True, 1)
|
self.current_file = TargetFile(TEST_DIR + self.sourcefile.filename, True, 1)
|
||||||
lines = len(self.sourcefile.content)
|
lines = len(self.sourcefile.content)
|
||||||
while self.line < lines:
|
while self.line < lines:
|
||||||
line = self.sourcefile.content[self.line].strip()
|
line = self.sourcefile.content[self.line].strip()
|
||||||
if "// #" in line:
|
if "// #" in line:
|
||||||
self.parse_trailing_directive(line)
|
self.parse_trailing_directive(line)
|
||||||
self.current_file.write(self.sourcefile.content[self.line])
|
self.current_file.write(self.sourcefile.content[self.line])
|
||||||
self.line += 1
|
self.line += 1
|
||||||
|
|
||||||
self.current_file.close()
|
self.current_file.close()
|
||||||
print("- " + str(self.conf.numtests) + "/" + str(
|
print("- " + str(self.conf.numtests) + "/" + str(
|
||||||
self.conf.numtests - self.conf.numsuccess - 1) + " " + self.sourcefile.filepath + ":", end="")
|
self.conf.numtests - self.conf.numsuccess - 1) + " " + self.sourcefile.filepath + ":", end="")
|
||||||
self.compile("--test compile-only " + self.current_file.filepath)
|
self.compile("--test compile-only " + self.current_file.filepath)
|
||||||
if not self.has_errors:
|
if not self.has_errors:
|
||||||
self.conf.numsuccess += 1
|
self.conf.numsuccess += 1
|
||||||
print(" Passed.")
|
print(" Passed.")
|
||||||
|
|
||||||
def parse_header_directive(self, line):
|
def parse_header_directive(self, line):
|
||||||
line = line[4:].strip()
|
line = line[4:].strip()
|
||||||
if line.startswith("safe:"):
|
if line.startswith("safe:"):
|
||||||
self.safe = line[5:].strip() == "yes"
|
self.safe = line[5:].strip() == "yes"
|
||||||
return
|
return
|
||||||
if line.startswith("debuginfo:"):
|
if line.startswith("debuginfo:"):
|
||||||
self.debuginfo = line[10:].strip() == "yes"
|
self.debuginfo = line[10:].strip() == "yes"
|
||||||
return
|
return
|
||||||
if line.startswith("opt:"):
|
if line.startswith("opt:"):
|
||||||
self.opts.append(line[4:].strip())
|
self.opts.append(line[4:].strip())
|
||||||
return
|
return
|
||||||
if line.startswith("target:"):
|
if line.startswith("target:"):
|
||||||
self.arch = line[7:].strip()
|
self.arch = line[7:].strip()
|
||||||
return
|
return
|
||||||
if line.startswith("file:"):
|
if line.startswith("file:"):
|
||||||
if self.current_file:
|
if self.current_file:
|
||||||
self.current_file.close()
|
self.current_file.close()
|
||||||
line = line[5:].strip()
|
line = line[5:].strip()
|
||||||
self.current_file = TargetFile(TEST_DIR + line, True, -self.line)
|
self.current_file = TargetFile(TEST_DIR + line, True, -self.line)
|
||||||
self.files.append(self.current_file)
|
self.files.append(self.current_file)
|
||||||
return
|
return
|
||||||
elif line.startswith("expect:"):
|
elif line.startswith("expect:"):
|
||||||
line = line[7:].strip()
|
line = line[7:].strip()
|
||||||
if self.current_file:
|
if self.current_file:
|
||||||
self.current_file.close()
|
self.current_file.close()
|
||||||
self.current_file = TargetFile(TEST_DIR + line, False, 0)
|
self.current_file = TargetFile(TEST_DIR + line, False, 0)
|
||||||
self.files.append(self.current_file)
|
self.files.append(self.current_file)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.exit_error("unknown header directive " + line)
|
self.exit_error("unknown header directive " + line)
|
||||||
|
|
||||||
def parse_trailing_directive(self, line):
|
def parse_trailing_directive(self, line):
|
||||||
line = line.split('// #', 2)[1].strip()
|
line = line.split('// #', 2)[1].strip()
|
||||||
if line.startswith("warning:"):
|
if line.startswith("warning:"):
|
||||||
print("TODO" + line)
|
print("TODO" + line)
|
||||||
exit(-1)
|
exit(-1)
|
||||||
elif line.startswith("target:"):
|
elif line.startswith("target:"):
|
||||||
self.arch = line[7:].strip()
|
self.arch = line[7:].strip()
|
||||||
elif line.startswith("error:"):
|
elif line.startswith("error:"):
|
||||||
line = line[6:].strip()
|
line = line[6:].strip()
|
||||||
self.errors[self.current_file.filename + ":%d" % (self.line + self.current_file.line_offset)] = line
|
self.errors[self.current_file.filename + ":%d" % (self.line + self.current_file.line_offset)] = line
|
||||||
else:
|
else:
|
||||||
self.exit_error("unknown trailing directive " + line)
|
self.exit_error("unknown trailing directive " + line)
|
||||||
|
|
||||||
def parse_template(self):
|
def parse_template(self):
|
||||||
lines = len(self.sourcefile.content)
|
lines = len(self.sourcefile.content)
|
||||||
while self.line < lines:
|
while self.line < lines:
|
||||||
line = self.sourcefile.content[self.line].strip()
|
line = self.sourcefile.content[self.line].strip()
|
||||||
if line.startswith("// #") or line.startswith("/* #"):
|
if line.startswith("// #") or line.startswith("/* #"):
|
||||||
self.parse_header_directive(line)
|
self.parse_header_directive(line)
|
||||||
self.line += 1
|
self.line += 1
|
||||||
continue
|
continue
|
||||||
elif "// #" in line:
|
elif "// #" in line:
|
||||||
self.parse_trailing_directive(line)
|
self.parse_trailing_directive(line)
|
||||||
if not self.current_file:
|
if not self.current_file:
|
||||||
self.current_file = TargetFile(TEST_DIR + self.sourcefile.filename[:-4] + ".c3", True, 1)
|
self.current_file = TargetFile(TEST_DIR + self.sourcefile.filename[:-4] + ".c3", True, 1)
|
||||||
self.files.append(self.current_file)
|
self.files.append(self.current_file)
|
||||||
self.current_file.write(self.sourcefile.content[self.line])
|
self.current_file.write(self.sourcefile.content[self.line])
|
||||||
self.line += 1
|
self.line += 1
|
||||||
|
|
||||||
if self.current_file:
|
if self.current_file:
|
||||||
self.current_file.close()
|
self.current_file.close()
|
||||||
self.current_file = None
|
self.current_file = None
|
||||||
|
|
||||||
print("- " + str(self.conf.numtests) + "/" + str(
|
print("- " + str(self.conf.numtests) + "/" + str(
|
||||||
self.conf.numtests - self.conf.numsuccess - 1) + " " + self.sourcefile.filepath + ":", end="")
|
self.conf.numtests - self.conf.numsuccess - 1) + " " + self.sourcefile.filepath + ":", end="")
|
||||||
files_to_compile = ""
|
files_to_compile = ""
|
||||||
for file in self.files:
|
for file in self.files:
|
||||||
if file.is_target:
|
if file.is_target:
|
||||||
files_to_compile += " " + file.filepath
|
files_to_compile += " " + file.filepath
|
||||||
|
|
||||||
self.compile("--test compile-only " + files_to_compile)
|
self.compile("--test compile-only " + files_to_compile)
|
||||||
if self.has_errors:
|
if self.has_errors:
|
||||||
return
|
return
|
||||||
|
|
||||||
for file in self.files:
|
for file in self.files:
|
||||||
if not file.is_target:
|
if not file.is_target:
|
||||||
if not os.path.exists(file.filepath):
|
if not os.path.exists(file.filepath):
|
||||||
self.set_failed()
|
self.set_failed()
|
||||||
print("Did not compile file " + file.filename)
|
print("Did not compile file " + file.filename)
|
||||||
return
|
return
|
||||||
with open(file.filepath) as reader:
|
with open(file.filepath) as reader:
|
||||||
lines = reader.read().splitlines()
|
lines = reader.read().splitlines()
|
||||||
searched_line = 0
|
searched_line = 0
|
||||||
current_line = 0
|
current_line = 0
|
||||||
total_lines = len(file.expected_lines)
|
total_lines = len(file.expected_lines)
|
||||||
while searched_line < total_lines:
|
while searched_line < total_lines:
|
||||||
line = file.expected_lines[searched_line].strip()
|
line = file.expected_lines[searched_line].strip()
|
||||||
next_line = None
|
next_line = None
|
||||||
if searched_line + 1 < total_lines:
|
if searched_line + 1 < total_lines:
|
||||||
alt_line = file.expected_lines[searched_line + 1].strip()
|
alt_line = file.expected_lines[searched_line + 1].strip()
|
||||||
if alt_line.startswith("??"):
|
if alt_line.startswith("??"):
|
||||||
next_line = alt_line[2:].strip()
|
next_line = alt_line[2:].strip()
|
||||||
if line == "":
|
if line == "":
|
||||||
searched_line += 1
|
searched_line += 1
|
||||||
continue
|
continue
|
||||||
if current_line >= len(lines):
|
if current_line >= len(lines):
|
||||||
self.set_failed()
|
self.set_failed()
|
||||||
print(file.filename + " did not contain: \"" + line + "\"")
|
print(file.filename + " did not contain: \"" + line + "\"")
|
||||||
print("\n\n\n---------------------------------------------------> " + file.filename + "\n\n")
|
print("\n\n\n---------------------------------------------------> " + file.filename + "\n\n")
|
||||||
print("\n".join(lines) + "\n")
|
print("\n".join(lines) + "\n")
|
||||||
print("<---------------------------------------------------- " + self.sourcefile.filename)
|
print("<---------------------------------------------------- " + self.sourcefile.filename)
|
||||||
print("")
|
print("")
|
||||||
return
|
return
|
||||||
if line in lines[current_line]:
|
if line in lines[current_line]:
|
||||||
current_line += 1
|
current_line += 1
|
||||||
searched_line += 1
|
searched_line += 1
|
||||||
continue
|
continue
|
||||||
if next_line is not None and next_line in lines[current_line]:
|
if next_line is not None and next_line in lines[current_line]:
|
||||||
current_line += 1
|
current_line += 1
|
||||||
searched_line += 2
|
searched_line += 2
|
||||||
continue
|
continue
|
||||||
current_line += 1
|
current_line += 1
|
||||||
if not self.has_errors:
|
if not self.has_errors:
|
||||||
self.conf.numsuccess += 1
|
self.conf.numsuccess += 1
|
||||||
print(" Passed.")
|
print(" Passed.")
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
if len(self.sourcefile.content) == 0:
|
if len(self.sourcefile.content) == 0:
|
||||||
self.exit_error("File was empty")
|
self.exit_error("File was empty")
|
||||||
is_skip = self.sourcefile.content[0].startswith("// #skip")
|
is_skip = self.sourcefile.content[0].startswith("// #skip")
|
||||||
if is_skip != self.skip:
|
if is_skip != self.skip:
|
||||||
print("- " + str(self.conf.numtests) + "/" + str(
|
print("- " + str(self.conf.numtests) + "/" + str(
|
||||||
self.conf.numtests - self.conf.numsuccess - 1) + " " + self.sourcefile.filepath + ": *SKIPPED*")
|
self.conf.numtests - self.conf.numsuccess - 1) + " " + self.sourcefile.filepath + ": *SKIPPED*")
|
||||||
self.conf.numskipped += 1
|
self.conf.numskipped += 1
|
||||||
return
|
return
|
||||||
if is_skip:
|
if is_skip:
|
||||||
self.line += 1
|
self.line += 1
|
||||||
if self.single:
|
if self.single:
|
||||||
self.parse_single()
|
self.parse_single()
|
||||||
else:
|
else:
|
||||||
self.parse_template()
|
self.parse_template()
|
||||||
|
|
||||||
|
|
||||||
def usage():
|
def usage():
|
||||||
print("Usage: " + sys.argv[0] + " <compiler path> <file/dir> [-s]")
|
print("Usage: " + sys.argv[0] + " <compiler path> <file/dir> [-s]")
|
||||||
print('')
|
print('')
|
||||||
print('Options:')
|
print('Options:')
|
||||||
print(" -s, --skipped only run skipped tests")
|
print(" -s, --skipped only run skipped tests")
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
|
|
||||||
def handle_file(filepath, conf):
|
def handle_file(filepath, conf):
|
||||||
if filepath.endswith('.c3'):
|
if filepath.endswith('.c3'):
|
||||||
single = True
|
single = True
|
||||||
elif filepath.endswith('.c3t'):
|
elif filepath.endswith('.c3t'):
|
||||||
single = False
|
single = False
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
shutil.rmtree(TEST_DIR, ignore_errors=True)
|
shutil.rmtree(TEST_DIR, ignore_errors=True)
|
||||||
os.mkdir(TEST_DIR, mode=0o777)
|
os.mkdir(TEST_DIR, mode=0o777)
|
||||||
|
|
||||||
conf.numtests += 1
|
conf.numtests += 1
|
||||||
|
|
||||||
issues = Issues(conf, File(filepath), single)
|
issues = Issues(conf, File(filepath), single)
|
||||||
issues.parse()
|
issues.parse()
|
||||||
|
|
||||||
|
|
||||||
def handle_dir(filepath, conf):
|
def handle_dir(filepath, conf):
|
||||||
for file in os.listdir(filepath):
|
for file in os.listdir(filepath):
|
||||||
file = filepath + "/" + file
|
file = filepath + "/" + file
|
||||||
if os.path.isdir(file):
|
if os.path.isdir(file):
|
||||||
handle_dir(file, conf)
|
handle_dir(file, conf)
|
||||||
elif os.path.isfile(file):
|
elif os.path.isfile(file):
|
||||||
handle_file(file, conf)
|
handle_file(file, conf)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
args = len(sys.argv)
|
args = len(sys.argv)
|
||||||
conf = Config()
|
conf = Config()
|
||||||
if args < 3 or args > 4:
|
if args < 3 or args > 4:
|
||||||
usage()
|
usage()
|
||||||
conf.compiler = os.getcwd() + "/" + sys.argv[1]
|
conf.compiler = os.getcwd() + "/" + sys.argv[1]
|
||||||
if not os.path.isfile(conf.compiler):
|
if not os.path.isfile(conf.compiler):
|
||||||
print("Error: Invalid path to compiler: " + conf.compiler)
|
print("Error: Invalid path to compiler: " + conf.compiler)
|
||||||
usage()
|
usage()
|
||||||
if args == 4:
|
if args == 4:
|
||||||
if sys.argv[3] != '-s' and sys.argv[3] != '--skipped':
|
if sys.argv[3] != '-s' and sys.argv[3] != '--skipped':
|
||||||
usage()
|
usage()
|
||||||
conf.run_skipped = True
|
conf.run_skipped = True
|
||||||
filepath = sys.argv[2]
|
filepath = sys.argv[2]
|
||||||
if filepath.endswith('/'):
|
if filepath.endswith('/'):
|
||||||
filepath = filepath[:-1]
|
filepath = filepath[:-1]
|
||||||
conf.cwd = os.getcwd()
|
conf.cwd = os.getcwd()
|
||||||
if os.path.isfile(filepath):
|
if os.path.isfile(filepath):
|
||||||
handle_file(filepath, conf)
|
handle_file(filepath, conf)
|
||||||
elif os.path.isdir(filepath):
|
elif os.path.isdir(filepath):
|
||||||
handle_dir(filepath, conf)
|
handle_dir(filepath, conf)
|
||||||
else:
|
else:
|
||||||
print("Error: Invalid path to tests: " + filepath)
|
print("Error: Invalid path to tests: " + filepath)
|
||||||
usage()
|
usage()
|
||||||
|
|
||||||
print("Found %d tests: %.1f%% (%d / %d) passed (%d skipped)." % (
|
print("Found %d tests: %.1f%% (%d / %d) passed (%d skipped)." % (
|
||||||
conf.numtests, 100 * conf.numsuccess / max(1, conf.numtests - conf.numskipped), conf.numsuccess,
|
conf.numtests, 100 * conf.numsuccess / max(1, conf.numtests - conf.numskipped), conf.numsuccess,
|
||||||
conf.numtests - conf.numskipped, conf.numskipped))
|
conf.numtests - conf.numskipped, conf.numskipped))
|
||||||
if conf.numsuccess != conf.numtests - conf.numskipped:
|
if conf.numsuccess != conf.numtests - conf.numskipped:
|
||||||
exit(-1)
|
exit(-1)
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user