Skip to content

Commit 50219fc

Browse files
authored
TESTSUITE: Extract cmake logs in testresults. (#8235)
## Summary of Changes This PR moves and adds some CMake logs to the test results. The changes of this Pull Request can be viewed [here](https://cgal.geometryfactory.com/~nsaillant/CmakeLogsTestsuite/TestReport_cgal_tester_Fedora) ## Release Management * Issue(s) solved (if any): #8165
2 parents 2be2e30 + 7c8d5a0 commit 50219fc

File tree

1 file changed

+165
-71
lines changed

1 file changed

+165
-71
lines changed
Lines changed: 165 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,169 @@
11
import sys
2-
import io
32
import re
43
import os
4+
import collections
5+
import logging
6+
from itertools import islice
57

6-
report_file=sys.argv[1]
7-
report_name=sys.argv[2]
8-
global_report_name=sys.argv[3]
9-
rx=re.compile('(.*Configuring (examples|demo|test)*( in )*(test\/|examples\/|demo\/)*)((?!done)\w+)')
10-
rx_demo=re.compile('.*in demo\/')
11-
rx_examples=re.compile('.*in examples\/')
12-
13-
14-
#open the Installation report
15-
#For each NAME, check if NAME is a directory. If not, create one, create a
16-
#text report, and write everything that is in the report until the next NAME
17-
#in it. Then, add 'NAME r' in the global report. This should allow to get all
18-
#the NOTICE and other info explaining why the configuration is skipped.
19-
20-
name=""
21-
is_writing=False
22-
is_ignored=False
23-
global_report=open(global_report_name, "a+")
24-
with open(report_file, "rt") as test_report:
25-
for myline in test_report:
26-
m=rx.match(myline)
27-
28-
if is_writing:
29-
if m:
30-
is_writing=False
31-
test_report.close()
32-
if is_ignored:
33-
print("{label} {result}".format(label=name, result='r'), file=global_report)
34-
is_ignored=False
35-
else:
36-
test_report.write(myline)
37-
if not is_writing:
38-
if m:
39-
name=m.group(0).replace(m.group(1), "")
40-
if rx_demo.match(myline):
41-
name="{str}_Demo".format(str=name)
42-
elif rx_examples.match(myline):
43-
name="{str}_Examples".format(str=name)
44-
elif name == "libCGAL":
45-
name="libCGAL_shared"
46-
elif name == "libCGAL_Core":
47-
name="libCGALCore_shared"
48-
elif name == "libCGAL_ImageIO":
49-
name="libCGALimageIO_shared"
50-
elif name == "libCGAL_Qt6":
51-
name="libCGALQt6_shared"
52-
if name=="incomplete":
53-
is_writing=False
54-
is_ignored=False
55-
continue
56-
else:
57-
if not os.path.isdir(name):
58-
is_ignored=True
59-
os.mkdir(name)
60-
test_report=open("{dir}/{file}".format(dir=name, file=report_name), "w+")
61-
print("""
62-
{scm_branch}
63-
""" .format(scm_branch=open("{}/../../../../../.scm-branch".format(os.getcwd()), 'r').read()),file=test_report)
64-
else:
65-
is_ignored=False
66-
test_report=open("{dir}/{file}".format(dir=name, file=report_name), "a+")
67-
test_report.write(" --- CMake Results: --- \n\n")
68-
is_writing=True
69-
if is_writing:
70-
is_writing=False
71-
test_report.close()
72-
if is_ignored:
73-
print("{label} {result}".format(label=name, result='r'), file=global_report)
74-
is_ignored=False
75-
global_report.close()
8+
CONFIG_REGEX = re.compile(
9+
r"(.*Configuring (examples|demo|test) *in *(test/|examples/|demo/))((?!done)\w+)"
10+
)
11+
DEMO_REGEX = re.compile(r".*in demo/")
12+
EXAMPLES_REGEX = re.compile(r'.*in examples/')
13+
SEPARATOR = "------------------------------------------------------------------"
14+
15+
def find_third_separator(contents):
16+
"""Find the position of the third separator line in the contents.
17+
If there are less than 3 separators, then return the position where the third separator
18+
should be inserted.
19+
"""
20+
separator_positions = (
21+
i for i, line in enumerate(contents) if line.strip() == SEPARATOR
22+
)
23+
return next(islice(separator_positions, 2, None), len(contents) + 2)
24+
25+
def last(iterator):
26+
"""Return the last item of an iterator or None if empty."""
27+
return collections.deque(iterator, maxlen=1).pop()
28+
29+
def find_last(contents, query_string):
30+
"""Find the number of the last line matching the query string."""
31+
position, _ = last(filter(lambda x: x[1].strip() == query_string, enumerate(contents)))
32+
return position
33+
34+
def read_file_lines(file_path):
35+
"""Read the lines of a file and return them as a list."""
36+
try:
37+
with open(file_path, "r", encoding="utf-8") as file:
38+
return file.readlines()
39+
except IOError as e:
40+
print(f"Error opening file {file_path}: {e}")
41+
return []
42+
43+
def write_file_lines(file_path, contents):
44+
"""Write the contents to a file. The contents should be a list of strings."""
45+
try:
46+
with open(file_path, "w", encoding="utf-8") as file:
47+
file.write("".join(contents))
48+
except IOError as e:
49+
print(f"Error writing to file {file_path}: {e}")
50+
51+
def mark_package_as_missing_requirements(global_report_file_name, name):
52+
"""Mark a package as missing requirements in the global report file."""
53+
try:
54+
with open(global_report_file_name, "a+", encoding="utf-8") as global_report:
55+
print(f"{name} r", file=global_report)
56+
except IOError as e:
57+
print(f"Error opening global report file {global_report_file_name}: {e}")
58+
59+
def handle_end_of_package(package_name, report_file_name, lines_to_write):
60+
"""Handle the end of a package by inserting the lines to write into the report file."""
61+
if not lines_to_write:
62+
return
63+
64+
file_path = f"{package_name}/{report_file_name}"
65+
contents = read_file_lines(file_path)
66+
position = find_third_separator(contents)
67+
68+
if not any(re.search("- CMake Results .*", content) for content in contents):
69+
lines_to_write.insert(0, f"""
70+
{SEPARATOR}
71+
- CMake Results for {package_name}
72+
{SEPARATOR}
73+
74+
""")
75+
contents[position:position] = lines_to_write
76+
77+
write_file_lines(file_path, contents)
78+
79+
80+
SCM_BRANCH_FILE_CONTENT = read_file_lines(f"{os.getcwd()}/../../../../../.scm-branch")
81+
82+
def handle_new_package__is_ignored(name, report_file_name, cmake_logs):
83+
"""Handle new package creation or update logs if package already exists."""
84+
if not os.path.isdir(name):
85+
os.mkdir(name)
86+
write_file_lines(f"{name}/{report_file_name}", SCM_BRANCH_FILE_CONTENT)
87+
return True
88+
else:
89+
file_path = f"{name}/{report_file_name}"
90+
contents = read_file_lines(file_path)
91+
position = find_third_separator(contents)
92+
93+
if not any(re.search("- CMake Logs .*", content) for content in contents):
94+
contents.insert(
95+
position - 1,
96+
SEPARATOR + "\n- CMake Logs from Installation \n" + SEPARATOR + "\n\n",
97+
)
98+
for log in cmake_logs:
99+
contents.insert(position, log)
100+
position += 1
101+
102+
write_file_lines(file_path, contents)
103+
return False
104+
105+
def retrieve_cmake_logs(file_path):
106+
"""Retrieve the CMake logs from a file and return them as a list."""
107+
logging.debug("Opening file %s", file_path)
108+
contents = read_file_lines(file_path)
109+
110+
position_begin = 1 + find_last(contents, SEPARATOR)
111+
position_end = 1 + find_last(contents, "== Generating build files for tests ==")
112+
113+
cmake_logs = contents[position_begin:position_end]
114+
115+
logging.debug("CMake log beginning is at line %d", position_begin)
116+
logging.debug("CMake log end is at line %d", position_end)
117+
logging.debug("Length of contents is %d", len(contents))
118+
logging.debug("Length of installation CMake logs is %d", len(cmake_logs))
119+
logging.debug("Installation CMake logs are %s", "".join(cmake_logs))
120+
return cmake_logs
121+
122+
def main():
123+
"""Main function that processes the input report file and performs necessary operations."""
124+
input_report_file_name = sys.argv[1]
125+
report_file_name = sys.argv[2]
126+
global_report_file_name = sys.argv[3]
127+
128+
cmake_logs = retrieve_cmake_logs(f"Installation/{report_file_name}")
129+
130+
package_name = ""
131+
lines_to_write = []
132+
133+
for line in read_file_lines(input_report_file_name):
134+
135+
line_matches_new_package = CONFIG_REGEX.match(line)
136+
if package_name and line_matches_new_package:
137+
handle_end_of_package(package_name, report_file_name, lines_to_write)
138+
lines_to_write = []
139+
package_name = ""
140+
141+
if line_matches_new_package:
142+
logging.debug("Found new package %s", line_matches_new_package.group(0))
143+
logging.debug(" group 1 %s", line_matches_new_package.group(1))
144+
new_package_name = line_matches_new_package.group(0).replace(
145+
line_matches_new_package.group(1), ""
146+
)
147+
logging.debug("Setting package name to %s", new_package_name)
148+
package_name = new_package_name
149+
if DEMO_REGEX.match(line):
150+
package_name = f"{package_name}_Demo"
151+
elif EXAMPLES_REGEX.match(line):
152+
package_name = f"{package_name}_Examples"
153+
154+
if package_name == "incomplete":
155+
package_name = ""
156+
continue
157+
else:
158+
is_ignored = handle_new_package__is_ignored(
159+
package_name, report_file_name, cmake_logs
160+
)
161+
logging.debug("Is package %s ignored? %s", package_name, is_ignored)
162+
if is_ignored:
163+
mark_package_as_missing_requirements(global_report_file_name, package_name)
164+
165+
if package_name and not line_matches_new_package and line.strip() != "":
166+
lines_to_write.append(line)
167+
168+
if __name__ == "__main__":
169+
main()

0 commit comments

Comments
 (0)