Viewing files at commit 3cd2661fdbe9Commit detailsView latest

Browse files
tests/test_publish_gate.py 579 lines · 26.6 KB · python
1
"""Tests for the pre-publish gate's mechanical checks."""
2
3
from __future__ import annotations
4
5
import contextlib
6
import io
7
import json
8
import sys
9
import tempfile
10
import unittest
11
from pathlib import Path
12
13
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
14
15
import publish_gate
16
17
18
OAK_SOURCE = {"source": {"oak_hash": "abc123", "oak_status": ""}}
19
ENV_ISOLATION = {"env_isolation_version": "1"}
20
21
22
def write_rows(directory: Path, name: str, rows: list[dict]) -> Path:
23
    path = directory / name
24
    path.write_text("\n".join(json.dumps(row) for row in rows) + "\n")
25
    return path
26
27
28
class GateTest(unittest.TestCase):
29
    def test_mixed_transport_operation_fails(self) -> None:
30
        with tempfile.TemporaryDirectory() as tmp:
31
            path = write_rows(
32
                Path(tmp),
33
                "rows.jsonl",
34
                [
35
                    {"subject": "oak", "operation": "x.push", "returncode": 0, "remote_transport": "network", **OAK_SOURCE},
36
                    {"subject": "oak", "operation": "x.push", "returncode": 0, "remote_transport": "local_file", **OAK_SOURCE},
37
                ],
38
            )
39
            self.assertEqual(publish_gate.main([str(path)]), 1)
40
41
    def test_side_by_side_subjects_may_use_different_transports(self) -> None:
42
        with tempfile.TemporaryDirectory() as tmp:
43
            path = write_rows(
44
                Path(tmp),
45
                "rows.jsonl",
46
                [
47
                    {"subject": "oak", "operation": "x.acquire", "returncode": 0, "remote_transport": "network", **OAK_SOURCE},
48
                    {"subject": "git", "operation": "x.acquire", "returncode": 0, "remote_transport": "local_file"},
49
                ],
50
            )
51
            self.assertEqual(publish_gate.main([str(path)]), 0)
52
53
    def test_null_returncode_row_is_treated_as_failure_not_a_crash(self) -> None:
54
        with tempfile.TemporaryDirectory() as tmp:
55
            path = write_rows(
56
                Path(tmp),
57
                "rows.jsonl",
58
                [
59
                    # Emitters may record returncode: null (unmeasured); the
60
                    # gate must treat it as a failure, never raise TypeError.
61
                    {"subject": "git", "operation": "status.clean", "returncode": None},
62
                    {"subject": "git", "operation": "x.push", "returncode": 0, "remote_transport": "local_file"},
63
                ],
64
            )
65
            with contextlib.redirect_stdout(io.StringIO()):
66
                code = publish_gate.main([str(path)])
67
            self.assertEqual(code, 0)
68
69
    def test_null_returncode_public_core_row_counts_as_failed_operation(self) -> None:
70
        with tempfile.TemporaryDirectory() as tmp:
71
            path = write_rows(
72
                Path(tmp),
73
                "rows.jsonl",
74
                [
75
                    {
76
                        "profile": "standard",
77
                        "subject": "git",
78
                        "scenario": "tiny_text_100",
79
                        "operation": "status.clean",
80
                        "run": 0,
81
                        "returncode": None,
82
                        "randomized_subject_order": True,
83
                        "subject_order": ["git"],
84
                    }
85
                ],
86
            )
87
            stdout = io.StringIO()
88
            with contextlib.redirect_stdout(stdout):
89
                code = publish_gate.main([str(path)])
90
            self.assertEqual(code, 1)
91
            self.assertIn("failed operations", stdout.getvalue())
92
93
    def test_remote_row_without_transport_fails(self) -> None:
94
        with tempfile.TemporaryDirectory() as tmp:
95
            path = write_rows(
96
                Path(tmp),
97
                "rows.jsonl",
98
                [
99
                    {
100
                        "subject": "oak",
101
                        "operation": "x.push",
102
                        "returncode": 0,
103
                        "remote_repo": "oak/bench-tmp",
104
                        "remote_server": "oak.space",
105
                        **OAK_SOURCE,
106
                    }
107
                ],
108
            )
109
            self.assertEqual(publish_gate.main([str(path)]), 1)
110
111
    def test_dirty_oak_source_fails(self) -> None:
112
        with tempfile.TemporaryDirectory() as tmp:
113
            path = write_rows(
114
                Path(tmp),
115
                "rows.jsonl",
116
                [
117
                    {
118
                        "subject": "oak_main",
119
                        "subject_kind": "oak",
120
                        "operation": "status.clean",
121
                        "returncode": 0,
122
                        "source": {"oak_hash": "abc123", "oak_status": "M cli/src/main.rs"},
123
                    }
124
                ],
125
            )
