Skip to content

Commit 091459f

Browse files
committed
test: Have tests where Firecracker exists mark VMs as killed
This is so that we do not try to kill them again in `Microvm.kill`, which would result in a test failure. Also remove various variants of "wait for Firecracker process to go away", as `mark_killed` has a `wait_for_termination` inside of it. Signed-off-by: Patrick Roy <[email protected]>
1 parent 155e2d6 commit 091459f

File tree

10 files changed

+43
-38
lines changed

10 files changed

+43
-38
lines changed

tests/integration_tests/functional/test_api.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,3 +1386,7 @@ def test_negative_snapshot_load_api(microvm_factory):
13861386
)
13871387

13881388
assert exc_info.value.args[2].headers["deprecation"]
1389+
1390+
# The snapshot/memory files above don't exist, but the request is otherwise syntactically valid.
1391+
# In this case, Firecracker exits.
1392+
vm.mark_killed()

tests/integration_tests/functional/test_api_server.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ def test_api_socket_in_use(uvm_plain):
2626
microvm.spawn()
2727
msg = "Failed to open the API socket at: /run/firecracker.socket. Check that it is not already used."
2828
microvm.check_log_message(msg)
29+
30+
microvm.mark_killed()

tests/integration_tests/functional/test_cmd_line_start.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ def test_config_start_no_api_exit(uvm_plain, vm_config_file):
166166
test_microvm.spawn() # Start Firecracker and MicroVM
167167
time.sleep(3) # Wait for startup
168168
test_microvm.ssh.run("reboot") # Exit
169-
time.sleep(3) # Wait for shutdown
169+
170+
test_microvm.mark_killed() # waits for process to terminate
170171

171172
# Check error log and exit code
172173
test_microvm.check_log_message("Firecracker exiting successfully")
@@ -190,6 +191,8 @@ def test_config_bad_machine_config(uvm_plain, vm_config_file):
190191
test_microvm.spawn()
191192
test_microvm.check_log_message("Configuration for VMM from one single json failed")
192193

194+
test_microvm.mark_killed()
195+
193196

194197
@pytest.mark.parametrize(
195198
"test_config",
@@ -228,6 +231,8 @@ def test_config_machine_config_params(uvm_plain, test_config):
228231
"Could not Start MicroVM from one single json",
229232
]
230233
)
234+
235+
test_microvm.mark_killed()
231236
else:
232237
test_microvm.check_log_message(
233238
"Successfully started microvm that was configured from one single json"
@@ -334,6 +339,8 @@ def test_start_with_metadata_limit(uvm_plain):
334339
"Populating MMDS from file failed: The MMDS patch request doesn't fit."
335340
)
336341

342+
test_microvm.mark_killed()
343+
337344

338345
def test_start_with_metadata_default_limit(uvm_plain):
339346
"""
@@ -352,6 +359,8 @@ def test_start_with_metadata_default_limit(uvm_plain):
352359
"Populating MMDS from file failed: The MMDS patch request doesn't fit."
353360
)
354361

362+
test_microvm.mark_killed()
363+
355364

356365
def test_start_with_missing_metadata(uvm_plain):
357366
"""
@@ -373,6 +382,8 @@ def test_start_with_missing_metadata(uvm_plain):
373382
)
374383
test_microvm.check_log_message("No such file or directory")
375384

385+
test_microvm.mark_killed()
386+
376387

