#include "providers.h" #include #include #include #include #include static void check(bool value,const char *message) { if (!value) throw std::runtime_error(message); } static std::vector read_file(const std::filesystem::path &path) { std::ifstream file(path,std::ios::binary | std::ios::ate); check(bool(file) && file.tellg()>0 && file.tellg()<1024*1024,"invalid exit fixture"); std::vector bytes(size_t(file.tellg())); file.seekg(0); check(bool(file.read(reinterpret_cast(bytes.data()),std::streamsize(bytes.size()))),"short exit fixture"); return bytes; } static uint32_t field(raven::ModuleSet &modules,const char *module,const char *name) { auto &loaded=modules.all().at(module)->loaded; const auto offset=modules.resolve({module,name,0,false,0})-loaded.base(); const auto bytes=loaded.data().subspan(size_t(offset),4); uint32_t value=0; for (unsigned i=0;i<4;++i) value|=uint32_t(bytes[i])<<(i*8); return value; } int main(int argc,char **argv) { try { check(argc==3,"bootstrap and exit fixture directory required"); const std::filesystem::path directory(argv[2]); for (unsigned mode=0;mode<9;++mode) { raven::ModuleSet modules; auto &entry=modules.add("client.exe",read_file(directory/("exit-"+std::to_string(mode)+".exe"))); unsigned loads=0,frames=0,removed=0; uint64_t window=0; const auto source=[&](std::string_view name)->std::optional> { ++loads; return read_file(directory/name); }; raven::DesktopPresentation presentation; presentation.present=[&](uint64_t handle,std::string_view title,uint32_t width,uint32_t height,std::span pixels) { check(handle && (!window || window==handle) && title=="Raven process exit" && width==8 && height==8 && pixels.size()==256,"exit callback surface differs"); window=handle; for (size_t at=0;at>child),"process exit retained native child"); } } catch (const std::exception &error) { std::cerr<