tests,stdlib: Add test to check gem5-resources downloading
This test ensures all the resources in resources.json can be downloaded
and that their md5 values are valid. This has been set as a
very-long/weekly test as downloading all the resources is costly.
Change-Id: Ia574d0a9610849af3653fc742acb214ea7496767
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/59771
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/python/gem5/resources/md5_utils.py b/src/python/gem5/resources/md5_utils.py
index cafaf34..b98a81e 100644
--- a/src/python/gem5/resources/md5_utils.py
+++ b/src/python/gem5/resources/md5_utils.py
@@ -45,6 +45,21 @@
hash = _md5_update_from_dir(path, hash)
return hash
+def md5(path: Path) -> str:
+ """
+ Gets the md5 value of a file or directory. `md5_file` is used if the path
+ is a file and `md5_dir` is used if the path is a directory. An exception
+ is returned if the path is not a valid file or directory.
+
+ :param path: The path to get the md5 of.
+ """
+ if path.is_file():
+ return md5_file(Path(path))
+ elif path.is_dir():
+ return md5_dir(Path(path))
+ else:
+ raise Exception(f"Path '{path}' is not a valid file or directory.")
+
def md5_file(filename: Path) -> str:
"""
Gives the md5 hash of a file
diff --git a/tests/gem5/configs/download_check.py b/tests/gem5/configs/download_check.py
new file mode 100644
index 0000000..f13ba70
--- /dev/null
+++ b/tests/gem5/configs/download_check.py
@@ -0,0 +1,105 @@
+# Copyright (c) 2022 The Regents of the University of California
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from gem5.resources.downloader import (
+ list_resources,
+ get_resources_json_obj,
+ get_resource,
+)
+
+from gem5.resources.md5_utils import md5
+
+import os
+import shutil
+import argparse
+from pathlib import Path
+
+parser = argparse.ArgumentParser(
+ description="A script that will checks that input resource IDs will "
+ "download a resource and that resources md5 value is correct. "
+ "If no resource IDs are specified, all will be checked."
+)
+
+parser.add_argument(
+ "ids",
+ nargs="*", # Accepts 0 or more arguments.
+ type=str,
+ help="The resource IDs to check. If not set, all resources will be "
+ "checked",
+)
+
+parser.add_argument(
+ "--download-directory",
+ type=str,
+ required=True,
+ help="The directory to download the resources as part of these test. The "
+ "contents of this directory will be wiped after running the tests.",
+)
+
+args = parser.parse_args()
+
+# If the directory doesn't exist, create it.
+if not Path(args.download_dir).exists():
+ os.makedirs(args.download_dir)
+
+
+ids = args.ids
+if len(ids) == 0:
+ ids = list_resources()
+
+# We log all the errors as they occur then dump them at the end. This means we
+# can be aware of all download errors in a single failure.
+errors = str()
+
+for id in ids:
+ if id not in list_resources():
+ errors += (
+ f"Resource with ID '{id}' not found in "
+ + f"`list_resources()`.{os.linesep}"
+ )
+ continue
+
+ resource_json = get_resources_json_obj(id)
+ download_path = os.path.join(args.download_dir, id)
+ try:
+ get_resource(resource_name=id, to_path=download_path)
+ except Exception:
+ errors += f"Failure to download resource '{id}'.{os.linesep}"
+ continue
+
+ if md5(Path(download_path)) != resource_json["md5sum"]:
+ errors += (
+ f"Downloaded resource '{id}' md5 "
+ + f"({md5(Path(download_path))}) differs to that in the "
+ + f"JSON ({resource_json['md5sum']}).{os.linesep}"
+ )
+
+ # Remove the downloaded resource.
+ shutil.rmtree(download_path, ignore_errors=True)
+
+# If errors exist, raise an exception highlighting them.
+if errors:
+ raise Exception(errors)
diff --git a/tests/gem5/gem5-resources/test_download_resources.py b/tests/gem5/gem5-resources/test_download_resources.py
new file mode 100644
index 0000000..acc72d7
--- /dev/null
+++ b/tests/gem5/gem5-resources/test_download_resources.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2022 The Regents of the University of California
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from testlib import *
+
+if config.bin_path:
+ resource_path = joinpath(config.bin_path, "resource-downloading-test")
+else:
+ resource_path = joinpath(
+ absdirpath(__file__), "..", "resources", "resource_downloading-test"
+ )
+
+gem5_verify_config(
+ name="test-resource-downloading",
+ fixtures=(),
+ verifiers=(),
+ config=joinpath(
+ config.base_dir, "tests", "gem5", "configs", "download_check.py"
+ ),
+ config_args=["--resource-directory", resource_path],
+ valid_isas=(constants.null_tag,),
+ length=constants.very_long_tag,
+)