377388
def test_start_with_invalid_metadata(uvm_plain):
378389
"""
@@ -392,6 +403,8 @@ def test_start_with_invalid_metadata(uvm_plain):
392403
test_microvm.check_log_message("MMDS error: metadata provided not valid json")
393404
test_microvm.check_log_message("EOF while parsing an object")
394405

406+
test_microvm.mark_killed()
407+
395408

396409
@pytest.mark.parametrize(
397410
"vm_config_file",

tests/integration_tests/functional/test_error_code.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66

77
import pytest
88

9-
from framework.utils import wait_process_termination
10-
119

1210
@pytest.mark.skipif(
1311
platform.machine() != "aarch64",
@@ -32,7 +30,7 @@ def test_enosys_error_code(uvm_plain):
3230
vm.start()
3331

3432
# Check if FC process is closed
35-
wait_process_termination(vm.firecracker_pid)
33+
vm.mark_killed()
3634

3735
vm.check_log_message(
3836
"Received ENOSYS error because KVM failed to emulate an instruction."

tests/integration_tests/functional/test_shut_down.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
# SPDX-License-Identifier: Apache-2.0
33
"""Tests scenarios for shutting down Firecracker/VM."""
44

5-
import os
65
import platform
7-
import time
86

97
from packaging import version
108

@@ -45,13 +43,7 @@ def test_reboot(uvm_plain_any):
4543
# the instance.
4644
vm.ssh.run("reboot")
4745

48-
while True:
49-
# Pytest's timeout will kill the test even if the loop doesn't exit.
50-
try:
51-
os.kill(firecracker_pid, 0)
52-
time.sleep(0.01)
53-
except OSError:
54-
break
46+
vm.mark_killed()
5547

5648
# Consume existing metrics
5749
datapoints = vm.get_all_metrics()

tests/integration_tests/functional/test_signals.py

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010

1111
import pytest
1212

13-
from framework import utils
14-
1513
signum_str = {
1614
SIGBUS: "sigbus",
1715
SIGSEGV: "sigsegv",
@@ -54,11 +52,10 @@ def test_generic_signal_handler(uvm_plain, signum):
5452
# This is going to fail if process has exited.
5553
microvm.api.actions.put(action_type="FlushMetrics")
5654
else:
57-
microvm.expect_kill_by_signal = True
58-
# Ensure that the process was terminated.
59-
utils.wait_process_termination(microvm.firecracker_pid)
6055
msg = "Shutting down VM after intercepting signal {}".format(signum)
6156

57+
microvm.mark_killed()
58+
6259
microvm.check_log_message(msg)
6360

6461
if signum != SIGSYS:
@@ -95,14 +92,8 @@ def test_sigxfsz_handler(uvm_plain_rw):
9592
# in order to make sure the SIGXFSZ metric is logged
9693
res.prlimit(firecracker_pid, res.RLIMIT_FSIZE, (size * 3, res.RLIM_INFINITY))
9794

98-
while True:
99-
try:
100-
utils.check_output("ps -p {}".format(firecracker_pid))
101-
sleep(1)
102-
except ChildProcessError:
103-
break
95+
microvm.mark_killed()
10496

105-
microvm.expect_kill_by_signal = True
10697
msg = "Shutting down VM after intercepting signal 25, code 0"
10798
microvm.check_log_message(msg)
10899
metric_line = json.loads(metrics_fd.readlines()[0])

tests/integration_tests/functional/test_snapshot_basic.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import host_tools.drive as drive_tools
1616
from framework.microvm import SnapshotType
1717
from framework.properties import global_props
18-
from framework.utils import check_filesystem, check_output, wait_process_termination
18+
from framework.utils import check_filesystem, check_output
1919
from framework.utils_vsock import (
2020
ECHO_SERVER_PORT,
2121
VSOCK_UDS_PATH,
@@ -277,8 +277,7 @@ def test_load_snapshot_failure_handling(uvm_plain):
277277
with pytest.raises(RuntimeError, match=expected_msg):
278278
vm.api.snapshot_load.put(mem_file_path=jailed_mem, snapshot_path=jailed_vmstate)
279279

280-
# Check if FC process is closed
281-
wait_process_termination(vm.firecracker_pid)
280+
vm.mark_killed()
282281

283282

284283
def test_cmp_full_and_first_diff_mem(microvm_factory, guest_kernel, rootfs):
@@ -380,6 +379,8 @@ def test_negative_snapshot_permissions(uvm_plain_rw, microvm_factory):
380379
with pytest.raises(RuntimeError, match=expected_err):
381380
microvm.restore_from_snapshot(snapshot, resume=True)
382381

382+
microvm.mark_killed()
383+
383384
# Remove permissions for state file.
384385
os.chmod(snapshot.vmstate, 0o000)
385386

@@ -393,6 +394,8 @@ def test_negative_snapshot_permissions(uvm_plain_rw, microvm_factory):
393394
with pytest.raises(RuntimeError, match=expected_err):
394395
microvm.restore_from_snapshot(snapshot, resume=True)
395396

397+
microvm.mark_killed()
398+
396399
# Restore permissions for state file.
397400
os.chmod(snapshot.vmstate, 0o744)
398401
os.chmod(snapshot.mem, 0o744)
@@ -407,6 +410,8 @@ def test_negative_snapshot_permissions(uvm_plain_rw, microvm_factory):
407410
with pytest.raises(RuntimeError, match=re.escape(expected_err)):
408411
microvm.restore_from_snapshot(snapshot, resume=True)
409412

413+
microvm.mark_killed()
414+
410415

411416
def test_negative_snapshot_create(uvm_nano):
412417
"""

