langfun 0.1.2.dev202509240805__py3-none-any.whl → 0.1.2.dev202509260805__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of langfun might be problematic. Click here for more details.

langfun/env/base_test.py CHANGED
@@ -11,384 +11,20 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- import contextlib
15
14
  import time
16
- from typing import Any, Iterator, Type
15
+ from typing import Any
17
16
  import unittest
18
17
 
19
- from langfun.env import base_environment
20
- from langfun.env import base_feature
21
18
  from langfun.env import base_sandbox
22
19
  from langfun.env import interface
23
- import pyglove as pg
20
+ from langfun.env import test_utils
21
+ from langfun.env.event_handlers import base as event_handler_base
24
22
 
25
23
 
26
- class TestingEnvironment(base_environment.BaseEnvironment):
27
-
28
- simulate_start_error: Type[BaseException] | None = None
29
- simulate_shutdown_error: Type[BaseException] | None = None
30
- simulate_ping_error: Type[BaseException] | None = None
31
- keepalive_interval: float | None = 60.0
32
- offline: bool = False
33
-
34
- @property
35
- def id(self) -> interface.EnvironmentId:
36
- return interface.EnvironmentId('testing-env')
37
-
38
- def wait_for_next_maintenance(self):
39
- maintenance_count = self._maintenance_count
40
- while self._maintenance_count == maintenance_count:
41
- time.sleep(0.1)
42
-
43
- def _create_sandbox(
44
- self,
45
- sandbox_id: str,
46
- reusable: bool,
47
- proactive_session_setup: bool,
48
- ) -> interface.Sandbox:
49
- if self.offline:
50
- raise interface.EnvironmentError(
51
- 'Unknown environment error.',
52
- environment=self,
53
- )
54
- return TestingSandbox(
55
- environment=self,
56
- id=interface.SandboxId(
57
- environment_id=self.id,
58
- sandbox_id=sandbox_id
59
- ),
60
- reusable=reusable,
61
- proactive_session_setup=proactive_session_setup,
62
- simulate_start_error=self.simulate_start_error,
63
- simulate_shutdown_error=self.simulate_shutdown_error,
64
- simulate_ping_error=self.simulate_ping_error,
65
- keepalive_interval=self.keepalive_interval,
66
- )
67
-
68
-
69
- class TestingSandbox(base_sandbox.BaseSandbox):
70
-
71
- simulate_start_error: Type[BaseException] | None = None
72
- simulate_shutdown_error: Type[BaseException] | None = None
73
- simulate_ping_error: Type[BaseException] | None = None
74
-
75
- def _on_bound(self) -> None:
76
- super()._on_bound()
77
- self._shell_history = []
78
- self._ping_history = []
79
-
80
- def _raise_error(self, message, error_type: Type[BaseException], **kwargs):
81
- if (error_type is interface.SandboxStateError or
82
- issubclass(error_type, interface.SandboxStateError)):
83
- kwargs['sandbox'] = self
84
- raise error_type(message, **kwargs)
85
- else:
86
- raise error_type(message)
87
-
88
- def wait_until(
89
- self,
90
- status: interface.Sandbox.Status | tuple[interface.Sandbox.Status, ...]
91
- ) -> None:
92
- if not isinstance(status, tuple):
93
- status = (status,)
94
- while self.status not in status:
95
- time.sleep(0.1)
96
-
97
- def wait_until_not(
98
- self,
99
- status: interface.Sandbox.Status | tuple[interface.Sandbox.Status, ...]
100
- ) -> None:
101
- if not isinstance(status, tuple):
102
- status = (status,)
103
- while self.status in status:
104
- time.sleep(0.1)
105
-
106
- def wait_until_next_housekeep(self) -> None:
107
- housekeep_count = self._housekeep_count
108
- while self._housekeep_count == housekeep_count:
109
- time.sleep(0.1)
110
-
111
- def _start(self) -> None:
112
- if self.simulate_start_error:
113
- self._raise_error('Sandbox start error', self.simulate_start_error)
114
- super()._start()
115
-
116
- def _shutdown(self) -> None:
117
- if self.simulate_shutdown_error:
118
- self._raise_error('Sandbox shutdown error', self.simulate_shutdown_error)
119
- super()._shutdown()
120
-
121
- @base_sandbox.sandbox_service(critical_errors=(RuntimeError,))
122
- def shell(
123
- self,
124
- code: str,
125
- raise_error: Type[BaseException] | None = None,
126
- ) -> str:
127
- self._shell_history.append(code)
128
- if raise_error is not None:
129
- self._raise_error(f'shell "{code}" failed', raise_error)
130
- return f'shell "{code}" succeeded'
131
-
132
- def _ping(self) -> None:
133
- self._ping_history.append(not self.simulate_ping_error)
134
- if self.simulate_ping_error:
135
- self._raise_error('Ping error', self.simulate_ping_error, code='ping')
136
-
137
-
138
- class TestingFeature(base_feature.BaseFeature):
139
- housekeep_interval = 0
140
- setup_session_delay: float = 0.0
141
- simulate_housekeep_error: Type[BaseException] | None = None
142
- simulate_setup_error: Type[BaseException] | None = None
143
- simulate_teardown_error: Type[BaseException] | None = None
144
- simulate_setup_session_error: Type[BaseException] | None = None
145
- simulate_teardown_session_error: Type[BaseException] | None = None
146
-
147
- class Service:
148
- """Sandbox."""
149
-
150
- def __init__(self, sandbox: interface.Sandbox):
151
- self._sandbox = sandbox
152
-
153
- def do(self, code: str, raise_error: Type[BaseException] | None = None):
154
- self._sandbox.shell(code, raise_error=raise_error)
155
-
156
- def _raise_error(self, message, error_type: Type[BaseException], **kwargs):
157
- self._sandbox._raise_error(message, error_type, **kwargs)
158
-
159
- def _setup(self) -> None:
160
- if self.simulate_setup_error:
161
- self._raise_error(f'{self.name} setup error', self.simulate_setup_error)
162
- self.sandbox.shell(f'"{self.name}" setup')
163
-
164
- def _teardown(self) -> None:
165
- if self.simulate_teardown_error:
166
- self._raise_error(
167
- f'{self.name} teardown error', self.simulate_teardown_error
168
- )
169
- self.sandbox.shell(f'"{self.name}" teardown')
170
-
171
- def _setup_session(self) -> None:
172
- if self.setup_session_delay > 0:
173
- time.sleep(self.setup_session_delay)
174
-
175
- if self.simulate_setup_session_error:
176
- self._raise_error(
177
- 'Feature session setup error', self.simulate_setup_session_error
178
- )
179
- self.sandbox.shell(f'"{self.name}" setup session')
180
-
181
- def _teardown_session(self) -> None:
182
- if self.simulate_teardown_session_error:
183
- self._raise_error(
184
- 'Feature session teardown error', self.simulate_teardown_session_error
185
- )
186
- self.sandbox.shell(f'"{self.name}" teardown session')
187
-
188
- @base_sandbox.sandbox_service()
189
- def num_shell_calls(self) -> None:
190
- return len(self.sandbox._shell_history)
191
-
192
- @base_sandbox.sandbox_service()
193
- def bad_shell_call(self) -> None:
194
- self.sandbox.shell('bad command', raise_error=RuntimeError)
195
-
196
- @base_sandbox.sandbox_service()
197
- def show_session_id(self):
198
- return self.session_id
199
-
200
- @base_sandbox.sandbox_service()
201
- def call_with_varargs(self, code: str, *args, **kwargs):
202
- del code, args, kwargs
203
- return 0
204
-
205
- def _on_bound(self) -> None:
206
- super()._on_bound()
207
- self._service = None
208
-
209
- @base_sandbox.sandbox_service()
210
- @contextlib.contextmanager
211
- def my_service(self) -> Iterator[Service]:
212
- try:
213
- self._service = TestingFeature.Service(sandbox=self.sandbox)
214
- yield self._service
215
- finally:
216
- self._service = None
217
-
218
- def _housekeep(self) -> None:
219
- if self.simulate_housekeep_error:
220
- raise interface.SandboxStateError(
221
- 'House keeping error', sandbox=self.sandbox
222
- )
223
-
224
-
225
- class TestingEnvironmentEventHandler(
226
- pg.Object, interface.EnvironmentEventHandler
227
- ):
228
- log_sandbox_status: bool = False
229
- log_feature_setup: bool = True
230
- log_session_setup: bool = False
231
-
232
- def _on_bound(self) -> None:
233
- super()._on_bound()
234
- self._logs = []
235
-
236
- @property
237
- def logs(self) -> list[str]:
238
- return self._logs
239
-
240
- def _add_message(self, message: str, error: Exception | None) -> None:
241
- """Adds a message to the history."""
242
- if error is None:
243
- self._logs.append(message)
244
- else:
245
- self._logs.append(f'{message} with {error.__class__.__name__}')
246
-
247
- def on_environment_start(
248
- self,
249
- environment: interface.Environment,
250
- error: Exception | None
251
- ) -> None:
252
- """Called when the environment is started."""
253
- self._add_message(f'[{environment.id}] environment started', error)
254
-
255
- def on_environment_shutdown(
256
- self,
257
- environment: interface.Environment,
258
- error: Exception | None
259
- ) -> None:
260
- """Called when the environment is shutdown."""
261
- self._add_message(f'[{environment.id}] environment shutdown', error)
262
-
263
- def on_sandbox_start(
264
- self,
265
- environment: interface.Environment,
266
- sandbox: interface.Sandbox,
267
- error: Exception | None
268
- ) -> None:
269
- del environment
270
- self._add_message(f'[{sandbox.id}] sandbox started', error)
271
-
272
- def on_sandbox_status_change(
273
- self,
274
- environment: interface.Environment,
275
- sandbox: interface.Sandbox,
276
- old_status: interface.Sandbox.Status,
277
- new_status: interface.Sandbox.Status,
278
- ) -> None:
279
- if self.log_sandbox_status:
280
- self._add_message(
281
- f'[{sandbox.id}] {old_status.value} -> {new_status.value}',
282
- None,
283
- )
284
-
285
- def on_sandbox_shutdown(
286
- self,
287
- environment: interface.Environment,
288
- sandbox: interface.Sandbox,
289
- error: Exception | None
290
- ) -> None:
291
- self._add_message(f'[{sandbox.id}] sandbox shutdown', error)
292
-
293
- def on_feature_setup(
294
- self,
295
- environment: interface.Environment,
296
- sandbox: interface.Sandbox,
297
- feature: interface.Feature,
298
- error: Exception | None
299
- ) -> None:
300
- """Called when a sandbox feature is setup."""
301
- if self.log_feature_setup:
302
- self._add_message(
303
- f'[{sandbox.id}/{feature.name}] feature setup', error
304
- )
305
-
306
- def on_feature_teardown(
307
- self,
308
- environment: interface.Environment,
309
- sandbox: interface.Sandbox,
310
- feature: interface.Feature,
311
- error: Exception | None
312
- ) -> None:
313
- """Called when a sandbox feature is teardown."""
314
- if self.log_feature_setup:
315
- self._add_message(
316
- f'[{sandbox.id}/{feature.name}] feature teardown', error
317
- )
318
-
319
- def on_feature_setup_session(
320
- self,
321
- environment: interface.Environment,
322
- sandbox: interface.Sandbox,
323
- feature: interface.Feature,
324
- session_id: str | None,
325
- error: Exception | None
326
- ) -> None:
327
- """Called when a sandbox feature is setup."""
328
- if self.log_session_setup:
329
- self._add_message(
330
- f'[{sandbox.id}/{feature.name}] feature setup session', error
331
- )
332
-
333
- def on_feature_teardown_session(
334
- self,
335
- environment: interface.Environment,
336
- sandbox: interface.Sandbox,
337
- feature: interface.Feature,
338
- session_id: str,
339
- error: Exception | None
340
- ) -> None:
341
- """Called when a sandbox feature is teardown."""
342
- if self.log_session_setup:
343
- self._add_message(
344
- f'[{sandbox.id}/{feature.name}] feature teardown session', error
345
- )
346
-
347
- def on_session_start(
348
- self,
349
- environment: interface.Environment,
350
- sandbox: interface.Sandbox,
351
- session_id: str,
352
- error: Exception | None
353
- ) -> None:
354
- """Called when a sandbox session starts."""
355
- self._add_message(
356
- f'[{sandbox.id}] session {session_id!r} started', error
357
- )
358
-
359
- def on_session_end(
360
- self,
361
- environment: interface.Environment,
362
- sandbox: interface.Sandbox,
363
- session_id: str,
364
- error: Exception | None
365
- ) -> None:
366
- """Called when a sandbox session ends."""
367
- self._add_message(
368
- f'[{sandbox.id}] session {session_id!r} ended', error
369
- )
370
-
371
- def on_session_activity(
372
- self,
373
- session_id: str,
374
- name: str,
375
- environment: interface.Environment,
376
- sandbox: interface.Sandbox,
377
- feature: interface.Feature | None,
378
- error: Exception | None,
379
- *,
380
- code: str | None = None,
381
- **kwargs
382
- ) -> None:
383
- """Called when a sandbox activity is performed."""
384
- del environment, kwargs
385
- self._add_message(
386
- f'[{sandbox.id}/{session_id}] {name}: {code}', error
387
- )
388
-
389
- #
390
- # Tests
391
- #
24
+ TestingEnvironment = test_utils.TestingEnvironment
25
+ TestingSandbox = test_utils.TestingSandbox
26
+ TestingFeature = test_utils.TestingFeature
27
+ TestingEventHandler = test_utils.TestingEventHandler
392
28
 
