test(companion): Add config validation tests

Cover validate_companion_workers (None becomes empty, non-list and non-dict
items rejected) and CompanionConfig.config_hash (stable for equal configs,
changes when a field changes, callable target keyed by qualified name and
hashed stably).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tanmoy Sarkar 2026-06-09 23:03:43 +05:30
parent 465aff870d
commit e780484d24
2 changed files with 38 additions and 3 deletions

View File

@ -695,7 +695,7 @@ No per-companion logic in Arbiter.
- [x] Close manager-only fds in companion child.
- [x] Add parent-death cleanup.
- [x] Add lifecycle logs.
- [ ] Add tests for config validation.
- [x] Add tests for config validation.
- [ ] Add tests for state transitions.
- [ ] Add tests for control commands.
- [ ] Add tests for transactional reread.

View File

@ -4,8 +4,8 @@
import pytest
from gunicorn.config import Config
from gunicorn.companion.config import build_companion_configs
from gunicorn.config import Config, validate_companion_workers
from gunicorn.companion.config import CompanionConfig, build_companion_configs
def make_config(workers, **overrides):
@ -45,3 +45,38 @@ def test_build_requires_name_and_target():
build_companion_configs(make_config([{"name": "rq"}]))
with pytest.raises(ValueError):
build_companion_configs(make_config([{"target": "pkg:run"}]))
def test_validate_companion_workers_accepts_none_and_list():
assert validate_companion_workers(None) == []
workers = [{"name": "rq", "target": "pkg:run"}]
assert validate_companion_workers(workers) == workers
def test_validate_companion_workers_rejects_non_list():
with pytest.raises(TypeError):
validate_companion_workers("rq")
def test_validate_companion_workers_rejects_non_dict_item():
with pytest.raises(TypeError):
validate_companion_workers(["rq"])
def test_config_hash_stable_and_field_sensitive():
base = CompanionConfig(name="rq", target="pkg:run")
same = CompanionConfig(name="rq", target="pkg:run")
changed = CompanionConfig(name="rq", target="pkg:run", stop_timeout=99)
assert base.config_hash == same.config_hash
assert base.config_hash != changed.config_hash
def test_config_hash_keys_callable_target_by_qualified_name():
def run():
pass
keyed = CompanionConfig._target_key(run)
assert ":" in keyed and keyed.endswith("run")
# A callable target hashes stably across CompanionConfig instances.
assert (CompanionConfig(name="rq", target=run).config_hash
== CompanionConfig(name="rq", target=run).config_hash)