tests/integration_tests/functional/test_uffd.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ def test_bad_socket_path(uvm_plain, snapshot):
7272
snapshot_path=jailed_vmstate,
7373
)
7474

75+
vm.mark_killed()
76+
7577

7678
def test_unbinded_socket(uvm_plain, snapshot):
7779
"""
@@ -96,6 +98,8 @@ def test_unbinded_socket(uvm_plain, snapshot):
9698
snapshot_path=jailed_vmstate,
9799
)
98100

101+
vm.mark_killed()
102+
99103

100104
def test_valid_handler(uvm_plain, snapshot, uffd_handler_paths):
101105
"""

tests/integration_tests/security/test_custom_seccomp.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import tempfile
88
import time
99

10-
import psutil
1110
import pytest
1211
import requests
1312

@@ -188,7 +187,6 @@ def test_failing_filter(uvm_plain):
188187
# Give time for the process to get killed
189188
time.sleep(1)
190189

191-
test_microvm.expect_kill_by_signal = True
192190
# Check the logger output
193191
ioctl_num = 16 if platform.machine() == "x86_64" else 29
194192
test_microvm.check_log_message(
@@ -207,8 +205,7 @@ def test_failing_filter(uvm_plain):
207205

208206
assert num_faults == 1
209207

210-
# assert that the process was killed
211-
assert not psutil.pid_exists(test_microvm.firecracker_pid)
208+
test_microvm.mark_killed()
212209

213210

214211
@pytest.mark.parametrize("vm_config_file", ["framework/vm_config.json"])
@@ -235,5 +232,4 @@ def test_invalid_bpf(uvm_plain, vm_config_file):
235232
# give time for the process to get killed
236233
time.sleep(1)
237234

238-
# assert that the process was killed
239-
assert not psutil.pid_exists(test_microvm.firecracker_pid)
235+
test_microvm.mark_killed()

tests/integration_tests/security/test_jail.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import time
1111
from pathlib import Path
1212

13-
import psutil
1413
import pytest
1514
import requests
1615
import urllib3
@@ -511,14 +510,13 @@ def test_negative_file_size_limit(uvm_plain):
511510
urllib3.exceptions.ProtocolError,
512511
requests.exceptions.ConnectionError,
513512
) as _error:
514-
test_microvm.expect_kill_by_signal = True
515513
# Check the microVM received signal `SIGXFSZ` (25),
516514
# which corresponds to exceeding file size limit.
517515
msg = "Shutting down VM after intercepting signal 25, code 0"
518516
test_microvm.check_log_message(msg)
519517
time.sleep(1)
520-
# Check that the process was terminated.
521-
assert not psutil.pid_exists(test_microvm.firecracker_pid)
518+
519+
test_microvm.mark_killed()
522520
else:
523521
assert False, "Negative test failed"
524522

@@ -535,6 +533,8 @@ def test_negative_no_file_limit(uvm_plain):
535533
test_microvm.spawn()
536534
except ChildProcessError as error:
537535
assert "No file descriptors available (os error 24)" in str(error)
536+
537+
test_microvm.mark_killed()
538538
else:
539539
assert False, "Negative test failed"
540540

0 commit comments

Comments
 (0)