|
1 | 1 | # pylint: disable=missing-function-docstring,missing-module-docstring
|
2 | 2 | from pathlib import Path
|
| 3 | +from tempfile import gettempdir |
3 | 4 | from typing import Optional
|
4 | 5 | from typing import Union
|
5 | 6 |
|
6 | 7 | import pytest
|
7 | 8 | from pytest_container import Container
|
8 | 9 | from pytest_container import DerivedContainer
|
| 10 | +from pytest_container.container import ContainerLauncher |
9 | 11 | from pytest_container.container import ImageFormat
|
10 | 12 | from pytest_container.runtime import OciRuntimeBase
|
11 | 13 |
|
@@ -76,6 +78,39 @@ def test_lockfile_unique() -> None:
|
76 | 78 | assert cont1.filelock_filename != cont2.filelock_filename
|
77 | 79 |
|
78 | 80 |
|
| 81 | +def test_removed_lockfile_does_not_kill_launcher( |
| 82 | + container_runtime: OciRuntimeBase, pytestconfig: pytest.Config |
| 83 | +) -> None: |
| 84 | + """Test that the container launcher doesn't die if the container lockfile |
| 85 | + got removed by another thread. |
| 86 | +
|
| 87 | + It can happen in certain scenarios that a ``Container`` is launched from two |
| 88 | + concurrently running test functions. These test functions will use the same |
| 89 | + lockfile. A nasty data race can occur, where both test functions unlock the |
| 90 | + lockfile nearly at the same time, but then only one of them can succeed in |
| 91 | + removing it and the other test inadvertently fails. This is a regression |
| 92 | + test, that such a situation is tolerated and doesn't cause a failure. |
| 93 | +
|
| 94 | + In this test we create a singleton container where we utilize that the |
| 95 | + lockfile is removed in ``__exit__()``. We hence already delete the lockfile |
| 96 | + in the ``with`` block and provoke a failure in ``__exit__()``. |
| 97 | +
|
| 98 | + See also https://github.com/dcermak/pytest_container/issues/232. |
| 99 | +
|
| 100 | + """ |
| 101 | + cont = Container(url=images.LEAP_URL, singleton=True) |
| 102 | + |
| 103 | + with ContainerLauncher.from_pytestconfig( |
| 104 | + cont, container_runtime, pytestconfig |
| 105 | + ) as launcher: |
| 106 | + launcher.launch_container() |
| 107 | + |
| 108 | + lockfile_abspath = Path(gettempdir()) / cont.filelock_filename |
| 109 | + assert lockfile_abspath.exists |
| 110 | + |
| 111 | + lockfile_abspath.unlink() |
| 112 | + |
| 113 | + |
79 | 114 | def test_derived_container_build_tag(
|
80 | 115 | container_runtime: OciRuntimeBase, pytestconfig: pytest.Config
|
81 | 116 | ) -> None:
|
|
0 commit comments