Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Tests/UnitTests/Android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application android:label="@string/app_name" />
<!-- The unit tests talk to a loopback HTTP server the test host starts (Shared/TestHttpServer.h);
plain http:// to 127.0.0.1 is cleartext, which targetSdk 28+ blocks unless opted in. -->
<application android:label="@string/app_name" android:usesCleartextTraffic="true" />

<uses-permission android:name="android.permission.INTERNET" />

Expand Down
3 changes: 2 additions & 1 deletion Tests/UnitTests/Android/app/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ add_library(UnitTestsJNI SHARED
${UNIT_TESTS_DIR}/Shared/StandardStreamLogger.cpp
${UNIT_TESTS_DIR}/Shared/TimeoutDispatcher.cpp
${UNIT_TESTS_DIR}/Shared/Shared.h
${UNIT_TESTS_DIR}/Shared/Shared.cpp)
${UNIT_TESTS_DIR}/Shared/Shared.cpp
${UNIT_TESTS_DIR}/Shared/TestHttpServer.cpp)

if(NAPI_JAVASCRIPT_ENGINE STREQUAL "V8")
target_sources(UnitTestsJNI PRIVATE ${UNIT_TESTS_DIR}/Shared/V8ForegroundTaskRunner.cpp)
Expand Down
4 changes: 3 additions & 1 deletion Tests/UnitTests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ set(SOURCES
"Shared/StandardStreamLogger.cpp"
"Shared/TimeoutDispatcher.cpp"
"Shared/Shared.cpp"
"Shared/Shared.h")
"Shared/Shared.h"
"Shared/TestHttpServer.cpp"
"Shared/TestHttpServer.h")

if(APPLE)
if(IOS)
Expand Down
49 changes: 32 additions & 17 deletions Tests/UnitTests/Scripts/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ Mocha.reporter('spec');

declare const hostPlatform: string;
declare const hostEngine: string;
declare const hostTestServer: string;

// Loopback HTTP server the host starts for this run (Shared/TestHttpServer.h); the network tests use
// it instead of public hosts so they never depend on github.com being reachable from the runner.
const testServer = {
ok: `${hostTestServer}/`,
notFound: `${hostTestServer}/babylonJS/BabylonNative404`,
// The same file name, "στρογγυλεμένος % κύβος.glb", in three spellings the client must all put on
// the wire as one correctly percent-encoded request-target.
unicodeAssetEscaped: `${hostTestServer}/assets/%CF%83%CF%84%CF%81%CE%BF%CE%B3%CE%B3%CF%85%CE%BB%CE%B5%CE%BC%CE%AD%CE%BD%CE%BF%CF%82%20%25%20%CE%BA%CF%8D%CE%B2%CE%BF%CF%82.glb`,
unicodeAssetUnescaped: `${hostTestServer}/assets/στρογγυλεμένος%20%25%20κύβος.glb`,
unicodeAssetUnescapedWithSpaces: `${hostTestServer}/assets/στρογγυλεμένος %25 κύβος.glb`,
// Responds after two seconds, so an abort issued right after send() is guaranteed to land in-flight.
slow: `${hostTestServer}/delay/2000`,
};
declare const setExitCode: (code: number) => void;