393
29
 
394
30
  class EnvironmentTests(unittest.TestCase):
@@ -407,9 +43,8 @@ class EnvironmentTests(unittest.TestCase):
407
43
  self.assertEqual(env.min_pool_size, 0)
408
44
  self.assertEqual(env.max_pool_size, 0)
409
45
  self.assertEqual(env.sandbox_pool, [])
410
- self.assertEqual(env.id, interface.EnvironmentId('testing-env'))
46
+ self.assertEqual(env.id, interface.Environment.Id('testing-env'))
411
47
  self.assertEqual(env.outage_grace_period, 1)
412
- self.assertEqual(env.stats_report_interval, 60)
413
48
  self.assertEqual(env.features['test_feature'].name, 'test_feature')
414
49
 
415
50
  self.assertIsNone(env.start_time)
@@ -425,12 +60,16 @@ class EnvironmentTests(unittest.TestCase):
425
60
 
426
61
  with env.sandbox('session1') as sb:
427
62
  self.assertEqual(
428
- sb.id, interface.SandboxId(environment_id=env.id, sandbox_id='0')
63
+ sb.id, interface.Sandbox.Id(environment_id=env.id, sandbox_id='0')
429
64
  )
430
65
  self.assertEqual(sb.session_id, 'session1')
431
66
  self.assertEqual(sb.working_dir, '/tmp/testing-env/0')
432
67
  self.assertTrue(sb.is_online)
433
68
  self.assertIs(sb.test_feature, sb.features['test_feature'])
69
+ self.assertEqual(
70
+ sb.test_feature.working_dir,
71
+ '/tmp/testing-env/0/test_feature'
72
+ )
434
73
  with self.assertRaises(AttributeError):
435
74
  _ = sb.test_feature2
436
75
  self.assertFalse(sb.is_online)
@@ -439,14 +78,26 @@ class EnvironmentTests(unittest.TestCase):
439
78
  with self.assertRaises(AttributeError):
440
79
  _ = env.test_feature2
441
80
 
81
+ def test_del(self):
82
+ env = TestingEnvironment(
83
+ features={'test_feature': TestingFeature()},
84
+ pool_size=0,
85
+ outage_grace_period=1,
86
+ outage_retry_interval=0,
87
+ sandbox_keepalive_interval=0,
88
+ )
89
+ env.start()
90
+ sb = env.acquire()
91
+ del sb
92
+ del env
93
+
442
94
  def test_acquire_env_offline(self):
443
95
  env = TestingEnvironment(
444
96
  features={'test_feature': TestingFeature()},
445
97
  pool_size=0,
446
98
  outage_grace_period=1,
447
99
  outage_retry_interval=0,
448
- keepalive_interval=0,
449
- stats_report_interval=1,
100
+ sandbox_keepalive_interval=0,
450
101
  )
