|
| 1 | +"""Validate actual delegated-Init skip scopes across threads and exception unwind.""" |
| 2 | +from pathlib import Path |
| 3 | +import argparse |
| 4 | +import re |
| 5 | +import subprocess |
| 6 | +import tempfile |
| 7 | +from test_shutdown_routing import function |
| 8 | + |
| 9 | +ROOT=Path(__file__).resolve().parents[1] |
| 10 | +PRELUDE=r''' |
| 11 | +#include <future> |
| 12 | +#include <chrono> |
| 13 | +#include <stdexcept> |
| 14 | +#include <cstdlib> |
| 15 | +#include <iostream> |
| 16 | +int checks=0; |
| 17 | +void check(bool ok) { if(!ok) { std::cerr << "Init scope check " << checks+1 << " failed\n"; std::exit(2); } ++checks; } |
| 18 | +''' |
| 19 | + |
| 20 | +def main(): |
| 21 | + parser=argparse.ArgumentParser(); parser.add_argument('--compiler',required=True); parser.add_argument('--driver') |
| 22 | + args=parser.parse_args(); cpp=PRELUDE; checks=[] |
| 23 | + for api in ('Dx11','Dx12','Vk'): |
| 24 | + source=(ROOT/f'OptiScaler/inputs/NVNGX_DLSS_{api}.cpp').read_text(encoding='utf-8') |
| 25 | + flag=re.search(r'static (?:thread_local )?bool _skipInit = false;',source).group(0) |
| 26 | + scope=function(source,'class ScopedInit'+api)+';' |
| 27 | + cpp+='\nnamespace '+api+' {\n'+flag+'\n'+scope+'\n}\n' |
| 28 | + checks.append(f''' |
| 29 | + {{ |
| 30 | + using namespace {api}; |
| 31 | + check(!_skipInit); |
| 32 | + {{ |
| 33 | + ScopedInit{api} outer; |
| 34 | + check(_skipInit); |
| 35 | + {{ ScopedInit{api} inner; check(_skipInit); }} |
| 36 | + check(_skipInit); |
| 37 | + auto other=std::async(std::launch::async, [] {{ |
| 38 | + if(_skipInit) return false; |
| 39 | + {{ ScopedInit{api} worker; if(!_skipInit) return false; |
| 40 | + {{ ScopedInit{api} nested; if(!_skipInit) return false; }} |
| 41 | + if(!_skipInit) return false; |
| 42 | + }} |
| 43 | + return !_skipInit; |
| 44 | + }}); |
| 45 | + check(other.wait_for(std::chrono::seconds(5))==std::future_status::ready && other.get()); |
| 46 | + check(_skipInit); |
| 47 | + }} |
| 48 | + check(!_skipInit); |
| 49 | + try {{ ScopedInit{api} guard; throw std::runtime_error("init"); }} catch(const std::runtime_error&) {{}} |
| 50 | + check(!_skipInit); |
| 51 | + }} |
| 52 | + ''') |
| 53 | + cpp+='int main() {\n'+ '\n'.join(checks)+'\nstd::cout << "PASS: " << checks << " native Init scope checks\\n";\n}\n' |
| 54 | + with tempfile.TemporaryDirectory(prefix='aurora-init-scopes-') as directory: |
| 55 | + path=Path(directory); test=path/'test.cpp'; exe=path/'test.exe'; test.write_text(cpp,encoding='utf-8') |
| 56 | + command=[args.compiler]+([args.driver] if args.driver else []) |
| 57 | + if Path(args.compiler).stem.lower()=='cl': command+=['/nologo','/EHsc','/std:c++20',str(test),'/Fe:'+str(exe)] |
| 58 | + else: command+=['-std=c++20',str(test),'-o',str(exe)] |
| 59 | + subprocess.run(command,cwd=path,check=True) |
| 60 | + subprocess.run([str(exe)],cwd=path,check=True,timeout=30) |
| 61 | + |
| 62 | +if __name__=='__main__': main() |
0 commit comments