1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
"""Reading `.config/nextest.toml` as the runner reads it.
The configuration is parsed as TOML rather than scraped. A text match
finds a ``slow-timeout`` inside a comment, inside a ``filter`` string,
or in a table nextest never consults; a commented-out ``global-timeout``
would keep reading as the budget in force long after the tier had been
switched off.
The reading that matters most is the per-test one. nextest warns once
per ``period`` and terminates after ``terminate-after`` of them, so the
budget is their product, and a ``slow-timeout`` naming no
``terminate-after`` never terminates anything at all. That form is
refused rather than read as a single period.
"""
"""Return the nextest configuration as TOML.
Parsing rather than scraping is the whole point of this reader. A
text match finds a ``slow-timeout`` inside a comment, inside a
``filter`` string, or in a table nextest never consults, and reports
a budget the runner does not use. A commented-out
``global-timeout`` is the case that matters most here: the guide and
this contract would both go on recording a tier that had been
switched off.
Parameters
----------
config_text : str
The nextest configuration file's text.
Returns
-------
dict[str, object]
The parsed document.
Raises
------
NextestConfigurationError
If the text is not valid TOML.
"""
return
= f
"""Return every table nextest reads a per-test budget from.
A profile's own table and each of its ``[[overrides]]`` entries,
each with the path that names it, so a failure can say which one is
at fault.
Parameters
----------
config : dict[str, object]
The parsed configuration.
Returns
-------
list of tuple
The dotted path and the table, in file order.
"""
: =
=
return
"""Return every ``slow-timeout`` the configuration declares.
Parameters
----------
config : dict[str, object]
The parsed configuration.
Returns
-------
list of tuple
The dotted path of the declaring table and the value.
"""
return
"""Return one ``slow-timeout`` table's per-test budget, in seconds.
Parameters
----------
path : str
The dotted path of the declaring table, for the message.
table : dict[str, object]
The parsed ``slow-timeout`` table.
Returns
-------
Fraction
The period multiplied by ``terminate-after``, exactly.
Raises
------
NextestConfigurationError
If the table names no ``period``.
UnboundedTestError
If the table names no ``terminate-after``, so nextest warns
about a slow test forever and never stops it.
"""
=
= f
=
=
return *
"""Return the per-test budget one ``slow-timeout`` value declares.
Parameters
----------
path : str
The dotted path of the declaring table, for the message.
value : object
The parsed value, a table or a bare duration.
Returns
-------
Fraction
The budget in seconds, exactly.
Raises
------
UnboundedTestError
If the value is a bare duration. That form sets a warning period
with no ``terminate-after``, so no test is ever terminated by it.
NextestConfigurationError
If the value is neither a table nor a string.
"""
:
:
return
:
=
:
= f
"""Return the longest a single test may run, in seconds.
nextest warns once per ``period`` and terminates after
``terminate-after`` of them, so the budget is their product.
Parameters
----------
config_text : str
The nextest configuration file's text.
Returns
-------
Fraction
The longest per-test budget, period multiplied by
``terminate-after``, exactly.
Raises
------
NextestConfigurationError
If the configuration declares no ``slow-timeout`` at all.
UnboundedTestError
If any ``slow-timeout`` terminates no test.
"""
=
=
=
return
"""Return whether a profile's own table terminates a slow test.
Only the profile's own ``slow-timeout`` counts. An override bounds
the tests its filter matches; the profile's own bounds the rest, so
a profile whose only ``terminate-after`` sits in an override leaves
every unmatched test running with no bound at all while
:func:`largest_test_allowance` still reports a comfortable number.
Parameters
----------
config_text
The nextest configuration file's text.
profile
The profile to read.
Returns
-------
bool
True when that profile's own ``slow-timeout`` is a table setting
``terminate-after``.
"""
=
=
=
return and is not None
"""Return the grace period one ``slow-timeout`` value puts in force.
``grace-period`` is a field of the ``slow-timeout`` setting rather
than a setting of its own, and nextest defaults it per declaration:
a table that omits it gets ten seconds, not the value some other
table names. A reader that skipped such a table would report five
seconds for a file whose override actually allows ten.
Absent and present-but-not-a-string are different states. nextest
deserializes the field through ``humantime_serde``, which takes a
string, so ``grace-period = 10`` is a configuration error there and
the file does not load at all. Folding that into the default would
let this reader report a budget for a configuration no run could
use.
Parameters
----------
path : str
The dotted path of the declaring table, for the message.
value : object
The parsed ``slow-timeout`` value.
Returns
-------
Fraction or None
The grace period this declaration puts in force, or None when
the value is not a table and so declares no termination window.
Raises
------
NextestConfigurationError
If ``grace-period`` is present and is not a duration string.
"""
return None
=
:
as:
return
:
=
:
return
"""Return the longest grace period the configuration puts in force.
Read from the configuration rather than fixed, so a profile that
raised its grace period raises the requirement too. Every
``slow-timeout`` table counts, including one that omits the field:
nextest gives that table its own ten-second default rather than
another table's value, so a file naming 5 s in one place and nothing
in another allows ten seconds, not five.
Parameters
----------
config_text : str
The nextest configuration file's text.
Returns
-------
Fraction
The largest grace period in force, or nextest's default when the
configuration declares no ``slow-timeout`` table at all.
Raises
------
NextestConfigurationError
If a ``slow-timeout`` table names a ``grace-period`` that is not
a duration string, which nextest itself refuses to load.
"""
=
return
"""Return the time nextest may take to stop the run, in seconds.
Two terms, not one: what nextest promises a test after ``SIGTERM``,
plus a margin for the teardown and report writing that follow it.
A single floor over the two would make a raised grace period look
free right up to the run it cancelled, since every value below the
margin would vanish into it.
Parameters
----------
config_text : str
The nextest configuration file's text.
Returns
-------
Fraction
The grace period plus the safety margin.
"""
return +
"""Return the whole-run budget, or None when none is set.
Read from ``[profile.default]`` alone. nextest's other profiles
inherit that table unless they override it, and this repository runs
the default profile, so a value elsewhere is not the budget in
force. An ``[[overrides]]`` entry cannot carry one at all, and a
reader that took one from there would report a tier nextest ignores.
Parameters
----------
config_text : str
The nextest configuration file's text.
Returns
-------
Fraction or None
The whole-run budget in seconds, or None when the default
profile declares none.
"""
=
=
return