bmc_hub/tests/test_workflow_uninstall.py

48 lines
2.8 KiB
Python
Raw Normal View History

"""Exercise exact downgrade SQL inside a rolled-back disposable DB transaction."""
import os
from pathlib import Path
import pytest
import psycopg2
from psycopg2.extensions import parse_dsn
ROOT=Path(__file__).resolve().parents[1]
def test_uninstall_preserves_business_data_and_removes_only_workflow():
dsn=os.environ.get('BMC_WORKFLOW_TEST_DSN')
if not dsn: pytest.skip('Disposable BMC_WORKFLOW_TEST_DSN required')
if not parse_dsn(dsn).get('dbname','').startswith('bmc_workflow_test'):
pytest.fail('Uninstall test refuses non-test database')
conn=psycopg2.connect(dsn)
preserved=('customers','sag_sager','tmodule_times','tags','entity_tags',
'tticket_prepaid_transactions','ordre_drafts','customer_fixed_price_agreements')
removed_columns={'tags':['parent_id','visibility','billing_relevant'],
'entity_tags':['source'],'tmodule_times':['workflow_revision'],
'tticket_prepaid_transactions':['workflow_time_entry_id'],
'customer_fixed_price_agreements':['workflow_coverage','monthly_price']}
try:
with conn.cursor() as cur:
# Compare every retained row after excluding explicitly removed metadata.
before={}
for table in preserved:
exclusions=removed_columns.get(table,[])
cur.execute(f"SELECT md5(COALESCE(string_agg(row_data::text,'|' ORDER BY row_data::text),'')) FROM (SELECT to_jsonb(t)-%s::text[] AS row_data FROM {table} t) x",(exclusions,))
before[table]=cur.fetchone()[0]
sql=(ROOT/'scripts/workflow_uninstall.sql').read_text()
# Keep script's operations atomic but retain test transaction for rollback.
sql=sql.replace('BEGIN;','',1).rsplit('COMMIT;',1)[0]
cur.execute(sql)
for table in preserved:
cur.execute(f"SELECT md5(COALESCE(string_agg(to_jsonb(t)::text,'|' ORDER BY to_jsonb(t)::text),'')) FROM {table} t")
assert cur.fetchone()[0]==before[table],table
cur.execute("SELECT tablename FROM pg_tables WHERE schemaname='public' AND (tablename LIKE 'bmc_workflow%' OR tablename LIKE 'workflow_tag%' OR tablename='bmc_billing_decisions')")
assert cur.fetchall()==[]
for table,columns in removed_columns.items():
cur.execute('SELECT column_name FROM information_schema.columns WHERE table_schema=%s AND table_name=%s AND column_name=ANY(%s)',('public',table,columns))
assert cur.fetchall()==[]
cur.execute("SELECT tgname FROM pg_trigger WHERE NOT tgisinternal AND (tgname LIKE 'bmc%workflow%' OR tgname='workflow_entity_tag_audit')")
assert cur.fetchall()==[]
finally:
conn.rollback()
conn.close()