pki_ca/tests/test_property.py

128 lines
4.1 KiB
Python

import unittest
import sys
from pathlib import Path
import psycopg
# Add core directory to path
code_path = Path(__file__).parent.parent / "ca_core"
sys.path.insert(0, str(code_path))
import entity
import property
DBNAME = "ca"
def get_last_log(cursor):
cursor.execute("SELECT entry FROM log ORDER BY id DESC LIMIT 1")
row = cursor.fetchone()
return row["entry"] if row else ""
class TestPropertyFunctions(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.conn = psycopg.connect(f"dbname={DBNAME}")
cls.cur = cls.conn.cursor(row_factory=psycopg.rows.dict_row)
@classmethod
def tearDownClass(cls):
cls.cur.close()
cls.conn.close()
def setUp(self):
self.conn.rollback()
def tearDown(self):
self.conn.rollback()
# ------------------------------------------------------------
# Basic property set/get
# ------------------------------------------------------------
def test_set_and_get_property(self):
creator_id = entity.insert_creator(self.cur, "Creator1", "pubkey1")
person_id = entity.enroll_person(
self.cur, "Person1", "pubkey_person", creator_id
)
property.set_property(self.cur, person_id, "prop1")
props = property.get_properties(self.cur, person_id)
self.assertIn("prop1", props)
details = property.get_property(self.cur, person_id, "prop1")
self.assertIsNotNone(details)
# CHAR(19) is space-padded in PostgreSQL; strip for comparison.
self.assertEqual(details["validation_policy"].strip(), "default")
self.assertIsNone(details["source"])
log_entry = get_last_log(self.cur).lower()
self.assertIn("set property", log_entry)
self.assertIn("prop1", log_entry)
# ------------------------------------------------------------
# Delete property
# ------------------------------------------------------------
def test_delete_property(self):
creator_id = entity.insert_creator(self.cur, "Creator2", "pubkey2")
person_id = entity.enroll_person(
self.cur, "Person2", "pubkey_person", creator_id
)
property.set_property(self.cur, person_id, "prop2")
property.delete_property(self.cur, person_id, "prop2")
props = property.get_properties(self.cur, person_id)
self.assertNotIn("prop2", props)
log_entry = get_last_log(self.cur).lower()
self.assertIn("deleted property", log_entry)
self.assertIn("prop2", log_entry)
def test_set_property_with_policy_and_source(self):
creator_id = entity.insert_creator(self.cur, "CreatorPolicy", "pubkey_policy")
person_id = entity.enroll_person(
self.cur, "PersonPolicy", "pubkey_person", creator_id
)
property.set_property(
self.cur,
person_id,
"prop_policy",
validation_policy="strict",
source="unit-test",
)
details = property.get_property(self.cur, person_id, "prop_policy")
self.assertIsNotNone(details)
self.assertEqual(details["validation_policy"].strip(), "strict")
self.assertEqual(details["source"], "unit-test")
log_entry = get_last_log(self.cur).lower()
self.assertIn("set property", log_entry)
self.assertIn("prop_policy", log_entry)
self.assertIn("strict", log_entry)
# ------------------------------------------------------------
# Immutability: revoked entity cannot mutate properties
# ------------------------------------------------------------
def test_revoked_entity_has_no_properties(self):
creator_id = entity.insert_creator(self.cur, "Creator3", "pubkey3")
person_id = entity.enroll_person(
self.cur, "Person3", "pubkey_person", creator_id
)
entity.set_entity_status(self.cur, person_id, "revoked", creator_id)
with self.assertRaises(ValueError):
property.set_property(self.cur, person_id, "prop3")
with self.assertRaises(ValueError):
property.delete_property(self.cur, person_id, "prop3")