Skip to content

Commit 7e4b1c8

Browse files
committed
feat: add strict2 mode that checks for any errorneous console logs
1 parent 317f9b1 commit 7e4b1c8

File tree

5 files changed

+118
-18
lines changed

5 files changed

+118
-18
lines changed

html2pdf4doc/main.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,12 @@ def get_inches_from_millimeters(mm: float) -> float:
295295
return mm / 25.4
296296

297297

298-
def get_pdf_from_html(driver: webdriver.Chrome, url: str) -> Tuple[bytes, int]:
298+
def get_pdf_from_html(
299+
*,
300+
driver: webdriver.Chrome,
301+
url: str,
302+
strict_mode_2: bool = False,
303+
) -> Tuple[bytes, int]:
299304
print(f"html2pdf4doc: Opening URL with ChromeDriver: {url}", flush=True) # noqa: T201
300305

301306
driver.get(url)
@@ -357,12 +362,29 @@ def __init__(self, page_count: int):
357362
)
358363
sys.exit(1)
359364

365+
bad_logs: List[Dict[str, str]] = []
366+
360367
print("html2pdf4doc: JS logs from the print session:") # noqa: T201
361368
print('"""') # noqa: T201
362369
for entry in logs:
363370
print(entry) # noqa: T201
371+
372+
if entry["level"] not in ("INFO", "DEBUG"):
373+
bad_logs.append(entry)
374+
364375
print('"""') # noqa: T201
365376

377+
if len(bad_logs) > 0:
378+
bad_logs_error_message = (
379+
"html2pdf4doc: Something went wrong: "
380+
"Detected console error/warning messages:\n"
381+
f"{bad_logs}"
382+
)
383+
if strict_mode_2:
384+
raise RuntimeError(bad_logs_error_message)
385+
else:
386+
print(bad_logs_error_message) # noqa: T201
387+
366388
#
367389
# Execute Print command with ChromeDriver.
368390
#
@@ -530,11 +552,21 @@ def main() -> None:
530552
action="store_true",
531553
help=(
532554
"Enables Strict mode. In this mode, the library always performs a "
533-
"validation of printed pages and raise a runtime error if the "
555+
"validation of printed pages and raises a runtime error if the "
534556
"validation fails. Without the Strict mode enabled, only a warning "
535557
"message is printed and the execution continues."
536558
),
537559
)
560+
command_parser_print.add_argument(
561+
"--strict2",
562+
action="store_true",
563+
help=(
564+
"Enables Strict mode (level 2). In this mode, the library always performs a "
565+
"validation of console logs and raises a runtime error if there are "
566+
"error/warning/severe messages. Without the Strict (level 2) mode enabled, "
567+
"only a warning message is printed and the execution continues."
568+
),
569+
)
538570
command_parser_print.add_argument(
539571
"paths", nargs="+", help="Paths to input HTML file."
540572
)
@@ -587,7 +619,11 @@ def exit_handler() -> None:
587619

588620
url = Path(os.path.abspath(path_to_input_html)).as_uri()
589621

590-
pdf_bytes, page_count = get_pdf_from_html(driver, url)
622+
pdf_bytes, page_count = get_pdf_from_html(
623+
driver=driver,
624+
url=url,
625+
strict_mode_2=args.strict2,
626+
)
591627
with open(path_to_output_pdf, "wb") as f:
592628
f.write(pdf_bytes)
593629

html2pdf4doc/main_fuzzer.py

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@ def measure_performance(title: str) -> Iterator[None]:
2626
print(f"{padded_name}{padded_time}s", flush=True) # noqa: T201
2727

2828

29-
def mutate_and_print(path_to_input_file: str, path_to_root: str) -> bool:
29+
def mutate_and_print(
30+
*,
31+
path_to_input_file: str,
32+
path_to_root: str,
33+
path_to_failed_mutants_dir: str,
34+
strict_mode: bool = False,
35+
strict_mode_2: bool = False,
36+
) -> bool:
3037
assert os.path.isfile(path_to_input_file), path_to_input_file
3138
assert os.path.isdir(path_to_root), path_to_root
3239
if not os.path.abspath(path_to_root):
@@ -72,25 +79,31 @@ def mutate_and_print(path_to_input_file: str, path_to_root: str) -> bool:
7279
"-m",
7380
"html2pdf4doc.main",
7481
"print",
75-
"--strict",
7682
]
83+
if strict_mode:
84+
cmd.append("--strict")
85+
if strict_mode_2:
86+
cmd.append("--strict2")
7787

7888
for path_to_print_ in paths_to_print:
7989
cmd.append(path_to_print_[0])
8090
cmd.append(path_to_print_[1])
8191

8292
relative_path_to_mut_html = Path(path_to_mut_html).relative_to(path_to_root)
83-
path_to_mut_output = f"output/{relative_path_to_mut_html}"
93+
path_to_mut_output = os.path.join(
94+
path_to_failed_mutants_dir, relative_path_to_mut_html
95+
)
8496

8597
def copy_files_if_needed() -> None:
8698
if os.path.isdir(path_to_mut_output):
8799
return
88100

89-
shutil.rmtree("output", ignore_errors=True)
90-
Path("output").mkdir(parents=True, exist_ok=True)
101+
Path(path_to_failed_mutants_dir).mkdir(parents=True, exist_ok=True)
91102

92103
shutil.copytree(
93-
"html2pdf4doc", "output/html2pdf4doc", dirs_exist_ok=True
104+
"html2pdf4doc",
105+
os.path.join(path_to_failed_mutants_dir, "html2pdf4doc"),
106+
dirs_exist_ok=True,
94107
)
95108

