test: add RED test for config schema advanced flags (TDD checkpoint)
Adds test_config_schema.py verifying every visible field has an explicit 'advanced' bool, basic fields are advanced=False, and sampled advanced fields are advanced=True.
This commit is contained in:
@@ -437,146 +437,148 @@ class Arma3ConfigGenerator:
|
|||||||
return args
|
return args
|
||||||
|
|
||||||
def get_ui_schema(self) -> dict:
|
def get_ui_schema(self) -> dict:
|
||||||
|
B, A = False, True # basic / advanced shorthand
|
||||||
return {
|
return {
|
||||||
"server": {
|
"server": {
|
||||||
# Identity
|
# Identity — basic
|
||||||
"hostname": {"widget": "text", "label": "Server Name"},
|
"hostname": {"widget": "text", "label": "Server Name", "advanced": B},
|
||||||
"max_players": {"widget": "number", "label": "Max Players", "min": 1, "max": 1000},
|
"max_players": {"widget": "number", "label": "Max Players", "min": 1, "max": 1000, "advanced": B},
|
||||||
"password": {"widget": "password", "label": "Join Password"},
|
"password": {"widget": "password", "label": "Join Password", "advanced": B},
|
||||||
"password_admin": {"widget": "password", "label": "Admin Password"},
|
"password_admin": {"widget": "password", "label": "Admin Password", "advanced": B},
|
||||||
"server_command_password": {"widget": "password", "label": "Server Command Password"},
|
"server_command_password": {"widget": "password", "label": "Server Command Password", "advanced": A},
|
||||||
# Message of the Day
|
# Message of the Day — basic
|
||||||
"motd_lines": {"widget": "textarea", "label": "Message of the Day (one line per row)"},
|
"motd_lines": {"widget": "textarea", "label": "Message of the Day (one line per row)", "advanced": B},
|
||||||
"motd_interval": {"widget": "number", "label": "MOTD Interval (sec)", "min": 1},
|
"motd_interval": {"widget": "number", "label": "MOTD Interval (sec)", "min": 1, "advanced": B},
|
||||||
# Mission / Rotation
|
# Mission / Rotation — basic
|
||||||
"forced_difficulty": {"widget": "select", "label": "Forced Difficulty",
|
"forced_difficulty": {"widget": "select", "label": "Forced Difficulty",
|
||||||
"options": ["Recruit", "Regular", "Veteran", "Custom"]},
|
"options": ["Recruit", "Regular", "Veteran", "Custom"], "advanced": B},
|
||||||
"auto_select_mission": {"widget": "toggle", "label": "Auto-Select Mission"},
|
"auto_select_mission": {"widget": "toggle", "label": "Auto-Select Mission", "advanced": B},
|
||||||
"random_mission_order": {"widget": "toggle", "label": "Random Mission Order"},
|
"random_mission_order": {"widget": "toggle", "label": "Random Mission Order", "advanced": B},
|
||||||
# Behaviour
|
# Behaviour — mixed
|
||||||
"persistent": {"widget": "toggle", "label": "Persistent (keep running when empty)"},
|
"persistent": {"widget": "toggle", "label": "Persistent (keep running when empty)", "advanced": B},
|
||||||
"kick_duplicate": {"widget": "toggle", "label": "Kick Duplicate Connections"},
|
"kick_duplicate": {"widget": "toggle", "label": "Kick Duplicate Connections", "advanced": A},
|
||||||
"skip_lobby": {"widget": "toggle", "label": "Skip Lobby (go straight to briefing)"},
|
"skip_lobby": {"widget": "toggle", "label": "Skip Lobby (go straight to briefing)", "advanced": B},
|
||||||
"drawing_in_map": {"widget": "toggle", "label": "Allow Drawing in Map"},
|
"drawing_in_map": {"widget": "toggle", "label": "Allow Drawing in Map", "advanced": B},
|
||||||
# Security
|
# Security — basic
|
||||||
"battleye": {"widget": "toggle", "label": "BattlEye Anti-Cheat"},
|
"battleye": {"widget": "toggle", "label": "BattlEye Anti-Cheat", "advanced": B},
|
||||||
"verify_signatures": {"widget": "select", "label": "Verify Addon Signatures",
|
"verify_signatures": {"widget": "select", "label": "Verify Addon Signatures",
|
||||||
"options": ["0 - Off", "1 - Kick unsigned", "2 - Strict (kick mismatched)"]},
|
"options": ["0 - Off", "1 - Kick unsigned", "2 - Strict (kick mismatched)"], "advanced": B},
|
||||||
"allowed_file_patching": {"widget": "select", "label": "Allow File Patching",
|
"allowed_file_patching": {"widget": "select", "label": "Allow File Patching",
|
||||||
"options": ["0 - Nobody", "1 - Lobby only", "2 - Everyone"]},
|
"options": ["0 - Nobody", "1 - Lobby only", "2 - Everyone"], "advanced": B},
|
||||||
# Voice
|
# Voice — basic
|
||||||
"disable_von": {"widget": "toggle", "label": "Disable Voice-over-Network (VoN)"},
|
"disable_von": {"widget": "toggle", "label": "Disable Voice-over-Network (VoN)", "advanced": B},
|
||||||
"von_codec": {"widget": "toggle", "label": "Use Opus VoN Codec"},
|
"von_codec": {"widget": "toggle", "label": "Use Opus VoN Codec", "advanced": B},
|
||||||
"von_codec_quality": {"widget": "number", "label": "VoN Codec Quality (0–30)", "min": 0, "max": 30},
|
"von_codec_quality": {"widget": "number", "label": "VoN Codec Quality (0–30)", "min": 0, "max": 30, "advanced": A},
|
||||||
# Network / Kick thresholds
|
# Network / Kick thresholds — advanced
|
||||||
"kick_on_ping": {"widget": "toggle", "label": "Kick on High Ping"},
|
"kick_on_ping": {"widget": "toggle", "label": "Kick on High Ping", "advanced": A},
|
||||||
"kick_on_packet_loss": {"widget": "toggle", "label": "Kick on High Packet Loss"},
|
"kick_on_packet_loss": {"widget": "toggle", "label": "Kick on High Packet Loss", "advanced": A},
|
||||||
"kick_on_desync": {"widget": "toggle", "label": "Kick on High Desync"},
|
"kick_on_desync": {"widget": "toggle", "label": "Kick on High Desync", "advanced": A},
|
||||||
"kick_on_timeout": {"widget": "toggle", "label": "Kick on Timeout"},
|
"kick_on_timeout": {"widget": "toggle", "label": "Kick on Timeout", "advanced": A},
|
||||||
"max_ping": {"widget": "number", "label": "Max Ping (ms)", "min": 1},
|
"max_ping": {"widget": "number", "label": "Max Ping (ms)", "min": 1, "advanced": A},
|
||||||
"max_packet_loss": {"widget": "number", "label": "Max Packet Loss (%)", "min": 0, "max": 100},
|
"max_packet_loss": {"widget": "number", "label": "Max Packet Loss (%)", "min": 0, "max": 100, "advanced": A},
|
||||||
"max_desync": {"widget": "number", "label": "Max Desync", "min": 0},
|
"max_desync": {"widget": "number", "label": "Max Desync", "min": 0, "advanced": A},
|
||||||
"disconnect_timeout": {"widget": "number", "label": "Disconnect Timeout (sec)", "min": 0},
|
"disconnect_timeout": {"widget": "number", "label": "Disconnect Timeout (sec)", "min": 0, "advanced": A},
|
||||||
# Voting
|
# Voting — advanced
|
||||||
"vote_threshold": {"widget": "number", "label": "Vote Threshold (0.0–1.0)", "min": 0, "max": 1},
|
"vote_threshold": {"widget": "number", "label": "Vote Threshold (0.0–1.0)", "min": 0, "max": 1, "advanced": A},
|
||||||
"vote_mission_players": {"widget": "number", "label": "Min Players to Start Vote", "min": 0},
|
"vote_mission_players": {"widget": "number", "label": "Min Players to Start Vote", "min": 0, "advanced": A},
|
||||||
"vote_timeout": {"widget": "number", "label": "Vote Timeout (sec)", "min": 0},
|
"vote_timeout": {"widget": "number", "label": "Vote Timeout (sec)", "min": 0, "advanced": A},
|
||||||
# Timeouts
|
# Timeouts — advanced
|
||||||
"role_timeout": {"widget": "number", "label": "Role Selection Timeout (sec)", "min": 0},
|
"role_timeout": {"widget": "number", "label": "Role Selection Timeout (sec)", "min": 0, "advanced": A},
|
||||||
"briefing_timeout": {"widget": "number", "label": "Briefing Timeout (sec)", "min": 0},
|
"briefing_timeout": {"widget": "number", "label": "Briefing Timeout (sec)", "min": 0, "advanced": A},
|
||||||
"debriefing_timeout": {"widget": "number", "label": "Debriefing Timeout (sec)", "min": 0},
|
"debriefing_timeout": {"widget": "number", "label": "Debriefing Timeout (sec)", "min": 0, "advanced": A},
|
||||||
"lobby_idle_timeout": {"widget": "number", "label": "Lobby Idle Timeout (sec)", "min": 0},
|
"lobby_idle_timeout": {"widget": "number", "label": "Lobby Idle Timeout (sec)", "min": 0, "advanced": A},
|
||||||
# Misc
|
# Misc — advanced
|
||||||
"statistics_enabled": {"widget": "toggle", "label": "Enable Steam Statistics"},
|
"statistics_enabled": {"widget": "toggle", "label": "Enable Steam Statistics", "advanced": A},
|
||||||
"upnp": {"widget": "toggle", "label": "Enable UPnP"},
|
"upnp": {"widget": "toggle", "label": "Enable UPnP", "advanced": A},
|
||||||
"loopback": {"widget": "toggle", "label": "Loopback Mode (LAN only)"},
|
"loopback": {"widget": "toggle", "label": "Loopback Mode (LAN only)", "advanced": A},
|
||||||
"timestamp_format": {"widget": "select", "label": "Log Timestamp Format",
|
"timestamp_format": {"widget": "select", "label": "Log Timestamp Format",
|
||||||
"options": ["none", "short", "full"]},
|
"options": ["none", "short", "full"], "advanced": A},
|
||||||
"log_file": {"widget": "text", "label": "Log File Name"},
|
"log_file": {"widget": "text", "label": "Log File Name", "advanced": A},
|
||||||
# Admin / Headless
|
# Admin / Headless — advanced
|
||||||
"admin_uids": {"widget": "tag-list", "label": "Admin Steam UIDs",
|
"admin_uids": {"widget": "tag-list", "label": "Admin Steam UIDs",
|
||||||
"placeholder": "76561198000000000"},
|
"placeholder": "76561198000000000", "advanced": A},
|
||||||
"headless_clients": {"widget": "tag-list", "label": "Headless Client IPs",
|
"headless_clients": {"widget": "tag-list", "label": "Headless Client IPs",
|
||||||
"placeholder": "127.0.0.1"},
|
"placeholder": "127.0.0.1", "advanced": A},
|
||||||
"local_clients": {"widget": "tag-list", "label": "Local Client IPs",
|
"local_clients": {"widget": "tag-list", "label": "Local Client IPs",
|
||||||
"placeholder": "127.0.0.1"},
|
"placeholder": "127.0.0.1", "advanced": A},
|
||||||
# missions managed by the Missions tab — hidden here
|
# missions managed by the Missions tab — hidden here
|
||||||
"missions": {"widget": "hidden"},
|
"missions": {"widget": "hidden"},
|
||||||
# default params applied to every mission without custom params
|
# default params — advanced
|
||||||
"default_mission_params": {"widget": "key-value", "label": "Default Mission Parameters",
|
"default_mission_params": {"widget": "key-value", "label": "Default Mission Parameters",
|
||||||
"help": "Applied to all missions without custom params. Empty = no Params block."},
|
"help": "Applied to all missions without custom params.", "advanced": A},
|
||||||
},
|
},
|
||||||
"basic": {
|
"basic": {
|
||||||
"min_bandwidth": {"widget": "number", "label": "Min Bandwidth (bps)", "min": 1},
|
# All network tuning fields are advanced
|
||||||
"max_bandwidth": {"widget": "number", "label": "Max Bandwidth (bps)", "min": 1},
|
"min_bandwidth": {"widget": "number", "label": "Min Bandwidth (bps)", "min": 1, "advanced": A},
|
||||||
"max_msg_send": {"widget": "number", "label": "Max Messages Sent per Frame", "min": 1},
|
"max_bandwidth": {"widget": "number", "label": "Max Bandwidth (bps)", "min": 1, "advanced": A},
|
||||||
"max_size_guaranteed": {"widget": "number", "label": "Max Guaranteed Packet Size (bytes)", "min": 1},
|
"max_msg_send": {"widget": "number", "label": "Max Messages Sent per Frame", "min": 1, "advanced": A},
|
||||||
"max_size_non_guaranteed": {"widget": "number", "label": "Max Non-Guaranteed Packet Size (bytes)", "min": 1},
|
"max_size_guaranteed": {"widget": "number", "label": "Max Guaranteed Packet Size (bytes)", "min": 1, "advanced": A},
|
||||||
"min_error_to_send": {"widget": "number", "label": "Min Error to Send"},
|
"max_size_non_guaranteed": {"widget": "number", "label": "Max Non-Guaranteed Packet Size (bytes)", "min": 1, "advanced": A},
|
||||||
"max_custom_file_size": {"widget": "number", "label": "Max Custom File Size (bytes)", "min": 0},
|
"min_error_to_send": {"widget": "number", "label": "Min Error to Send", "advanced": A},
|
||||||
|
"max_custom_file_size": {"widget": "number", "label": "Max Custom File Size (bytes)", "min": 0, "advanced": A},
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
# Damage / health
|
# Basic difficulty options
|
||||||
"reduced_damage": {"widget": "toggle", "label": "Reduced Damage"},
|
"reduced_damage": {"widget": "toggle", "label": "Reduced Damage", "advanced": A},
|
||||||
# Indicators (0=Never, 1=Limited distance, 2=Fade out, 3=Always)
|
|
||||||
"group_indicators": {"widget": "select", "label": "Group Indicators",
|
"group_indicators": {"widget": "select", "label": "Group Indicators",
|
||||||
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"]},
|
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"], "advanced": B},
|
||||||
"friendly_tags": {"widget": "select", "label": "Friendly Name Tags",
|
"friendly_tags": {"widget": "select", "label": "Friendly Name Tags",
|
||||||
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"]},
|
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"], "advanced": B},
|
||||||
"enemy_tags": {"widget": "select", "label": "Enemy Name Tags",
|
"enemy_tags": {"widget": "select", "label": "Enemy Name Tags",
|
||||||
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"]},
|
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"], "advanced": B},
|
||||||
"detected_mines": {"widget": "select", "label": "Detected Mines",
|
"detected_mines": {"widget": "select", "label": "Detected Mines",
|
||||||
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"]},
|
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"], "advanced": A},
|
||||||
"commands": {"widget": "select", "label": "Map Commands",
|
"commands": {"widget": "select", "label": "Map Commands",
|
||||||
"options": ["0 - Never", "1 - High command", "2 - Fade out", "3 - Always"]},
|
"options": ["0 - Never", "1 - High command", "2 - Fade out", "3 - Always"], "advanced": B},
|
||||||
"waypoints": {"widget": "select", "label": "Waypoints",
|
"waypoints": {"widget": "select", "label": "Waypoints",
|
||||||
"options": ["0 - Never", "1 - Known positions", "2 - Fade out", "3 - Always"]},
|
"options": ["0 - Never", "1 - Known positions", "2 - Fade out", "3 - Always"], "advanced": B},
|
||||||
"tactical_ping": {"widget": "toggle", "label": "Tactical Ping"},
|
"tactical_ping": {"widget": "toggle", "label": "Tactical Ping", "advanced": A},
|
||||||
"weapon_info": {"widget": "select", "label": "Weapon Info",
|
"weapon_info": {"widget": "select", "label": "Weapon Info",
|
||||||
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"]},
|
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"], "advanced": B},
|
||||||
"stance_indicator": {"widget": "select", "label": "Stance Indicator",
|
"stance_indicator": {"widget": "select", "label": "Stance Indicator",
|
||||||
"options": ["0 - Never", "1 - Experimental", "2 - Always", "3 - Always (soldier)"]},
|
"options": ["0 - Never", "1 - Experimental", "2 - Always", "3 - Always (soldier)"], "advanced": B},
|
||||||
"stamina_bar": {"widget": "select", "label": "Stamina Bar",
|
"stamina_bar": {"widget": "select", "label": "Stamina Bar",
|
||||||
"options": ["0 - Never", "1 - Low stamina only", "2 - Always"]},
|
"options": ["0 - Never", "1 - Low stamina only", "2 - Always"], "advanced": A},
|
||||||
"weapon_crosshair": {"widget": "toggle", "label": "Weapon Crosshair"},
|
"weapon_crosshair": {"widget": "toggle", "label": "Weapon Crosshair", "advanced": A},
|
||||||
"vision_aid": {"widget": "toggle", "label": "Vision Aid"},
|
"vision_aid": {"widget": "toggle", "label": "Vision Aid", "advanced": A},
|
||||||
"third_person_view": {"widget": "toggle", "label": "Third Person View"},
|
"third_person_view": {"widget": "toggle", "label": "Third Person View", "advanced": A},
|
||||||
"camera_shake": {"widget": "toggle", "label": "Camera Shake"},
|
"camera_shake": {"widget": "toggle", "label": "Camera Shake", "advanced": A},
|
||||||
"score_table": {"widget": "toggle", "label": "Show Score Table"},
|
"score_table": {"widget": "toggle", "label": "Show Score Table", "advanced": A},
|
||||||
"death_messages": {"widget": "toggle", "label": "Death Messages"},
|
"death_messages": {"widget": "toggle", "label": "Death Messages", "advanced": A},
|
||||||
"von_id": {"widget": "toggle", "label": "Show VoN Speaker ID"},
|
"von_id": {"widget": "toggle", "label": "Show VoN Speaker ID", "advanced": A},
|
||||||
"map_content_friendly": {"widget": "select", "label": "Map — Friendly Units",
|
"map_content_friendly": {"widget": "select", "label": "Map — Friendly Units",
|
||||||
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"]},
|
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"], "advanced": A},
|
||||||
"map_content_enemy": {"widget": "select", "label": "Map — Enemy Units",
|
"map_content_enemy": {"widget": "select", "label": "Map — Enemy Units",
|
||||||
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"]},
|
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"], "advanced": A},
|
||||||
"map_content_mines": {"widget": "select", "label": "Map — Mines",
|
"map_content_mines": {"widget": "select", "label": "Map — Mines",
|
||||||
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"]},
|
"options": ["0 - Never", "1 - Limited distance", "2 - Fade out", "3 - Always"], "advanced": A},
|
||||||
"auto_report": {"widget": "toggle", "label": "Auto Report (automatic radio reports)"},
|
"auto_report": {"widget": "toggle", "label": "Auto Report (automatic radio reports)", "advanced": A},
|
||||||
"multiple_saves": {"widget": "toggle", "label": "Multiple Saves"},
|
"multiple_saves": {"widget": "toggle", "label": "Multiple Saves", "advanced": A},
|
||||||
"ai_level_preset": {"widget": "select", "label": "AI Level Preset",
|
"ai_level_preset": {"widget": "select", "label": "AI Level Preset",
|
||||||
"options": ["0 - Low", "1 - Normal", "2 - High", "3 - Custom", "4 - Ultra"]},
|
"options": ["0 - Low", "1 - Normal", "2 - High", "3 - Custom", "4 - Ultra"], "advanced": B},
|
||||||
"skill_ai": {"widget": "number", "label": "AI Skill (0.0–1.0)", "min": 0, "max": 1},
|
"skill_ai": {"widget": "number", "label": "AI Skill (0.0–1.0)", "min": 0, "max": 1, "advanced": B},
|
||||||
"precision_ai": {"widget": "number", "label": "AI Precision / Accuracy (0.0–1.0)", "min": 0, "max": 1},
|
"precision_ai": {"widget": "number", "label": "AI Precision / Accuracy (0.0–1.0)", "min": 0, "max": 1, "advanced": B},
|
||||||
},
|
},
|
||||||
"launch": {
|
"launch": {
|
||||||
"world": {"widget": "text", "label": "Default World (map name)"},
|
# All launch/startup fields are advanced
|
||||||
"limit_fps": {"widget": "number", "label": "FPS Limit", "min": 1, "max": 1000},
|
"world": {"widget": "text", "label": "Default World (map name)", "advanced": A},
|
||||||
"cpu_count": {"widget": "number", "label": "CPU Core Count (0 = auto)", "min": 0},
|
"limit_fps": {"widget": "number", "label": "FPS Limit", "min": 1, "max": 1000, "advanced": A},
|
||||||
"ex_threads": {"widget": "number", "label": "Extra Thread Count", "min": 0},
|
"cpu_count": {"widget": "number", "label": "CPU Core Count (0 = auto)", "min": 0, "advanced": A},
|
||||||
"max_mem": {"widget": "number", "label": "Max RAM (MB, 0 = auto)", "min": 0},
|
"ex_threads": {"widget": "number", "label": "Extra Thread Count", "min": 0, "advanced": A},
|
||||||
"auto_init": {"widget": "toggle", "label": "Auto-Init (skip mission select)"},
|
"max_mem": {"widget": "number", "label": "Max RAM (MB, 0 = auto)", "min": 0, "advanced": A},
|
||||||
"load_mission_to_memory": {"widget": "toggle", "label": "Load Mission to Memory"},
|
"auto_init": {"widget": "toggle", "label": "Auto-Init (skip mission select)", "advanced": A},
|
||||||
"enable_ht": {"widget": "toggle", "label": "Enable HyperThreading"},
|
"load_mission_to_memory": {"widget": "toggle", "label": "Load Mission to Memory", "advanced": A},
|
||||||
"huge_pages": {"widget": "toggle", "label": "Enable Huge Pages (performance)"},
|
"enable_ht": {"widget": "toggle", "label": "Enable HyperThreading", "advanced": A},
|
||||||
"no_logs": {"widget": "toggle", "label": "Disable Server Logging"},
|
"huge_pages": {"widget": "toggle", "label": "Enable Huge Pages (performance)", "advanced": A},
|
||||||
"netlog": {"widget": "toggle", "label": "Enable Network Log"},
|
"no_logs": {"widget": "toggle", "label": "Disable Server Logging", "advanced": A},
|
||||||
|
"netlog": {"widget": "toggle", "label": "Enable Network Log", "advanced": A},
|
||||||
"extra_params": {"widget": "tag-list", "label": "Additional Startup Parameters",
|
"extra_params": {"widget": "tag-list", "label": "Additional Startup Parameters",
|
||||||
"placeholder": "-filePatching"},
|
"placeholder": "-filePatching", "advanced": A},
|
||||||
},
|
},
|
||||||
"rcon": {
|
"rcon": {
|
||||||
"rcon_password": {"widget": "password", "label": "RCon Password"},
|
"rcon_password": {"widget": "password", "label": "RCon Password", "advanced": B},
|
||||||
"max_ping": {"widget": "number", "label": "Max Ping for RCon (ms)", "min": 1},
|
"max_ping": {"widget": "number", "label": "Max Ping for RCon (ms)", "min": 1, "advanced": A},
|
||||||
"enabled": {"widget": "toggle", "label": "Enable RCon"},
|
"enabled": {"widget": "toggle", "label": "Enable RCon", "advanced": B},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
89
backend/tests/adapters/arma3/test_config_schema.py
Normal file
89
backend/tests/adapters/arma3/test_config_schema.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
"""Tests for Arma3ConfigGenerator.get_ui_schema() — advanced flag completeness."""
|
||||||
|
import pytest
|
||||||
|
from adapters.arma3.config_generator import Arma3ConfigGenerator
|
||||||
|
|
||||||
|
BASIC_FIELDS = {
|
||||||
|
"server": {
|
||||||
|
"hostname", "max_players", "password", "password_admin",
|
||||||
|
"motd_lines", "motd_interval",
|
||||||
|
"forced_difficulty", "auto_select_mission", "random_mission_order",
|
||||||
|
"persistent", "skip_lobby", "drawing_in_map",
|
||||||
|
"battleye", "verify_signatures", "allowed_file_patching",
|
||||||
|
"disable_von", "von_codec",
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"group_indicators", "friendly_tags", "enemy_tags",
|
||||||
|
"commands", "waypoints", "weapon_info", "stance_indicator",
|
||||||
|
"ai_level_preset", "skill_ai", "precision_ai",
|
||||||
|
},
|
||||||
|
"rcon": {"rcon_password", "enabled"},
|
||||||
|
}
|
||||||
|
|
||||||
|
ADVANCED_SAMPLES = {
|
||||||
|
"server": {
|
||||||
|
"server_command_password", "kick_duplicate", "vote_threshold",
|
||||||
|
"max_ping", "max_packet_loss", "disconnect_timeout",
|
||||||
|
"kick_on_ping", "log_file", "upnp", "loopback",
|
||||||
|
"admin_uids", "headless_clients", "local_clients",
|
||||||
|
"default_mission_params",
|
||||||
|
},
|
||||||
|
"basic": {
|
||||||
|
"min_bandwidth", "max_bandwidth", "max_msg_send",
|
||||||
|
"max_size_guaranteed", "min_error_to_send",
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"reduced_damage", "tactical_ping", "weapon_crosshair",
|
||||||
|
"vision_aid", "third_person_view", "score_table",
|
||||||
|
"death_messages", "von_id",
|
||||||
|
},
|
||||||
|
"launch": {
|
||||||
|
"world", "limit_fps", "cpu_count", "max_mem",
|
||||||
|
"enable_ht", "huge_pages", "no_logs", "netlog",
|
||||||
|
},
|
||||||
|
"rcon": {"max_ping"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def schema():
|
||||||
|
return Arma3ConfigGenerator().get_ui_schema()
|
||||||
|
|
||||||
|
|
||||||
|
def test_every_visible_field_has_advanced_key(schema):
|
||||||
|
"""Every non-hidden field must carry an explicit `advanced` bool."""
|
||||||
|
for section, fields in schema.items():
|
||||||
|
for field, entry in fields.items():
|
||||||
|
if entry.get("widget") == "hidden":
|
||||||
|
continue
|
||||||
|
assert "advanced" in entry, (
|
||||||
|
f"section={section!r} field={field!r} is missing 'advanced' key"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_basic_fields_are_not_advanced(schema):
|
||||||
|
"""Confirmed basic fields must have advanced=False."""
|
||||||
|
for section, field_names in BASIC_FIELDS.items():
|
||||||
|
for field in field_names:
|
||||||
|
entry = schema[section][field]
|
||||||
|
assert entry["advanced"] is False, (
|
||||||
|
f"section={section!r} field={field!r} should be basic (advanced=False)"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_advanced_samples_are_marked_advanced(schema):
|
||||||
|
"""Sampled advanced fields must have advanced=True."""
|
||||||
|
for section, field_names in ADVANCED_SAMPLES.items():
|
||||||
|
for field in field_names:
|
||||||
|
entry = schema[section][field]
|
||||||
|
assert entry["advanced"] is True, (
|
||||||
|
f"section={section!r} field={field!r} should be advanced (advanced=True)"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_hidden_fields_excluded_from_advanced_requirement(schema):
|
||||||
|
"""Hidden fields (e.g. missions) are exempt from the advanced check."""
|
||||||
|
for section, fields in schema.items():
|
||||||
|
for field, entry in fields.items():
|
||||||
|
if entry.get("widget") == "hidden":
|
||||||
|
# No advanced key required — just confirm widget is hidden
|
||||||
|
assert entry["widget"] == "hidden"
|
||||||
Reference in New Issue
Block a user