While I was working on this PR, I discovered some behaviour in Scenario that appears to be incorrect.
When simulating events for relations whose endpoint names contain hyphens (e.g. receive-ca-cert), Scenario sets JUJU_HOOK_NAME to a mixed format with underscores in the prefix and hyphens in the suffix (e.g. receive_ca_cert-relation-changed), instead of the all-hyphens format that real Juju provides (receive-ca-cert-relation-changed).
This causes unit tests to pass against incorrect hook name values, masking real bugs in charm code that depends on JUJU_HOOK_NAME.
Step 1 — Normalisation
In the function _normalise_name...
def _normalise_name(s: str):
"""Event names, in Scenario, uniformly use underscores instead of dashes."""
return s.replace('-', '_')
all dashes become underscores: "receive-ca-cert-relation-changed" → "receive_ca_cert_relation_changed"
Step 2 — _EventPath.__new__
Then in _EventPath.__new__
def __new__(cls, string: str):
string = _normalise_name(string)
instance = super().__new__(cls, string)
instance.name = name = string.split('.')[-1]
instance.owner_path = string.split('.')[:-1] or ['on']
instance.suffix, instance.type = _EventPath._get_suffix_and_type(name)
instance.prefix = string.removesuffix(instance.suffix)
instance._is_custom = instance.suffix == ''
return instance
For "receive_ca_cert_relation_changed":
# This is the event name as Juju provides it, with dashes not underscores.
object.__setattr__(self, '_juju_name', f'{path.prefix}{path.suffix.replace("_", "-")}')
Only the suffix gets underscores converted back to hyphens:
path.prefix = "receive_ca_cert" (underscores preserved)
path.suffix.replace("_", "-") = "-relation-changed"
- Result:
"receive_ca_cert-relation-changed" ← WRONG
'JUJU_HOOK_NAME': '' if event._is_action_event else event._juju_name,
Expected behaviour
JUJU_HOOK_NAME should be set to "receive-ca-cert-relation-changed" (all hyphens), matching real Juju behaviour.
From Juju logs I see:
ran "receive-ca-cert-relation-created" hook (via hook dispatching script: dispatch)
how to reproduce it
from ops.testing import Context, Relation, State
from charm import MyCharm
ctx = Context(MyCharm)
rel = Relation("receive-ca-cert", remote_app_data={"certificates": "[]"})
state = State(leader=True, relations=[rel])
# During ctx.run(), JUJU_HOOK_NAME will be "receive_ca_cert-relation-changed"
# instead of the correct "receive-ca-cert-relation-changed"
ctx.run(ctx.on.relation_changed(rel), state)
event = ctx.on.relation_changed(rel)
print(event._juju_name) # receive_ca_cert-relation-changed
While I was working on this PR, I discovered some behaviour in Scenario that appears to be incorrect.
When simulating events for relations whose endpoint names contain hyphens (e.g.
receive-ca-cert), Scenario setsJUJU_HOOK_NAMEto a mixed format with underscores in the prefix and hyphens in the suffix (e.g.receive_ca_cert-relation-changed), instead of the all-hyphens format that real Juju provides (receive-ca-cert-relation-changed).This causes unit tests to pass against incorrect hook name values, masking real bugs in charm code that depends on
JUJU_HOOK_NAME.Step 1 — Normalisation
In the function
_normalise_name...all dashes become underscores:
"receive-ca-cert-relation-changed"→"receive_ca_cert_relation_changed"Step 2 —
_EventPath.__new__Then in
_EventPath.__new__For
"receive_ca_cert_relation_changed":suffix="_relation_changed"(matched from_RELATION_EVENTS_SUFFIX)prefix="receive_ca_cert"Step 3 —
_juju_nameconstructionOnly the suffix gets underscores converted back to hyphens:
path.prefix="receive_ca_cert"(underscores preserved)path.suffix.replace("_", "-")="-relation-changed""receive_ca_cert-relation-changed"← WRONGStep 4 — Assignment to
JUJU_HOOK_NAMEExpected behaviour
JUJU_HOOK_NAMEshould be set to"receive-ca-cert-relation-changed"(all hyphens), matching real Juju behaviour.From Juju logs I see:
how to reproduce it