96109
shutil.rmtree(path_to_mut_output, ignore_errors=True)
@@ -110,6 +123,12 @@ def copy_mutated_file() -> None:
110123
)
111124
shutil.copy(path_to_mut_html, path_to_mut_html_out)
112125

126+
if not os.path.isfile(path_to_mut_pdf):
127+
print( # noqa: T201
128+
f"html2pdf4doc_fuzzer: warning: Mutated PDF is missing: {path_to_mut_pdf}"
129+
)
130+
return
131+
113132
path_to_mut_pdf_out = os.path.join(
114133
path_to_mut_output,
115134
f"{relative_path_to_mut_html}.{timestamp}.pdf",
@@ -143,19 +162,28 @@ def copy_mutated_file() -> None:
143162

144163

145164
def fuzz_test(
146-
*, path_to_input_file: str, path_to_root: str, total_mutations: int = 20
165+
*,
166+
path_to_input_file: str,
167+
path_to_root: str,
168+
path_to_failed_mutants_dir: str,
169+
total_mutations: int = 20,
170+
strict_mode: bool = False,
171+
strict_mode_2: bool = False,
147172
) -> None:
148-
shutil.rmtree("output", ignore_errors=True)
149-
Path("output").mkdir(parents=True, exist_ok=True)
150-
151173
success_count, failure_count = 0, 0
152174
for i in range(1, total_mutations + 1):
153175
print( # noqa: T201
154176
f"html2pdf4doc_fuzzer print cycle #{i}/{total_mutations} — "
155177
f"So far: 🟢{success_count} / 🔴{failure_count}",
156178
flush=True,
157179
)
158-
success = mutate_and_print(path_to_input_file, path_to_root)
180+
success = mutate_and_print(
181+
path_to_input_file=path_to_input_file,
182+
path_to_root=path_to_root,
183+
path_to_failed_mutants_dir=path_to_failed_mutants_dir,
184+
strict_mode=strict_mode,
185+
strict_mode_2=strict_mode_2,
186+
)
159187
if success:
160188
success_count += 1
161189
else:
@@ -182,24 +210,40 @@ def main() -> None:
182210

183211
parser.add_argument("input_file", type=str, help="TODO")
184212
parser.add_argument("root_path", type=str, help="TODO")
213+
parser.add_argument("path_to_failed_mutants_dir", type=str, help="TODO")
185214
parser.add_argument(
186215
"--total-mutations",
187216
type=int,
188217
choices=range(1, 1001),
189218
required=True,
190219
help="An integer between 1 and 1000",
191220
)
192-
221+
parser.add_argument(
222+
"--strict",
223+
action="store_true",
224+
help="Enables Strict mode (level 1).",
225+
)
226+
parser.add_argument(
227+
"--strict2",
228+
action="store_true",
229+
help="Enables Strict mode (level 2).",
230+
)
193231
args = parser.parse_args()
194232

195233
path_to_input_file = args.input_file
196234
path_to_root = args.root_path
235+
path_to_failed_mutants_dir = args.failed_mutants_path
197236
total_mutations = args.total_mutations
237+
strict_mode = args.strict
238+
strict_mode_2 = args.strict2
198239

199240
fuzz_test(
200241
path_to_input_file=path_to_input_file,
201242
path_to_root=path_to_root,
243+
path_to_failed_mutants_dir=path_to_failed_mutants_dir,
202244
total_mutations=total_mutations,
245+
strict_mode=strict_mode,
246+
strict_mode_2=strict_mode_2,
203247
)
204248

205249

tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ def test_fuzz(context, focus=None, total_mutations: int = 10, output=False):
210210

211211
focus_argument = f"-k {focus}" if focus is not None else ""
212212
long_argument = (
213-
f"--fuzz-total-mutations {total_mutations}" if total_mutations else ""
213+
f"--fuzz-total-mutations={total_mutations}" if total_mutations else ""
214214
)
215215
output_argument = "--capture=no" if output else ""
216216

tests/fuzz/01_strictdoc_guide_202510/test_case.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22

33
from html2pdf4doc.main_fuzzer import fuzz_test
4-
from tests.fuzz.conftest import create_build_folder, FuzzConfig
4+
from tests.fuzz.conftest import create_build_folder, FuzzConfig, create_failed_mutants_folder
55

66
PATH_TO_THIS_FOLDER = os.path.dirname(__file__)
77

@@ -14,5 +14,8 @@ def test(fuzz_config: FuzzConfig):
1414
"strictdoc/docs/strictdoc_01_user_guide-PDF.html"
1515
),
1616
path_to_root=build_folder,
17-
total_mutations=fuzz_config.total_mutations
17+
path_to_failed_mutants_dir=create_failed_mutants_folder(PATH_TO_THIS_FOLDER),
18+
total_mutations=fuzz_config.total_mutations,
19+
strict_mode=True,
20+
strict_mode_2=False,
1821
)

tests/fuzz/conftest.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import datetime
12
import os
23
import shutil
34
from dataclasses import dataclass
@@ -46,3 +47,19 @@ def create_build_folder(test_folder: str) -> str:
4647
shutil.copytree(test_folder, build_folder)
4748

4849
return build_folder
50+
51+
52+
def create_failed_mutants_folder(test_folder: str) -> str:
53+
assert os.path.isdir(test_folder), test_folder
54+
assert os.path.isabs(test_folder), test_folder
55+
56+
relative_path_to_test_folder = Path(test_folder).relative_to(PATH_TO_TESTS_FUZZ_FOLDER)
57+
58+
mutants_folder = os.path.join(
59+
"build",
60+
"tests_fuzz_failed_mutants",
61+
datetime.datetime.now().strftime("%Y%m%d_%H%M%S"),
62+
relative_path_to_test_folder
63+
)
64+
65+
return mutants_folder

0 commit comments

Comments
 (0)