52 lines
3.3 KiB
Python
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')
|