Skip to content

Commit

Permalink
Set TEST_INFO in a single location
Browse files Browse the repository at this point in the history
  • Loading branch information
tysmith committed Nov 27, 2023
1 parent b697fc2 commit 10d283f
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 42 deletions.
3 changes: 2 additions & 1 deletion grizzly/common/fuzzmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from FTB.Signatures.CrashInfo import CrashInfo

from .reporter import Quality
from .storage import TEST_INFO
from .utils import grz_tmp

FM_CONFIG = Path.home() / ".fuzzmanagerconf"
Expand Down Expand Up @@ -334,7 +335,7 @@ def testcases(self, subset=None):
# - 'foo-0' (most recent)
# see FuzzManagerReporter for more info
self._contents = sorted(
(x.parent for x in self._storage.rglob("test_info.json")),
(x.parent for x in self._storage.rglob(TEST_INFO)),
reverse=True,
)

Expand Down
17 changes: 9 additions & 8 deletions grizzly/common/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@


LOG = getLogger(__name__)
TEST_INFO = "test_info.json"


class TestCaseLoadFailure(Exception):
Expand Down Expand Up @@ -288,7 +289,7 @@ def dump(self, dst_path, include_details=False):
Args:
dst_path (str): Path to directory to output data.
include_details (bool): Output "test_info.json" file.
include_details (bool): Output test info file.
Returns:
None
Expand Down Expand Up @@ -325,7 +326,7 @@ def dump(self, dst_path, include_details=False):
info["assets"] = self.assets
info["assets_path"] = "_assets_"
copytree(self.assets_path, dst_path / info["assets_path"])
with (dst_path / "test_info.json").open("w") as out_fp:
with (dst_path / TEST_INFO).open("w") as out_fp:
json.dump(info, out_fp, indent=2, sort_keys=True)