451
102
  with self.assertRaises(interface.EnvironmentOutageError):
452
103
  env.acquire()
@@ -457,12 +108,14 @@ class EnvironmentTests(unittest.TestCase):
457
108
  pool_size=0,
458
109
  outage_grace_period=1,
459
110
  outage_retry_interval=0,
460
- keepalive_interval=0,
461
- stats_report_interval=1,
111
+ sandbox_keepalive_interval=0,
462
112
  )
463
113
  with env:
464
114
  sb = env.acquire()
465
115
  self.assertEqual(sb.status, interface.Sandbox.Status.ACQUIRED)
116
+ self.assertIsNone(env.working_dir)
117
+ self.assertIsNone(sb.working_dir)
118
+ self.assertIsNone(sb.test_feature.working_dir)
466
119
 
467
120
  def test_acquire_no_pooling_with_error(self):
468
121
  env = TestingEnvironment(
@@ -474,8 +127,7 @@ class EnvironmentTests(unittest.TestCase):
474
127
  pool_size=0,
475
128
  outage_grace_period=1,
476
129
  outage_retry_interval=0,
477
- keepalive_interval=0,
478
- stats_report_interval=1,
130
+ sandbox_keepalive_interval=0,
479
131
  )
480
132
  with env:
481
133
  with self.assertRaises(interface.EnvironmentOutageError):
@@ -487,8 +139,7 @@ class EnvironmentTests(unittest.TestCase):
487
139
  pool_size=1,
488
140
  outage_grace_period=1,
489
141
  outage_retry_interval=0,
490
- keepalive_interval=0,
491
- stats_report_interval=1,
142
+ sandbox_keepalive_interval=0,
492
143
  )
493
144
  with env:
494
145
  sb = env.acquire()
@@ -500,8 +151,7 @@ class EnvironmentTests(unittest.TestCase):
500
151
  pool_size=1,
501
152
  outage_grace_period=1,
502
153
  outage_retry_interval=0,
503
- keepalive_interval=0,
504
- stats_report_interval=1,
154
+ sandbox_keepalive_interval=0,
505
155
  )
506
156
  with env:
507
157
  sb = env.acquire()
@@ -515,17 +165,76 @@ class EnvironmentTests(unittest.TestCase):
515
165
  pool_size=(1, 3),
516
166
  outage_grace_period=1,
517
167
  outage_retry_interval=0,
518
- keepalive_interval=0,
519
- stats_report_interval=1,
168
+ sandbox_keepalive_interval=0,
520
169
  )
521
170
  with env:
522
171
  self.assertEqual(len(env.sandbox_pool), 1)
172
+ self.assertEqual(
173
+ env.stats(),
174
+ {
175
+ 'sandbox': {
176
+ 'created': 0,
177
+ 'setting_up': 0,
178
+ 'ready': 1,
179
+ 'acquired': 0,
180
+ 'in_session': 0,
181
+ 'exiting_session': 0,
182
+ 'shutting_down': 0,
183
+ 'offline': 0,
184
+ }
185
+ }
186
+ )
523
187
  sb = env.acquire()
524
188
  self.assertEqual(sb.status, interface.Sandbox.Status.ACQUIRED)
189
+ self.assertEqual(
190
+ env.stats(),
191
+ {
192
+ 'sandbox': {
193
+ 'created': 0,
194
+ 'setting_up': 0,
195
+ 'ready': 0,
196
+ 'acquired': 1,
197
+ 'in_session': 0,
198
+ 'exiting_session': 0,
199
+ 'shutting_down': 0,
200
+ 'offline': 0,
201
+ }
202
+ }
203
+ )
525
204
  self.assertEqual(len(env.sandbox_pool), 1)
526
205
  sb2 = env.acquire()
527
206
  self.assertEqual(sb2.status, interface.Sandbox.Status.ACQUIRED)
528
207
  self.assertEqual(len(env.sandbox_pool), 2)
208
+ self.assertEqual(
209
+ env.stats(),
210
+ {
211
+ 'sandbox': {
212
+ 'created': 0,
213
+ 'setting_up': 0,
214
+ 'ready': 0,
215
+ 'acquired': 2,
216
+ 'in_session': 0,
217
+ 'exiting_session': 0,
218
+ 'shutting_down': 0,
219
+ 'offline': 0,
220
+ }
221
+ }
222
+ )
223
+ self.assertEqual(
224
+ env.stats(),
225
+ {
226
+ 'sandbox': {
227
+ 'created': 0,
228
+ 'setting_up': 0,
229
+ 'ready': 0,
230
+ 'acquired': 0,
231
+ 'in_session': 0,
232
+ 'exiting_session': 0,
233
+ 'shutting_down': 0,
234
+ 'offline': 0,
235
+ }
236
+ }
237
+ )
529
238
 
530
239
  def test_acquire_with_growing_pool_failure(self):
531
240
  env = TestingEnvironment(
@@ -533,8 +242,7 @@ class EnvironmentTests(unittest.TestCase):
533
242
  pool_size=(1, 3),
534
243
  outage_grace_period=1,
535
244
  outage_retry_interval=0,
536
- keepalive_interval=0,
537
- stats_report_interval=1,
245
+ sandbox_keepalive_interval=0,
538
246
  )
539
247
  with env:
540
248
  self.assertEqual(len(env.sandbox_pool), 1)
@@ -549,15 +257,14 @@ class EnvironmentTests(unittest.TestCase):
549
257
  with self.assertRaises(interface.EnvironmentOutageError):
550
258
  env.acquire()
551
259
 
552
- def test_maintenance_error(self):
260
+ def test_housekeep_error(self):
553
261
  env = TestingEnvironment(
554
262
  features={'test_feature': TestingFeature()},
555
263
  pool_size=1,
556
264
  proactive_session_setup=True,
557
265
  outage_grace_period=1,
558
266
  outage_retry_interval=0,
559
- keepalive_interval=0,
560
- stats_report_interval=1,
267
+ sandbox_keepalive_interval=0,
561
268
  )
562
269
  with env:
563
270
  self.assertEqual(len(env.sandbox_pool), 1)
@@ -573,7 +280,7 @@ class EnvironmentTests(unittest.TestCase):
573
280
  with self.assertRaises(interface.SandboxStateError):
574
281
  sb.shell('bad command', raise_error=interface.SandboxStateError)
575
282
  self.assertEqual(sb.status, interface.Sandbox.Status.OFFLINE)
576
- env.wait_for_next_maintenance()
283
+ env.wait_for_housekeeping()
577
284
  self.assertFalse(env.is_online)
578
285
 
579
286
 
@@ -581,7 +288,7 @@ class SandboxStatusTests(unittest.TestCase):
581
288
 
582
289
  def setUp(self):
583
290
  super().setUp()
584
- self.event_handler = TestingEnvironmentEventHandler(
291
+ self.event_handler = TestingEventHandler(
585
292
  log_sandbox_status=True,
586
293
  log_feature_setup=True,
587
294
  log_session_setup=True,
@@ -611,6 +318,7 @@ class SandboxStatusTests(unittest.TestCase):
611
318
  'feature2': TestingFeature(),
612
319
  },
613
320
  )
321
+ self.assertFalse(env.enable_pooling)
614
322
  with env:
615
323
  with env.sandbox('session1') as sb:
616
324
  sb.shell('echo "hello"')
@@ -618,7 +326,9 @@ class SandboxStatusTests(unittest.TestCase):
618
326
  self.event_handler.logs,
