116 lines
4.3 KiB
Python
116 lines
4.3 KiB
Python
import copy
|
|
from pathlib import Path
|
|
import sys
|
|
import unittest
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
APP_DIR = ROOT / 'app'
|
|
sys.path.insert(0, str(APP_DIR))
|
|
|
|
import docker_depth_experiment as depth
|
|
from tests.test_docker_depth_experiment import valid_config
|
|
|
|
|
|
class DockerDepthResolverRefundTests(unittest.TestCase):
|
|
def setUp(self):
|
|
validated = depth.validate_docker_depth_config(
|
|
valid_config(enabled=True), managed_postgres=True, final_cutover=True,
|
|
)
|
|
self.experiment = validated.experiment
|
|
self.policy_sha256 = 'a' * 64
|
|
self.authority = depth._docker_depth_authority(
|
|
self.experiment, self.policy_sha256,
|
|
)
|
|
|
|
def _entry(self, *, work_state='pending', attempts=2, last_error=None):
|
|
target = 'owner/repository'
|
|
last_error = last_error or depth.DOCKER_DEPTH_RESOLVER_REFUND_OLD_ERROR
|
|
row = {
|
|
'id': 21,
|
|
'effective_repository_queue_id': 31,
|
|
'query_ordinal': 2,
|
|
'repository_rank': 1,
|
|
'work_state': work_state,
|
|
'resolver_attempts': attempts,
|
|
'last_error_code': last_error,
|
|
'normalized_target': target,
|
|
}
|
|
line = (
|
|
f'Unable to fetch Docker Hub tags for {target}: '
|
|
f'{depth.DOCKER_DEPTH_RESOLVER_REFUND_OLD_ERROR}'
|
|
)
|
|
return depth._docker_depth_resolver_refund_entry(row, [line, line])
|
|
|
|
def _manifest(self, entries):
|
|
manifest = {
|
|
'schema': 1,
|
|
'type': depth.DOCKER_DEPTH_RESOLVER_REFUND_MANIFEST_TYPE,
|
|
'version': 1,
|
|
'experiment_id': 1,
|
|
'experiment_key': self.authority['experiment_key'],
|
|
'source': self.authority['source'],
|
|
'config_sha256': self.authority['config_sha256'],
|
|
'ordered_queries_sha256': self.authority['ordered_queries_sha256'],
|
|
'selector_sha256': self.authority['selector_sha256'],
|
|
'provenance_policy_sha256': self.authority['provenance_policy_sha256'],
|
|
'plan_sha256': 'b' * 64,
|
|
'hold_reason_code': 'resolver_attempt_limit',
|
|
'recovery_kind': depth.DOCKER_DEPTH_RESOLVER_REFUND_KIND,
|
|
'refund_attempts': 2,
|
|
'evidence_log_name': 'dockerhub.log',
|
|
'evidence_log_sha256': 'c' * 64,
|
|
'entry_count': len(entries),
|
|
'held_entry_count': sum(
|
|
item['prior_work_state'] == 'held' for item in entries
|
|
),
|
|
'selection_sha256': depth._canonical_sha256(entries),
|
|
'entries': entries,
|
|
}
|
|
return manifest
|
|
|
|
def test_entry_requires_exactly_two_target_bound_old_bug_events(self):
|
|
entry = self._entry()
|
|
self.assertEqual(entry['refund_attempts'], 2)
|
|
self.assertEqual(entry['next_resolver_attempts'], 0)
|
|
self.assertNotIn('target', entry)
|
|
self.assertNotIn('last_error_code', entry)
|
|
|
|
target = 'owner/repository'
|
|
row = {
|
|
'id': 21, 'effective_repository_queue_id': 31,
|
|
'query_ordinal': 2, 'repository_rank': 1,
|
|
'work_state': 'pending', 'resolver_attempts': 2,
|
|
'last_error_code': depth.DOCKER_DEPTH_RESOLVER_REFUND_OLD_ERROR,
|
|
'normalized_target': target,
|
|
}
|
|
unrelated = (
|
|
'Unable to fetch Docker Hub tags for another/repository: '
|
|
+ depth.DOCKER_DEPTH_RESOLVER_REFUND_OLD_ERROR
|
|
)
|
|
self.assertIsNone(depth._docker_depth_resolver_refund_entry(
|
|
row, [unrelated, unrelated],
|
|
))
|
|
|
|
def test_manifest_accepts_one_held_entry_and_rejects_refund_drift(self):
|
|
held = self._entry(
|
|
work_state='held', attempts=3, last_error='resolver_attempt_limit',
|
|
)
|
|
manifest = self._manifest([held])
|
|
normalized, digest = depth.validate_docker_depth_resolver_refund_manifest(
|
|
manifest, self.experiment, self.policy_sha256,
|
|
)
|
|
self.assertEqual(normalized, manifest)
|
|
self.assertRegex(digest, r'^[a-f0-9]{64}$')
|
|
|
|
changed = copy.deepcopy(manifest)
|
|
changed['refund_attempts'] = 3
|
|
with self.assertRaisesRegex(ValueError, 'evidence conflicts'):
|
|
depth.validate_docker_depth_resolver_refund_manifest(
|
|
changed, self.experiment, self.policy_sha256,
|
|
)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|