126
            self.assertEqual(publish_gate.main([str(path)]), 1)
127
128
    def test_missing_oak_source_hash_fails(self) -> None:
129
        with tempfile.TemporaryDirectory() as tmp:
130
            path = write_rows(
131
                Path(tmp),
132
                "rows.jsonl",
133
                [
134
                    {
135
                        "subject": "oak_main",
136
                        "subject_kind": "oak",
137
                        "operation": "status.clean",
138
                        "returncode": 0,
139
                    }
140
                ],
141
            )
142
            self.assertEqual(publish_gate.main([str(path)]), 1)
143
144
    def test_core_public_cells_require_randomized_n30(self) -> None:
145
        with tempfile.TemporaryDirectory() as tmp:
146
            rows = []
147
            for run in range(29):
148
                for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
149
                    rows.append(
150
                        {
151
                            "profile": "standard",
152
                            "subject": subject,
153
                            "subject_kind": "oak" if subject == "oak_main" else "git",
154
                            "scenario": "tiny_text_100",
155
                            "operation": "status.clean",
156
                            "run": run,
157
                            "returncode": 0,
158
                            "randomized_subject_order": True,
159
                            "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
160
                            **(OAK_SOURCE if subject == "oak_main" else {}),
161
                        }
162
                    )
163
            path = write_rows(Path(tmp), "rows.jsonl", rows)
164
            self.assertEqual(publish_gate.main([str(path)]), 1)
165
166
    def test_core_public_cells_pass_with_randomized_n30(self) -> None:
167
        with tempfile.TemporaryDirectory() as tmp:
168
            rows = []
169
            for run in range(30):
170
                for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
171
                    rows.append(
172
                        {
173
                            "profile": "standard",
174
                            "subject": subject,
175
                            "subject_kind": "oak" if subject == "oak_main" else "git",
176
                            "scenario": "tiny_text_100",
177
                            "operation": "status.clean",
178
                            "run": run,
179
                            "returncode": 0,
180
                            "randomized_subject_order": True,
181
                            "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
182
                            **ENV_ISOLATION,
183
                            **(OAK_SOURCE if subject == "oak_main" else {}),
184
                        }
185
                    )
186
            path = write_rows(Path(tmp), "rows.jsonl", rows)
187
            self.assertEqual(publish_gate.main([str(path)]), 0)
188
189
    def test_public_core_rows_reject_weak_content_trust_sources(self) -> None:
190
        weak_sources = [
191
            ("mixed_payload_sources", ["git_head_payload_sha256", "git_lfs_worktree_payload_sha256"]),
192
            ("worktree_payload_sha256", ["worktree_payload_sha256"]),
193
            ("git_lfs_worktree_payload_sha256", ["git_lfs_worktree_payload_sha256"]),
194
        ]
195
        for source, sources in weak_sources:
196
            with self.subTest(source=source):
197
                with tempfile.TemporaryDirectory() as tmp:
198
                    rows = []
199
                    for run in range(30):
200
                        for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
201
                            content_fields = (
202
                                {
203
                                    "content_integrity_check_passed": True,
204
                                    "content_integrity_source": source,
205
                                    "content_integrity_sources": sources,
206
                                    "content_integrity_public_trust_passed": False,
207
                                }
208
                                if subject == "oak_main"
209
                                else {}
210
                            )
211
                            rows.append(
212
                                {
213
                                    "profile": "standard",
214
                                    "subject": subject,
215
                                    "subject_kind": "oak" if subject == "oak_main" else "git",
216
                                    "scenario": "tiny_text_100",
217
                                    "operation": "status.clean",
218
                                    "run": run,
219
                                    "returncode": 0,
220
                                    "randomized_subject_order": True,
221
                                    "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
222
                                    **ENV_ISOLATION,
223
                                    **content_fields,
224
                                    **(OAK_SOURCE if subject == "oak_main" else {}),
225
                                }
226
                            )
227
                    path = write_rows(Path(tmp), "rows.jsonl", rows)
228
                    stdout = io.StringIO()
229
                    with contextlib.redirect_stdout(stdout):
230
                        code = publish_gate.main([str(path)])
231
                    self.assertEqual(code, 1)
232
                    self.assertIn("content-trust", stdout.getvalue())
233
234
    def test_public_core_rows_accept_strong_content_trust_source(self) -> None:
235
        with tempfile.TemporaryDirectory() as tmp:
236
            rows = []
237
            for run in range(30):
