Build independent base gameplay and source-bound native verification
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
"""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')
|
||||
Reference in New Issue
Block a user