mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
Fix S3 storage test
Fix the storage test by converting it from bash to python and also testing all the occasions where a save should be triggered.
This commit is contained in:
@@ -11,4 +11,4 @@ commands:
|
||||
- type: revng-qa.compiled
|
||||
filter: example-executable-1 and with-debug-info
|
||||
command: |-
|
||||
"${SOURCES_ROOT}/share/revng/test/tests/storage.sh" "$INPUT" "$$(temp -d)"
|
||||
"${SOURCES_ROOT}/share/revng/test/tests/s3_storage.py" "$INPUT" "$$(temp -d)"
|
||||
|
||||
Executable
+126
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
#
|
||||
|
||||
import atexit
|
||||
import hashlib
|
||||
import json
|
||||
import socket
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from subprocess import DEVNULL, Popen
|
||||
from uuid import uuid4
|
||||
|
||||
import yaml
|
||||
|
||||
from revng.internal.api import make_manager
|
||||
|
||||
|
||||
def get_free_port():
|
||||
"""Get an unbound port to spawn the S3 server on. Note that this is not
|
||||
failproof and might fail since there's a time gap between when the script
|
||||
is run and the server actually binds the socket"""
|
||||
with socket.socket() as s:
|
||||
s.bind(("127.0.0.1", 0))
|
||||
return s.getsockname()[1]
|
||||
|
||||
|
||||
def file_hash(path: str | Path):
|
||||
with open(path, "rb") as f:
|
||||
return hashlib.file_digest(f, "sha256").hexdigest()
|
||||
|
||||
|
||||
def resolve_path(root: Path, subpath: str):
|
||||
index_file = root / "index.yml._S3rver_object"
|
||||
assert index_file.is_file()
|
||||
with open(index_file) as f:
|
||||
index_data = yaml.safe_load(f)
|
||||
return root / f"{index_data[subpath]}._S3rver_object"
|
||||
|
||||
|
||||
def main():
|
||||
input_binary = sys.argv[1]
|
||||
temporary_dir = sys.argv[2]
|
||||
temporary_dir_path = Path(temporary_dir)
|
||||
|
||||
server_port = get_free_port()
|
||||
# Run the server with the specified port
|
||||
server_process = Popen(
|
||||
[
|
||||
"s3rver",
|
||||
"--directory",
|
||||
temporary_dir,
|
||||
"--address",
|
||||
"127.0.0.1",
|
||||
"--port",
|
||||
str(server_port),
|
||||
"--configure-bucket",
|
||||
"test",
|
||||
],
|
||||
stdout=DEVNULL,
|
||||
stderr=DEVNULL,
|
||||
)
|
||||
atexit.register(server_process.kill)
|
||||
|
||||
workdir = f"s3://S3RVER:S3RVER@region+127.0.0.1:{server_port}/test/project-test-dir"
|
||||
s3_root = temporary_dir_path / "test/project-test-dir"
|
||||
manager = make_manager(workdir)
|
||||
|
||||
with open(input_binary, "rb") as f:
|
||||
manager.set_input("input", f.read())
|
||||
|
||||
manager.run_analyses_list("revng-initial-auto-analysis").unwrap()
|
||||
|
||||
# Simple file check, this looks into the persistence directory of s3rver and
|
||||
# checks that the input file and the file in 'begin/input' have the same
|
||||
# contents. This is to guarantee that the S3 backend does not change the
|
||||
# contents of the file.
|
||||
s3_input_file_path = resolve_path(s3_root, "begin/input")
|
||||
assert file_hash(input_binary) == file_hash(s3_input_file_path)
|
||||
|
||||
# Produce some stuff and then check that the file is actually saved
|
||||
step_name = "disassemble"
|
||||
container_name = "assembly.ptml.tar.gz"
|
||||
targets = manager.get_targets(step_name, container_name)
|
||||
manager.produce_target(step_name, [t.serialize() for t in targets], container_name)
|
||||
assert manager.save()
|
||||
|
||||
s3_decompiled_path = resolve_path(s3_root, "disassemble/assembly.ptml.tar.gz")
|
||||
assert s3_decompiled_path.is_file() and s3_decompiled_path.stat().st_size > 0
|
||||
s3_decompiled_metadata = s3_decompiled_path.parent / (
|
||||
s3_decompiled_path.name.removesuffix("._S3rver_object") + "._S3rver_metadata.json"
|
||||
)
|
||||
with open(s3_decompiled_metadata) as f:
|
||||
metadata = json.load(f)
|
||||
assert metadata["content-encoding"] == "gzip"
|
||||
|
||||
# Rename the first function in the model and check if it exists in the
|
||||
# saved model
|
||||
model = yaml.safe_load(manager.get_global("model.yml"))
|
||||
first_function = model["Functions"][0]
|
||||
unique_id = str(uuid4()).replace("-", "")
|
||||
diff = {
|
||||
"Path": f"/Functions/{first_function['Entry']}/CustomName",
|
||||
"Add": unique_id,
|
||||
"Remove": "",
|
||||
}
|
||||
if "CustomName" in first_function:
|
||||
diff["Remove"] = first_function["CustomName"]
|
||||
|
||||
diff_content = yaml.safe_dump({"Changes": [diff]})
|
||||
manager.run_analysis(
|
||||
"initial",
|
||||
"apply-diff",
|
||||
{},
|
||||
{"apply-diff-global-name": "model.yml", "apply-diff-diff-content": diff_content},
|
||||
).unwrap()
|
||||
model_path = resolve_path(s3_root, "context/model.yml")
|
||||
assert unique_id in model_path.read_text()
|
||||
# Also check that the partial save did not delete some file
|
||||
assert s3_decompiled_path.is_file() and s3_decompiled_path.stat().st_size > 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Python oneliner to get an unbound port to spawn the S3 server on. Note that
|
||||
# this is not failproof and might fail since there's a time gap between when
|
||||
# the script is run and the server actually binds the socket
|
||||
S3_PORT=$(python -c 'import socket; s=socket.socket(); s.bind(("127.0.0.1", 0)); print(s.getsockname()[1]); s.close()')
|
||||
# Run the server with the specified port
|
||||
s3rver --directory "$2" --address 127.0.0.1 --port "$S3_PORT" --configure-bucket test &>/dev/null &
|
||||
# Save the server pid to kill it on exit
|
||||
S3RVER_PID=$!
|
||||
trap 'kill -9 $S3RVER_PID' EXIT
|
||||
|
||||
# Run revng with the server as the resume directory
|
||||
revng artifact \
|
||||
--resume="s3://S3RVER:S3RVER@region+127.0.0.1:$S3_PORT/test/project-test-dir" \
|
||||
--analyze \
|
||||
-o /dev/null \
|
||||
disassemble "$1"
|
||||
|
||||
# Simple file check, this looks into the persistence directory of s3rver and
|
||||
# checks that the input file and the file in 'begin/input' have the same
|
||||
# contents. This is to guarantee that the S3 backend does not change the
|
||||
# contents of the file.
|
||||
INDEX_FILE="$2/test/project-test-dir/index.yml._S3rver_object"
|
||||
test -f "$INDEX_FILE"
|
||||
INPUT_ID="$(grep -Po '(?<=^begin/input:).*' "$INDEX_FILE" | tr -d ' ' | tr -d "'")"
|
||||
INPUT_FILE="$2/test/project-test-dir/$INPUT_ID._S3rver_object"
|
||||
sha256sum --quiet --check <(sha256sum <"$INPUT_FILE") <"$1"
|
||||
Reference in New Issue
Block a user