238
                for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
239
                    content_fields = (
240
                        {
241
                            "content_integrity_check_passed": True,
242
                            "content_integrity_source": "git_head_payload_sha256",
243
                            "content_integrity_sources": ["git_head_payload_sha256"],
244
                            "content_integrity_public_trust_passed": True,
245
                        }
246
                        if subject == "oak_main"
247
                        else {}
248
                    )
249
                    rows.append(
250
                        {
251
                            "profile": "standard",
252
                            "subject": subject,
253
                            "subject_kind": "oak" if subject == "oak_main" else "git",
254
                            "scenario": "tiny_text_100",
255
                            "operation": "status.clean",
256
                            "run": run,
257
                            "returncode": 0,
258
                            "randomized_subject_order": True,
259
                            "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
260
                            **ENV_ISOLATION,
261
                            **content_fields,
262
                            **(OAK_SOURCE if subject == "oak_main" else {}),
263
                        }
264
                    )
265
            path = write_rows(Path(tmp), "rows.jsonl", rows)
266
            self.assertEqual(publish_gate.main([str(path)]), 0)
267
268
    def test_public_core_rows_require_env_isolation_version(self) -> None:
269
        with tempfile.TemporaryDirectory() as tmp:
270
            rows = []
271
            for run in range(30):
272
                for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
273
                    rows.append(
274
                        {
275
                            "profile": "standard",
276
                            "subject": subject,
277
                            "subject_kind": "oak" if subject == "oak_main" else "git",
278
                            "scenario": "tiny_text_100",
279
                            "operation": "status.clean",
280
                            "run": run,
281
                            "returncode": 0,
282
                            "randomized_subject_order": True,
283
                            "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
284
                            **(OAK_SOURCE if subject == "oak_main" else {}),
285
                        }
286
                    )
287
            path = write_rows(Path(tmp), "rows.jsonl", rows)
288
            stdout = io.StringIO()
289
            with contextlib.redirect_stdout(stdout):
290
                code = publish_gate.main([str(path)])
291
            self.assertEqual(code, 1)
292
            self.assertIn("env-isolation", stdout.getvalue())
293
294
    def test_public_core_rows_reject_mixed_env_isolation_versions(self) -> None:
295
        with tempfile.TemporaryDirectory() as tmp:
296
            rows = []
297
            for run in range(30):
298
                for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
299
                    rows.append(
300
                        {
301
                            "profile": "standard",
302
                            "subject": subject,
303
                            "subject_kind": "oak" if subject == "oak_main" else "git",
304
                            "scenario": "tiny_text_100",
305
                            "operation": "status.clean",
306
                            "run": run,
307
                            "returncode": 0,
308
                            "randomized_subject_order": True,
309
                            "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
310
                            "env_isolation_version": "2" if subject == "oak_main" else "1",
311
                            **(OAK_SOURCE if subject == "oak_main" else {}),
312
                        }
313
                    )
314
            path = write_rows(Path(tmp), "rows.jsonl", rows)
315
            stdout = io.StringIO()
316
            with contextlib.redirect_stdout(stdout):
317
                code = publish_gate.main([str(path)])
318
            self.assertEqual(code, 1)
319
            self.assertIn("mix env_isolation_version", stdout.getvalue())
320
321
    def test_public_core_failed_operation_fails_gate(self) -> None:
322
        with tempfile.TemporaryDirectory() as tmp:
323
            rows = []
324
            for run in range(30):
325
                for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
326
                    rows.append(
327
                        {
328
                            "profile": "standard",
329
                            "subject": subject,
330
                            "subject_kind": "oak" if subject == "oak_main" else "git",
331
                            "scenario": "tiny_text_100",
332
                            "operation": "status.clean",
333
                            "run": run,
334
                            "returncode": 1 if subject == "oak_main" and run == 0 else 0,
335
                            "randomized_subject_order": True,
336
                            "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
337
                            **(OAK_SOURCE if subject == "oak_main" else {}),
338
                        }
339
                    )
340
            path = write_rows(Path(tmp), "rows.jsonl", rows)
341
            self.assertEqual(publish_gate.main([str(path)]), 1)
342
343
    def test_public_core_zero_success_group_fails_gate(self) -> None:
344
        with tempfile.TemporaryDirectory() as tmp:
345
            rows = []
346
            for run in range(30):
347
                for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
348
                    rows.append(
349
                        {
350
                            "profile": "standard",
351
                            "subject": subject,
352
                            "subject_kind": "oak" if subject == "oak_main" else "git",
353
                            "scenario": "tiny_text_100",
354
                            "operation": "status.clean",
355
                            "run": run,
356
                            "returncode": 1 if subject == "oak_main" else 0,
357
                            "randomized_subject_order": True,
358
                            "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
359
                            **(OAK_SOURCE if subject == "oak_main" else {}),
360
                        }
361
                    )
