Skip to content

Commit 4cf23b7

Browse files
committed
tests: fix snapshot tests for older versions
Previously, the snapshot tests that were supposed to retrieve the older Firecracker binaries from S3 were not filtering the artifacts by version number. This results in test failures for patch releases, where the test will use both older and newer binaries. Added support in the testing framework for this and fixed the respective tests. Signed-off-by: alindima <[email protected]>
1 parent d7ac0c6 commit 4cf23b7

File tree

4 files changed

+73
-13
lines changed

4 files changed

+73
-13
lines changed

tests/framework/artifacts.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import boto3
1313
import botocore.client
1414
from host_tools.snapshot_helper import merge_memory_bitmaps
15+
from framework.utils import compare_versions
1516

1617

1718
ARTIFACTS_LOCAL_ROOT = "/tmp/ci-artifacts"
@@ -269,6 +270,12 @@ def jailer(self):
269270
jailer_path,
270271
artifact_type=ArtifactType.JAILER)
271272

273+
@property
274+
def version(self):
275+
"""Return the artifact's version: `X.Y.Z`."""
276+
# Get the filename, remove the extension and trim the leading 'v'.
277+
return os.path.splitext(os.path.basename(self.key))[0][1:]
278+
272279

273280
class ArtifactCollection:
274281
"""Provides easy access to different artifact types."""
@@ -348,7 +355,7 @@ def snapshots(self, keyword=None):
348355
# Filter out the snapshot artifacts root folder.
349356
# Select only files with specified keyword.
350357
if (key[-1] == "/" and key != prefix and
351-
(keyword is None or keyword in snapshot_dir.key)):
358+
(keyword is None or keyword in snapshot_dir.key)):
352359
artifact_type = ArtifactType.SNAPSHOT
353360
artifacts.append(SnapshotArtifact(self.bucket,
354361
key,
@@ -366,19 +373,29 @@ def microvms(self, keyword=None):
366373
keyword=keyword
367374
)
368375

369-
def firecrackers(self, keyword=None):
376+
def firecrackers(self, keyword=None, older_than=None):
370377
"""Return fc/jailer artifacts for the current arch."""
371-
return self._fetch_artifacts(
378+
firecrackers = self._fetch_artifacts(
372379
ArtifactCollection.ARTIFACTS_BINARIES,
373380
ArtifactCollection.FC_EXTENSION,
374381
ArtifactType.FC,
375382
FirecrackerArtifact,
376383
keyword=keyword
377384
)
378385

379-
def firecracker_versions(self):
386+
# Filter out binaries with versions newer than the `older_than` arg.
387+
if older_than is not None:
388+
return list(filter(
389+
lambda fc: compare_versions(fc.version, older_than) <= 0,
390+
firecrackers
391+
))
392+
393+
return firecrackers
394+
395+
def firecracker_versions(self, older_than=None):
380396
"""Return fc/jailer artifacts' versions for the current arch."""
381-
return [fc.base_name()[1:] for fc in self.firecrackers()]
397+
return [fc.base_name()[1:]
398+
for fc in self.firecrackers(older_than=older_than)]
382399

383400
def kernels(self, keyword=None):
384401
"""Return kernel artifacts for the current arch."""

tests/framework/utils.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,3 +476,41 @@ def wait_process_termination(p_pid):
476476
except ChildProcessError:
477477
return
478478
raise Exception("{} process is still alive: ".format(stdout.strip()))
479+
480+
481+
def get_firecracker_version_from_toml():
482+
"""
483+
Return the version of the firecracker crate, from Cargo.toml.
484+
485+
Usually different from the output of `./firecracker --version`, if
486+
the code has not been released.
487+
"""
488+
cmd = "cd ../src/firecracker && cargo pkgid | cut -d# -f2 | cut -d: -f2"
489+
490+
rc, stdout, _ = run_cmd(cmd)
491+
assert rc == 0
492+
493+
return stdout
494+
495+
496+
def compare_versions(first, second):
497+
"""
498+
Compare two versions with format `X.Y.Z`.
499+
500+
:param first: first version string
501+
:param second: second version string
502+
:returns: 0 if equal, <0 if first < second, >0 if second < first
503+
"""
504+
first = list(map(int, first.split('.')))
505+
second = list(map(int, second.split('.')))
506+
507+
if first[0] == second[0]:
508+
if first[1] == second[1]:
509+
if first[2] == second[2]:
510+
return 0
511+
512+
return first[2] - second[2]
513+
514+
return first[1] - second[1]
515+
516+
return first[0] - second[0]

tests/integration_tests/functional/test_snapshot_advanced.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from framework.artifacts import ArtifactCollection, NetIfaceConfig
1212
from framework.builder import MicrovmBuilder, SnapshotBuilder, SnapshotType
1313
from framework.microvms import VMNano
14+
from framework.utils import get_firecracker_version_from_toml
1415
import host_tools.network as net_tools # pylint: disable=import-error
1516
import host_tools.drive as drive_tools
1617

@@ -46,7 +47,8 @@ def test_restore_old_snapshot_all_devices(bin_cloner_path):
4647
# Fetch all firecracker binaries.
4748
# With each binary create a snapshot and try to restore in current
4849
# version.
49-
firecracker_artifacts = artifacts.firecrackers()
50+
firecracker_artifacts = artifacts.firecrackers(
51+
older_than=get_firecracker_version_from_toml())
5052
for firecracker in firecracker_artifacts:
5153
firecracker.download()
5254
jailer = firecracker.jailer()
@@ -96,7 +98,8 @@ def test_restore_old_version_all_devices(bin_cloner_path):
9698
# Fetch all firecracker binaries.
9799
# Create a snapshot with current build and restore with each FC binary
98100
# artifact.
99-
firecracker_artifacts = artifacts.firecrackers()
101+
firecracker_artifacts = artifacts.firecrackers(
102+
older_than=get_firecracker_version_from_toml())
100103
for firecracker in firecracker_artifacts:
101104
firecracker.download()
102105
jailer = firecracker.jailer()

tests/integration_tests/performance/test_snapshot_perf.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from framework.matrix import TestMatrix, TestContext
1212
from framework.microvms import VMMicro
1313
from framework.builder import MicrovmBuilder, SnapshotBuilder, SnapshotType
14-
from framework.utils import CpuMap
14+
from framework.utils import CpuMap, get_firecracker_version_from_toml
1515
import host_tools.network as net_tools # pylint: disable=import-error
1616
import host_tools.logging as log_tools
1717

@@ -78,7 +78,8 @@ def _test_snapshot_create_latency(context):
7878
logger.info("Fetching firecracker/jailer versions from {}."
7979
.format(DEFAULT_TEST_IMAGES_S3_BUCKET))
8080
artifacts = ArtifactCollection(_test_images_s3_bucket())
81-
firecracker_versions = artifacts.firecracker_versions()
81+
firecracker_versions = artifacts.firecracker_versions(
82+
older_than=get_firecracker_version_from_toml())
8283
assert len(firecracker_versions) > 0
8384

8485
# Test snapshot creation for every supported target version.
@@ -193,9 +194,9 @@ def _test_snapshot_resume_latency(context):
193194

194195
for i in range(SAMPLE_COUNT):
195196
microvm, metrics_fifo = vm_builder.build_from_snapshot(
196-
snapshot,
197-
True,
198-
enable_diff_snapshots)
197+
snapshot,
198+
True,
199+
enable_diff_snapshots)
199200

200201
# Attempt to connect to resumed microvm.
201202
ssh_connection = net_tools.SSHConnection(microvm.ssh_config)
@@ -336,7 +337,8 @@ def test_older_snapshot_resume_latency(bin_cloner_path):
336337
# Fetch all firecracker binaries.
337338
# With each binary create a snapshot and try to restore in current
338339
# version.
339-
firecracker_artifacts = artifacts.firecrackers()
340+
firecracker_artifacts = artifacts.firecrackers(
341+
older_than=get_firecracker_version_from_toml())
340342
assert len(firecracker_artifacts) > 0
341343

342344
for firecracker in firecracker_artifacts:

0 commit comments

Comments
 (0)