619
327
  [
620
328
  '[testing-env] environment started',
329
+ '[testing-env/0] shell: "feature1" setup',
621
330
  '[testing-env/0/feature1] feature setup',
331
+ '[testing-env/0] shell: "feature2" setup',
622
332
  '[testing-env/0/feature2] feature setup',
623
333
  '[testing-env/0] created -> ready',
624
334
  '[testing-env/0] sandbox started',
@@ -631,14 +341,17 @@ class SandboxStatusTests(unittest.TestCase):
631
341
  '[testing-env/0] setting_up -> in_session',
632
342
  "[testing-env/0] session 'session1' started",
633
343
  '[testing-env/0/session1] shell: echo "hello"',
344
+ '[testing-env/0] in_session -> exiting_session',
634
345
  '[testing-env/0/session1] shell: "feature1" teardown session',
635
346
  '[testing-env/0/feature1] feature teardown session',
636
347
  '[testing-env/0/session1] shell: "feature2" teardown session',
637
348
  '[testing-env/0/feature2] feature teardown session',
638
349
  "[testing-env/0] session 'session1' ended",
639
- '[testing-env/0] in_session -> acquired',
350
+ '[testing-env/0] exiting_session -> acquired',
640
351
  '[testing-env/0] acquired -> shutting_down',
352
+ '[testing-env/0] shell: "feature1" teardown',
641
353
  '[testing-env/0/feature1] feature teardown',
354
+ '[testing-env/0] shell: "feature2" teardown',
642
355
  '[testing-env/0/feature2] feature teardown',
643
356
  '[testing-env/0] shutting_down -> offline',
644
357
  '[testing-env/0] sandbox shutdown'
@@ -654,6 +367,7 @@ class SandboxStatusTests(unittest.TestCase):
654
367
  pool_size=1,
655
368
  proactive_session_setup=True,
656
369
  )
370
+ self.assertTrue(env.enable_pooling)
657
371
  with env:
658
372
  with env.sandbox('session1') as sb:
659
373
  sb.shell('echo "hello"')
@@ -667,9 +381,13 @@ class SandboxStatusTests(unittest.TestCase):
667
381
  self.assertEqual(
668
382
  self.event_handler.logs,
669
383
  [
384
+ '[testing-env/0] shell: "feature1" setup',
670
385
  '[testing-env/0/feature1] feature setup',
386
+ '[testing-env/0] shell: "feature2" setup',
671
387
  '[testing-env/0/feature2] feature setup',
388
+ '[testing-env/0] shell: "feature1" setup session',
672
389
  '[testing-env/0/feature1] feature setup session',
390
+ '[testing-env/0] shell: "feature2" setup session',
673
391
  '[testing-env/0/feature2] feature setup session',
674
392
  '[testing-env/0] created -> ready',
675
393
  '[testing-env/0] sandbox started',
@@ -679,13 +397,16 @@ class SandboxStatusTests(unittest.TestCase):
679
397
  '[testing-env/0] setting_up -> in_session',
680
398
  "[testing-env/0] session 'session1' started",
681
399
  '[testing-env/0/session1] shell: echo "hello"',
400
+ '[testing-env/0] in_session -> exiting_session',
682
401
  '[testing-env/0/session1] shell: "feature1" teardown session',
683
402
  '[testing-env/0/feature1] feature teardown session',
684
403
  '[testing-env/0/session1] shell: "feature2" teardown session',
685
404
  '[testing-env/0/feature2] feature teardown session',
686
405
  "[testing-env/0] session 'session1' ended",
687
- '[testing-env/0] in_session -> setting_up',
406
+ '[testing-env/0] exiting_session -> setting_up',
407
+ '[testing-env/0] shell: "feature1" setup session',
688
408
  '[testing-env/0/feature1] feature setup session',
409
+ '[testing-env/0] shell: "feature2" setup session',
689
410
  '[testing-env/0/feature2] feature setup session',
690
411
  '[testing-env/0] setting_up -> ready'
691
412
  ]
@@ -696,7 +417,7 @@ class SandboxStatusTests(unittest.TestCase):
696
417
  features={'test_feature': TestingFeature(setup_session_delay=0.5)},
697
418
  pool_size=1,
698
419
  )
