Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
60 lines
3.7 KiB
Python
60 lines
3.7 KiB
Python
"""Exercise the production client tick with HTTP/audio substituted, across worlds."""
|
|
from policy_harness import ROOT, body, run
|
|
p = ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_WelcomeVoice.c'
|
|
url = body(p, 'static bool URL(')
|
|
connection = 'class Connection { bool m_Attempted=false; public: ' + '\n'.join(body(p,s) for s in ['void MainMenu()', 'bool Claim()', 'bool Attempted()']) + '};'
|
|
tick = body(p, 'void Tick(')
|
|
for old,new in [('m_Connection.', 'm_Connection->'), ('m_Callback.', 'm_Callback->'),
|
|
('context.', 'context->'), ('RestContext context', 'RestContext* context'),
|
|
('GetGame().GetRestApi().GetContext', 'game.api.GetContext'),
|
|
('null', 'nullptr'), ('ERR_WelcomeVoiceRules.URL', 'Rules::URL'), ('ERR_WelcomeVoiceRules.HTTPReady', 'Rules::HTTPReady'),
|
|
('FileIO.DeleteFile', 'FileIO::DeleteFile'), ('LogLevel.WARNING','0')]:
|
|
tick=tick.replace(old,new)
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <string>
|
|
struct string:std::string { using std::string::string; string(std::string s):std::string(s){}
|
|
bool IsEmpty(){return empty();} int Length(){return size();}
|
|
int IndexOf(string s){auto p=find(s);return p==npos?-1:int(p);}
|
|
};
|
|
bool httpReady=true;
|
|
struct Rules { static bool HTTPReady(){return httpReady;} '''+url+r''' };
|
|
'''+connection+r'''
|
|
struct RestCallback { void SetOnSuccess(int){} void SetOnError(int){} };
|
|
int requests=0;
|
|
struct RestContext { void SetTimeout(int){} void GET(RestCallback*,string){requests++;} } context;
|
|
struct Api { RestContext* GetContext(string){return &context;} };
|
|
struct Game { Api api; } game;
|
|
struct FileIO { static void DeleteFile(string){} };
|
|
void Print(string,int=0){}
|
|
struct Client {
|
|
Connection* m_Connection; bool m_Stopped=false,m_Downloaded=false,m_Started=false,current=true;
|
|
float m_Wait=0; string m_Path,m_Text; RestCallback* m_Callback=nullptr; int Downloaded=0,Failed=0,plays=0;
|
|
Client(Connection* c):m_Connection(c){} ~Client(){delete m_Callback;}
|
|
bool permit=true; bool Permit(){return permit;} bool Current(){return current;} void Play(){plays++;}
|
|
'''+tick+r'''
|
|
};
|
|
int main(){
|
|
Connection connection;
|
|
Client first(&connection);
|
|
httpReady=false; first.Tick(60,true,"http://voice/clip", ""); assert(requests==0 && !connection.Attempted()); httpReady=true;
|
|
first.Tick(60,true,"", ""); assert(requests==0 && !connection.Attempted());
|
|
first.Tick(60,false,"http://voice/clip", "hello"); assert(requests==0);
|
|
first.permit=false; first.Tick(60,true,"http://voice/clip", "hello"); assert(requests==0 && !connection.Attempted()); first.permit=true; first.m_Wait=0;
|
|
first.Tick(2,true,"http://voice/clip", "hello"); assert(requests==0);
|
|
first.Tick(1,true,"http://voice/clip", "hello"); assert(requests==1);
|
|
first.m_Downloaded=true;
|
|
first.Tick(1,false,"http://voice/clip", "changed"); assert(first.plays==0);
|
|
first.Tick(1,true,"http://voice/clip", "changed"); assert(first.plays==1 && first.m_Text=="hello");
|
|
for(int i=0;i<100;i++)first.Tick(60,true,"http://voice/new", "changed");
|
|
assert(first.plays==1 && requests==1);
|
|
Client nextWorld(&connection); nextWorld.Tick(60,true,"http://voice/new", "new terrain"); assert(requests==1);
|
|
first.m_Stopped=true; first.m_Downloaded=true; first.Tick(60,true,"http://voice/new", ""); assert(first.plays==1);
|
|
connection.MainMenu();
|
|
Client reconnect(&connection); reconnect.Tick(3,true,"http://voice/new", "new terrain"); assert(requests==2);
|
|
// A failed request is still consumed for this connection, including a reload.
|
|
Client afterFailure(&connection); afterFailure.Tick(60,true,"http://voice/new", ""); assert(requests==2);
|
|
}
|
|
''')
|
|
print('PASS: actual welcome tick waits for URL/readiness/server permit, preserves local once-only state across worlds and refuses stopped callbacks')
|