Skip to content

Commit 884421a

Browse files
pb8oandreitraistaru
authored andcommitted
test: improve test and fixtures
- split the tests so we can see which ones pass - only test firecracker supported versions (drop 0.24, 0.25) - make a new firecracker fixture so it is simple to use in tests - give tests more descriptive names Signed-off-by: Pablo Barbáchano <[email protected]>
1 parent 0154f37 commit 884421a

File tree

4 files changed

+130
-138
lines changed

4 files changed

+130
-138
lines changed

tests/conftest.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,11 @@ def test_with_any_microvm(test_microvm_any):
9494
from host_tools import proc
9595
from framework import utils
9696
from framework import defs
97-
from framework.artifacts import ArtifactCollection
97+
from framework.artifacts import ArtifactCollection, FirecrackerArtifact
9898
from framework.microvm import Microvm
9999
from framework.s3fetcher import MicrovmImageS3Fetcher
100100
from framework.scheduler import PytestScheduler
101+
from framework.utils import get_firecracker_version_from_toml
101102

102103
# Tests root directory.
103104
SCRIPT_FOLDER = os.path.dirname(os.path.realpath(__file__))
@@ -503,6 +504,35 @@ def aarch64(body):
503504
assert mitigated, "SPECTREv2 not mitigated {}".format(body)
504505

505506

507+
def firecracker_id(fc):
508+
"""Render a nice ID for pytest parametrize."""
509+
if isinstance(fc, FirecrackerArtifact):
510+
return f"firecracker-{fc.version}"
511+
return None
512+
513+
514+
def firecracker_artifacts(*args, **kwargs):
515+
"""Return all supported firecracker binaries."""
516+
params = {
517+
"min_version": "1.1.0",
518+
"max_version": get_firecracker_version_from_toml(),
519+
}
520+
params.update(kwargs)
521+
return ARTIFACTS_COLLECTION.firecrackers(
522+
*args,
523+
**params,
524+
)
525+
526+
527+
@pytest.fixture(params=firecracker_artifacts(), ids=firecracker_id)
528+
def firecracker_release(request):
529+
"""Return all supported firecracker binaries."""
530+
firecracker = request.param
531+
firecracker.download()
532+
firecracker.jailer().download()
533+
return firecracker
534+
535+
506536
def pytest_generate_tests(metafunc):
507537
"""Implement customized parametrization scheme.
508538

tests/framework/artifacts.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# SPDX-License-Identifier: Apache-2.0
33
"""Define classes for interacting with CI artifacts in s3."""
44

5+
import functools
56
import os
67
import platform
78
import tempfile
@@ -12,6 +13,7 @@
1213

1314
import boto3
1415
import botocore.client
16+
1517
from framework.defs import DEFAULT_TEST_SESSION_ROOT_PATH, SUPPORTED_KERNELS
1618
from framework.utils import compare_versions
1719
from host_tools.snapshot_helper import merge_memory_bitmaps
@@ -93,7 +95,7 @@ def download(self, target_folder=ARTIFACTS_LOCAL_ROOT, force=False):
9395
Path(self.local_dir()).mkdir(parents=True, exist_ok=True)
9496
if force or not os.path.exists(self.local_path()):
9597
self._bucket.download_file(self._key, self.local_path())
96-
# Artifacts are read only by design.
98+
# Artifacts are read-only by design.
9799
os.chmod(self.local_path(), S_IREAD)
98100

99101
def local_path(self):
@@ -276,11 +278,12 @@ def ssh_key(self):
276278
class FirecrackerArtifact(Artifact):
277279
"""Provides access to associated jailer artifact."""
278280

281+
@functools.lru_cache
279282
def jailer(self):
280283
"""Return a jailer binary artifact."""
281284
# Jailer and FC binaries have different extensions and share
282285
# file name when stored in S3:
283-
# Firecracker binary: v0.22.firecrcker
286+
# Firecracker binary: v0.22.firecracker
284287
# Jailer binary: v0.23.0.jailer
285288
jailer_path = str(Path(self.key).with_suffix(".jailer"))
286289
return Artifact(self.bucket, jailer_path, artifact_type=ArtifactType.JAILER)
@@ -291,6 +294,25 @@ def version(self):
291294
# Get the filename, remove the extension and trim the leading 'v'.
292295
return os.path.splitext(os.path.basename(self.key))[0][1:]
293296

297+
@property
298+
def version_tuple(self):
299+
"""Return the artifact's version as a tuple `(X, Y, Z)`."""
300+
return tuple(int(x) for x in self.version.split("."))
301+
302+
@property
303+
def snapshot_version_tuple(self):
304+
"""Return the artifact's snapshot version as a tuple: `X.Y.0`."""
305+
return self.version_tuple[:2] + (0,)
306+
307+
@property
308+
def snapshot_version(self):
309+
"""Return the artifact's snapshot version: `X.Y.0`.
310+
311+
Due to how Firecracker maps release versions to snapshot versions, we
312+
have to request the minor version instead of the actual version.
313+
"""
314+
return ".".join(str(x) for x in self.snapshot_version_tuple)
315+
294316

295317
class ArtifactCollection:
296318
"""Provides easy access to different artifact types."""

tests/integration_tests/functional/test_cmd_line_parameters.py