Expand Down Expand Up @@ -124,39 +139,39 @@ describe("XMLHTTPRequest", function () {
this.timeout(0);

it("should have readyState=4 when load ends", async function () {
const xhr = await createRequest("GET", "https://github.com/");
const xhr = await createRequest("GET", testServer.ok);
expect(xhr.readyState).to.equal(4);
});

it("should have status=200 for a file that exists", async function () {
const xhr = await createRequest("GET", "https://github.com/");
const xhr = await createRequest("GET", testServer.ok);
expect(xhr.status).to.equal(200);
});

it("should load URLs with escaped unicode characters", async function () {
const xhr = await createRequest("GET", "https://raw.githubusercontent.com/BabylonJS/Assets/master/meshes/%CF%83%CF%84%CF%81%CE%BF%CE%B3%CE%B3%CF%85%CE%BB%CE%B5%CE%BC%CE%AD%CE%BD%CE%BF%CF%82%20%25%20%CE%BA%CF%8D%CE%B2%CE%BF%CF%82.glb");
const xhr = await createRequest("GET", testServer.unicodeAssetEscaped);
expect(xhr.status).to.equal(200);
});

it("should load URLs with unescaped unicode characters", async function () {
const xhr = await createRequest("GET", "https://raw.githubusercontent.com/BabylonJS/Assets/master/meshes/στρογγυλεμένος%20%25%20κύβος.glb");
const xhr = await createRequest("GET", testServer.unicodeAssetUnescaped);
expect(xhr.status).to.equal(200);
});

it("should load URLs with unescaped unicode characters and spaces", async function () {
const xhr = await createRequest("GET", "https://raw.githubusercontent.com/BabylonJS/Assets/master/meshes/στρογγυλεμένος %25 κύβος.glb");
const xhr = await createRequest("GET", testServer.unicodeAssetUnescapedWithSpaces);
expect(xhr.status).to.equal(200);
});

it("should have status=404 for a file that does not exist", async function () {
const xhr = await createRequest("GET", "https://github.com/babylonJS/BabylonNative404");
const xhr = await createRequest("GET", testServer.notFound);
expect(xhr.status).to.equal(404);
});

it("should expose statusText", async function () {
const okXhr = await createRequest("GET", "https://github.com/");
const okXhr = await createRequest("GET", testServer.ok);
expect(okXhr.statusText).to.equal("OK");
const notFoundXhr = await createRequest("GET", "https://github.com/babylonJS/BabylonNative404");
const notFoundXhr = await createRequest("GET", testServer.notFound);
expect(notFoundXhr.statusText).to.equal("Not Found");
});

Expand All @@ -176,7 +191,7 @@ describe("XMLHTTPRequest", function () {
clearTimeout(guard);
resolve({ errorFired, loadendFired, status: xhr.status, readyState: xhr.readyState });
});
xhr.open("GET", "https://github.com/babylonJS/BabylonNative404");
xhr.open("GET", testServer.notFound);
xhr.send();
});
expect(result.status).to.equal(404);
Expand Down Expand Up @@ -306,21 +321,21 @@ describe("fetch", function () {
this.timeout(30000);

it("should resolve with ok=true and status=200 for a resource that exists", async function () {
const response = await fetch("https://github.com/");
const response = await fetch(testServer.ok);
expect(response.ok).to.equal(true);
expect(response.status).to.equal(200);
});

it("should resolve (not reject) with ok=false and status=404 for a resource that does not exist", async function () {
const response = await fetch("https://github.com/babylonJS/BabylonNative404");
const response = await fetch(testServer.notFound);
expect(response.ok).to.equal(false);
expect(response.status).to.equal(404);
});

it("should expose statusText", async function () {
const okResponse = await fetch("https://github.com/");
const okResponse = await fetch(testServer.ok);
expect(okResponse.statusText).to.equal("OK");
const notFoundResponse = await fetch("https://github.com/babylonJS/BabylonNative404");
const notFoundResponse = await fetch(testServer.notFound);
expect(notFoundResponse.statusText).to.equal("Not Found");
});

Expand Down Expand Up @@ -362,7 +377,7 @@ describe("fetch", function () {
});

it("headers.get() should be case-insensitive and headers.has() should work", async function () {
const response = await fetch("https://github.com/");
const response = await fetch(testServer.ok);
expect(response.headers.has("Content-Type")).to.equal(true);
expect(response.headers.get("CONTENT-TYPE")).to.equal(response.headers.get("content-type"));
});
Expand All @@ -375,7 +390,7 @@ describe("fetch", function () {
});

it("should accept a method in the init object", async function () {
const response = await fetch("https://github.com/", { method: "GET" });
const response = await fetch(testServer.ok, { method: "GET" });
expect(response.status).to.equal(200);
});

Expand Down Expand Up @@ -436,7 +451,7 @@ describe("fetch", function () {

let error: any;
try {
await fetch("https://github.com/", { signal: controller.signal } as any);
await fetch(testServer.ok, { signal: controller.signal } as any);
} catch (e) {
error = e;
}
Expand All @@ -447,7 +462,7 @@ describe("fetch", function () {
it("should reject with an AbortError when aborted in-flight", async function () {
this.timeout(30000);
const controller = new AbortController();
const promise = fetch("https://github.com/", { signal: controller.signal } as any);
const promise = fetch(testServer.slow, { signal: controller.signal } as any);
// Abort before the response can arrive.
controller.abort();

Expand Down
7 changes: 6 additions & 1 deletion Tests/UnitTests/Shared/Shared.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "Shared.h"
#include "TestHttpServer.h"
#include <Babylon/AppRuntime.h>
#include <Babylon/ScriptLoader.h>
#include <Babylon/Polyfills/AbortController.h>
Expand Down Expand Up @@ -62,9 +63,12 @@ TEST(JavaScript, All)
options.WaitForDebugger = true;
}

// The network tests talk to this loopback server (see TestHttpServer.h) rather than to public hosts.
Babylon::Test::TestHttpServer testServer{};

Babylon::AppRuntime runtime{options};

runtime.Dispatch([&exitCodePromise](Napi::Env env) mutable {
runtime.Dispatch([&exitCodePromise, &testServer](Napi::Env env) mutable {
Babylon::Polyfills::Console::Initialize(env, [env](const char* message, Babylon::Polyfills::Console::LogLevel logLevel) {
std::cout << "[" << EnumToString(logLevel) << "] " << message;
if (logLevel == Babylon::Polyfills::Console::LogLevel::Error)
Expand Down Expand Up @@ -101,6 +105,7 @@ TEST(JavaScript, All)

env.Global().Set("hostPlatform", Napi::Value::From(env, JSRUNTIMEHOST_PLATFORM));
env.Global().Set("hostEngine", Napi::Value::From(env, NAPI_JAVASCRIPT_ENGINE));
env.Global().Set("hostTestServer", Napi::Value::From(env, testServer.Origin()));
});

Babylon::ScriptLoader loader{runtime};
Expand Down
Loading