Files
EscapistsReintroduced/tests/test_environment_policy.py
T

52 lines
3.3 KiB
Python

"""Execute actual environment parsing/formatting and settings policy bodies.
Calendar validity expectations come from Python's independent datetime calendar.
"""
from datetime import date
import re
from policy_harness import ROOT, body, run
settings = ROOT/'addons/core/Scripts/Game/ERR/ERR_Settings.c'
service = ROOT/'addons/core/Scripts/Game/ERR/ERR_EnvironmentService.c'
admin = ROOT/'addons/core/Scripts/Game/ERR/ERR_AdminService.c'
def translate(source):
source = (source.replace('string ', 'std::string ').replace('out int ', 'int& ')
.replace('text.Length()', 'int(text.size())').replace('.IsEmpty()', '.empty()')
.replace('.Substring(', '.substr(')
.replace('"0123456789".IndexOf(', 'std::string("0123456789").find(')
.replace(' < 0) return false;', ' == std::string::npos) return false;')
.replace('text.ToInt()', 'std::stoi(text)')
.replace('ERR_CommandArguments.Integer', 'Integer').replace('ERR_Settings.Valid', 'Valid'))
return re.sub(r'(\w+)\.ToString\(\)', r'std::to_string(\1)', source)
functions='\n'.join(translate(body(path, sig)) for path, sig in (
(settings,'static bool Valid('), (settings,'static int AddedDefault('),
(admin,'static bool Integer('), (service,'static string Pad2('),
(service,'static string Date('), (service,'static bool ParseDate('),
(service,'static string ProfileName('), (service,'static string WeatherStateName('),
(service,'static bool ParseProfile('),
))
cases=[]
# Every calendar boundary in range, including leap/century rules and malformed days.
for year in range(1900,2051):
for month in range(1,13):
for day in (0,1,28,29,30,31,32):
code=(year-1900)*10000+month*100+day
text=f'{year:04}-{month:02}-{day:02}'
try: date(year,month,day); valid=True
except ValueError: valid=False
cases.append(f'{{{code},"{text}",{str(valid).lower()}}}')
run('#include <cassert>\n#include <string>\n'+functions+'\nstruct Case {int code; const char* text; bool valid;};\nstatic Case cases[]={' + ','.join(cases) + '};\nint main(){int parsed=-1;' + r'''
for (auto c:cases) {assert(Valid("startDateCode",c.code)==c.valid); assert(ParseDate(c.text,parsed)==c.valid); if(c.valid)assert(parsed==c.code && Date(parsed)==c.text);}
assert(AddedDefault("startDateCode")==0 && AddedDefault("weatherProfile")==0);
assert(Valid("startDateCode",0) && Date(0)=="authored" && ParseDate("authored",parsed) && parsed==0);
for(std::string text:{"1900-00-00","1900-00-01","2050-13-01","1899-12-31","2051-01-01","1989-6-01","1989-06-1","1989-06-01junk"," 1989-06-01","1989-06-01 ","198a-06-01","", "1989/06/01"}) assert(!ParseDate(text,parsed));
assert(!Valid("startDateCode",-1) && !Valid("startDateCode",1501232));
for(int p=0;p<=3;p++){assert(Valid("weatherProfile",p)); assert(ParseProfile(ProfileName(p),parsed)&&parsed==p);}
assert(ParseProfile("rainy",parsed)&&parsed==3);
assert(!ParseProfile("random",parsed)&&!ParseProfile("storm",parsed));
assert(!Valid("weatherProfile",-1)&&!Valid("weatherProfile",4));
assert(WeatherStateName(0)=="" && WeatherStateName(1)=="Clear" && WeatherStateName(2)=="Overcast" && WeatherStateName(3)=="Rainy");
}
''')
print('PASS: native settings policy matches calendar boundaries 1900-2050, date/profile parsing is strict, authored defaults preserve old worlds')