Skip to content

Commit cacd3c4

Browse files
committed
feat: upgrade a couple of assertions to ValueErrors
1 parent 94b581c commit cacd3c4

File tree

3 files changed

+108
-75
lines changed

3 files changed

+108
-75
lines changed

src/ffpuppet/sanitizer_util.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ def add(self, flag: str, value: str, overwrite: bool = False) -> None:
6161
Returns:
6262
None
6363
"""
64-
assert flag
65-
if ":" in value or " " in value:
66-
assert self.is_quoted(value), f"{value} ({flag}) must be quoted"
64+
if not flag:
65+
raise ValueError("Flag name cannot be empty")
66+
if (":" in value or " " in value) and not self.is_quoted(value):
67+
raise ValueError(f"'{value}' ({flag}) must be quoted")
6768
if flag not in self._options or overwrite:
6869
self._options[flag] = value
6970

src/ffpuppet/test_helpers.py

Lines changed: 57 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
# You can obtain one at http://mozilla.org/MPL/2.0/.
44
"""ffpuppet helpers tests"""
55

6-
from contextlib import suppress
76
from os import getpid
87
from pathlib import Path
98
from subprocess import CalledProcessError
@@ -26,69 +25,66 @@
2625

2726
def test_helpers_01(tmp_path):
2827
"""test _configure_sanitizers()"""
29-
30-
def parse(opt_str):
31-
opts = {}
32-
for entry in SanitizerOptions.re_delim.split(opt_str):
33-
with suppress(ValueError):
34-
key, value = entry.split("=", maxsplit=1)
35-
opts[key] = value
36-
return opts
37-
3828
# test with empty environment
39-
env = {}
40-
env = _configure_sanitizers(env, tmp_path, "blah")
29+
env = _configure_sanitizers({}, tmp_path, "blah")
4130
assert "ASAN_OPTIONS" in env
42-
asan_opts = parse(env["ASAN_OPTIONS"])
43-
assert "external_symbolizer_path" not in asan_opts
44-
assert "detect_leaks" in asan_opts
45-
assert asan_opts["detect_leaks"] == "false"
46-
assert asan_opts["log_path"] == "'blah'"
31+
opts = SanitizerOptions(env["ASAN_OPTIONS"])
32+
assert opts.get("external_symbolizer_path") is None
33+
assert opts.get("detect_leaks") == "false"
34+
assert opts.get("log_path") == "'blah'"
4735
assert "LSAN_OPTIONS" in env
4836
assert "UBSAN_OPTIONS" in env
4937
# test with presets environment
50-
env = {
51-
"ASAN_OPTIONS": "detect_leaks=true",
52-
"LSAN_OPTIONS": "a=1",
53-
"UBSAN_OPTIONS": "",
54-
}
55-
env = _configure_sanitizers(env, tmp_path, "blah")
38+
env = _configure_sanitizers(
39+
{
40+
"ASAN_OPTIONS": "detect_leaks=true",
41+
"LSAN_OPTIONS": "a=1",
42+
"UBSAN_OPTIONS": "",
43+
},
44+
tmp_path,
45+
"blah",
46+
)
5647
assert "ASAN_OPTIONS" in env
57-
asan_opts = parse(env["ASAN_OPTIONS"])
58-
assert "detect_leaks" in asan_opts
59-
assert asan_opts["detect_leaks"] == "true"
48+
opts = SanitizerOptions(env["ASAN_OPTIONS"])
49+
assert opts.get("detect_leaks") == "true"
6050
assert "LSAN_OPTIONS" in env
6151
assert "UBSAN_OPTIONS" in env
62-
ubsan_opts = parse(env["UBSAN_OPTIONS"])
63-
assert "print_stacktrace" in ubsan_opts
52+
opts = SanitizerOptions(env["UBSAN_OPTIONS"])
53+
assert opts.get("print_stacktrace") is not None
6454
# test suppression file
6555
sup = tmp_path / "test.sup"
6656
sup.touch()
67-
env = {"ASAN_OPTIONS": f"suppressions='{sup}'"}
68-
env = _configure_sanitizers(env, tmp_path, "blah")
69-
asan_opts = parse(env["ASAN_OPTIONS"])
70-
assert "suppressions" in asan_opts
57+
env = _configure_sanitizers(
58+
{"ASAN_OPTIONS": f"suppressions='{sup}'"}, tmp_path, "blah"
59+
)
60+
opts = SanitizerOptions(env["ASAN_OPTIONS"])
61+
assert opts.get("suppressions") is not None
7162
# test overwrite log_path
72-
env = {
73-
"ASAN_OPTIONS": "log_path='overwrite'",
74-
"TSAN_OPTIONS": "log_path='overwrite'",
75-
"UBSAN_OPTIONS": "log_path='overwrite'",
76-
}
77-
env = _configure_sanitizers(env, tmp_path, "blah")
63+
env = _configure_sanitizers(
64+
{
65+
"ASAN_OPTIONS": "log_path='overwrite'",
66+
"TSAN_OPTIONS": "log_path='overwrite'",
67+
"UBSAN_OPTIONS": "log_path='overwrite'",
68+
},
69+
tmp_path,
70+
"blah",
71+
)
7872
assert "ASAN_OPTIONS" in env
79-
asan_opts = parse(env["ASAN_OPTIONS"])
80-
assert asan_opts["log_path"] == "'blah'"
73+
opts = SanitizerOptions(env["ASAN_OPTIONS"])
74+
assert opts.get("log_path") == "'blah'"
8175
assert "UBSAN_OPTIONS" in env
82-
ubsan_opts = parse(env["UBSAN_OPTIONS"])
83-
assert ubsan_opts["log_path"] == "'blah'"
76+
opts = SanitizerOptions(env["UBSAN_OPTIONS"])
77+
assert opts.get("log_path") == "'blah'"
8478
# test missing suppression file
85-
env = {"ASAN_OPTIONS": "suppressions=not_a_file"}
8679
with raises(AssertionError, match="missing suppressions file"):
87-
_configure_sanitizers(env, tmp_path, "blah")
80+
_configure_sanitizers(
81+
{"ASAN_OPTIONS": "suppressions=not_a_file"}, tmp_path, "blah"
82+
)
8883
# unquoted path containing ':'
89-
env = {"ASAN_OPTIONS": "strip_path_prefix=x:\\foo\\bar"}
90-
with raises(AssertionError, match=r"\(strip_path_prefix\) must be quoted"):
91-
_configure_sanitizers(env, tmp_path, "blah")
84+
with raises(ValueError, match=r"\(strip_path_prefix\) must be quoted"):
85+
_configure_sanitizers(
86+
{"ASAN_OPTIONS": "strip_path_prefix=x:\\foo\\bar"}, tmp_path, "blah"
87+
)
9288
# multiple options
9389
options = (
9490
"opt1=1",
@@ -100,34 +96,29 @@ def parse(opt_str):
10096
"opt7='/with space/'",
10197
"opt8='x:\\with a space\\or two'",
10298
)
103-
env = {"ASAN_OPTIONS": ":".join(options)}
104-
env = _configure_sanitizers(env, tmp_path, "blah")
105-
asan_opts = parse(env["ASAN_OPTIONS"])
99+
env = _configure_sanitizers({"ASAN_OPTIONS": ":".join(options)}, tmp_path, "blah")
100+
opts = SanitizerOptions(env["ASAN_OPTIONS"])
106101
for key, value in (x.split(sep="=", maxsplit=1) for x in options):
107-
assert asan_opts[key] == value
102+
assert opts.get(key) == value
108103
# test using packaged llvm-symbolizer
109104
llvm_sym_packed = tmp_path / LLVM_SYMBOLIZER
110105
llvm_sym_packed.touch()
111-
env = {"ASAN_OPTIONS": ":".join(options)}
112-
env = _configure_sanitizers(env, tmp_path, "blah")
113-
asan_opts = parse(env["ASAN_OPTIONS"])
114-
assert "external_symbolizer_path" in asan_opts
115-
assert asan_opts["external_symbolizer_path"].strip("'") == str(llvm_sym_packed)
106+
env = _configure_sanitizers({"ASAN_OPTIONS": ":".join(options)}, tmp_path, "blah")
107+
opts = SanitizerOptions(env["ASAN_OPTIONS"])
108+
assert opts.get("external_symbolizer_path").strip("'") == str(llvm_sym_packed)
116109
# test malformed option pair
117-
env = {"ASAN_OPTIONS": "a=b=c:x"}
118-
env = _configure_sanitizers(env, tmp_path, "blah")
119-
asan_opts = parse(env["ASAN_OPTIONS"])
120-
assert asan_opts["a"] == "b=c"
121-
assert "x" not in asan_opts
110+
env = _configure_sanitizers({"ASAN_OPTIONS": "a=b=c:malformed"}, tmp_path, "blah")
111+
opts = SanitizerOptions(env["ASAN_OPTIONS"])
112+
assert opts.get("a") == "b=c"
113+
assert "malformed" not in str(opts)
122114
# test ASAN_SYMBOLIZER_PATH
123115
(tmp_path / "a").mkdir()
124116
llvm_sym_a = tmp_path / "a" / "llvm-symbolizer"
125117
llvm_sym_a.touch()
126118
env = {"ASAN_SYMBOLIZER_PATH": str(llvm_sym_a)}
127119
env = _configure_sanitizers(env, tmp_path, "blah")
128-
asan_opts = parse(env["ASAN_OPTIONS"])
129-
assert "external_symbolizer_path" in asan_opts
130-
assert asan_opts["external_symbolizer_path"].strip("'") == str(llvm_sym_a)
120+
opts = SanitizerOptions(env["ASAN_OPTIONS"])
121+
assert opts.get("external_symbolizer_path").strip("'") == str(llvm_sym_a)
131122
# test ASAN_SYMBOLIZER_PATH override by ASAN_OPTIONS=external_symbolizer_path
132123
(tmp_path / "b").mkdir()
133124
llvm_sym_b = tmp_path / "b" / "llvm-symbolizer"
@@ -137,9 +128,8 @@ def parse(opt_str):
137128
"ASAN_OPTIONS": f"external_symbolizer_path='{llvm_sym_b}'",
138129
}
139130
env = _configure_sanitizers(env, tmp_path, "blah")
140-
asan_opts = parse(env["ASAN_OPTIONS"])
141-
assert "external_symbolizer_path" in asan_opts
142-
assert asan_opts["external_symbolizer_path"].strip("'") == str(llvm_sym_b)
131+
opts = SanitizerOptions(env["ASAN_OPTIONS"])
132+
assert opts.get("external_symbolizer_path").strip("'") == str(llvm_sym_b)
143133

144134

145135
def test_helpers_02(tmp_path):

src/ffpuppet/test_sanitizer_util.py

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# You can obtain one at http://mozilla.org/MPL/2.0/.
44
"""ffpuppet sanitizer_util tests"""
55

6-
from pytest import mark
6+
from pytest import mark, raises
77

88
from .sanitizer_util import SanitizerOptions
99

@@ -34,7 +34,7 @@
3434
),
3535
],
3636
)
37-
def test_sanitizer_options_01(init, add, result, overwrite):
37+
def test_sanitizer_options_parsing_adding(init, add, result, overwrite):
3838
"""test SanitizerOptions() - parsing and adding"""
3939
opts = SanitizerOptions(init)
4040
for key, value in add.items():
@@ -57,7 +57,49 @@ def test_sanitizer_options_01(init, add, result, overwrite):
5757
assert not result[-1]
5858

5959

60-
def test_sanitizer_options_02():
60+
def test_sanitizer_load_options():
61+
"""test SanitizerOptions.load_options -"""
62+
opts = SanitizerOptions()
63+
# empty
64+
assert not opts
65+
assert len(opts) == 0
66+
# single options
67+
opts.load_options("a=1")
68+
assert opts
69+
assert len(opts) == 1
70+
assert opts.pop("a") == "1"
71+
# multiple options
72+
opts.load_options("a=1:b=2")
73+
assert len(opts) == 2
74+
assert opts.pop("a") == "1"
75+
assert opts.pop("b") == "2"
76+
# malformed option
77+
opts.load_options("foo")
78+
assert len(opts) == 0
79+
# malformed option with valid option
80+
opts.load_options("a=1:foo")
81+
assert len(opts) == 1
82+
assert opts.pop("a") == "1"
83+
84+
85+
@mark.parametrize(
86+
"flag, value, msg",
87+
[
88+
# empty flag name
89+
("", "test", r"Flag name cannot be empty"),
90+
# missing quotes with ':'
91+
("test", "a:b", r"'a:b' \(test\) must be quoted"),
92+
# missing quotes with ' '
93+
("test", "a b", r"'a b' \(test\) must be quoted"),
94+
],
95+
)
96+
def test_sanitizer_options_invalid_add(flag, value, msg):
97+
"""test SanitizerOptions() -"""
98+
with raises(ValueError, match=msg):
99+
SanitizerOptions().add(flag, value)
100+
101+
102+
def test_sanitizer_options_get_pop():
61103
"""test SanitizerOptions() - get() and pop()"""
62104
opts = SanitizerOptions()
63105
assert opts.get("missing") is None
@@ -67,7 +109,7 @@ def test_sanitizer_options_02():
67109
assert opts.get("exists") is None
68110

69111

70-
def test_sanitizer_options_03(tmp_path):
112+
def test_sanitizer_options_check_path(tmp_path):
71113
"""test SanitizerOptions() - check_path()"""
72114
opts = SanitizerOptions()
73115
# test missing key
@@ -82,7 +124,7 @@ def test_sanitizer_options_03(tmp_path):
82124
assert not opts.check_path("file")
83125

84126

85-
def test_sanitizer_options_04():
127+
def test_sanitizer_options_is_quoted():
86128
"""test SanitizerOptions.is_quoted()"""
87129
assert SanitizerOptions.is_quoted("'quoted'")
88130
assert SanitizerOptions.is_quoted('"quoted"')

0 commit comments

Comments
 (0)