699
- event_handler = TestingEnvironmentEventHandler(
420
+ event_handler = TestingEventHandler(
700
421
  log_sandbox_status=True,
701
422
  log_feature_setup=True,
702
423
  log_session_setup=True,
@@ -719,12 +440,14 @@ class SandboxStatusTests(unittest.TestCase):
719
440
  self.assertEqual(
720
441
  event_handler.logs,
721
442
  [
443
+ '[testing-env/0] in_session -> exiting_session',
722
444
  '[testing-env/0/session1] shell: "test_feature" teardown session',
723
445
  '[testing-env/0/test_feature] feature teardown session',
724
446
  "[testing-env/0] session 'session1' ended",
725
- '[testing-env/0] in_session -> setting_up',
447
+ '[testing-env/0] exiting_session -> setting_up',
726
448
  '[testing-env/0/test_feature] feature setup session with SandboxStateError', # pylint: disable=line-too-long
727
449
  '[testing-env/0] setting_up -> shutting_down',
450
+ '[testing-env/0] shell: "test_feature" teardown',
728
451
  '[testing-env/0/test_feature] feature teardown',
729
452
  '[testing-env/0] shutting_down -> offline',
730
453
  '[testing-env/0] sandbox shutdown'
@@ -797,7 +520,9 @@ class SandboxStatusTests(unittest.TestCase):
797
520
  self.event_handler.logs,
798
521
  [
799
522
  '[testing-env] environment started',
523
+ '[testing-env/0] shell: "feature1" setup',
800
524
  '[testing-env/0/feature1] feature setup',
525
+ '[testing-env/0] shell: "feature2" setup',
801
526
  '[testing-env/0/feature2] feature setup',
802
527
  '[testing-env/0] created -> ready',
803
528
  '[testing-env/0] sandbox started',
@@ -810,14 +535,17 @@ class SandboxStatusTests(unittest.TestCase):
810
535
  '[testing-env/0] setting_up -> in_session',
811
536
  "[testing-env/0] session 'session1' started",
812
537
  '[testing-env/0/session1] shell: echo "hello"',
538
+ '[testing-env/0] in_session -> exiting_session',
813
539
  '[testing-env/0/session1] shell: "feature1" teardown session',
814
540
  '[testing-env/0/feature1] feature teardown session',
815
541
  '[testing-env/0/session1] shell: "feature2" teardown session',
816
542
  '[testing-env/0/feature2] feature teardown session',
817
543
  "[testing-env/0] session 'session1' ended",
818
- '[testing-env/0] in_session -> acquired',
544
+ '[testing-env/0] exiting_session -> acquired',
819
545
  '[testing-env/0] acquired -> shutting_down',
546
+ '[testing-env/0] shell: "feature1" teardown',
820
547
  '[testing-env/0/feature1] feature teardown',
548
+ '[testing-env/0] shell: "feature2" teardown',
821
549
  '[testing-env/0/feature2] feature teardown',
822
550
  '[testing-env/0] shutting_down -> offline',
823
551
  '[testing-env/0] sandbox shutdown with ValueError',
@@ -841,15 +569,21 @@ class SandboxStatusTests(unittest.TestCase):
841
569
  self.assertEqual(
842
570
  self.event_handler.logs,
843
571
  [
572
+ '[testing-env/0] shell: "feature1" setup',
844
573
  '[testing-env/0/feature1] feature setup',
574
+ '[testing-env/0] shell: "feature2" setup',
845
575
  '[testing-env/0/feature2] feature setup',
576
+ '[testing-env/0] shell: "feature1" setup session',
846
577
  '[testing-env/0/feature1] feature setup session',
578
+ '[testing-env/0] shell: "feature2" setup session',
847
579
  '[testing-env/0/feature2] feature setup session',
848
580
  '[testing-env/0] created -> ready',
849
581
  '[testing-env/0] sandbox started',
850
582
  '[testing-env] environment started',
851
583
  '[testing-env/0] ready -> shutting_down',
584
+ '[testing-env/0] shell: "feature1" teardown',
852
585
  '[testing-env/0/feature1] feature teardown',
586
+ '[testing-env/0] shell: "feature2" teardown',
853
587
  '[testing-env/0/feature2] feature teardown',
854
588
  '[testing-env/0] shutting_down -> offline',
855
589
  '[testing-env/0] sandbox shutdown with ValueError',
@@ -873,7 +607,9 @@ class SandboxStatusTests(unittest.TestCase):
873
607
  self.event_handler.logs,
874
608
  [
875
609
  '[testing-env] environment started',
610
+ '[testing-env/0] shell: "feature1" setup',
876
611
  '[testing-env/0/feature1] feature setup',
612
+ '[testing-env/0] shell: "feature2" setup',
877
613
  '[testing-env/0/feature2] feature setup',
878
614
  '[testing-env/0] created -> ready',
879
615
  '[testing-env/0] sandbox started',
@@ -886,14 +622,17 @@ class SandboxStatusTests(unittest.TestCase):
886
622
  '[testing-env/0] setting_up -> in_session',
887
623
  "[testing-env/0] session 'session1' started",
888
624
  '[testing-env/0/session1] shell: echo "hello"',
625
+ '[testing-env/0] in_session -> exiting_session',
889
626
  '[testing-env/0/session1] shell: "feature1" teardown session',
890
627
  '[testing-env/0/feature1] feature teardown session',
891
628
  '[testing-env/0/session1] shell: "feature2" teardown session',
892
629
  '[testing-env/0/feature2] feature teardown session',
893
630
  "[testing-env/0] session 'session1' ended",
894
- '[testing-env/0] in_session -> acquired',
631
+ '[testing-env/0] exiting_session -> acquired',
895
632
  '[testing-env/0] acquired -> shutting_down',
633
+ '[testing-env/0] shell: "feature1" teardown',
896
634
  '[testing-env/0/feature1] feature teardown',
635
+ '[testing-env/0] shell: "feature2" teardown',
897
636
  '[testing-env/0/feature2] feature teardown',
898
637
  '[testing-env/0] shutting_down -> offline',
899
638
  '[testing-env/0] sandbox shutdown with SandboxStateError',
@@ -918,11 +657,14 @@ class SandboxStatusTests(unittest.TestCase):
918
657
  self.event_handler.logs,
919
658
  [
920
659
  '[testing-env] environment started',
660
+ '[testing-env/0] shell: "feature1" setup',
921
661
  '[testing-env/0/feature1] feature setup',
922
662
  '[testing-env/0/feature2] feature setup with ValueError',
923
663
  '[testing-env/0] sandbox started with ValueError',
924
664
  '[testing-env/0] created -> shutting_down',
665
+ '[testing-env/0] shell: "feature1" teardown',
925
666
  '[testing-env/0/feature1] feature teardown',
667
+ '[testing-env/0] shell: "feature2" teardown',
926
668
  '[testing-env/0/feature2] feature teardown',
927
669
  '[testing-env/0] shutting_down -> offline',
928
670
  '[testing-env/0] sandbox shutdown'
@@ -949,6 +691,7 @@ class SandboxStatusTests(unittest.TestCase):
949
691
  '[testing-env/0/feature1] feature setup with SandboxStateError',
950
692
  '[testing-env/0] sandbox started with SandboxStateError',
951
693
  '[testing-env/0] created -> shutting_down',
694
+ '[testing-env/0] shell: "feature1" teardown',
952
695
  '[testing-env/0/feature1] feature teardown',
953
696
  '[testing-env/0] shutting_down -> offline',
954
697
  '[testing-env/0] sandbox shutdown',
@@ -973,7 +716,9 @@ class SandboxStatusTests(unittest.TestCase):
973
716
  self.event_handler.logs,
974
717
  [
975
718
  '[testing-env] environment started',
719
+ '[testing-env/0] shell: "feature1" setup',
976
720
  '[testing-env/0/feature1] feature setup',
721
+ '[testing-env/0] shell: "feature2" setup',
977
722
  '[testing-env/0/feature2] feature setup',
978
723
  '[testing-env/0] created -> ready',
979
724
  '[testing-env/0] sandbox started',
@@ -985,13 +730,15 @@ class SandboxStatusTests(unittest.TestCase):
985
730
  '[testing-env/0/feature2] feature setup session',
986
731
  '[testing-env/0] setting_up -> in_session',
987
732
  "[testing-env/0] session 'session1' started",
733
+ '[testing-env/0] in_session -> exiting_session',
988
734
  '[testing-env/0/session1] shell: "feature1" teardown session',
989
735
  '[testing-env/0/feature1] feature teardown session',
990
736
  '[testing-env/0/session1] shell: "feature2" teardown session',
991
737
  '[testing-env/0/feature2] feature teardown session',
992
738
  "[testing-env/0] session 'session1' ended",
993
- '[testing-env/0] in_session -> acquired',
739
+ '[testing-env/0] exiting_session -> acquired',
994
740
  '[testing-env/0] acquired -> shutting_down',
741
+ '[testing-env/0] shell: "feature1" teardown',
995
742
  '[testing-env/0/feature1] feature teardown',
996
743
  '[testing-env/0/feature2] feature teardown with ValueError',
997
744
  '[testing-env/0] shutting_down -> offline',
@@ -1017,7 +764,9 @@ class SandboxStatusTests(unittest.TestCase):
1017
764
  self.event_handler.logs,
1018
765
  [
1019
766
  '[testing-env] environment started',
767
+ '[testing-env/0] shell: "feature1" setup',
1020
768
  '[testing-env/0/feature1] feature setup',
769
+ '[testing-env/0] shell: "feature2" setup',
1021
770
  '[testing-env/0/feature2] feature setup',
1022
771
  '[testing-env/0] created -> ready',
1023
772
  '[testing-env/0] sandbox started',
@@ -1029,14 +778,16 @@ class SandboxStatusTests(unittest.TestCase):
1029
778
  '[testing-env/0/feature2] feature setup session',
1030
779
  '[testing-env/0] setting_up -> in_session',
1031
780
  "[testing-env/0] session 'session1' started",
781
+ '[testing-env/0] in_session -> exiting_session',
1032
782
  '[testing-env/0/session1] shell: "feature1" teardown session',
1033
783
  '[testing-env/0/feature1] feature teardown session',
1034
784
  '[testing-env/0/session1] shell: "feature2" teardown session',
1035
785
  '[testing-env/0/feature2] feature teardown session',
1036
786
  "[testing-env/0] session 'session1' ended",
1037
- '[testing-env/0] in_session -> acquired',
787
+ '[testing-env/0] exiting_session -> acquired',
1038
788
  '[testing-env/0] acquired -> shutting_down',
1039
789
  '[testing-env/0/feature1] feature teardown with SandboxStateError', # pylint: disable=line-too-long
790
+ '[testing-env/0] shell: "feature2" teardown',
1040
791
  '[testing-env/0/feature2] feature teardown',
1041
792
  '[testing-env/0] shutting_down -> offline',
1042
793
  '[testing-env/0] sandbox shutdown with FeatureTeardownError'
@@ -1060,7 +811,9 @@ class SandboxStatusTests(unittest.TestCase):
1060
811
  self.event_handler.logs,
1061
812
  [
1062
813
  '[testing-env] environment started',
814
+ '[testing-env/0] shell: "feature1" setup',
1063
815
  '[testing-env/0/feature1] feature setup',
816
+ '[testing-env/0] shell: "feature2" setup',
1064
817
  '[testing-env/0/feature2] feature setup',
1065
818
  '[testing-env/0] created -> ready',
1066
819
  '[testing-env/0] sandbox started',
@@ -1098,7 +851,9 @@ class SandboxStatusTests(unittest.TestCase):
1098
851
  self.event_handler.logs,
1099
852
  [
1100
853
  '[testing-env] environment started',
854
+ '[testing-env/0] shell: "feature1" setup',
1101
855
  '[testing-env/0/feature1] feature setup',
856
+ '[testing-env/0] shell: "feature2" setup',
1102
857
  '[testing-env/0/feature2] feature setup',
1103
858
  '[testing-env/0] created -> ready',
1104
859
  '[testing-env/0] sandbox started',
@@ -1111,13 +866,16 @@ class SandboxStatusTests(unittest.TestCase):
1111
866
  '[testing-env/0] setting_up -> in_session',
1112
867
  "[testing-env/0] session 'session1' started",
1113
868
  '[testing-env/0/session1] shell: echo "hello"',
869
+ '[testing-env/0] in_session -> exiting_session',
1114
870
  '[testing-env/0/feature1] feature teardown session with ValueError', # pylint: disable=line-too-long
1115
871
  '[testing-env/0/session1] shell: "feature2" teardown session',
1116
872
  '[testing-env/0/feature2] feature teardown session',
1117
873
  "[testing-env/0] session 'session1' ended",
1118
- '[testing-env/0] in_session -> acquired',
874
+ '[testing-env/0] exiting_session -> acquired',
1119
875
  '[testing-env/0] acquired -> shutting_down',
876
+ '[testing-env/0] shell: "feature1" teardown',
1120
877
  '[testing-env/0/feature1] feature teardown',
878
+ '[testing-env/0] shell: "feature2" teardown',
1121
879
  '[testing-env/0/feature2] feature teardown',
1122
880
  '[testing-env/0] shutting_down -> offline',
1123
881
  '[testing-env/0] sandbox shutdown'
@@ -1142,7 +900,9 @@ class SandboxStatusTests(unittest.TestCase):
1142
900
  self.event_handler.logs,
1143
901
  [
1144
902
  '[testing-env] environment started',
903
+ '[testing-env/0] shell: "feature1" setup',
1145
904
  '[testing-env/0/feature1] feature setup',
905
+ '[testing-env/0] shell: "feature2" setup',
1146
906
  '[testing-env/0/feature2] feature setup',
1147
907
  '[testing-env/0] created -> ready',
1148
908
  '[testing-env/0] sandbox started',
@@ -1155,13 +915,64 @@ class SandboxStatusTests(unittest.TestCase):
1155
915
  '[testing-env/0] setting_up -> in_session',
1156
916
  "[testing-env/0] session 'session1' started",
1157
917
  '[testing-env/0/session1] shell: echo "hello"',
918
+ '[testing-env/0] in_session -> exiting_session',
1158
919
  '[testing-env/0/feature1] feature teardown session with SandboxStateError', # pylint: disable=line-too-long
1159
920
  '[testing-env/0/session1] shell: "feature2" teardown session',
1160
921
  '[testing-env/0/feature2] feature teardown session',
1161
922
  "[testing-env/0] session 'session1' ended with SandboxStateError",
1162
- '[testing-env/0] in_session -> acquired',
923
+ '[testing-env/0] exiting_session -> acquired',
924
+ '[testing-env/0] acquired -> shutting_down',
925
+ '[testing-env/0] shell: "feature1" teardown',
926
+ '[testing-env/0/feature1] feature teardown',
927
+ '[testing-env/0] shell: "feature2" teardown',
928
+ '[testing-env/0/feature2] feature teardown',
929
+ '[testing-env/0] shutting_down -> offline',
930
+ '[testing-env/0] sandbox shutdown'
931
+ ]
932
+ )
933
+
934
+ def test_feature_teardown_session_calling_end_session(self):
935
+ env = self._create_env(
936
+ features={
937
+ 'feature1': TestingFeature(
938
+ call_end_session_on_teardown_session=True
939
+ ),
940
+ 'feature2': TestingFeature(),
941
+ },
942
+ )
943
+ with env:
944
+ with env.sandbox('session1') as sb:
945
+ sb.shell('echo "hello"')
946
+ self.assertEqual(
947
+ self.event_handler.logs,
948
+ [
949
+ '[testing-env] environment started',
950
+ '[testing-env/0] shell: "feature1" setup',
951
+ '[testing-env/0/feature1] feature setup',
952
+ '[testing-env/0] shell: "feature2" setup',
953
+ '[testing-env/0/feature2] feature setup',
954
+ '[testing-env/0] created -> ready',
955
+ '[testing-env/0] sandbox started',
956
+ '[testing-env/0] ready -> acquired',
957
+ '[testing-env/0] acquired -> setting_up',
958
+ '[testing-env/0/session1] shell: "feature1" setup session',
959
+ '[testing-env/0/feature1] feature setup session',
960
+ '[testing-env/0/session1] shell: "feature2" setup session',
961
+ '[testing-env/0/feature2] feature setup session',
962
+ '[testing-env/0] setting_up -> in_session',
963
+ "[testing-env/0] session 'session1' started",
964
+ '[testing-env/0/session1] shell: echo "hello"',
965
+ '[testing-env/0] in_session -> exiting_session',
966
+ '[testing-env/0/session1] shell: "feature1" teardown session',
967
+ '[testing-env/0/feature1] feature teardown session',
968
+ '[testing-env/0/session1] shell: "feature2" teardown session',
969
+ '[testing-env/0/feature2] feature teardown session',
970
+ "[testing-env/0] session 'session1' ended",
971
+ '[testing-env/0] exiting_session -> acquired',
1163
972
  '[testing-env/0] acquired -> shutting_down',
973
+ '[testing-env/0] shell: "feature1" teardown',
1164
974
  '[testing-env/0/feature1] feature teardown',
975
+ '[testing-env/0] shell: "feature2" teardown',
1165
976
  '[testing-env/0/feature2] feature teardown',
1166
977
  '[testing-env/0] shutting_down -> offline',
1167
978
  '[testing-env/0] sandbox shutdown'
@@ -1182,11 +993,14 @@ class SandboxStatusTests(unittest.TestCase):
1182
993
  self.assertEqual(len(sb.state_errors), 0)
1183
994
  sb.shell('echo bar')
1184
995
  self.assertEqual(sb.status, interface.Sandbox.Status.IN_SESSION)
996
+ sb.wait_until_not(interface.Sandbox.Status.SETTING_UP)
1185
997
  self.assertEqual(sb.status, interface.Sandbox.Status.READY)
1186
998
  self.assertEqual(
1187
999
  self.event_handler.logs,
1188
1000
  [
1001
+ '[testing-env/0] shell: "feature1" setup',
1189
1002
  '[testing-env/0/feature1] feature setup',
1003
+ '[testing-env/0] shell: "feature1" setup session',
1190
1004
  '[testing-env/0/feature1] feature setup session',
1191
1005
  '[testing-env/0] created -> ready',
1192
1006
  '[testing-env/0] sandbox started',
@@ -1197,10 +1011,12 @@ class SandboxStatusTests(unittest.TestCase):
1197
1011
  "[testing-env/0] session 'session1' started",
1198
1012
  '[testing-env/0/session1] shell: echo foo with ValueError',
1199
1013
  '[testing-env/0/session1] shell: echo bar',
1014
+ '[testing-env/0] in_session -> exiting_session',
1200
1015
  '[testing-env/0/session1] shell: "feature1" teardown session',
1201
1016
  '[testing-env/0/feature1] feature teardown session',
1202
1017
  "[testing-env/0] session 'session1' ended",
1203
- '[testing-env/0] in_session -> setting_up',
1018
+ '[testing-env/0] exiting_session -> setting_up',
1019
+ '[testing-env/0] shell: "feature1" setup session',
1204
1020
  '[testing-env/0/feature1] feature setup session',
1205
1021
  '[testing-env/0] setting_up -> ready',
1206
1022
  ]
@@ -1223,7 +1039,9 @@ class SandboxStatusTests(unittest.TestCase):
1223
1039
  self.assertEqual(
1224
1040
  self.event_handler.logs,
1225
1041
  [
1042
+ '[testing-env/0] shell: "feature1" setup',
1226
1043
  '[testing-env/0/feature1] feature setup',
1044
+ '[testing-env/0] shell: "feature1" setup session',
1227
1045
  '[testing-env/0/feature1] feature setup session',
1228
1046
  '[testing-env/0] created -> ready',
1229
1047
  '[testing-env/0] sandbox started',
@@ -1233,14 +1051,17 @@ class SandboxStatusTests(unittest.TestCase):
1233
1051
  '[testing-env/0] setting_up -> in_session',
1234
1052
  "[testing-env/0] session 'session1' started",
1235
1053
  '[testing-env/0/session1] shell: echo foo with RuntimeError',
1054
+ '[testing-env/0] in_session -> exiting_session',
1236
1055
  '[testing-env/0/session1] shell: "feature1" teardown session',
1237
1056
  '[testing-env/0/feature1] feature teardown session',
1238
1057
  "[testing-env/0] session 'session1' ended with SandboxStateError",
1239
- '[testing-env/0] in_session -> acquired',
1058
+ '[testing-env/0] exiting_session -> acquired',
1240
1059
  '[testing-env/0] acquired -> shutting_down',
1060
+ '[testing-env/0] shell: "feature1" teardown',
1241
1061
  '[testing-env/0/feature1] feature teardown',
1242
1062
  '[testing-env/0] shutting_down -> offline',
1243
- '[testing-env/0] sandbox shutdown'
1063
+ '[testing-env/0] sandbox shutdown',
1064
+ '[testing-env/0] shell: echo bar',
1244
1065
  ]
1245
1066
  )
1246
1067
 
@@ -1274,7 +1095,7 @@ class SandboxActivityTests(unittest.TestCase):
1274
1095
  env = TestingEnvironment(
1275
1096
  features={'test_feature': TestingFeature(housekeep_interval=0)},
1276
1097
  pool_size=1,
1277
- keepalive_interval=0,
1098
+ sandbox_keepalive_interval=0,
1278
1099
  )
1279
1100
  with env:
1280
1101
  with env.sandbox('session1') as sb:
@@ -1291,22 +1112,22 @@ class SandboxActivityTests(unittest.TestCase):
1291
1112
  pool_size=1,
1292
1113
  outage_grace_period=0,
1293
1114
  outage_retry_interval=0,
1294
- keepalive_interval=0,
1115
+ sandbox_keepalive_interval=0,
1295
1116
  )
1296
1117
  with env:
1297
1118
  with env.sandbox('session1') as sb:
1298
1119
  self.assertEqual(len(env.sandbox_pool), 1)
1299
1120
  self.assertEqual(sb.status, interface.Sandbox.Status.IN_SESSION)
1300
1121
  self.assertEqual(sb.session_id, 'session1')
1301
- housekeep_count = sb._housekeep_count
1122
+ housekeep_count = sb.housekeep_counter
1302
1123
  sb.test_feature.rebind(
1303
1124
  simulate_housekeep_error=interface.SandboxStateError,
1304
1125
  skip_notification=True
1305
1126
  )
1306
- while sb._housekeep_count == housekeep_count or (
1127
+ while sb.housekeep_counter == housekeep_count or (
1307
1128
  sb.status == interface.Sandbox.Status.IN_SESSION
1308
1129
  ):
1309
- time.sleep(0.1)
1130
+ time.sleep(0.01)
1310
1131
  self.assertEqual(sb.status, interface.Sandbox.Status.OFFLINE)
1311
1132
 
1312
1133
  def test_remove_event_handler(self):
@@ -1315,10 +1136,9 @@ class SandboxActivityTests(unittest.TestCase):
1315
1136
  pool_size=1,
1316
1137
  outage_grace_period=0,
1317
1138
  outage_retry_interval=0,
1318
- keepalive_interval=0,
1319
- stats_report_interval=1,
1139
+ sandbox_keepalive_interval=0,
1320
1140
  )
1321
- event_handler = TestingEnvironmentEventHandler()
1141
+ event_handler = TestingEventHandler()
1322
1142
  with env:
1323
1143
  with env.sandbox('session1') as sb:
1324
1144
  sb.add_event_handler(event_handler)
@@ -1336,32 +1156,32 @@ class SandboxServiceTests(unittest.TestCase):
1336
1156
  def setUp(self):
1337
1157
  super().setUp()
1338
1158
  self.maxDiff = None
1339
- self.event_handler = TestingEnvironmentEventHandler()
1159
+ self.event_handler = TestingEventHandler()
1340
1160
  self.env = TestingEnvironment(
1341
1161
  features={'test_feature': TestingFeature()},
1342
1162
  pool_size=0,
1343
1163
  outage_grace_period=0,
1344
1164
  outage_retry_interval=0,
1345
- keepalive_interval=0,
1165
+ sandbox_keepalive_interval=0,
1346
1166
  event_handlers=[self.event_handler],
1347
- stats_report_interval=1,
1348
1167
  random_seed=1,
1349
1168
  )
1350
1169
 
1351
1170
  def test_service_call_activity_log(self):
1352
1171
 
1353
- class CustomEventHandler(interface.EnvironmentEventHandler):
1172
+ class CustomEventHandler(event_handler_base.EventHandler):
1354
1173
 
1355
1174
  def __init__(self):
1356
1175
  self.calls = []
1357
1176
 
1358
- def on_session_activity(
1177
+ def on_sandbox_activity(
1359
1178
  self,
1360
- session_id: str,
1361
1179
  name: str,
1362
1180
  environment: interface.Environment,
1363
1181
  sandbox: interface.Sandbox,
1364
1182
  feature: interface.Feature | None,
1183
+ session_id: str | None,
1184
+ duration: float,
1365
1185
  error: BaseException | None,
1366
1186
  **kwargs: Any):
1367
1187
  self.calls.append((session_id, name, kwargs))
@@ -1379,9 +1199,11 @@ class SandboxServiceTests(unittest.TestCase):
1379
1199
  self.assertEqual(
1380
1200
  event_handler.calls,
1381
1201
  [
1202
+ (None, 'shell', {'code': '"test_feature" setup'}),
1382
1203
  ('session1', 'shell', {'code': '"test_feature" setup session'}),
1383
- ('session1', 'call_with_varargs', {'args': (1, 2), 'code': 'sum', 'debug': True}), # pylint: disable=line-too-long
1204
+ ('session1', 'test_feature.call_with_varargs', {'args': (1, 2), 'code': 'sum', 'debug': True}), # pylint: disable=line-too-long
1384
1205
  ('session1', 'shell', {'code': '"test_feature" teardown session'}),
1206
+ (None, 'shell', {'code': '"test_feature" teardown'}),
1385
1207
  ]
1386
1208
  )
1387
1209
 
@@ -1395,14 +1217,16 @@ class SandboxServiceTests(unittest.TestCase):
1395
1217
  [
1396
1218
  # pylint: disable=line-too-long
1397
1219
  '[testing-env] environment started',
1220
+ '[testing-env/0] shell: "test_feature" setup',
1398
1221
  '[testing-env/0/test_feature] feature setup',
1399
1222
  '[testing-env/0] sandbox started',
1400
1223
  '[testing-env/0/session1] shell: "test_feature" setup session',
1401
1224
  "[testing-env/0] session 'session1' started",
1402
- '[testing-env/0/session1] num_shell_calls: None',
1403
- '[testing-env/0/session1] num_shell_calls: None',
1225
+ '[testing-env/0/session1/test_feature] test_feature.num_shell_calls: None',
1226
+ '[testing-env/0/session1/test_feature] test_feature.num_shell_calls: None',
1404
1227
  '[testing-env/0/session1] shell: "test_feature" teardown session',
1405
1228
  "[testing-env/0] session 'session1' ended",
1229
+ '[testing-env/0] shell: "test_feature" teardown',
1406
1230
  '[testing-env/0/test_feature] feature teardown',
1407
1231
  '[testing-env/0] sandbox shutdown',
1408
1232
  '[testing-env] environment shutdown'
@@ -1422,16 +1246,18 @@ class SandboxServiceTests(unittest.TestCase):
1422
1246
  [
1423
1247
  # pylint: disable=line-too-long
1424
1248
  '[testing-env] environment started',
1249
+ '[testing-env/0] shell: "test_feature" setup',
1425
1250
  '[testing-env/0/test_feature] feature setup',
1426
1251
  '[testing-env/0] sandbox started',
1427
1252
  '[testing-env/0/session1] shell: "test_feature" setup session',
1428
1253
  "[testing-env/0] session 'session1' started",
1429
1254
  '[testing-env/0/session1] shell: bad command with RuntimeError',
1255
+ '[testing-env/0/session1/test_feature] test_feature.bad_shell_call: None with SandboxStateError',
1430
1256
  '[testing-env/0/session1] shell: "test_feature" teardown session',
1431
1257
  "[testing-env/0] session 'session1' ended with SandboxStateError",
1258
+ '[testing-env/0] shell: "test_feature" teardown',
1432
1259
  '[testing-env/0/test_feature] feature teardown',
1433
1260
  '[testing-env/0] sandbox shutdown',
1434
- '[testing-env/0/session1] bad_shell_call: None with SandboxStateError',
1435
1261
  '[testing-env] environment shutdown'
1436
1262
  # pylint: enable=line-too-long
1437
1263
  ]
@@ -1445,13 +1271,15 @@ class SandboxServiceTests(unittest.TestCase):
1445
1271
  [
1446
1272
  # pylint: disable=line-too-long
1447
1273
  '[testing-env] environment started',
1274
+ '[testing-env/0] shell: "test_feature" setup',
1448
1275
  '[testing-env/0/test_feature] feature setup',
1449
1276
  '[testing-env/0] sandbox started',
1450
1277
  '[testing-env/0/session-2291d8c] shell: "test_feature" setup session',
1451
1278
  "[testing-env/0] session 'session-2291d8c' started",
1452
- '[testing-env/0/session-2291d8c] num_shell_calls: None',
1279
+ '[testing-env/0/session-2291d8c/test_feature] test_feature.num_shell_calls: None',
1453
1280
  '[testing-env/0/session-2291d8c] shell: "test_feature" teardown session',
1454
1281
  "[testing-env/0] session 'session-2291d8c' ended",
1282
+ '[testing-env/0] shell: "test_feature" teardown',
1455
1283
  '[testing-env/0/test_feature] feature teardown',
1456
1284
  '[testing-env/0] sandbox shutdown',
1457
1285
  '[testing-env] environment shutdown'
@@ -1468,16 +1296,18 @@ class SandboxServiceTests(unittest.TestCase):
1468
1296
  [
1469
1297
  # pylint: disable=line-too-long
1470
1298
  '[testing-env] environment started',
1299
+ '[testing-env/0] shell: "test_feature" setup',
1471
1300
  '[testing-env/0/test_feature] feature setup',
1472
1301
  '[testing-env/0] sandbox started',
1473
1302
  '[testing-env/0/session1] shell: "test_feature" setup session',
1474
1303
  "[testing-env/0] session 'session1' started",
1475
1304
  '[testing-env/0/session1] shell: bad command with RuntimeError',
1305
+ '[testing-env/0/session1/test_feature] test_feature.bad_shell_call: None with SandboxStateError',
1476
1306
  '[testing-env/0/session1] shell: "test_feature" teardown session',
1477
1307
  "[testing-env/0] session 'session1' ended with SandboxStateError",
1308
+ '[testing-env/0] shell: "test_feature" teardown',
1478
1309
  '[testing-env/0/test_feature] feature teardown',
1479
1310
  '[testing-env/0] sandbox shutdown',
1480
- '[testing-env/0/session1] bad_shell_call: None with SandboxStateError',
1481
1311
  '[testing-env] environment shutdown'
1482
1312
  # pylint: enable=line-too-long
1483
1313
  ]
@@ -1495,15 +1325,17 @@ class SandboxServiceTests(unittest.TestCase):
1495
1325
  [
1496
1326
  # pylint: disable=line-too-long
1497
1327
  '[testing-env] environment started',
1328
+ '[testing-env/0] shell: "test_feature" setup',
1498
1329
  '[testing-env/0/test_feature] feature setup',
1499
1330
  '[testing-env/0] sandbox started',
1500
1331
  '[testing-env/0/session1] shell: "test_feature" setup session',
1501
1332
  "[testing-env/0] session 'session1' started",
1502
- '[testing-env/0/session1] my_service: None',
1503
1333
  '[testing-env/0/session1] shell: hello',
1334
+ '[testing-env/0/session1/test_feature] test_feature.my_service: None',
1504
1335
  '[testing-env/0/session1] shell: foo',
1505
1336
  '[testing-env/0/session1] shell: "test_feature" teardown session',
1506
1337
  "[testing-env/0] session 'session1' ended",
1338
+ '[testing-env/0] shell: "test_feature" teardown',
1507
1339
  '[testing-env/0/test_feature] feature teardown',
1508
1340
  '[testing-env/0] sandbox shutdown',
1509
1341
  '[testing-env] environment shutdown'
@@ -1523,14 +1355,16 @@ class SandboxServiceTests(unittest.TestCase):
1523
1355
  [
1524
1356
  # pylint: disable=line-too-long
1525
1357
  '[testing-env] environment started',
1358
+ '[testing-env/0] shell: "test_feature" setup',
1526
1359
  '[testing-env/0/test_feature] feature setup',
1527
1360
  '[testing-env/0] sandbox started',
1528
1361
  '[testing-env/0/session1] shell: "test_feature" setup session',
1529
1362
  "[testing-env/0] session 'session1' started",
1530
- '[testing-env/0/session1] my_service: None',
1531
1363
  '[testing-env/0/session1] shell: hello with SandboxStateError',
1364
+ '[testing-env/0/session1/test_feature] test_feature.my_service: None with SandboxStateError',
1532
1365
  '[testing-env/0/session1] shell: "test_feature" teardown session',
1533
1366
  "[testing-env/0] session 'session1' ended with SandboxStateError",
1367
+ '[testing-env/0] shell: "test_feature" teardown',
1534
1368
  '[testing-env/0/test_feature] feature teardown',
1535
1369
  '[testing-env/0] sandbox shutdown',
1536
1370
  '[testing-env] environment shutdown'
@@ -1549,24 +1383,28 @@ class SandboxServiceTests(unittest.TestCase):
1549
1383
  [
1550
1384
  # pylint: disable=line-too-long
1551
1385
  '[testing-env] environment started',
1386
+ '[testing-env/0] shell: "test_feature" setup',
1552
1387
  '[testing-env/0/test_feature] feature setup',
1553
1388
  '[testing-env/0] sandbox started',
1554
1389
  '[testing-env/0/session1] shell: "test_feature" setup session',
1555
1390
  "[testing-env/0] session 'session1' started",
1556
- '[testing-env/0/session1] my_service: None',
1557
1391
  '[testing-env/0/session1] shell: foo',
1392
+ '[testing-env/0/session1/test_feature] test_feature.my_service: None',
1558
1393
  '[testing-env/0/session1] shell: "test_feature" teardown session',
1559
1394
  "[testing-env/0] session 'session1' ended",
1395
+ '[testing-env/0] shell: "test_feature" teardown',
1560
1396
  '[testing-env/0/test_feature] feature teardown',
1561
1397
  '[testing-env/0] sandbox shutdown',
1398
+ '[testing-env/1] shell: "test_feature" setup',
1562
1399
  '[testing-env/1/test_feature] feature setup',
1563
1400
  '[testing-env/1] sandbox started',
1564
1401
  '[testing-env/1/session-2291d8c] shell: "test_feature" setup session',
1565
1402
  "[testing-env/1] session 'session-2291d8c' started",
1566
- '[testing-env/1/session-2291d8c] my_service: None',
1567
1403
  '[testing-env/1/session-2291d8c] shell: bar',
1404
+ '[testing-env/1/session-2291d8c/test_feature] test_feature.my_service: None',
1568
1405
  '[testing-env/1/session-2291d8c] shell: "test_feature" teardown session',
1569
1406
  "[testing-env/1] session 'session-2291d8c' ended",
1407
+ '[testing-env/1] shell: "test_feature" teardown',
1570
1408
  '[testing-env/1/test_feature] feature teardown',
1571
1409
  '[testing-env/1] sandbox shutdown',
1572
1410
  '[testing-env] environment shutdown'
@@ -1584,14 +1422,16 @@ class SandboxServiceTests(unittest.TestCase):
1584
1422
  [
1585
1423
  # pylint: disable=line-too-long
1586
1424
  '[testing-env] environment started',
1425
+ '[testing-env/0] shell: "test_feature" setup',
1587
1426
  '[testing-env/0/test_feature] feature setup',
1588
1427
  '[testing-env/0] sandbox started',
1589
1428
  '[testing-env/0/session-2291d8c] shell: "test_feature" setup session',
1590
1429
  "[testing-env/0] session 'session-2291d8c' started",
1591
- '[testing-env/0/session-2291d8c] my_service: None',
1592
1430
  '[testing-env/0/session-2291d8c] shell: hello with SandboxStateError',
1431
+ '[testing-env/0/session-2291d8c/test_feature] test_feature.my_service: None with SandboxStateError',
1593
1432
  '[testing-env/0/session-2291d8c] shell: "test_feature" teardown session',
1594
1433
  "[testing-env/0] session 'session-2291d8c' ended with SandboxStateError",
1434
+ '[testing-env/0] shell: "test_feature" teardown',
1595
1435
  '[testing-env/0/test_feature] feature teardown',
1596
1436
  '[testing-env/0] sandbox shutdown',
1597
1437
  '[testing-env] environment shutdown'