Lines changed: 45 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -7,81 +7,64 @@
77
from pathlib import Path
88

99
import host_tools.logging as log_tools
10-
from host_tools.cargo_build import get_firecracker_binaries
11-
from conftest import _test_images_s3_bucket
12-
from framework.artifacts import ArtifactCollection
1310
from framework.builder import MicrovmBuilder, SnapshotBuilder, SnapshotType
14-
from framework.utils import run_cmd, get_firecracker_version_from_toml
11+
from framework.utils import run_cmd
12+
from host_tools.cargo_build import get_firecracker_binaries
1513

1614

17-
def test_describe_snapshot_all_versions(bin_cloner_path):
15+
def test_describe_snapshot_all_versions(bin_cloner_path, firecracker_release):
1816
"""
1917
Test `--describe-snapshot` correctness for all snapshot versions.
2018
19+
For each release create a snapshot and verify the data version of the
20+
snapshot state file.
21+
2122
@type: functional
2223
"""
2324
logger = logging.getLogger("describe_snapshot")
2425
builder = MicrovmBuilder(bin_cloner_path)
25-
artifacts = ArtifactCollection(_test_images_s3_bucket())
26-
# Fetch all firecracker binaries.
27-
# For each binary create a snapshot and verify the data version
28-
# of the snapshot state file.
26+
jailer = firecracker_release.jailer()
27+
target_version = firecracker_release.snapshot_version
28+
29+
logger.info(
30+
"Creating snapshot with Firecracker: %s", firecracker_release.local_path()
31+
)
32+
logger.info("Using Jailer: %s", jailer.local_path())
33+
logger.info("Using target version: %s", target_version)
2934

30-
firecracker_artifacts = artifacts.firecrackers(
31-
max_version=get_firecracker_version_from_toml()
35+
vm_instance = builder.build_vm_nano(
36+
fc_binary=firecracker_release.local_path(),
37+
jailer_binary=jailer.local_path(),
38+
diff_snapshots=True,
3239
)
40+
vm = vm_instance.vm
41+
vm.start()
42+
43+
# Create a snapshot builder from a microvm.
44+
snapshot_builder = SnapshotBuilder(vm)
45+
disks = [vm_instance.disks[0].local_path()]
3346

34-
for firecracker in firecracker_artifacts:
35-
firecracker.download()
36-
jailer = firecracker.jailer()
37-
jailer.download()
38-
39-
target_version = firecracker.base_name()[1:]
40-
# Skip for aarch64, since the snapshotting feature
41-
# was introduced in v0.24.0.
42-
if platform.machine() == "aarch64" and "v0.23" in target_version:
43-
continue
44-
45-
logger.info("Creating snapshot with Firecracker: %s", firecracker.local_path())
46-
logger.info("Using Jailer: %s", jailer.local_path())
47-
logger.info("Using target version: %s", target_version)
48-
49-
# v0.23 does not support creating diff snapshots.
50-
diff_snapshots = "0.23" not in target_version
51-
vm_instance = builder.build_vm_nano(
52-
fc_binary=firecracker.local_path(),
53-
jailer_binary=jailer.local_path(),
54-
diff_snapshots=diff_snapshots,
55-
)
56-
vm = vm_instance.vm
57-
vm.start()
58-
59-
# Create a snapshot builder from a microvm.
60-
snapshot_builder = SnapshotBuilder(vm)
61-
disks = [vm_instance.disks[0].local_path()]
62-
63-
# Version 0.24 and greater have Diff support.
64-
snap_type = SnapshotType.DIFF if diff_snapshots else SnapshotType.FULL
65-
66-
snapshot = snapshot_builder.create(
67-
disks,
68-
vm_instance.ssh_key,
69-
target_version=target_version,
70-
snapshot_type=snap_type,
71-
)
72-
logger.debug("========== Firecracker create snapshot log ==========")
73-
logger.debug(vm.log_data)
74-
vm.kill()
75-
76-
# Fetch Firecracker binary for the latest version
77-
fc_binary, _ = get_firecracker_binaries()
78-
# Verify the output of `--describe-snapshot` command line parameter
79-
cmd = [fc_binary] + ["--describe-snapshot", snapshot.vmstate]
80-
81-
code, stdout, stderr = run_cmd(cmd)
82-
assert code == 0
83-
assert stderr == ""
84-
assert target_version in stdout
47+
# Version 0.24 and greater have Diff support.
48+
snap_type = SnapshotType.DIFF
49+
50+
snapshot = snapshot_builder.create(
51+
disks,
52+
vm_instance.ssh_key,
53+
snapshot_type=snap_type,
54+
)
55+
logger.debug("========== Firecracker create snapshot log ==========")
56+
logger.debug(vm.log_data)
57+
vm.kill()
58+
59+
# Fetch Firecracker binary for the latest version
60+
fc_binary, _ = get_firecracker_binaries()
61+
# Verify the output of `--describe-snapshot` command line parameter
62+
cmd = [fc_binary] + ["--describe-snapshot", snapshot.vmstate]
63+
64+
code, stdout, stderr = run_cmd(cmd)
65+
assert code == 0, stderr
66+
assert stderr == ""
67+
assert target_version in stdout
8568

8669

8770
def test_cli_metrics_path(test_microvm_with_api):

0 commit comments

Comments
 (0)