diff --git a/Apps/UnitTests/Shared/Tests.h b/Apps/UnitTests/Shared/Tests.h index 97a0a4a37..61590aff1 100644 --- a/Apps/UnitTests/Shared/Tests.h +++ b/Apps/UnitTests/Shared/Tests.h @@ -62,10 +62,72 @@ TEST(JSTest, JavaScriptTests) EXPECT_EQ(code, 0); } +TEST(NativeAPI, Shutdown) +{ + static constexpr char* testScripts[] = { + + // warmup, should not crash. Just here to verify StepCode + R"( + var engine = new BABYLON.NativeEngine(); + var scene = new BABYLON.Scene(engine); + StepCode(); + )", + // Async operation (crash with v8, not Chakra) + R"( + var engine = new BABYLON.NativeEngine(); + var scene = new BABYLON.Scene(engine); + const texture = new BABYLON.Texture("https://assets.babylonjs.com/textures/earth.jpg", scene, false, false, 0, ()=>{ + console.log("onLoadObservable", texture.getSize().width); + }); + StepCode(); + )", + // crash with V8/Chakra : Looks like GC is kicking texture (?) before onLoadObservable is called. => Access violation reading location 0x0000000000000000. + R"( + var engine = new BABYLON.NativeEngine(); + var scene = new BABYLON.Scene(engine); + const texture = new BABYLON.Texture("https://assets.babylonjs.com/textures/earth.jpg", scene); + texture.onLoadObservable.addOnce(() => { + console.log("onLoadObservable", texture.getSize().width); + StepCode(); + }); + )", + }; + int scriptIndex{}; + for (const auto testScript: testScripts) + { + Babylon::Graphics::Device device = deviceTestConfig; + std::promise stepCode; + + Babylon::AppRuntime runtime{}; + runtime.Dispatch([&device, &stepCode](Napi::Env env) { + device.AddToJavaScript(env); + + Babylon::Polyfills::XMLHttpRequest::Initialize(env); + Babylon::Polyfills::Console::Initialize(env, [](const char* message, auto) { + printf("%s", message); + fflush(stdout); + }); + + env.Global().Set("StepCode", Napi::Function::New(env, [&stepCode](const Napi::CallbackInfo& ) { + stepCode.set_value(1); + }, "StepCode")); + + Babylon::Polyfills::Window::Initialize(env); + Babylon::Plugins::NativeEngine::Initialize(env); + }); + + Babylon::ScriptLoader loader{runtime}; + loader.LoadScript("app:///Scripts/babylon.max.js"); + loader.LoadScript("app:///Scripts/babylonjs.materials.js"); + loader.Eval(testScript, "testScript"); + auto code{stepCode.get_future().get()}; // waiting step before disposing appruntime + printf("End of test %d\n", scriptIndex++); + } +} /* This test does a serie of initialization and shutdowns. It needs the shutdown PR to be merged before running properly. -TEST(NativeAPI, LifeCycle) +TEST(NativeAPI, life_cycle) { for (int cycle = 0; cycle < 20; cycle++) {