@staticmethod
Expand Down Expand Up @@ -423,7 +424,7 @@ def load(cls, path, entry_point=None, catalog=False):
if (
not entry.is_dir()
and test.assets_path not in entry.parents
and entry.name != "test_info.json"
and entry.name != TEST_INFO
):
test.add_from_file(
entry, file_name=entry.relative_to(test.root).as_posix()
Expand All @@ -438,7 +439,7 @@ def load_meta(cls, path, entry_point=None):
"""Process and sanitize TestCase meta data.
Args:
path (Path): Directory containing test_info.json file.
path (Path): Directory containing test info file.
entry_point (): See TestCase.load().
Returns:
Expand Down Expand Up @@ -490,20 +491,20 @@ def read_info(path):
"""Attempt to load test info.
Args:
path (Path): Directory containing test_info.json.
path (Path): Directory containing test info file.
Yields:
dict: Test info.
"""
try:
with (path / "test_info.json").open("r") as in_fp:
with (path / TEST_INFO).open("r") as in_fp:
info = json.load(in_fp)
except FileNotFoundError:
info = None
except ValueError:
raise TestCaseLoadFailure("Invalid 'test_info.json'") from None
raise TestCaseLoadFailure(f"Invalid '{TEST_INFO}'") from None
if info is not None and not isinstance(info.get("target"), str):
raise TestCaseLoadFailure("Invalid 'target' entry in 'test_info.json'")
raise TestCaseLoadFailure(f"Invalid 'target' entry in '{TEST_INFO}'")
return info or {}

@property
Expand Down
5 changes: 3 additions & 2 deletions grizzly/common/test_fuzzmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from pytest import mark, raises

from .fuzzmanager import Bucket, CrashEntry, load_fm_data
from .storage import TEST_INFO


def test_bucket_1(mocker):
Expand Down Expand Up @@ -178,8 +179,8 @@ def test_crash_3(mocker, tmp_path):
for i in (1, 3, 2, 0):
test = tmp_path / f"test-{i}"
test.mkdir()
(test / "test_info.json").touch()
zip_fp.write(test / "test_info.json", arcname=f"test-{i}/test_info.json")
(test / TEST_INFO).touch()
zip_fp.write(test / TEST_INFO, arcname=f"test-{i}/{TEST_INFO}")
with CrashEntry(234) as crash:
assert crash.testcase == "test.zip" # pre-load data dict so I can re-patch get
coll.return_value.get.return_value = mocker.Mock(
Expand Down
56 changes: 27 additions & 29 deletions grizzly/common/test_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pytest import mark, raises

from ..target import AssetManager
from .storage import TestCase, TestCaseLoadFailure, TestFileExists
from .storage import TEST_INFO, TestCase, TestCaseLoadFailure, TestFileExists


def test_testcase_01(tmp_path):
Expand Down Expand Up @@ -38,7 +38,7 @@ def test_testcase_01(tmp_path):
tcase.dump(tmp_path)
assert not any(tmp_path.iterdir())
tcase.dump(tmp_path, include_details=True)
assert (tmp_path / "test_info.json").is_file()
assert (tmp_path / TEST_INFO).is_file()
tcase.cleanup()
assert not tcase.root.is_dir()

Expand Down Expand Up @@ -142,20 +142,18 @@ def test_testcase_06():

def test_testcase_07(tmp_path):
"""test TestCase.read_info()"""
# missing test_info.json
# missing test info file
assert not TestCase.read_info(tmp_path)
# invalid test_info.json
(tmp_path / "test_info.json").write_text("X")
with raises(TestCaseLoadFailure, match="Invalid 'test_info.json'"):
# invalid test info file
(tmp_path / TEST_INFO).write_text("X")
with raises(TestCaseLoadFailure, match=f"Invalid '{TEST_INFO}'"):
TestCase.read_info(tmp_path)
# test_info.json missing 'target' entry
(tmp_path / "test_info.json").write_text("{}")
with raises(
TestCaseLoadFailure, match="Invalid 'target' entry in 'test_info.json'"
):
# test info file missing 'target' entry
(tmp_path / TEST_INFO).write_text("{}")
with raises(TestCaseLoadFailure, match=f"Invalid 'target' entry in '{TEST_INFO}'"):
TestCase.read_info(tmp_path)
# success
(tmp_path / "test_info.json").write_text('{"target": "foo"}')
(tmp_path / TEST_INFO).write_text('{"target": "foo"}')
assert TestCase.read_info(tmp_path) == {"target": "foo"}


Expand All @@ -165,7 +163,7 @@ def test_testcase_08(tmp_path):
with raises(TestCaseLoadFailure, match="Could not determine entry point"):
TestCase._find_entry_point(tmp_path)
# missing potential entry point
(tmp_path / "test_info.json").touch()
(tmp_path / TEST_INFO).touch()
with raises(TestCaseLoadFailure, match="Could not determine entry point"):
TestCase._find_entry_point(tmp_path)
# success
Expand Down Expand Up @@ -194,21 +192,21 @@ def test_testcase_09(tmp_path):
entry_point, info = TestCase.load_meta(tmp_path / "test_01.html")
assert entry_point == tmp_path / "test_01.html"
assert not info
# success (test_info.json)
(tmp_path / "test_info.json").write_text('{"target": "test_01.html"}')
# success (with test info file)
(tmp_path / TEST_INFO).write_text('{"target": "test_01.html"}')
(tmp_path / "other.html").touch()
entry_point, info = TestCase.load_meta(tmp_path)
assert entry_point == (tmp_path / "test_01.html")
assert info.get("target") == "test_01.html"
# success (test_info.json) override entry point
# success (with test info file) override entry point
entry_point, info = TestCase.load_meta(
tmp_path, entry_point=(tmp_path / "other.html")
)
assert entry_point == tmp_path / "other.html"
assert info.get("target") == "other.html"
# invalid test_info.json (will fallback to searching for test)
# invalid test info file (will fallback to searching for test)
(tmp_path / "other.html").unlink()
(tmp_path / "test_info.json").write_text("{}")
(tmp_path / TEST_INFO).write_text("{}")
entry_point, info = TestCase.load_meta(tmp_path)
assert entry_point == (tmp_path / "test_01.html")
assert not info
Expand Down Expand Up @@ -242,7 +240,7 @@ def test_testcase_10(tmp_path):


def test_testcase_11(tmp_path):
"""test TestCase.load() existing test case with simple test_info.json"""
"""test TestCase.load() existing test case with simple test info file"""
# build a test case
src = tmp_path / "src"
with TestCase("test.html", "test-adapter") as test:
Expand All @@ -259,7 +257,7 @@ def test_testcase_11(tmp_path):

@mark.parametrize("catalog", [False, True])
def test_testcase_12(tmp_path, catalog):
"""test TestCase.load() existing test case with test_info.json"""
"""test TestCase.load() existing test case with test info file"""
# build a test case
asset_file = tmp_path / "asset.txt"
asset_file.touch()
Expand All @@ -284,7 +282,7 @@ def test_testcase_12(tmp_path, catalog):
assert "optional.bin" in loaded.optional
assert "nested/a.html" in loaded.optional
assert "_assets_/asset.txt" not in loaded.optional
assert "test_info.json" not in loaded.optional
assert TEST_INFO not in loaded.optional
else:
assert not any(loaded.optional)
assert loaded.assets == {"example": "asset.txt"}
Expand All @@ -297,32 +295,32 @@ def test_testcase_12(tmp_path, catalog):


def test_testcase_13(tmp_path):
"""test TestCase.load() test_info.json error cases"""
# bad 'assets' entry in test_info.json
"""test TestCase.load() test info file error cases"""
# bad 'assets' entry in test info file
src_dir = tmp_path / "src"
src_dir.mkdir()
entry_point = src_dir / "target.html"
entry_point.touch()
with TestCase("target.html", "test-adapter") as src:
src.dump(src_dir, include_details=True)
test_info = loads((src_dir / "test_info.json").read_text())
test_info = loads((src_dir / TEST_INFO).read_text())
test_info["assets"] = {"bad": 1}
(src_dir / "test_info.json").write_text(dumps(test_info))
(src_dir / TEST_INFO).write_text(dumps(test_info))
with raises(TestCaseLoadFailure, match="'assets' contains invalid entry"):
TestCase.load(src_dir)
# bad 'env' entry in test_info.json
# bad 'env' entry in test info file
with TestCase("target.html", "test-adapter") as src:
src.dump(src_dir, include_details=True)
test_info = loads((src_dir / "test_info.json").read_text())
test_info = loads((src_dir / TEST_INFO).read_text())
test_info["env"] = {"bad": 1}
(src_dir / "test_info.json").write_text(dumps(test_info))
(src_dir / TEST_INFO).write_text(dumps(test_info))
with raises(TestCaseLoadFailure, match="'env' contains invalid entry"):
TestCase.load(src_dir)
# missing asset data
test_info["env"].clear()
test_info["assets"] = {"a": "a"}
test_info["assets_path"] = "missing"
(src_dir / "test_info.json").write_text(dumps(test_info))
(src_dir / TEST_INFO).write_text(dumps(test_info))
with TestCase.load(src_dir) as loaded:
assert not loaded.assets
assert loaded.assets_path is None
Expand Down
4 changes: 2 additions & 2 deletions grizzly/reduce/strategies/beautify.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
except ImportError: # pragma: no cover
HAVE_JSBEAUTIFIER = False

from ...common.storage import TestCase
from ...common.storage import TEST_INFO, TestCase
from . import Strategy, _contains_dd

LOG = getLogger(__name__)
Expand Down Expand Up @@ -64,7 +64,7 @@ class _BeautifyStrategy(Strategy, ABC):
"""

all_extensions = None
ignore_files = {"test_info.json", "prefs.js"}
ignore_files = {TEST_INFO, "prefs.js"}
import_available = None
import_name = None
native_extension = None
Expand Down

0 comments on commit 10d283f

Please sign in to comment.