"""Execute fixture's actual ownership/cleanup and callback-evidence decisions. Explicit native boundary doubles; this is not a native rendering/camera test. """ import re from policy_harness import ROOT, body, run SOURCE = ROOT / 'addons/core/Scripts/Game/ERR/30_Map/ERRM_NativeMapOwnershipProbe.c' def method(signature): text = body(SOURCE, signature).replace('protected ', '') text = re.sub(r'^ Print\(string\.Format[^\n]+\n', '', text, flags=re.M) text = text.replace('SCR_MapEntity.GetMapInstance()', 'Map::current') text = text.replace('SCR_MapEntity.GetOnMapClose().Remove(OnMapClosed)', 'closeObserver.Remove(this)') text = text.replace('SCR_MapEntity.GetOnMapOpenComplete().Remove(OnMapReady)', 'readyObserver.Remove(this)') text = text.replace('SCR_EntityHelper.DeleteEntityAndChildren(', 'DeleteEntityAndChildren(') for field in ['m_Map', 'm_ReplacementConfig', 'm_ReplacementRoot', 'm_Capture', 'm_Spare']: text = text.replace(field + '.', field + '->') return re.sub(r'\bnull\b', 'nullptr', text) methods = '\n'.join(method(x) for x in [ 'protected bool ReplacementIsCurrent(', 'void Stop()', 'protected void SaveCounters(', 'protected bool VerifyStaleAndStop(', 'protected bool DeletionComplete(', 'protected void RequestOwnedDeletion(', 'void ObserveDeletion(']) # The first Stop in this file is the fixture method; adapters are named distinctly. run(r''' #include #include #include #include struct Probe; struct Widget { int removes=0;void RemoveFromHierarchy(){removes++;} }; struct Config { Widget* RootWidgetRef=nullptr; }; struct Entity { int deletes=0; }; void DeleteEntityAndChildren(Entity*& value){value->deletes++;value=nullptr;} struct Map { static Map* current;bool opened=true;Config* config=nullptr;Widget* root=nullptr; int closes=0;float pan=0,zoom=0;bool IsOpen(){return opened;}Config* GetMapConfig(){return config;} Widget* GetMapMenuRoot(){return root;}void CloseMap(){closes++;opened=false;} float GetCurrentPan(){return pan;}float GetTargetZoomPPU(){return zoom;} };Map* Map::current=nullptr; struct Capture {int stops=0;void ERRM_StopOwnershipCapture(){stops++;}}; struct Observer {std::vector owners;void Remove(Probe* p){owners.erase(std::remove(owners.begin(),owners.end(),p),owners.end());}}; Observer closeObserver,readyObserver; struct Probe { Map* m_Map=nullptr;Widget* m_ReplacementRoot=nullptr;Config* m_ReplacementConfig=nullptr;Config* m_ReadyConfig=nullptr; Capture *m_Capture=nullptr,*m_Spare=nullptr;Entity *m_CaptureEntity=nullptr,*m_SpareEntity=nullptr,*m_Holder=nullptr; bool m_DeleteRequested=false,m_DeleteStateFailed=false;int m_CaptureDeleted=0,m_SpareDeleted=0; bool m_Stopped=false;int m_CloseEvents=0,m_RestoreCalls=0,m_RestoreAuthorized=0,m_Completions=0,m_CenterCalls=0,m_FinishCalls=0; int m_CloseBaseline=0,m_RestoreBaseline=0,m_AuthorizedBaseline=0,m_CompletionBaseline=0,m_CenterBaseline=0,m_FinishBaseline=0; float m_PanBaseline=0,m_ZoomBaseline=0; bool Check(bool result,const std::string&){if(!result)Stop();return result;} '''+methods+r''' void Bind(Map& map,Config& cfg,Widget& root,Capture& c,Capture& s,Entity& ce,Entity& se){ m_Map=↦Map::current=↦m_ReplacementConfig=&cfg;m_ReplacementRoot=&root; map.opened=true;map.config=&cfg;map.root=&root;cfg.RootWidgetRef=&root; m_Capture=&c;m_Spare=&s;m_CaptureEntity=&ce;m_SpareEntity=&se; closeObserver.owners.push_back(this);readyObserver.owners.push_back(this); } }; int main(){ Map map;Config cfg,foreignCfg;Widget root,foreignRoot;Capture capture,spare;Entity ce,se; Probe foreign;foreign.Bind(map,cfg,root,capture,spare,ce,se); Probe other;closeObserver.owners.push_back(&other);readyObserver.owners.push_back(&other); // Same object reused with another native root must not be closed in cleanup. cfg.RootWidgetRef=&foreignRoot;map.root=&foreignRoot; assert(!foreign.ReplacementIsCurrent());foreign.Stop(); assert(map.closes==0&&map.opened&&root.removes==1&&foreignRoot.removes==0); assert(ce.deletes==1&&se.deletes==1&&capture.stops==1&&spare.stops==1); assert(closeObserver.owners.size()==1&&closeObserver.owners[0]==&other); assert(readyObserver.owners.size()==1&&readyObserver.owners[0]==&other); foreign.Stop();assert(root.removes==1&&ce.deletes==1); // no duplicate cleanup Probe changed;changed.Bind(map,cfg,root,capture,spare,ce,se);map.config=&foreignCfg; changed.Stop();assert(map.closes==0); // distinct active config also preserved Probe oldWorld;oldWorld.Bind(map,cfg,root,capture,spare,ce,se);Map replacementWorld;Map::current=&replacementWorld; oldWorld.Stop();assert(map.closes==0); // old singleton cannot be closed Probe exact;exact.Bind(map,cfg,root,capture,spare,ce,se);exact.Stop();assert(map.closes==1&&!map.opened); // A correct view without callbacks running must not pass native evidence. Probe missed;missed.Bind(map,cfg,root,capture,spare,ce,se);missed.SaveCounters();missed.m_RestoreCalls++; assert(!missed.VerifyStaleAndStop()&&missed.m_Stopped); Probe observed;observed.Bind(map,cfg,root,capture,spare,ce,se);observed.SaveCounters(); observed.m_CenterCalls+=2;observed.m_FinishCalls++;observed.m_RestoreCalls++; assert(observed.VerifyStaleAndStop()&&!observed.m_Stopped&&map.opened); observed.Stop(); Probe moved;moved.Bind(map,cfg,root,capture,spare,ce,se);moved.SaveCounters(); moved.m_CenterCalls+=2;moved.m_FinishCalls++;moved.m_RestoreCalls++;map.pan=1; assert(!moved.VerifyStaleAndStop()); // actual changed map pan invalidates evidence map.pan=0; Probe closed;closed.Bind(map,cfg,root,capture,spare,ce,se);closed.SaveCounters(); closed.m_CenterCalls+=2;closed.m_FinishCalls++;closed.m_RestoreCalls++;closed.m_CloseEvents++; assert(!closed.VerifyStaleAndStop()); // even a close/reopen to same view fails // Request return is not deletion completion. Native refs and superclass // completion are separate observations, all required, without timeout waiver. Probe delayed;delayed.Bind(map,cfg,root,capture,spare,ce,se); assert(!delayed.DeletionComplete());delayed.RequestOwnedDeletion(); int ceDeletes=ce.deletes,seDeletes=se.deletes;delayed.RequestOwnedDeletion(); assert(ce.deletes==ceDeletes&&se.deletes==seDeletes); // exactly one request assert(!delayed.m_CaptureEntity&&!delayed.m_SpareEntity&&!delayed.DeletionComplete()); delayed.ObserveDeletion(1,true);delayed.ObserveDeletion(2,true); assert(!delayed.DeletionComplete()); // callbacks alone don't invalidate native refs delayed.m_Capture=nullptr;delayed.m_Spare=nullptr; // explicit native-boundary simulation assert(delayed.DeletionComplete());delayed.ObserveDeletion(2,true); assert(!delayed.DeletionComplete()); // duplicate cleanup is never accepted Probe unreleased;unreleased.m_DeleteRequested=true; unreleased.ObserveDeletion(1,false);unreleased.ObserveDeletion(2,true); assert(!unreleased.DeletionComplete()); // a post-super leftover field fails Probe premature;premature.ObserveDeletion(1,true);premature.m_DeleteRequested=true; premature.ObserveDeletion(2,true);assert(!premature.DeletionComplete()); } ''') text = SOURCE.read_text() assert text.startswith('#ifdef WORKBENCH\n') and text.rstrip().endswith('#endif') for name in ('CenterMapOnHolder', 'FinishMapCapture', 'RestoreCharacterCamera', 'CompleteMapModeSwitch'): assert 'super.' + name + '();' in body(SOURCE, 'protected override void ' + name + '(') deletion = body(SOURCE, 'protected override void OnDelete(') assert deletion.index('super.OnDelete(owner)') < deletion.index('probe.ObserveDeletion(') assert 'now >= m_DeleteDeadline' in text and 'm_DeleteDeadline = now + 3000' in text assert 'SetCharacterCameraRenderActive(' not in text # no guessed getter or explicit write assert 'GetOnMapOpenComplete().Insert(OnMapReady)' in text assert 'm_ReadyConfig == m_ReplacementConfig' in text assert 'CallLater(CenterMapOnHolder, 100, false)' in text assert 'CallLater(FinishMapCapture, 200, false)' in text print('PASS: actual native-map fixture ownership, cleanup and callback evidence fail closed; native execution remains separate')