362
            path = write_rows(Path(tmp), "rows.jsonl", rows)
363
            self.assertEqual(publish_gate.main([str(path)]), 1)
364
365
    def test_tuned_git_setup_failure_fails_gate(self) -> None:
366
        with tempfile.TemporaryDirectory() as tmp:
367
            rows = []
368
            for run in range(30):
369
                for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
370
                    rows.append(
371
                        {
372
                            "profile": "standard",
373
                            "subject": subject,
374
                            "subject_kind": "oak" if subject == "oak_main" else "git",
375
                            "scenario": "tiny_text_100",
376
                            "operation": "status.clean",
377
                            "run": run,
378
                            "returncode": 0,
379
                            "randomized_subject_order": True,
380
                            "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
381
                            **(OAK_SOURCE if subject == "oak_main" else {}),
382
                        }
383
                    )
384
            rows.append(
385
                {
386
                    "profile": "standard",
387
                    "subject": "git_fsmonitor",
388
                    "subject_kind": "git",
389
                    "scenario": "tiny_text_100",
390
                    "operation": "mode.setup.fsmonitor",
391
                    "run": 0,
392
                    "returncode": 1,
393
                    "randomized_subject_order": True,
394
                    "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
395
                }
396
            )
397
            path = write_rows(Path(tmp), "rows.jsonl", rows)
398
            self.assertEqual(publish_gate.main([str(path)]), 1)
399
400
    def test_tuned_lfs_setup_failure_fails_gate(self) -> None:
401
        # Mirrors the fsmonitor case: a nonzero mode.setup.lfs_* row means the
402
        # git_lfs subject silently measured stock git, so nothing publishes.
403
        for setup_operation in ("mode.setup.lfs_install", "mode.setup.lfs_track"):
404
            with tempfile.TemporaryDirectory() as tmp:
405
                rows = []
406
                for run in range(30):
407
                    for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
408
                        rows.append(
409
                            {
410
                                "profile": "standard",
411
                                "subject": subject,
412
                                "subject_kind": "oak" if subject == "oak_main" else "git",
413
                                "scenario": "tiny_text_100",
414
                                "operation": "status.clean",
415
                                "run": run,
416
                                "returncode": 0,
417
                                "randomized_subject_order": True,
418
                                "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
419
                                **(OAK_SOURCE if subject == "oak_main" else {}),
420
                            }
421
                        )
422
                rows.append(
423
                    {
424
                        "profile": "standard",
425
                        "subject": "git_lfs",
426
                        "subject_kind": "git",
427
                        "scenario": "single_large_binary",
428
                        "operation": setup_operation,
429
                        "run": 0,
430
                        "returncode": 1,
431
                        "randomized_subject_order": True,
432
                        "subject_order": ["git", "git_lfs"],
433
                    }
434
                )
435
                path = write_rows(Path(tmp), "rows.jsonl", rows)
436
                with contextlib.redirect_stdout(io.StringIO()):
437
                    code = publish_gate.main([str(path)])
438
                self.assertEqual(code, 1, setup_operation)
439
440
    def test_missing_git_lfs_rows_do_not_fail_gate(self) -> None:
441
        # git_lfs only applies to binary-fixture scenarios on hosts with
442
        # git-lfs installed; absence is an honest gap, not a gate failure.
443
        self.assertNotIn("git_lfs", publish_gate.REQUIRED_TUNED_GIT_SUBJECTS)
444
        self.assertIn("git_lfs", publish_gate.TUNED_GIT_SUBJECTS)
445
446
    def test_core_public_cells_require_randomization_metadata(self) -> None:
447
        with tempfile.TemporaryDirectory() as tmp:
448
            rows = []
449
            for run in range(30):
450
                for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
451
                    rows.append(
452
                        {
453
                            "profile": "standard",
454
                            "subject": subject,
455
                            "subject_kind": "oak" if subject == "oak_main" else "git",
456
                            "scenario": "tiny_text_100",
457
                            "operation": "status.clean",
458
                            "run": run,
459
                            "returncode": 0,
460
                            "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
461
                            **(OAK_SOURCE if subject == "oak_main" else {}),
462
                        }
463
                    )
464
            path = write_rows(Path(tmp), "rows.jsonl", rows)
465
            self.assertEqual(publish_gate.main([str(path)]), 1)
466
467
    def test_public_core_rows_randomized_false_fails(self) -> None:
468
        with tempfile.TemporaryDirectory() as tmp:
