shard-wiki/tests/test_engine_profile.py

99 lines
2.8 KiB
Python
Raw Normal View History

"""Tests for capability-profile-derived-from-extensions (SHARD-WP-0014 T4, E-5)."""
import pytest
from shard_wiki.engine import (
Extension,
ExtensionRuntime,
Hook,
ProfileContribution,
derive_profile,
engine_base_profile,
)
from shard_wiki.model import (
Addressing,
ContentOpacity,
NativeQuery,
ProfileError,
Verb,
)
class StructExt(Extension):
id = "ext.struct"
def hooks(self):
return {
Hook.ON_PROFILE: lambda payload, ctx: ProfileContribution(
verbs_add=frozenset({Verb.STRUCTURED_PAYLOAD})
)
}
class AddrExt(Extension):
id = "ext.addr"
def hooks(self):
return {
Hook.ON_PROFILE: lambda payload, ctx: ProfileContribution(
addressing=Addressing.SPAN, verbs_add=frozenset({Verb.TRANSCLUDE_SOURCE})
)
}
class EncryptExt(Extension):
id = "ext.encrypt"
def hooks(self):
return {Hook.ON_PROFILE: lambda p, c: ProfileContribution(content_opacity=ContentOpacity.ENCRYPTED)}
class QueryExt(Extension):
id = "ext.query"
def hooks(self):
return {Hook.ON_PROFILE: lambda p, c: ProfileContribution(native_query=NativeQuery.DB_QUERY)}
def _active(*exts, ids=None):
rt = ExtensionRuntime()
for e in exts:
rt.register(e)
return rt.activate(ids if ids is not None else {e.id for e in exts})
def test_base_profile_is_valid_kernel_minimum():
p = engine_base_profile()
assert p.supports(Verb.READ) and p.supports(Verb.WRITE)
assert not p.supports(Verb.STRUCTURED_PAYLOAD)
assert p.addressing is Addressing.PATH
def test_no_extensions_yields_base():
rt = ExtensionRuntime()
active = rt.activate(set())
assert derive_profile(active) == engine_base_profile()
def test_activating_extension_raises_the_profile():
active = _active(StructExt(), AddrExt())
p = derive_profile(active)
assert p.supports(Verb.STRUCTURED_PAYLOAD) # from ext.struct
assert p.supports(Verb.TRANSCLUDE_SOURCE) # from ext.addr
assert p.addressing is Addressing.SPAN # raised by ext.addr
assert p.supports(Verb.READ) # base preserved
def test_profile_changes_with_active_set():
only_struct = derive_profile(_active(StructExt(), AddrExt(), ids={"ext.struct"}))
both = derive_profile(_active(StructExt(), AddrExt()))
assert not only_struct.supports(Verb.TRANSCLUDE_SOURCE)
assert both.supports(Verb.TRANSCLUDE_SOURCE) # E-5: profile reflects what's active
def test_composition_cannot_yield_an_impossible_profile():
# encrypted opacity + native query violates §6.5 implication rules -> derive must reject.
active = _active(EncryptExt(), QueryExt())
with pytest.raises(ProfileError):
derive_profile(active)