packages feed

mariadb-haskell-0.1.0.0: validation/test_stage4_benchmarks.py

"""Independently verify reuse work, immutable baselines and publication evidence."""
import copy
import hashlib
import json
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch

import feature_benchmarks as features
import stage4_benchmarks as reuse


class ReuseEvidenceTests(unittest.TestCase):
    def setUp(self):
        self.spec = reuse.specification()
        self.inputs = {'sha256': 'current', 'commit': 'code',
                       'files': {name: 'digest' for name in reuse.WORKLOAD_PATHS}}
        self.data = {'complete': True, 'repetitions': 7, 'inputs': copy.deepcopy(self.inputs),
                     'server': {}, 'machine': {}, 'dependencies': [],
                     'haskell_benchmark_rts': ['-N4', '-T'],
                     'build': {'ghc': 'compiler', 'cabal': 'tool', 'git_commit': 'code'},
                     'profiles': {}, 'comparisons': {}}
        for ident, count in reuse.PROFILES.items():
            sample = {'units': count, 'elapsed_ns': count * 100, 'allocated_bytes': count * 200,
                      'cpu_ns': count * 80, 'gc_cpu_ns': count * 10, 'checksum': count}
            profile = {'samples': [copy.deepcopy(sample) for _ in range(7)]}
            for key in ('elapsed_ns', 'allocated_bytes', 'cpu_ns', 'gc_cpu_ns'):
                profile['median_' + key + '_per_unit'] = sample[key] / count
            self.data['profiles'][ident] = profile
        for name, (current, baseline) in reuse.PAIRS.items():
            self.data['comparisons'][name] = {'current': current, 'baseline': baseline,
                'change_percent': {'elapsed_ns': 0.0, 'allocated_bytes': 0.0}}
        folder = tempfile.TemporaryDirectory()
        self.addCleanup(folder.cleanup)
        root = Path(folder.name)
        self.directory = root / reuse.BASELINE_DIRECTORY
        self.directory.mkdir(parents=True)
        artifacts = {'results.json': json.dumps(self.data).encode(), 'SUMMARY.md': b'first reuse capture\n'}
        for name, raw in artifacts.items():
            (self.directory / name).write_bytes(raw)
        (self.directory / 'SHA256SUMS').write_text(''.join(
            hashlib.sha256(raw).hexdigest() + '  ' + name + '\n' for name, raw in artifacts.items()))
        location = patch.object(features.run, 'HERE', root)
        location.start()
        self.addCleanup(location.stop)
        features.attach_baseline_comparison(self.spec, self.data)

    def verify(self):
        reuse.verify_evidence(self.data, self.inputs)

    def test_complete_data(self):
        self.verify()

    def test_wrong_units_for_same_checksum(self):
        self.data['profiles']['reuse.tcp.reset']['samples'][0]['units'] = 1
        with self.assertRaisesRegex(ValueError, 'unit count'):
            self.verify()

    def test_wrong_checksum(self):
        self.data['profiles']['reuse.tls.reset']['samples'][0]['checksum'] = 0
        with self.assertRaisesRegex(ValueError, 'checksum'):
            self.verify()

    def test_snapshot_has_its_own_unit_count(self):
        self.data['profiles']['session.snapshot']['samples'][0]['units'] = 30
        with self.assertRaisesRegex(ValueError, 'unit count'):
            self.verify()

    def test_missing_transport(self):
        del self.data['profiles']['reuse.socket.reconnect']
        with self.assertRaisesRegex(ValueError, 'profiles'):
            self.verify()

    def test_missing_repetition(self):
        self.data['profiles']['reuse.tcp.reset']['samples'].pop()
        with self.assertRaisesRegex(ValueError, 'repetitions'):
            self.verify()

    def test_edited_median(self):
        self.data['profiles']['reuse.tcp.reset']['median_elapsed_ns_per_unit'] = 1
        with self.assertRaisesRegex(ValueError, 'summary'):
            self.verify()

    def test_missing_comparison(self):
        del self.data['comparisons']['tls']
        with self.assertRaisesRegex(ValueError, 'comparison profiles'):
            self.verify()

    def test_reversed_comparison(self):
        self.data['comparisons']['tcp']['baseline'] = 'reuse.tcp.reset'
        with self.assertRaisesRegex(ValueError, 'identity'):
            self.verify()

    def test_edited_change(self):
        self.data['comparisons']['tcp']['change_percent']['elapsed_ns'] = -50
        with self.assertRaisesRegex(ValueError, 'comparison'):
            self.verify()

    def test_old_input_fingerprint(self):
        self.data['inputs']['sha256'] = 'old'
        with self.assertRaisesRegex(ValueError, 'stale'):
            self.verify()

    def test_same_digest_cannot_hide_different_files(self):
        self.data['inputs']['files'][reuse.WORKLOAD_PATHS[0]] = 'fake mismatch'
        with self.assertRaisesRegex(ValueError, 'input file'):
            self.verify()

    def test_wrong_tested_commit(self):
        self.data['build']['git_commit'] = 'old'
        with self.assertRaisesRegex(ValueError, 'tested commit'):
            self.verify()

    def test_missing_baseline_is_rejected(self):
        (self.directory / 'results.json').unlink()
        with self.assertRaisesRegex(ValueError, 'required session reuse baseline'):
            self.verify()

    def test_changed_baseline_is_rejected(self):
        (self.directory / 'results.json').write_text('{}')
        with self.assertRaisesRegex(ValueError, 'checksum'):
            self.verify()

    def test_changed_summary_is_rejected(self):
        (self.directory / 'SUMMARY.md').write_text('different')
        with self.assertRaisesRegex(ValueError, 'checksum'):
            self.verify()

    def test_omitted_baseline_comparison(self):
        del self.data['baseline_comparison']
        with self.assertRaisesRegex(ValueError, 'baseline comparison'):
            self.verify()

    def test_cannot_hide_comparability(self):
        self.data['baseline_comparison']['comparable'] = False
        with self.assertRaisesRegex(ValueError, 'baseline comparison'):
            self.verify()

    def test_cannot_hide_timing_alarm(self):
        self.data['baseline_comparison']['timing_investigations'] = [{'id': 'x', 'percent': 99}]
        with self.assertRaisesRegex(ValueError, 'baseline comparison'):
            self.verify()

    def test_environment_change_withholds_deltas(self):
        self.data['server'] = {'different': True}
        comparison = features.baseline_comparison(self.spec, self.data)
        self.assertFalse(comparison['comparable'])
        self.assertEqual({}, comparison['profiles'])

    def test_duplicate_and_wrong_markers(self):
        line = 'STAGE4\treuse.tcp.reset\t30\t100\t200\t80\t10\t30\n'
        for content in (line * 2, line.replace('STAGE4', 'STAGE3')):
            with self.assertRaises(ValueError):
                features.sample(self.spec, content, 'reuse.tcp.reset')


if __name__ == '__main__':
    unittest.main()