469
            rows = []
470
            for run in range(30):
471
                for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
472
                    rows.append(
473
                        {
474
                            "profile": "standard",
475
                            "subject": subject,
476
                            "subject_kind": "oak" if subject == "oak_main" else "git",
477
                            "scenario": "tiny_text_100",
478
                            "operation": "status.clean",
479
                            "run": run,
480
                            "returncode": 0,
481
                            "randomized_subject_order": False,
482
                            "subject_order": ["git", "git_untracked_cache", "git_fsmonitor", "oak_main"],
483
                            **(OAK_SOURCE if subject == "oak_main" else {}),
484
                        }
485
                    )
486
            path = write_rows(Path(tmp), "rows.jsonl", rows)
487
            self.assertEqual(publish_gate.main([str(path)]), 1)
488
489
    def test_randomized_core_public_cells_require_subject_order(self) -> None:
490
        with tempfile.TemporaryDirectory() as tmp:
491
            rows = []
492
            for run in range(30):
493
                for subject in ("git", "git_untracked_cache", "git_fsmonitor", "oak_main"):
494
                    rows.append(
495
                        {
496
                            "profile": "standard",
497
                            "subject": subject,
498
                            "subject_kind": "oak" if subject == "oak_main" else "git",
499
                            "scenario": "tiny_text_100",
500
                            "operation": "status.clean",
501
                            "run": run,
502
                            "returncode": 0,
503
                            "randomized_subject_order": True,
504
                            **(OAK_SOURCE if subject == "oak_main" else {}),
505
                        }
506
                    )
507
            path = write_rows(Path(tmp), "rows.jsonl", rows)
508
            self.assertEqual(publish_gate.main([str(path)]), 1)
509
510
    def test_skip_without_reason_fails(self) -> None:
511
        with tempfile.TemporaryDirectory() as tmp:
512
            path = write_rows(
513
                Path(tmp), "rows.jsonl", [{"operation": "x", "returncode": 77}]
514
            )
515
            self.assertEqual(publish_gate.main([str(path)]), 1)
516
517
    def test_clean_rows_pass(self) -> None:
518
        with tempfile.TemporaryDirectory() as tmp:
519
            path = write_rows(
520
                Path(tmp),
521
                "rows.jsonl",
522
                [
523
                    {"operation": "x.push", "returncode": 0, "remote_transport": "network"},
524
                    {"operation": "x", "returncode": 77, "skip_reason": "set FOO"},
525
                ],
526
            )
527
            self.assertEqual(publish_gate.main([str(path)]), 0)
528
529
    def test_fake_provider_rows_are_never_publishable(self) -> None:
530
        with tempfile.TemporaryDirectory() as tmp:
531
            path = write_rows(
532
                Path(tmp),
533
                "rows.jsonl",
534
                [
535
                    {
536
                        "profile": "platform",
537
                        "benchmark_track": "platform-hosted",
538
                        "scenario": "branch_triage_n4",
539
                        "operation": "triage.total",
540
                        "platform": "github",
541
                        "driver": "fake-provider",
542
                        "branch_triage_provider": "fake",
543
                        "returncode": 0,
544
                    }
545
                ],
546
            )
547
            stdout = io.StringIO()
548
            with contextlib.redirect_stdout(stdout):
549
                code = publish_gate.main([str(path)])
550
            self.assertEqual(code, 1)
551
            self.assertIn("fake-provider", stdout.getvalue())
552
553
    def test_mixed_instruction_levels_in_one_file_fail(self) -> None:
554
        with tempfile.TemporaryDirectory() as tmp:
555
            path = write_rows(
556
                Path(tmp),
557
                "rows.jsonl",
558
                [
559
                    {"operation": "agent.workflow", "returncode": 0, "instruction_level": "zero-shot"},
560
                    {"operation": "agent.workflow", "returncode": 0, "instruction_level": "cheat-sheet"},
561
                ],
562
            )
563
            self.assertEqual(publish_gate.main([str(path)]), 1)
564
565
    def test_mixed_benchmark_tracks_in_one_file_fail(self) -> None:
566
        with tempfile.TemporaryDirectory() as tmp:
567
            path = write_rows(
568
                Path(tmp),
569
                "rows.jsonl",
570
                [
571
                    {"operation": "agent.workflow", "returncode": 0, "benchmark_track": "agent-default"},
572
                    {"operation": "agent.workflow", "returncode": 0, "benchmark_track": "core-equivalent"},
573
                ],
574
            )
575
            self.assertEqual(publish_gate.main([str(path)]), 1)
576
577
578
if __name__ == "__main__":
579
    unittest.main()