1
- """
2
- Pytest configuration that spins up a single localstack instance that is shared across test modules.
3
- See: https://docs.pytest.org/en/6.2.x/fixture.html#conftest-py-sharing-fixtures-across-multiple-files
4
-
5
- It is thread/process safe to run with pytest-parallel, however not for pytest-xdist.
6
- """
7
- import logging
8
- import multiprocessing as mp
9
- import os
10
- import threading
11
-
12
- import pytest
1
+ from _pytest .config import Config
13
2
14
3
from localstack import config as localstack_config
15
4
from localstack import constants
16
- from localstack .config import is_env_true
17
- from localstack .constants import ENV_INTERNAL_TEST_RUN
18
- from localstack .runtime import events
19
- from localstack .services import infra
20
- from localstack .testing .aws .util import is_aws_cloud
21
- from localstack .utils .common import safe_requests
22
5
from tests .aws .services .es .test_es import install_async as es_install_async
23
6
from tests .aws .services .opensearch .test_opensearch import install_async as opensearch_install_async
24
7
from tests .aws .test_terraform import TestTerraform
25
8
26
- logger = logging .getLogger (__name__ )
27
-
28
- localstack_started = mp .Event () # event indicating whether localstack has been started
29
- localstack_stop = mp .Event () # event that can be triggered to stop localstack
30
- localstack_stopped = mp .Event () # event indicating that localstack has been stopped
31
- startup_monitor_event = mp .Event () # event that can be triggered to start localstack
32
-
33
- # collection of functions that should be executed to initialize tests
34
- test_init_functions = set ()
35
-
36
- if localstack_config .is_collect_metrics_mode ():
37
- pytest_plugins = "localstack.testing.pytest.metric_collection"
38
9
39
-
40
- @pytest .hookimpl ()
41
- def pytest_configure (config ):
42
- # patch default boto waiter config when running on AWS
43
- if is_aws_cloud ():
44
- localstack_config .DEFAULT_DELAY = 5
45
- localstack_config .DEFAULT_MAX_ATTEMPTS = 60
46
-
47
- # first pytest lifecycle hook
48
- _start_monitor ()
10
+ def pytest_configure (config : Config ):
11
+ # FIXME: note that this should be the same as in tests/integration/conftest.py since both are currently
12
+ # run in the same CI test step, but only one localstack instance is started for both.
13
+ config .option .start_localstack = True
14
+ localstack_config .FORCE_SHUTDOWN = False
15
+ localstack_config .GATEWAY_LISTEN = [
16
+ localstack_config .HostAndPort (host = "0.0.0.0" , port = constants .DEFAULT_PORT_EDGE )
17
+ ]
49
18
50
19
51
20
def pytest_runtestloop (session ):
52
21
# second pytest lifecycle hook (before test runner starts)
22
+ test_init_functions = set ()
53
23
54
24
# collect test classes
17A7
span>
55
25
test_classes = set ()
@@ -68,7 +38,6 @@ def pytest_runtestloop(session):
68
38
for test_class in test_classes :
69
39
# set flag that terraform will be used
70
40
if TestTerraform is test_class :
71
- logger .info ("will initialize TestTerraform" )
72
41
test_init_functions .add (TestTerraform .init_async )
73
42
continue
74
43
@@ -78,110 +47,5 @@ def pytest_runtestloop(session):
78
47
if session .config .option .collectonly :
79
48
return
80
49
81
- # trigger localstack startup in startup_monitor and wait until it becomes ready
82
- startup_monitor_event .set ()
83
- localstack_started .wait ()
84
-
85
-
86
- @pytest .hookimpl ()
87
- def pytest_unconfigure (config ):
88
- # last pytest lifecycle hook (before pytest exits)
89
- _trigger_stop ()
90
- # wait for localstack to stop. We do not want to exit immediately, otherwise new threads during shutdown will fail
91
- if not localstack_stopped .wait (timeout = 10 ):
92
- logger .warning ("LocalStack did not exit in time!" )
93
-
94
-
95
- def _start_monitor ():
96
- threading .Thread (target = startup_monitor ).start ()
97
-
98
-
99
- def _trigger_stop ():
100
- localstack_stop .set ()
101
- startup_monitor_event .set ()
102
-
103
-
104
- def startup_monitor () -> None :
105
- """
106
- The startup monitor is a thread that waits for the startup_monitor_event and, once the event is true, starts a
107
- localstack instance in its own thread context.
108
- """
109
- logger .info ("waiting on localstack_start signal" )
110
- startup_monitor_event .wait ()
111
-
112
- if localstack_stop .is_set ():
113
- # this is called if _trigger_stop() is called before any test has requested the localstack_runtime fixture.
114
- logger .info ("ending startup_monitor" )
115
- localstack_stopped .set ()
116
- return
117
-
118
- if is_env_true ("TEST_SKIP_LOCALSTACK_START" ) or os .environ .get ("TEST_TARGET" ) == "AWS_CLOUD" :
119
- logger .info ("TEST_SKIP_LOCALSTACK_START is set, not starting localstack" )
120
- localstack_started .set ()
121
- localstack_stopped .set ()
122
- return
123
-
124
- logger .info ("running localstack" )
125
- run_localstack ()
126
-
127
-
128
- def run_localstack ():
129
- """
130
- Start localstack and block until it terminates. Terminate localstack by calling _trigger_stop().
131
- """
132
- # configure
133
- os .environ [ENV_INTERNAL_TEST_RUN ] = "1"
134
- safe_requests .verify_ssl = False
135
- localstack_config .FORCE_SHUTDOWN = False
136
- localstack_config .GATEWAY_LISTEN = [
137
- localstack_config .HostAndPort (host = "0.0.0.0" , port = constants .DEFAULT_PORT_EDGE )
138
- ]
139
-
140
- def watchdog ():
141
- logger .info ("waiting stop event" )
142
- localstack_stop .wait () # triggered by _trigger_stop()
143
- logger .info ("stopping infra" )
144
- infra .stop_infra ()
145
-
146
- monitor = threading .Thread (target = watchdog )
147
- monitor .start ()
148
-
149
- logger .info ("starting localstack infrastructure" )
150
- infra .start_infra (asynchronous = True )
151
-
152
50
for fn in test_init_functions :
153
- try :
154
- # asynchronous init functions
155
- fn ()
156
- except Exception :
157
- logger .exception ("exception while running init function for test" )
158
-
159
- logger .info ("waiting for infra to be ready" )
160
- events .infra_ready .wait () # wait for infra to start (threading event)
161
- localstack_started .set () # set conftest inter-process Event
162
-
163
- logger .info ("waiting for shutdown" )
164
- try :
165
- logger .info ("waiting for watchdog to join" )
166
- monitor .join ()
167
- finally :
168
- logger .info ("ok bye" )
169
- localstack_stopped .set ()
170
-
171
-
172
- @pytest .fixture (scope = "session" , autouse = True )
173
- def localstack_runtime ():
174
- """
175
- This is a dummy fixture. Each test requests the fixture, but it actually just makes sure that localstack is running,
176
- blocks until localstack is running, or starts localstack the first time the fixture is requested.
177
- It doesn't actually do anything but signal to the `startup_monitor` function.
178
- """
179
- if localstack_started .is_set ():
180
- # called by all tests after the startup has completed and the initial tests are unblocked
181
- yield
182
- return
183
-
184
- startup_monitor_event .set ()
185
- localstack_started .wait ()
186
- yield
187
- return
51
+ fn ()
0 commit comments