#!/usr/bin/env python3
import copy
import json
import unittest
from pathlib import Path
from compare import compare


class MutationTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        base = Path(__file__).parent
        cls.b = json.loads((base / 'evidence-B.json').read_text())
        cls.c = json.loads((base / 'evidence-C.json').read_text())
        cls.old = json.loads((base / 'baseline-before-serializer-B.json').read_text())

    def reject(self, mutate):
        c = copy.deepcopy(self.c); mutate(c)
        with self.assertRaises(AssertionError): compare(self.b, c, self.old)

    def test_green(self): compare(self.b, self.c, self.old)
    def test_missing_case(self): self.reject(lambda c: c['cases'].pop())
    def test_money_type(self):
        def mutate(c):
            case = next(x for x in c['cases'] if x['scenario'] == 'PILOT_GRC_STORE_PLAN_LIST_NONEMPTY')
            case['body']['data']['list']['data'][0]['money'] = 5.5
        self.reject(mutate)
    def test_gift_zero_type(self):
        def mutate(c):
            case = next(x for x in c['cases'] if x['scenario'] == 'PILOT_GRC_STORE_PLAN_LIST_NONEMPTY')
            case['body']['data']['list']['data'][0]['gift_money'] = 0
        self.reject(mutate)
    def test_json_equity_type(self):
        def mutate(c):
            case = next(x for x in c['cases'] if x['scenario'] == 'PILOT_GRC_STORE_GRADE_ALL_ENABLED')
            case['body']['data']['list'][0]['equity']['discount'] = 9.8
        self.reject(mutate)
    def test_sort_order(self):
        def mutate(c):
            case = next(x for x in c['cases'] if x['scenario'] == 'PILOT_GRC_STORE_PLAN_LIST_SORT_TIE_PK')
            case['body']['data']['list']['data'].reverse()
        self.reject(mutate)
    def test_scope(self): self.reject(lambda c: c['write_audit'][0].__setitem__('owned_scope_verified', False))
    def test_other_table_write(self): self.reject(lambda c: c['write_audit'][0].__setitem__('table', 'yoshop_user'))
    def test_cleanup(self): self.reject(lambda c: c['cleanup']['fresh_pdo_owned_rows'].__setitem__('user_grade', 1))
    def test_reference(self): self.reject(lambda c: c['cleanup']['owned_reference_columns'][0].__setitem__('remaining_owned_references', 1))
    def test_natural_sha(self): self.reject(lambda c: c['cleanup'].__setitem__('natural_two_tables_full_sha_unchanged', False))
    def test_raw_object_array(self): self.reject(lambda c: c['cases'][0]['raw_json_shape'].__setitem__('object', []))
    def test_trace_format(self): self.reject(lambda c: c['cases'][0].__setitem__('trace_format_valid', False))
    def test_mysql_baseline(self):
        old = copy.deepcopy(self.old); old['cases'][0]['body']['message'] = 'different'
        with self.assertRaises(AssertionError): compare(self.b, self.c, old)


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