import copy import itertools import os from pathlib import Path import re import sys import tempfile import unittest from unittest import mock ROOT = Path(__file__).resolve().parents[1] APP_DIR = ROOT / 'app' sys.path.insert(0, str(APP_DIR)) import docker_depth_experiment as depth import scanner_db from scanner_db import ScanEventConflictError, ScannerDB QUERIES = tuple(f'cohort-query-{index:02d}' for index in range(61)) CONFIG_SHA256 = 'a' * 64 POLICY_SHA256 = 'b' * 64 PLAN_SHA256 = 'c' * 64 HOLD_SHA256 = 'd' * 64 def experiment_config(enabled=False): config = { 'global': { 'database_url': 'postgresql://example.invalid/truf', 'sync_file_queues': False, }, 'sources': {'dockerhub': { 'mode': 'search', 'require_digest': True, 'queries': list(QUERIES), 'docker_platform_candidate_tags': 20, 'docker_images_per_repository': 3, 'docker_depth_experiment': { 'experiment_key': 'cohort-hold-test-v1', 'enabled': enabled, 'queries': list(QUERIES), 'repositories_per_query': 10, 'shallow_images_per_repository': 1, 'deep_repositories_per_query': 1, 'deep_images_per_repository': 10, 'target_limit': 1200, 'selector_version': depth.DOCKER_DEPTH_SELECTOR_VERSION, }, }}, } return depth.validate_docker_depth_config(config).experiment def breadth_experiment_config(enabled=False): config = { 'global': { 'database_url': 'postgresql://example.invalid/truf', 'sync_file_queues': False, }, 'sources': {'dockerhub': { 'mode': 'search', 'require_digest': True, 'queries': list(QUERIES), 'docker_platform_candidate_tags': 20, 'docker_images_per_repository': 3, 'docker_depth_experiment': { 'experiment_key': 'rank1-breadth-test-v1', 'enabled': enabled, 'queries': list(QUERIES), 'repositories_per_query': 39, 'shallow_images_per_repository': 1, 'deep_repositories_per_query': 1, 'deep_images_per_repository': 1, 'target_limit': 2000, 'selector_version': depth.DOCKER_RANK1_BREADTH_SELECTOR_VERSION, }, }}, } return depth.validate_docker_depth_config(config).experiment def cohort_candidates(reverse=False): candidates = {} for query_ordinal, query in enumerate(QUERIES): rows = [ { 'repository_queue_id': query_ordinal * 100 + index + 1, 'eligibility_page_id': query_ordinal * 100 + index + 10001, 'best_search_rank': index + 1, 'valid_distinct_graph_count': 20 if index == 6 else index % 3, } for index in range(12) ] candidates[query] = list(reversed(rows)) if reverse else rows return dict(reversed(list(candidates.items()))) if reverse else candidates class SQLitePostgresShape: """Execute PostgreSQL locking shapes against SQLite for focused unit tests.""" is_postgres = True is_sqlite = False def __init__(self, connection): self.connection = connection def execute(self, sql, params=None): sql = re.sub( r'\s+FOR UPDATE(?:\s+OF\s+[a-z0-9_,.\s]+)?\s*$', '', str(sql).strip(), flags=re.IGNORECASE, ) return self.connection.execute(sql, params) def commit(self): return self.connection.commit() def rollback(self): return self.connection.rollback() def __getattr__(self, name): return getattr(self.connection, name) class DockerDepthCohortUnitTests(unittest.TestCase): def test_plan_is_deterministic_ranked_and_round_robin(self): experiment = experiment_config() first = depth.build_docker_depth_cohort_plan( experiment, POLICY_SHA256, cohort_candidates(), ) second = depth.build_docker_depth_cohort_plan( experiment, POLICY_SHA256, cohort_candidates(reverse=True), ) self.assertEqual(first, second) self.assertEqual( depth.canonical_docker_depth_plan_hash(first), depth.canonical_docker_depth_plan_hash(second), ) first_manifest = depth.build_docker_depth_cohort_manifest( experiment, POLICY_SHA256, cohort_candidates(), ) second_manifest = depth.build_docker_depth_cohort_manifest( experiment, POLICY_SHA256, cohort_candidates(reverse=True), ) self.assertEqual(first_manifest, second_manifest) self.assertEqual( depth.validate_docker_depth_cohort_manifest( first_manifest, experiment, POLICY_SHA256, )[1], depth.validate_docker_depth_cohort_manifest( second_manifest, experiment, POLICY_SHA256, )[1], ) self.assertEqual(len(first['queries']), 61) self.assertEqual(len(first['repository_round_robin']), 610) for query_plan in first['queries']: self.assertEqual( [row['repository_rank'] for row in query_plan['repositories']], list(range(1, 11)), ) self.assertEqual( [row['repository_rank'] for row in query_plan['repositories'] if row['is_deep_probe']], [7], ) self.assertEqual( [(row['query_ordinal'], row['repository_rank']) for row in first['repository_round_robin'][:61]], [(ordinal, 1) for ordinal in range(61)], ) self.assertEqual( [(row['query_ordinal'], row['repository_rank']) for row in first['repository_round_robin'][61:122]], [(ordinal, 2) for ordinal in range(61)], ) def test_plan_preserves_honest_per_query_scarcity(self): candidates = cohort_candidates() candidates[QUERIES[17]] = candidates[QUERIES[17]][:9] candidates[QUERIES[33]] = [] plan = depth.build_docker_depth_cohort_plan( experiment_config(), POLICY_SHA256, candidates, ) self.assertEqual(plan['queries'][17]['selected_repository_count'], 9) self.assertEqual(plan['queries'][33]['selected_repository_count'], 0) self.assertEqual(len(plan['queries'][17]['repositories']), 9) self.assertEqual(plan['queries'][33]['repositories'], []) self.assertEqual( sum(row['is_deep_probe'] for row in plan['queries'][17]['repositories']), 1, ) self.assertFalse(any( row['query_ordinal'] == 33 for row in plan['repository_round_robin'] )) self.assertEqual(len(plan['repository_round_robin']), 599) manifest = depth.build_docker_depth_cohort_manifest( experiment_config(), POLICY_SHA256, candidates, ) self.assertEqual(manifest['repository_count'], 599) depth.validate_docker_depth_cohort_manifest( manifest, experiment_config(), POLICY_SHA256, ) def test_rank1_breadth_plan_is_exact_balanced_and_physically_unique(self): candidates = {} shared_queue_id = 9000000 for ordinal, query in enumerate(QUERIES): if ordinal < 9: candidates[query] = [] continue candidates[query] = [{ 'repository_queue_id': shared_queue_id, 'eligibility_page_id': ordinal * 1000 + 1, 'best_search_rank': 1, 'valid_distinct_graph_count': 1, }] + [{ 'repository_queue_id': ordinal * 1000 + rank + 100, 'eligibility_page_id': ordinal * 1000 + rank + 500, 'best_search_rank': rank + 1, 'valid_distinct_graph_count': rank % 5, } for rank in range(1, 51)] experiment = breadth_experiment_config() plan = depth.build_docker_depth_cohort_plan( experiment, POLICY_SHA256, candidates, ) selected = [ row['repository_queue_id'] for query in plan['queries'] for row in query['repositories'] ] counts = [query['selected_repository_count'] for query in plan['queries']] self.assertEqual(len(selected), 2000) self.assertEqual(len(set(selected)), 2000) self.assertEqual(counts[:9], [0] * 9) self.assertEqual(counts[9:33], [39] * 24) self.assertEqual(counts[33:], [38] * 28) self.assertEqual(len(plan['repository_round_robin']), 2000) manifest = depth.build_docker_depth_cohort_manifest( experiment, POLICY_SHA256, candidates, ) depth.validate_docker_depth_cohort_manifest( manifest, experiment, POLICY_SHA256, ) def test_review_manifest_binds_provenance_even_when_membership_is_unchanged(self): experiment = experiment_config() candidates = cohort_candidates() first = depth.build_docker_depth_cohort_manifest( experiment, POLICY_SHA256, candidates, ) changed = copy.deepcopy(candidates) changed[QUERIES[0]][6]['valid_distinct_graph_count'] += 1 second = depth.build_docker_depth_cohort_manifest( experiment, POLICY_SHA256, changed, ) self.assertEqual(first['type'], depth.DOCKER_DEPTH_COHORT_MANIFEST_TYPE) self.assertEqual(first['version'], 2) self.assertEqual(first['plan'], second['plan']) self.assertNotEqual( first['provenance_snapshot_sha256'], second['provenance_snapshot_sha256'], ) self.assertNotEqual(depth._canonical_sha256(first), depth._canonical_sha256(second)) def test_reviewed_hold_manifest_is_canonical_and_tamper_evident(self): experiment = experiment_config() entries = [{ 'queue_id': 11, 'source': 'dockerhub', 'platform': 'docker', 'query': QUERIES[0], 'prior_status': 'deferred', 'prior_updated_at': '2026-09-10T00:00:00+00:00', }] conflicts = [{ 'queue_id': 12, 'source': 'dockerhub', 'platform': 'docker', 'query': QUERIES[0], 'status': 'cold', 'prior_updated_at': '2026-09-10T00:00:00+00:00', 'reason': 'independently_cold', }] manifest = { 'schema': 1, 'type': depth.DOCKER_DEPTH_HOLD_MANIFEST_TYPE, 'experiment_id': 7, 'experiment_key': experiment.experiment_key, 'source': 'dockerhub', 'config_sha256': experiment.config_hash, 'ordered_queries_sha256': experiment.ordered_query_hash, 'selector_sha256': experiment.selector_hash, 'provenance_policy_sha256': POLICY_SHA256, 'plan_sha256': PLAN_SHA256, 'reason_code': depth.DOCKER_DEPTH_HOLD_REASON, 'entry_count': 1, 'conflict_count': 1, 'selection_sha256': depth._canonical_sha256(entries), 'conflicts_sha256': depth._canonical_sha256(conflicts), 'entries': entries, 'conflicts': conflicts, } normalized, manifest_sha256 = depth.validate_docker_depth_hold_manifest( manifest, experiment, POLICY_SHA256, ) self.assertEqual(normalized, manifest) self.assertEqual(manifest_sha256, depth._canonical_sha256(manifest)) tampered = copy.deepcopy(manifest) tampered['entries'][0]['queue_id'] = 13 with self.assertRaisesRegex(ValueError, 'evidence conflicts'): depth.validate_docker_depth_hold_manifest( tampered, experiment, POLICY_SHA256, ) def test_review_manifest_bound_and_chunks_cover_more_than_one_hundred_thousand(self): configured_bound = ( depth.DOCKER_DEPTH_QUERY_COUNT * depth.DOCKERHUB_DISCOVERY_MAX_PAGES * depth.DOCKERHUB_DISCOVERY_MAX_PER_PAGE ) self.assertEqual(configured_bound, 183000) self.assertLess(configured_bound, depth.DOCKER_DEPTH_REVIEW_MANIFEST_MAX_ROWS) chunks = list(ScannerDB._target_queue_policy_chunks(range(configured_bound))) self.assertEqual(sum(map(len, chunks)), configured_bound) self.assertEqual( list(itertools.chain.from_iterable(chunks)), list(range(configured_bound)), ) entries = [{ 'queue_id': index + 1, 'source': 'dockerhub', 'platform': 'docker', 'query': QUERIES[index % len(QUERIES)], 'prior_status': 'deferred', 'prior_updated_at': '2026-09-10T00:00:00+00:00', } for index in range(100001)] normalized = depth._normalize_hold_entries( entries, depth.DOCKER_DEPTH_REVIEW_MANIFEST_MAX_ROWS, ) self.assertEqual((len(normalized), normalized[-1]['queue_id']), (100001, 100001)) class DockerDepthSQLiteShapeTests(unittest.TestCase): def setUp(self): self.environment = mock.patch.dict( os.environ, {'SCANNER_DB_URL': '', 'DATABASE_URL': ''}, ) self.environment.start() self.temp = tempfile.TemporaryDirectory() self.db = ScannerDB(db_path=os.path.join(self.temp.name, 'scanner.db')) def tearDown(self): self.db.close() self.temp.cleanup() self.environment.stop() def postgres_shape(self): self.db.conn = SQLitePostgresShape(self.db.conn) def insert_experiment( self, key='cohort-hold-test-v1', state='holding', plan_sha256=PLAN_SHA256, hold_sha256=HOLD_SHA256, ): experiment = experiment_config() now = scanner_db.utc_now_iso() row = self.db.conn.execute( '''INSERT INTO docker_depth_experiments( experiment_key, source, state, config_sha256, ordered_queries_sha256, selector_version, selector_sha256, provenance_policy_sha256, query_count, repositories_per_query, images_per_repository, target_limit, plan_sha256, hold_manifest_sha256, created_at, updated_at ) VALUES (?, 'dockerhub', ?, ?, ?, ?, ?, ?, 61, 10, 10, 1200, ?, ?, ?, ?) RETURNING id''', ( key, state, experiment.config_hash, experiment.ordered_query_hash, experiment.selector_version, experiment.selector_hash, POLICY_SHA256, plan_sha256, hold_sha256, now, now, ), ).fetchone() self.db.conn.commit() return int(row['id']) def insert_queue(self, target, query=QUERIES[0], status='deferred'): now = scanner_db.utc_now_iso() row = self.db.conn.execute( '''INSERT INTO target_queue( source, platform, query, target, normalized_target, status, resolver_state, created_at, updated_at ) VALUES ('dockerhub', 'docker', ?, ?, ?, ?, 'pending', ?, ?) RETURNING id, updated_at''', (query, target, target, status, now, now), ).fetchone() self.db.conn.commit() return dict(row) def test_mutating_planner_requires_reviewed_manifest(self): with self.assertRaisesRegex(RuntimeError, 'reviewed cohort manifest'): depth.plan_docker_depth_experiment( self.db, experiment_config(), POLICY_SHA256, ) count = self.db.conn.execute( 'SELECT COUNT(*) FROM docker_depth_experiments' ).fetchone()[0] self.assertEqual(count, 0) def test_cohort_generation_is_read_only_when_coverage_is_incomplete(self): self.postgres_shape() for _ in range(2): with self.assertRaisesRegex(RuntimeError, 'complete fresh deep discovery pass'): depth.generate_docker_depth_cohort_manifest( self.db, experiment_config(), POLICY_SHA256, ) counts = self.db.conn.execute( '''SELECT (SELECT COUNT(*) FROM docker_depth_experiments) AS experiments, (SELECT COUNT(*) FROM docker_depth_experiment_queries) AS queries, (SELECT COUNT(*) FROM docker_depth_experiment_repositories) AS repositories''', ).fetchone() self.assertEqual(tuple(counts), (0, 0, 0)) def test_cold_and_reactivation_require_exact_experiment_owner(self): experiment_id = self.insert_experiment() other_experiment_id = self.insert_experiment(key='other-experiment-v1') queue = self.insert_queue('owner/experiment-owned') self.postgres_shape() cold_entry = { 'queue_id': queue['id'], 'source': 'dockerhub', 'platform': 'docker', 'query': QUERIES[0], 'prior_status': 'deferred', 'prior_updated_at': queue['updated_at'], } applied = self.db.cold_target_queue_rows( [cold_entry], reason_code=depth.DOCKER_DEPTH_HOLD_REASON, config_sha256=experiment_config().config_hash, policy_sha256=POLICY_SHA256, manifest_sha256=HOLD_SHA256, experiment_id=experiment_id, ) self.assertEqual(applied['transitioned'], 1) cold_event = self.db.conn.execute( '''SELECT event.id, event.experiment_id, queue.updated_at FROM target_queue_policy_events event JOIN target_queue queue ON queue.id = event.queue_id WHERE event.queue_id = ?''', (queue['id'],), ).fetchone() reactivation = { 'queue_id': queue['id'], 'source': 'dockerhub', 'platform': 'docker', 'query': QUERIES[0], 'cold_event_id': int(cold_event['id']), 'restore_status': 'deferred', 'prior_updated_at': str(cold_event['updated_at']), } for wrong_owner in (None, other_experiment_id): with self.subTest(wrong_owner=wrong_owner), self.assertRaises( ScanEventConflictError, ): self.db.reactivate_cold_target_queue_rows( [reactivation], reason_code=depth.DOCKER_DEPTH_RELEASE_REASON, config_sha256=experiment_config().config_hash, policy_sha256=POLICY_SHA256, manifest_sha256='e' * 64, experiment_id=wrong_owner, ) restored = self.db.reactivate_cold_target_queue_rows( [reactivation], reason_code=depth.DOCKER_DEPTH_RELEASE_REASON, config_sha256=experiment_config().config_hash, policy_sha256=POLICY_SHA256, manifest_sha256='e' * 64, experiment_id=experiment_id, ) self.assertEqual(restored['transitioned'], 1) row = self.db.conn.execute( 'SELECT status FROM target_queue WHERE id = ?', (queue['id'],), ).fetchone() owners = self.db.conn.execute( '''SELECT action, experiment_id FROM target_queue_policy_events WHERE queue_id = ? ORDER BY id''', (queue['id'],), ).fetchall() self.assertEqual(row['status'], 'deferred') self.assertEqual( [(item['action'], item['experiment_id']) for item in owners], [('cold', experiment_id), ('reactivate', experiment_id)], ) def test_reviewed_hold_preserves_legacy_query_outside_pinned_set(self): experiment_id = self.insert_experiment() queue = self.insert_queue( 'owner/legacy-unconfigured', query='legacy-unconfigured-query', ) self.postgres_shape() self.db.cold_target_queue_rows( [{ 'queue_id': queue['id'], 'source': 'dockerhub', 'platform': 'docker', 'query': 'legacy-unconfigured-query', 'prior_status': 'deferred', 'prior_updated_at': queue['updated_at'], }], reason_code=depth.DOCKER_DEPTH_HOLD_REASON, config_sha256=experiment_config().config_hash, policy_sha256=POLICY_SHA256, manifest_sha256=HOLD_SHA256, experiment_id=experiment_id, ) experiment = self.db.conn.execute( 'SELECT * FROM docker_depth_experiments WHERE id = ?', (experiment_id,), ).fetchone() authority = depth.docker_depth_resolver_authority( experiment_config(True), POLICY_SHA256, ) self.assertIsNone( self.db._docker_depth_hold_event_drift_reason_locked( experiment, authority, ) ) def test_new_noncohort_admission_is_held_in_the_page_transaction(self): experiment_id = self.insert_experiment() now = scanner_db.utc_now_iso() self.db.conn.execute( '''INSERT INTO docker_depth_experiment_queries( experiment_id, source, query_ordinal, query, query_sha256, required_repository_count, selected_repository_count, created_at ) VALUES (?, 'dockerhub', 0, ?, ?, 10, 10, ?)''', (experiment_id, QUERIES[0], depth._canonical_sha256(QUERIES[0]), now), ) self.db.conn.commit() self.postgres_shape() self.db.conn.execute( '''INSERT OR REPLACE INTO runtime_final_cutover( id, marker, checked_at, evidence_sha256 ) VALUES (1, ?, ?, ?)''', (scanner_db.FINAL_CUTOVER_MARKER, now, 'e' * 64), ) self.db.conn.commit() authority = depth.docker_depth_resolver_authority( experiment_config(True), POLICY_SHA256, ) observation = { 'cycle_id': None, 'query_ordinal': 0, 'query_count': 61, 'page_number': 1, 'page_limit': 30, 'per_page': 100, 'total_count': 200, 'policy_sha256': POLICY_SHA256, 'pass_kind': 'deep', 'collection_generation': depth.DOCKER_DEPTH_COLLECTION_GENERATION, 'ordered_query_hash': experiment_config().ordered_query_hash, 'query_complete': False, } with mock.patch.object( self.db, '_docker_depth_persisted_drift_reason_locked', return_value=None, ): result = self.db.persist_dockerhub_discovery_page( 'dockerhub', QUERIES[0], ['owner/dynamic-hold'], observation=observation, experiment_authority=authority, final_cutover=True, ) self.assertEqual(result['dynamic_hold_count'], 1) held = self.db.conn.execute( '''SELECT queue.status, event.reason_code, event.experiment_id FROM target_queue queue JOIN target_queue_policy_events event ON event.queue_id = queue.id WHERE queue.normalized_target = 'owner/dynamic-hold' ''', ).fetchone() self.assertEqual(tuple(held), ( 'cold', depth.DOCKER_DEPTH_DYNAMIC_HOLD_REASON, experiment_id, )) with mock.patch.object( depth, 'DOCKER_DEPTH_REVIEW_MANIFEST_MAX_ROWS', 1, ), mock.patch.object( self.db, '_docker_depth_persisted_drift_reason_locked', return_value=None, ), self.assertRaisesRegex( ScanEventConflictError, 'dynamic hold capacity is exhausted', ): self.db.persist_dockerhub_discovery_page( 'dockerhub', QUERIES[0], ['owner/dynamic-hold-overflow'], observation=dict(observation, page_number=2, total_count=300), experiment_authority=authority, final_cutover=True, ) overflow = self.db.conn.execute( "SELECT 1 FROM target_queue WHERE normalized_target = 'owner/dynamic-hold-overflow'" ).fetchone() self.assertIsNone(overflow) drifted_authority = dict(authority, config_sha256='f' * 64) with mock.patch.object( self.db, '_docker_depth_persisted_drift_reason_locked', return_value=None, ), self.assertRaisesRegex(ScanEventConflictError, 'config_hash_drift'): self.db.persist_dockerhub_discovery_page( 'dockerhub', QUERIES[0], ['owner/must-roll-back'], observation=dict(observation, page_number=2, total_count=300), experiment_authority=drifted_authority, final_cutover=True, ) absent = self.db.conn.execute( "SELECT 1 FROM target_queue WHERE normalized_target = 'owner/must-roll-back'" ).fetchone() self.assertIsNone(absent) held = self.db.conn.execute( '''SELECT state, hold_reason_code FROM docker_depth_experiments WHERE id = ?''', (experiment_id,), ).fetchone() self.assertEqual(tuple(held), ('held', 'config_hash_drift')) def test_malformed_page_authority_rejects_without_holding_experiment(self): experiment_id = self.insert_experiment(state='resolving') self.postgres_shape() authority = depth.docker_depth_resolver_authority( experiment_config(True), POLICY_SHA256, ) malformed = dict(authority, selector_sha256='0' * 64) observation = { 'cycle_id': None, 'query_ordinal': 0, 'query_count': 61, 'page_number': 1, 'page_limit': 30, 'per_page': 100, 'total_count': 0, 'policy_sha256': POLICY_SHA256, 'pass_kind': 'deep', 'collection_generation': depth.DOCKER_DEPTH_COLLECTION_GENERATION, 'ordered_query_hash': experiment_config().ordered_query_hash, 'query_complete': True, } with self.assertRaisesRegex( ScanEventConflictError, 'authority_payload_invalid', ): self.db.persist_dockerhub_discovery_page( 'dockerhub', QUERIES[0], [], observation=observation, experiment_authority=malformed, final_cutover=True, ) experiment = self.db.conn.execute( '''SELECT state, hold_reason_code FROM docker_depth_experiments WHERE id = ?''', (experiment_id,), ).fetchone() self.assertEqual(tuple(experiment), ('resolving', None)) def test_unique_target_capacity_locks_deduplicates_and_counts_once(self): experiment_id = self.insert_experiment( state='resolving', hold_sha256=HOLD_SHA256, ) target = self.insert_queue( 'owner/image@sha256:' + ('1' * 64), status='pending', ) now = scanner_db.utc_now_iso() manifest = self.db.conn.execute( '''INSERT INTO docker_image_manifests( target_queue_id, source, repository, manifest_digest, manifest_media_type, graph_sha256, layer_count, resolved_at, created_at ) VALUES (?, 'dockerhub', 'owner/image', ?, 'application/vnd.oci.image.manifest.v1+json', ?, 1, ?, ?) RETURNING id''', (target['id'], 'sha256:' + ('2' * 64), '3' * 64, now, now), ).fetchone() self.db.conn.commit() self.postgres_shape() first = self.db.reserve_docker_depth_experiment_target_capacity_locked( experiment_id, target['id'], manifest['id'], 1, 1, now, ) second = self.db.reserve_docker_depth_experiment_target_capacity_locked( experiment_id, target['id'], manifest['id'], 1, 1, now, ) self.db.conn.commit() self.assertTrue(first['inserted']) self.assertFalse(second['inserted']) experiment = self.db.conn.execute( 'SELECT target_count FROM docker_depth_experiments WHERE id = ?', (experiment_id,), ).fetchone() physical = self.db.conn.execute( '''SELECT COUNT(*) AS count FROM docker_depth_experiment_targets WHERE experiment_id = ?''', (experiment_id,), ).fetchone() self.assertEqual((experiment['target_count'], physical['count']), (1, 1)) def test_reviewed_release_rejects_every_noncompleted_phase(self): experiment_id = self.insert_experiment(state='holding') self.postgres_shape() for state in ('holding', 'resolving', 'active', 'draining', 'held'): self.db.conn.execute( 'UPDATE docker_depth_experiments SET state = ? WHERE id = ?', (state, experiment_id), ) self.db.conn.commit() with self.subTest(state=state), self.assertRaisesRegex( RuntimeError, 'requires a completed experiment', ): depth.generate_docker_depth_reactivation_manifest( self.db, experiment_config(), POLICY_SHA256, ) class DockerDepthPlannerSQLiteShapeTests(unittest.TestCase): def test_complete_pass_sparse_cohort_persists_once_and_replays_immutable_hash(self): with mock.patch.dict(os.environ, {'SCANNER_DB_URL': '', 'DATABASE_URL': ''}): with tempfile.TemporaryDirectory() as directory: db = ScannerDB(db_path=os.path.join(directory, 'scanner.db')) try: now = scanner_db.utc_now_iso() discovery_pass = db.conn.execute( '''INSERT INTO docker_discovery_passes( pass_token, source, pass_kind, policy_sha256, ordered_queries_sha256, expected_query_count, completed_query_count, state, started_at, completed_at, created_at, updated_at ) VALUES (?, 'dockerhub', 'deep', ?, ?, 61, 61, 'complete', ?, ?, ?, ?) RETURNING id''', ( 'planner-pass-token-0001', POLICY_SHA256, experiment_config().ordered_query_hash, now, now, now, now, ), ).fetchone() for query_ordinal, query in enumerate(QUERIES): repository_count = 9 if query_ordinal == 0 else ( 0 if query_ordinal == 1 else 10 ) page = db.conn.execute( '''INSERT INTO docker_discovery_pages( pass_id, query, query_ordinal, page_number, result_count, admitted_count, query_complete, admission_kind, page_sha256, observed_at, created_at ) VALUES (?, ?, ?, 1, ?, ?, 1, 'main', ?, ?, ?) RETURNING id''', ( discovery_pass['id'], query, query_ordinal, repository_count, repository_count, f'{query_ordinal + 1:064x}', now, now, ), ).fetchone() for rank in range(1, repository_count + 1): repository = f'owner/q{query_ordinal:02d}-repo-{rank:02d}' queue = db.conn.execute( '''INSERT INTO target_queue( source, platform, query, target, normalized_target, status, resolver_state, created_at, updated_at ) VALUES ('dockerhub', 'docker', ?, ?, ?, 'deferred', 'pending', ?, ?) RETURNING id''', (query, repository, repository, now, now), ).fetchone() db.conn.execute( '''INSERT INTO docker_repository_query_provenance( source, query, repository_queue_id, provenance_kind, first_observed_at, last_observed_at, first_search_rank, best_search_rank, last_search_rank, first_page_id, last_page_id, first_policy_sha256, last_policy_sha256, observation_count, fresh_observation_count, fresh_complete_observation_count, fresh_coverage_eligible, created_at, updated_at ) VALUES ('dockerhub', ?, ?, 'fresh_page', ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 1, 1, 1, ?, ?)''', ( query, queue['id'], now, now, rank, rank, rank, page['id'], page['id'], POLICY_SHA256, POLICY_SHA256, now, now, ), ) db.conn.execute( '''INSERT INTO docker_repository_query_observations( page_id, repository_queue_id, source, query, search_rank, observed_at ) VALUES (?, ?, 'dockerhub', ?, ?, ?)''', (page['id'], queue['id'], query, rank, now), ) db.conn.commit() db.conn = SQLitePostgresShape(db.conn) cohort_manifest, cohort_manifest_sha256 = ( depth.generate_docker_depth_cohort_manifest( db, experiment_config(), POLICY_SHA256, ) ) with self.assertRaisesRegex(ValueError, 'hash conflicts'): depth.apply_docker_depth_cohort_manifest( db, experiment_config(), POLICY_SHA256, cohort_manifest, 'f' * 64, ) stale_queue_id = ( cohort_manifest['plan']['queries'][0]['repositories'][0][ 'repository_queue_id' ] ) db.conn.execute( "UPDATE target_queue SET status = 'cold' WHERE id = ?", (stale_queue_id,), ) db.conn.commit() with self.assertRaisesRegex(RuntimeError, 'selection drifted after review'): depth.apply_docker_depth_cohort_manifest( db, experiment_config(), POLICY_SHA256, cohort_manifest, cohort_manifest_sha256, ) self.assertEqual(db.conn.execute( 'SELECT COUNT(*) FROM docker_depth_experiments' ).fetchone()[0], 0) db.conn.execute( "UPDATE target_queue SET status = 'deferred' WHERE id = ?", (stale_queue_id,), ) db.conn.commit() first = depth.apply_docker_depth_cohort_manifest( db, experiment_config(), POLICY_SHA256, cohort_manifest, cohort_manifest_sha256, ) replay = depth.apply_docker_depth_cohort_manifest( db, experiment_config(), POLICY_SHA256, cohort_manifest, cohort_manifest_sha256, ) self.assertTrue(first['planned']) self.assertFalse(replay['planned']) self.assertEqual(first['plan_sha256'], replay['plan_sha256']) self.assertEqual(first['plan'], replay['plan']) self.assertEqual( [(row['query_ordinal'], row['repository_rank']) for row in first['plan']['repository_round_robin'] if row['repository_rank'] == 1], [(ordinal, 1) for ordinal in range(61) if ordinal != 1], ) counts = db.conn.execute( '''SELECT (SELECT COUNT(*) FROM docker_depth_experiment_queries) AS queries, (SELECT COUNT(*) FROM docker_depth_experiment_repositories) AS repositories, (SELECT COUNT(*) FROM docker_depth_experiments) AS experiments''', ).fetchone() self.assertEqual(tuple(counts), (61, 599, 1)) selected_counts = db.conn.execute( '''SELECT query_ordinal, required_repository_count, selected_repository_count FROM docker_depth_experiment_queries WHERE query_ordinal IN (0, 1) ORDER BY query_ordinal''' ).fetchall() self.assertEqual( [tuple(row) for row in selected_counts], [(0, 10, 9), (1, 10, 0)], ) hold_target = 'owner/reviewed-noncohort' independent_target = 'owner/independently-cold' held_queue = db.conn.execute( '''INSERT INTO target_queue( source, platform, query, target, normalized_target, status, resolver_state, created_at, updated_at ) VALUES ('dockerhub', 'docker', ?, ?, ?, 'deferred', 'pending', ?, ?) RETURNING id''', (QUERIES[0], hold_target, hold_target, now, now), ).fetchone() independent_queue = db.conn.execute( '''INSERT INTO target_queue( source, platform, query, target, normalized_target, status, resolver_state, created_at, updated_at ) VALUES ('dockerhub', 'docker', ?, ?, ?, 'cold', 'pending', ?, ?) RETURNING id''', (QUERIES[0], independent_target, independent_target, now, now), ).fetchone() db.conn.commit() hold_manifest, hold_manifest_sha256 = ( depth.generate_docker_depth_hold_manifest( db, experiment_config(), POLICY_SHA256, ) ) self.assertEqual( [entry['queue_id'] for entry in hold_manifest['entries']], [held_queue['id']], ) self.assertEqual( [(item['queue_id'], item['reason']) for item in hold_manifest['conflicts']], [(independent_queue['id'], 'independently_cold')], ) applied_hold = depth.apply_docker_depth_hold_manifest( db, experiment_config(), POLICY_SHA256, hold_manifest, hold_manifest_sha256, ) replayed_hold = depth.apply_docker_depth_hold_manifest( db, experiment_config(), POLICY_SHA256, hold_manifest, hold_manifest_sha256, ) self.assertEqual( (applied_hold['transitioned'], replayed_hold['duplicates']), (1, 1), ) experiment = db.conn.execute( 'SELECT * FROM docker_depth_experiments WHERE id = ?', (first['experiment_id'],), ).fetchone() members = db.conn.execute( '''SELECT * FROM docker_depth_experiment_repositories WHERE experiment_id = ? ORDER BY id''', (first['experiment_id'],), ).fetchall() for member in members: repository_queue_id = int( member['replacement_repository_queue_id'] or member['repository_queue_id'] ) db._record_docker_depth_candidate_skip_locked( experiment, member, repository_queue_id, 'repository', int(member['replacement_count']) + 1, {'repository_queue_id': repository_queue_id}, depth.DOCKER_DEPTH_REPOSITORY_SKIP_REASON, now, ) db.conn.execute( '''UPDATE docker_depth_experiment_repositories SET work_state = 'skipped', is_deep_probe = 0, selected_image_count = 0, last_error_code = ?, resolved_at = ?, updated_at = ? WHERE experiment_id = ?''', ( depth.DOCKER_DEPTH_REPOSITORY_SKIP_REASON, now, now, first['experiment_id'], ), ) db.conn.execute( "UPDATE docker_depth_experiments SET state = 'completed' " 'WHERE id = ?', (first['experiment_id'],), ) db.conn.commit() release_manifest, release_manifest_sha256 = ( depth.generate_docker_depth_reactivation_manifest( db, experiment_config(), POLICY_SHA256, ) ) db.conn.execute( "UPDATE docker_depth_experiments SET state = 'active' " 'WHERE id = ?', (first['experiment_id'],), ) db.conn.commit() with self.assertRaisesRegex( RuntimeError, 'requires a completed experiment', ): depth.apply_docker_depth_reactivation_manifest( db, experiment_config(), POLICY_SHA256, release_manifest, release_manifest_sha256, ) self.assertEqual(db.conn.execute( 'SELECT state FROM docker_depth_experiments WHERE id = ?', (first['experiment_id'],), ).fetchone()['state'], 'active') self.assertEqual(db.conn.execute( 'SELECT status FROM target_queue WHERE id = ?', (held_queue['id'],), ).fetchone()['status'], 'cold') db.conn.execute( "UPDATE docker_depth_experiments SET state = 'completed' " 'WHERE id = ?', (first['experiment_id'],), ) db.conn.commit() released = depth.apply_docker_depth_reactivation_manifest( db, experiment_config(), POLICY_SHA256, release_manifest, release_manifest_sha256, ) replayed_release = depth.apply_docker_depth_reactivation_manifest( db, experiment_config(), POLICY_SHA256, release_manifest, release_manifest_sha256, ) self.assertEqual( (released['transitioned'], replayed_release['duplicates']), (1, 1), ) final_rows = db.conn.execute( '''SELECT normalized_target, status FROM target_queue WHERE id IN (?, ?) ORDER BY id''', (held_queue['id'], independent_queue['id']), ).fetchall() final_experiment = db.conn.execute( '''SELECT state FROM docker_depth_experiments WHERE id = ?''', (first['experiment_id'],), ).fetchone() owned_events = db.conn.execute( '''SELECT action, experiment_id FROM target_queue_policy_events WHERE queue_id = ? ORDER BY id''', (held_queue['id'],), ).fetchall() self.assertEqual( [(row['normalized_target'], row['status']) for row in final_rows], [(hold_target, 'deferred'), (independent_target, 'cold')], ) self.assertEqual(final_experiment['state'], 'released') self.assertEqual( [(row['action'], row['experiment_id']) for row in owned_events], [('cold', first['experiment_id']), ('reactivate', first['experiment_id'])], ) db.conn.execute( '''DELETE FROM target_queue_policy_events WHERE queue_id = ? AND action = 'reactivate' ''', (held_queue['id'],), ) db.conn.commit() with self.assertRaisesRegex(RuntimeError, 'released hold set changed'): depth.apply_docker_depth_reactivation_manifest( db, experiment_config(), POLICY_SHA256, release_manifest, release_manifest_sha256, ) finally: db.close() if __name__ == '__main__': unittest.main()