"""Actual fixture ownership/terminal cleanup plus explicit selector contracts.""" import os,re from pathlib import Path from policy_harness import ROOT,body,run root=Path(os.environ.get('ERR_NATIVE_OBJECTIVE_MAP_ROOT',ROOT));p=root/'addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveMapProbe.c' def adapt(s): s=s.replace('protected ','').replace('null','nullptr').replace('SCR_MapEntity.','SCR_MapEntity::') for name in ['m_Map','m_Config','m_Marker','m_Presentation','m_SharedRoot','m_ReusedRoot']: s=s.replace(name+'.',name+'->') for name in ['GetGame','GetMenuManager','GetOnMapOpenComplete','GetOnMapClose']: s=s.replace(name+'().',name+'()->') return s.replace('Remove(Ready)','Remove(this)').replace('Remove(Closed)','Remove(this)').replace('MapConfiguration config','Config* config') methods='\n'.join(adapt(body(p,s)) for s in ['protected bool OwnsMap(', 'protected bool CloseStandard(', 'protected int StandardClosed(', 'protected void Closed(', 'void Stop(']) run('''#include #include #include using string=std::string; struct Widget{int deletes=0;void RemoveFromHierarchy(){deletes++;}}; struct Config{Widget*RootWidgetRef=nullptr;}; struct Event{std::setowners;void Remove(void*p){owners.erase(p);}}; struct SCR_MapEntity{static inline SCR_MapEntity*current=nullptr;static inline Event opened,closed;Config*config=nullptr;Widget*root=nullptr;bool open=true;int closes=0;static SCR_MapEntity*GetMapInstance(){return current;}static Event*GetOnMapOpenComplete(){return &opened;}static Event*GetOnMapClose(){return &closed;}bool IsOpen(){return open;}Config*GetMapConfig(){return config;}Widget*GetMapMenuRoot(){return root;}void CloseMap(){closes++;open=false;}}; struct Marker{int deletes=0;void OnDelete(){deletes++;}};struct Presentation{int stops=0;Widget*root=nullptr;Widget*ERR_ProbeRoot(){return root;}void Stop(){stops++;root=nullptr;}};struct Menu{}; struct Manager{int closes=0;bool asynchronous=false;bool CloseMenu(Menu*){closes++;if(!asynchronous&&SCR_MapEntity::current)SCR_MapEntity::current->CloseMap();return true;}}; struct Game{Manager manager;Manager*GetMenuManager(){return &manager;}}game;Game*GetGame(){return &game;} struct Probe{bool m_Stopped=false,m_CloseRequested=false,m_CloseObserved=false;bool Check(bool ok,string){if(!ok)Stop();return ok;}SCR_MapEntity*m_Map=nullptr;Config*m_Config=nullptr,*m_Ready=nullptr;Widget*m_ExpectedRoot=nullptr,*m_SharedRoot=nullptr,*m_ReusedRoot=nullptr;Marker*m_Marker=nullptr;Presentation*m_Presentation=nullptr;Menu*m_Menu=nullptr; '''+methods+''' }; int main(){SCR_MapEntity map;SCR_MapEntity::current=↦Config cfg;Widget root,otherRoot,shared,reused;cfg.RootWidgetRef=&root;map.root=&root;map.config=&cfg; Probe p;p.m_Map=↦p.m_Config=&cfg;p.m_ExpectedRoot=&root;Marker marker;Presentation presentation;Menu menu;p.m_Marker=▮p.m_Presentation=&presentation;p.m_Menu=&menu;p.m_SharedRoot=&shared;p.m_ReusedRoot=&reused; assert(p.OwnsMap());cfg.RootWidgetRef=&otherRoot;assert(!p.OwnsMap());cfg.RootWidgetRef=&root;map.root=&otherRoot;assert(!p.OwnsMap());map.root=&root; SCR_MapEntity replacement;SCR_MapEntity::current=&replacement;assert(!p.OwnsMap());SCR_MapEntity::current=↦ SCR_MapEntity::opened.owners.insert(&p);p.Stop();assert(p.m_Stopped&&marker.deletes==1&&presentation.stops==1&&game.manager.closes==1&&map.closes==1&&shared.deletes==1&&reused.deletes==1&&!SCR_MapEntity::opened.owners.count(&p)); p.Stop();assert(marker.deletes==1&&map.closes==1&&shared.deletes==1); Probe interrupted;interrupted.m_Map=↦interrupted.m_Config=&cfg;interrupted.m_ExpectedRoot=&root;interrupted.m_Menu=&menu;map.open=true;map.root=&otherRoot;interrupted.Stop();assert(map.open&&map.closes==1&&game.manager.closes==1); Probe partial;partial.Stop();assert(partial.m_Stopped&&game.manager.closes==1); // Native CloseMenu can return while MapMenu.OnMenuClose has not happened. map.root=&root;map.open=true;game.manager.asynchronous=true; Probe pending;pending.m_Map=↦pending.m_Config=&cfg;pending.m_ExpectedRoot=&root;pending.m_Menu=&menu;pending.m_Presentation=&presentation;presentation.root=&shared; assert(pending.CloseStandard()&&pending.m_Menu==&menu&&pending.m_CloseRequested&&map.open);assert(game.manager.closes==2); assert(pending.StandardClosed()==0&&!pending.m_Stopped);assert(pending.StandardClosed()==0&&game.manager.closes==2); Config foreign;pending.Closed(&foreign);assert(!pending.m_CloseObserved); pending.Closed(&cfg);assert(pending.m_CloseObserved&&pending.StandardClosed()==0); // callback occurs before IsOpen clears map.open=false;presentation.root=nullptr;assert(pending.StandardClosed()==1&&!pending.m_Menu&&!pending.m_CloseRequested);assert(game.manager.closes==2); // Closed state alone cannot replace the observed exact native callback. Probe noEvent;noEvent.m_Map=↦noEvent.m_Config=&cfg;noEvent.m_ExpectedRoot=&root;noEvent.m_Menu=&menu;noEvent.m_Presentation=&presentation;map.open=true;assert(noEvent.CloseStandard());map.open=false;assert(noEvent.StandardClosed()==0&&noEvent.m_Menu==&menu);noEvent.Stop(); // A close request is not repeated by Stop or after foreign map adoption. Probe cancel;cancel.m_Map=↦cancel.m_Config=&cfg;cancel.m_ExpectedRoot=&root;cancel.m_Menu=&menu;map.open=true;assert(cancel.CloseStandard());int requests=game.manager.closes;cancel.Stop();assert(game.manager.closes==requests&&map.open); Probe displaced;displaced.m_Map=↦displaced.m_Config=&cfg;displaced.m_ExpectedRoot=&root;displaced.m_Menu=&menu;displaced.m_Presentation=&presentation;assert(displaced.CloseStandard());requests=game.manager.closes;map.root=&otherRoot;assert(displaced.StandardClosed()==-1&&displaced.m_Stopped&&map.open&&game.manager.closes==requests); // Exact close callback with a leaked production widget still fails. map.root=&root;Probe leak;leak.m_Map=↦leak.m_Config=&cfg;leak.m_ExpectedRoot=&root;leak.m_Menu=&menu;leak.m_Presentation=&presentation;assert(leak.CloseStandard());leak.Closed(&cfg);map.open=false;presentation.root=&shared;assert(leak.StandardClosed()==-1&&leak.m_Stopped); } ''') s=p.read_text();assert s.startswith('#ifdef WORKBENCH') assert 'System.GetTickCount() + 90000' in s and 'System.GetTickCount() + 180000' in s assert s.count('System.MakeScreenshot(')==7 assert s.count('ERR OBJECTIVE CAPTURE READY: ')==7 assert s.count('m_Wait = now + 1500; return 0;')==7 assert 'm_Stage >= 16 && m_Stage <= 23 && !Check(ReadyToInspect()' in s assert 'm_Stage == 6' in s and 'm_Stage == 15' in s and s.count('int closed = StandardClosed();')==2 assert 'SetBlocked(' not in s and 'SetPrivileged' not in s base=(root/'addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c').read_text() assert '"objective-map"' in base.split('ERR_NativeObjectiveProbe.BeginRound();')[0] runner=(root/'tools/headless_workbench.py').read_text() assert runner.index("objective-map requires --project core --rounds 1") < runner.index('steam, compat, profile =') # Actual invalid CLI must refuse before nonexistent prefix/profile processing. import subprocess,sys,tempfile with tempfile.TemporaryDirectory(prefix='err-objective-selector-') as temporary: sandbox=Path(temporary); profile=sandbox/'must-not-exist'; prefix=sandbox/'absent-prefix' environment=os.environ.copy(); environment['PYTHONPATH']=str(ROOT/'tools') for project,rounds in [('chat','1'),('core','2')]: result=subprocess.run([sys.executable,str(root/'tools/headless_workbench.py'),'--smoke','objective-map','--project',project,'--rounds',rounds,'--compat',str(prefix),'--profile',str(profile)],capture_output=True,text=True,env=environment) assert result.returncode==2 and 'objective-map requires --project core --rounds 1' in result.stderr,result.stderr assert not profile.exists() and not prefix.exists() print('PASS: actual native fixture root/config ownership and idempotent cleanup preserve foreign map, selector excludes ordinary route, fixed budgets/screenshots/UGC boundaries retained; native operations not executed') # Execute the complete actual Inspect method: parent identity and frame projection # are checked independently from native image-box coordinates. These are API # doubles, not proof of engine widget parenting, pixels or pointer transparency. inspect=body(p,'protected bool Inspect(').replace('protected ','') for t in ['Widget','ERR_ObjectiveMapElement','TextWidget','ImageWidget']: inspect=re.sub(r'\b'+t+r' (?=\w)',t+'* ',inspect) for name in ['m_Presentation','m_Map','m_ExpectedRoot','m_Marker','root','element','container','nativeIcons','text','image']: inspect=inspect.replace(name+'.',name+'->') for name in ['GetGame','GetWorkspace','GetMapWidget']: inspect=inspect.replace(name+'().',name+'()->') for name in ['TextWidget','ImageWidget','ERR_DiscoveryMapRules','FrameSlot','Math']: inspect=inspect.replace(name+'.',name+'::') run(r''' #include #include #include #include using string=std::string;using vector=std::array; struct Widget{Widget*parent=nullptr,*container=nullptr,*overlay=nullptr,*text=nullptr,*image=nullptr;vector placed={0,0,0};float sx=0,sy=0,width=36,height=36;bool visible=true;virtual ~Widget()=default;Widget*GetParent(){return parent;}Widget*FindAnyWidget(string n){if(n=="UIIconsContainer")return container;if(n=="ERR_ObjectiveOverlay")return overlay;if(n=="ObjectiveText")return text;if(n=="Image")return image;return nullptr;}int GetZOrder(){return 20;}bool IsVisible(){return visible;}void GetScreenPos(float&x,float&y){x=sx;y=sy;}void GetScreenSize(float&w,float&h){w=width;h=height;}}; struct TextWidget:Widget{string label;static TextWidget*Cast(Widget*w){return dynamic_cast(w);}string GetText(){return label;}}; struct ImageWidget:Widget{static ImageWidget*Cast(Widget*w){return dynamic_cast(w);}void GetImageSize(int,int&w,int&h){w=64;h=64;}}; struct ERR_ObjectiveMapElement{vector pos;vector GetPos(){return pos;}}; struct Presentation{Widget*root=nullptr,*canvas=nullptr,*container=nullptr;ERR_ObjectiveMapElement*element=nullptr;Widget*ERR_ProbeRoot(){return root;}Widget*ERR_ProbeCanvas(){return canvas;}Widget*ERR_ProbeContainer(){return container;}ERR_ObjectiveMapElement*ERR_ProbeElement(){return element;}}; struct Map{Widget*canvas=nullptr;int x=240,y=180;Widget*GetMapWidget(){return canvas;}void WorldToScreen(int,int,int&ox,int&oy,bool pan){assert(pan);ox=x;oy=y;}}; struct Marker{int x=6123,y=7027;void GetWorldPos(int p[2]){p[0]=x;p[1]=y;}}; struct Workspace{float dpi=2;float DPIUnscale(float x){return x/dpi;}}; struct Game{Workspace workspace;Workspace*GetWorkspace(){return &workspace;}}game;Game*GetGame(){return &game;} struct FrameSlot{static vector GetPos(Widget*w){return w->placed;}}; struct Math{static float AbsFloat(float x){return std::fabs(x);}}; struct ERR_DiscoveryMapRules{static int Coordinate(float x,int knowledge){return knowledge==1?int(std::floor(x/500))*500+250:int(x);}}; templatevoid PrintFormat(T...){} struct Probe{Presentation*m_Presentation;Map*m_Map;Widget*m_ExpectedRoot;Marker*m_Marker;vector m_Point={6123,0,7027};int m_Stage=3;bool ready=true;bool ReadyToInspect(){return ready;}bool Check(bool b,string){return b;} '''+inspect+r''' }; int main(){Widget menu,container,nativeIcons,canvas,root,foreign;TextWidget text;ImageWidget image;ERR_ObjectiveMapElement element;Presentation presentation;Map map;Marker marker; menu.container=&nativeIcons;nativeIcons.parent=&container;root.parent=&container;root.text=&text;root.image=ℑtext.label="Radio station";element.pos={6123,0,7027}; canvas.sx=100;canvas.sy=60;container.sx=24;container.sy=10; presentation.root=&root;presentation.canvas=&canvas;presentation.container=&container;presentation.element=&element;map.canvas=&canvas; // Canvas-relative projection240,180 -> screen340,240; supported parent has // origin24,10, so slot(158,115) at DPI2, not slot(120,90). root.placed={158,115,0};image.sx=322;image.sy=222; Probe probe{&presentation,&map,&menu,&marker};assert(probe.Inspect(text.label,false)); root.placed={120,90,0};assert(!probe.Inspect(text.label,false));root.placed={158,115,0}; root.parent=&canvas;assert(!probe.Inspect(text.label,false));root.parent=&container; nativeIcons.parent=&foreign;assert(!probe.Inspect(text.label,false));nativeIcons.parent=&container; presentation.container=&foreign;assert(!probe.Inspect(text.label,false));presentation.container=&container; presentation.canvas=&foreign;assert(!probe.Inspect(text.label,false));presentation.canvas=&canvas; image.sx+=4;assert(!probe.Inspect(text.label,false));image.sx-=4; element.pos[0]+=1;assert(!probe.Inspect(text.label,false));element.pos[0]-=1; root.visible=false;assert(!probe.Inspect(text.label,false));root.visible=true; probe.ready=false;assert(!probe.Inspect(text.label,false));probe.ready=true; // Another valid parent origin and non-unit DPI cannot be compensated by // dropping screen-origin offsets from the projection assertion. container.sx=120;container.sy=110;game.workspace.dpi=1.25;root.placed={176,104,0};assert(probe.Inspect(text.label,false)); // Shared render roots choose their dedicated overlay instead of native icons. menu.overlay=&container;nativeIcons.parent=&foreign;assert(probe.Inspect(text.label,false)); menu.overlay=&foreign;assert(!probe.Inspect(text.label,false));menu.overlay=&container; marker.x=6250;marker.y=7250;element.pos={6250,0,7250};assert(probe.Inspect(text.label,true)); } ''') print('PASS: actual full Inspect rejects canvas parenting, wrong active container/canvas, omitted origin offset, wrong rendered box and stale coordinates; differing origins and DPI accepted') # Execute the added actual three phase blocks. Long-label capture must happen # before reset/close, and the radio label must be restored for later reopening. phases='\n'.join(body(p,'if (m_Stage == '+str(stage)+')') for stage in [5,22,23]) phases=phases.replace('m_Marker.','m_Marker->').replace('System.','System::') run(r''' #include #include using string=std::string; struct Marker{string label="Radio station";void SetCustomText(string text){label=text;}}; struct System{static inline int captures=0;static void MakeScreenshot(string path){assert(path=="$logs:err-objective-map-standard-long-warning");captures++;}}; int checkpoints=0;void Print(string text){assert(text=="ERR OBJECTIVE CAPTURE READY: standard-long-warning");checkpoints++;} struct Probe{Marker*m_Marker;int m_Stage=5,closes=0,inspections=0;float m_Wait=0;bool Inspect(string text,bool rough){inspections++;return !rough&&m_Marker->label==text;}bool CloseStandard(){assert(m_Marker->label=="Radio station");closes++;return true;} int Advance(float now){if(now').replace('Math.Min','std::min').replace('std::min(100, width * 0.25)', 'std::min(100.f, width * 0.25f)').replace('protected ','').replace('m_Marker.','m_Marker->').replace('m_Map.','m_Map->') run(r''' #include #include #include #include struct Canvas{float width=500;void GetScreenSize(float&w,float&h){w=width;h=500;}}; struct Marker{int x=6250,y=7250;void GetWorldPos(int p[2]){p[0]=x;p[1]=y;}}; struct Map{Canvas canvas;Canvas*GetMapWidget(){return &canvas;}float zoom=0,x=0,y=0,duration=0;int calls=0;void ZoomPanSmooth(float z,float px,float py,float t){zoom=z;x=px;y=py;duration=t;calls++;}}; struct Probe{Marker*m_Marker;Map*m_Map; '''+center+r''' }; int main(){Marker marker;Map map;Probe p{&marker,&map};for(float zoom:{0.3f,0.6f}){p.Center(zoom);assert(map.zoom==zoom&&map.y==7250&&std::abs(map.duration-0.1f)<0.001f);assert(std::abs((marker.x-map.x)*zoom+100.0f)<0.01f);assert(marker.x==6250&&marker.y==7250);}assert(map.calls==2);map.canvas.width=124;p.Center(.3f);assert(std::abs((map.x-marker.x)*.3f-31)<.01f);} ''') print('PASS: actual Center keeps marker offset within large and small native viewports at both fixture zooms without altering disclosed coordinates')