Skip to content

Commit 6134e5b

Browse files
authored
Add compilation tests (#165)
- Outsourced the tests into seperate python scripts - Added new compilability test
1 parent e15d128 commit 6134e5b

3 files changed

Lines changed: 137 additions & 36 deletions

File tree

.github/workflows/build_and_test.yml

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
uses: actions/checkout@v4
1414
- uses: xu-cheng/texlive-action@v2
1515
with:
16-
scheme: full # Consider changing to 'basic' or 'medium' if possible
16+
scheme: full # Consider changing to 'basic' or 'medium' if possible
1717
run: |
1818
apk add make
1919
apk add g++
@@ -40,41 +40,18 @@ jobs:
4040
- name: Install pdfgrep
4141
run: sudo apt-get update && sudo apt-get install -y pdfgrep
4242

43-
- name: Extract and Check URLs
44-
run: |
45-
urls=$(pdfgrep -o -P 'https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)' vorkurs.pdf | sort -u)
46-
error_count=0
43+
- name: Install required python package
44+
run: pip install urllib3
4745

48-
for url in $urls; do
49-
echo "Checking URL: $url"
46+
- name: Run Link Checker
47+
run: python .github/workflows/test_scripts/check_links.py
5048

51-
if [[ ! "$url" =~ ^https:// ]]; then
52-
echo "ERROR: URL is not HTTPS: $url"
53-
error_count=$((error_count + 1))
54-
continue
55-
fi
56-
57-
if ! curl -Isf --fail-early --connect-timeout 10 "$url" > /dev/null 2>&1; then
58-
curl_error=$(curl -Isf --fail-early --connect-timeout 10 "$url" 2>&1 > /dev/null)
59-
if [[ $curl_error == *"Failed to connect"* ]]; then
60-
echo "ERROR: Connection failed: $url"
61-
elif [[ $curl_error == *"Could not resolve host"* ]]; then
62-
echo "ERROR: DNS resolution failed: $url"
63-
elif [[ $curl_error == *"SSL certificate problem"* ]]; then
64-
echo "ERROR: Initial SSL certificate problem: $url"
65-
else
66-
echo "ERROR: Failed to access: $url (curl error: $curl_error)"
67-
fi
68-
if ! openssl s_client -connect "$(echo "$url" | sed 's/https\?:\/\///' | cut -d/ -f1):443" -servername "$(echo "$url" | sed 's/https\?:\/\///' | cut -d/ -f1)" 2>/dev/null </dev/null | openssl x509 -noout; then
69-
echo " -> CERTIFICATE ERROR DETECTED!"
70-
fi
71-
72-
error_count=$((error_count + 1))
73-
fi
74-
done
49+
check-compilability:
50+
runs-on: ubuntu-latest
51+
needs: build
52+
steps:
53+
- name: Checkout code
54+
uses: actions/checkout@v4
7555

76-
if [ "$error_count" -gt 0 ]; then
77-
echo "::error::Found $error_count broken or insecure links!"
78-
exit 1
79-
fi
80-
shell: bash
56+
- name: Run compilability checker
57+
run: python .github/workflows/test_scripts/check_compilability.py
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import pathlib
2+
import subprocess
3+
4+
# Thats where our cpps are currently
5+
BASE_PATH = "vorkurs/"
6+
7+
8+
def find_all_cpp_files(findWorking):
9+
vorkurs_path = pathlib.Path(BASE_PATH)
10+
broken_cpp_files = set(vorkurs_path.rglob("*broken.cpp"))
11+
12+
if not findWorking:
13+
return [str(cpp_file) for cpp_file in broken_cpp_files]
14+
15+
cpp_files = set(vorkurs_path.rglob("*.cpp"))
16+
working_cpp_files = cpp_files.difference(broken_cpp_files)
17+
return [str(cpp_file) for cpp_file in working_cpp_files]
18+
19+
20+
def test_single_cpp_file(file_path, shouldCompile):
21+
compile_status = subprocess.getoutput(f"g++ {file_path}")
22+
23+
if (compile_status != "" and shouldCompile) or (
24+
compile_status == "" and not shouldCompile
25+
):
26+
print("\n" + 20 * "=")
27+
print(f"Error in file {file_path}:\n")
28+
print(compile_status)
29+
print(20 * "=" + "\n")
30+
return False
31+
32+
return True
33+
34+
35+
def main():
36+
error_count_working = 0
37+
error_count_broken = 0
38+
working_cpp_files = find_all_cpp_files(True)
39+
broken_cpp_files = find_all_cpp_files(False)
40+
41+
for cpp_file in working_cpp_files:
42+
if not test_single_cpp_file(cpp_file, True):
43+
error_count_working += 1
44+
45+
for cpp_file in broken_cpp_files:
46+
if not test_single_cpp_file(cpp_file, False):
47+
error_count_broken += 1
48+
49+
if error_count_working > 0:
50+
print(
51+
f"::error::Found {error_count_working} non compiling files which should compile"
52+
)
53+
exit(1)
54+
55+
if error_count_broken > 0:
56+
print(
57+
f"::error:Found {error_count_broken} files that should be broken but compile"
58+
)
59+
exit(1)
60+
61+
exit(0)
62+
63+
64+
if __name__ == "__main__":
65+
main()
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import re
2+
import subprocess
3+
import ssl
4+
import socket
5+
from urllib.parse import urlparse
6+
7+
def extract_urls(file_path):
8+
with open(file_path, 'r', encoding='latin-1') as file:
9+
content = file.read()
10+
url_pattern = re.compile(r'https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)')
11+
urls = url_pattern.findall(content)
12+
return sorted(set(url[0] for url in urls))
13+
14+
def check_url(url):
15+
if not url.startswith("https://"):
16+
print(f"ERROR: URL is not HTTPS: {url}")
17+
return False
18+
19+
try:
20+
subprocess.run(["curl", "-Isf", "--fail-early", "--connect-timeout", "10", url], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
21+
except subprocess.CalledProcessError as e:
22+
curl_error = e.stderr.decode() if e.stderr else ""
23+
if "Failed to connect" in curl_error:
24+
print(f"ERROR: Connection failed: {url}")
25+
elif "Could not resolve host" in curl_error:
26+
print(f"ERROR: DNS resolution failed: {url}")
27+
elif "SSL certificate problem" in curl_error:
28+
print(f"ERROR: Initial SSL certificate problem: {url}")
29+
else:
30+
print(f"ERROR: Failed to access: {url} (curl error: {curl_error})")
31+
32+
hostname = urlparse(url).hostname
33+
try:
34+
with socket.create_connection((hostname, 443), timeout=10) as sock:
35+
context = ssl.create_default_context()
36+
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
37+
ssock.do_handshake()
38+
except ssl.SSLError:
39+
print(" -> CERTIFICATE ERROR DETECTED!")
40+
return False
41+
return True
42+
43+
def main():
44+
file_path = "vorkurs.pdf"
45+
urls = extract_urls(file_path)
46+
error_count = 0
47+
48+
for url in urls:
49+
print(f"Checking URL: {url}")
50+
if not check_url(url):
51+
error_count += 1
52+
53+
if error_count > 0:
54+
print(f"::error::Found {error_count} broken or insecure links!")
55+
exit(1)
56+
57+
if __name__ == "__main__":
58+
main()
59+

0 commit comments

Comments
 (0)