microsoft/hve-core

Public

mirrored from https://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fix/1124-exclude-python-env-dirs-from-skill-validation

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

.github/skills/experimental/powerpoint/tests/fuzz_harness.py

235lines · modecode

1# Copyright (c) Microsoft Corporation.
2# SPDX-License-Identifier: MIT
3"""Polyglot fuzz harness for PowerPoint skill priority modules.
4
5Runs as a pytest test when Atheris is not installed (CI default).
6Runs as an Atheris coverage-guided fuzz target when executed directly.
7"""
8
9from __future__ import annotations
10
11import sys
12from contextlib import suppress
13
14try:
15 import atheris
16
17 FUZZING = True
18except ImportError:
19 FUZZING = False
20
21from extract_content import _has_formatting_variation
22from pptx_colors import hex_brightness, resolve_color
23from validate_deck import max_severity
24
25# ---------------------------------------------------------------------------
26# Fuzz targets — pure functions exercised by both modes
27# ---------------------------------------------------------------------------
28
29
30def fuzz_resolve_color(data):
31 """Fuzz resolve_color with str and dict inputs."""
32 fdp = atheris.FuzzedDataProvider(data)
33 hex_str = "#" + fdp.ConsumeUnicodeNoSurrogates(6)
34 with suppress(ValueError, IndexError):
35 resolve_color(hex_str)
36 theme_ref = "@" + fdp.ConsumeUnicodeNoSurrogates(20)
37 with suppress(ValueError, IndexError):
38 resolve_color(theme_ref)
39 theme_dict = {
40 "theme": fdp.ConsumeUnicodeNoSurrogates(15),
41 "brightness": fdp.ConsumeFloatInRange(-1.0, 1.0),
42 }
43 with suppress(ValueError, IndexError):
44 resolve_color(theme_dict)
45 nested_dict = {"color": "#" + fdp.ConsumeUnicodeNoSurrogates(6)}
46 with suppress(ValueError, IndexError):
47 resolve_color(nested_dict)
48
49
50def fuzz_hex_brightness(data):
51 """Fuzz hex_brightness with arbitrary strings."""
52 fdp = atheris.FuzzedDataProvider(data)
53 hex_str = fdp.ConsumeUnicodeNoSurrogates(10)
54 with suppress(ValueError, IndexError):
55 hex_brightness(hex_str)
56
57
58def fuzz_max_severity(data):
59 """Fuzz max_severity with structured dict inputs."""
60 fdp = atheris.FuzzedDataProvider(data)
61 severities = ["error", "warning", "info", fdp.ConsumeUnicodeNoSurrogates(8)]
62 num_slides = fdp.ConsumeIntInRange(0, 5)
63 slides = []
64 for _ in range(num_slides):
65 num_issues = fdp.ConsumeIntInRange(0, 4)
66 issues = [
67 {"severity": severities[fdp.ConsumeIntInRange(0, len(severities) - 1)]}
68 for _ in range(num_issues)
69 ]
70 slides.append({"issues": issues})
71 num_deck_issues = fdp.ConsumeIntInRange(0, 3)
72 deck_issues = [
73 {"severity": severities[fdp.ConsumeIntInRange(0, len(severities) - 1)]}
74 for _ in range(num_deck_issues)
75 ]
76 results = {}
77 if fdp.ConsumeBool():
78 results["slides"] = slides
79 if fdp.ConsumeBool():
80 results["deck_issues"] = deck_issues
81 with suppress(KeyError):
82 max_severity(results)
83
84
85def fuzz_has_formatting_variation(data):
86 """Fuzz _has_formatting_variation with lists of run dicts."""
87 fdp = atheris.FuzzedDataProvider(data)
88 num_runs = fdp.ConsumeIntInRange(0, 6)
89 runs = []
90 for _ in range(num_runs):
91 run = {}
92 if fdp.ConsumeBool():
93 run["font"] = fdp.ConsumeUnicodeNoSurrogates(10)
94 if fdp.ConsumeBool():
95 run["size"] = fdp.ConsumeIntInRange(6, 72)
96 if fdp.ConsumeBool():
97 run["color"] = "#" + fdp.ConsumeUnicodeNoSurrogates(6)
98 if fdp.ConsumeBool():
99 run["bold"] = fdp.ConsumeBool()
100 if fdp.ConsumeBool():
101 run["italic"] = fdp.ConsumeBool()
102 if fdp.ConsumeBool():
103 run["underline"] = fdp.ConsumeBool()
104 runs.append(run)
105 _has_formatting_variation(runs)
106
107
108FUZZ_TARGETS = [
109 fuzz_resolve_color,
110 fuzz_hex_brightness,
111 fuzz_max_severity,
112 fuzz_has_formatting_variation,
113]
114
115
116def fuzz_dispatch(data):
117 """Route Atheris input to one of the registered fuzz targets."""
118 if len(data) < 2:
119 return
120 idx = data[0] % len(FUZZ_TARGETS)
121 FUZZ_TARGETS[idx](data[1:])
122
123
124# ---------------------------------------------------------------------------
125# pytest mode — property-based tests for the same targets
126# ---------------------------------------------------------------------------
127
128import pytest # noqa: E402
129
130
131class TestFuzzResolveColor:
132 """Property tests for resolve_color edge cases."""
133
134 @pytest.mark.parametrize(
135 "value",
136 [
137 "#000000",
138 "#FFFFFF",
139 "#abcdef",
140 "@accent1",
141 "@nonexistent_theme",
142 "",
143 {"theme": "accent1", "brightness": 0.5},
144 {"theme": "accent1"},
145 {"color": "#FF0000"},
146 {"color": "#FF0000", "theme": ""},
147 ],
148 )
149 def test_resolve_color_returns_dict(self, value):
150 result = resolve_color(value)
151 assert isinstance(result, dict)
152
153 def test_resolve_color_depth_limit(self):
154 deep = {"color": {"color": {"color": "#000000"}}}
155 with pytest.raises(ValueError, match="depth"):
156 resolve_color(deep, max_depth=2)
157
158 def test_resolve_color_short_hex(self):
159 result = resolve_color("#AB")
160 assert "rgb" in result
161 assert str(result["rgb"]) == "000000"
162
163
164class TestFuzzHexBrightness:
165 """Property tests for hex_brightness."""
166
167 @pytest.mark.parametrize(
168 "hex_color,expected",
169 [
170 ("#000000", 0),
171 ("#FFFFFF", 255),
172 ("#FF0000", 76),
173 ],
174 )
175 def test_known_values(self, hex_color, expected):
176 assert hex_brightness(hex_color) == expected
177
178 def test_short_hex_returns_zero(self):
179 assert hex_brightness("#AB") == 0
180
181
182class TestFuzzMaxSeverity:
183 """Property tests for max_severity."""
184
185 def test_empty_slides(self):
186 assert max_severity({"slides": [], "deck_issues": []}) == "none"
187
188 def test_error_dominates(self):
189 results = {
190 "slides": [{"issues": [{"severity": "info"}, {"severity": "error"}]}],
191 "deck_issues": [{"severity": "warning"}],
192 }
193 assert max_severity(results) == "error"
194
195 def test_warning_over_info(self):
196 results = {
197 "slides": [{"issues": [{"severity": "info"}]}],
198 "deck_issues": [{"severity": "warning"}],
199 }
200 assert max_severity(results) == "warning"
201
202 def test_missing_slides_key(self):
203 with pytest.raises(KeyError):
204 max_severity({"deck_issues": []})
205
206 def test_missing_deck_issues_key(self):
207 assert max_severity({"slides": []}) == "none"
208
209
210class TestFuzzHasFormattingVariation:
211 """Property tests for _has_formatting_variation."""
212
213 def test_single_run(self):
214 assert _has_formatting_variation([{"font": "Arial"}]) is False
215
216 def test_identical_runs(self):
217 runs = [{"font": "Arial", "bold": True}, {"font": "Arial", "bold": True}]
218 assert _has_formatting_variation(runs) is False
219
220 def test_different_fonts(self):
221 runs = [{"font": "Arial"}, {"font": "Calibri"}]
222 assert _has_formatting_variation(runs) is True
223
224 def test_empty_list(self):
225 assert _has_formatting_variation([]) is False
226
227
228# ---------------------------------------------------------------------------
229# Atheris entry point — only runs when executed directly with Atheris installed
230# ---------------------------------------------------------------------------
231
232if __name__ == "__main__" and FUZZING:
233 atheris.instrument_all()
234 atheris.Setup(sys.argv, fuzz_dispatch)
235 atheris.Fuzz()
236