Skip to content
Merged
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
18 changes: 16 additions & 2 deletions src/mono/wasm/templates/templates/console/app-support.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,25 @@ function set_exit_code(exit_code, reason) {
}

if (App && App.INTERNAL) {
App.INTERNAL.mono_wasm_exit(exit_code);
let _flush = function(_stream) {
return new Promise((resolve, reject) => {
_stream.on('error', (error) => reject(error));
_stream.write('', function() { resolve () });
});
};
let stderrFlushed = _flush(process.stderr);
let stdoutFlushed = _flush(process.stdout);

Promise.all([ stdoutFlushed, stderrFlushed ])
.then(
() => App.INTERNAL.mono_wasm_exit(exit_code),
reason => {
console.error(`flushing std* streams failed: ${reason}`);
App.INTERNAL.mono_wasm_exit(123456);
});
}
}


let runArgs = {};
let is_debugging = false;

Expand Down
29 changes: 13 additions & 16 deletions src/mono/wasm/test-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,26 +105,23 @@ function set_exit_code(exit_code, reason) {

} else if (App && App.INTERNAL) {
if (is_node) {
let _flush = function (_stream) {
return new Promise((resolve, reject) => {
if (!_stream.write('')) {
_stream.on('drain', () => resolve());
setTimeout(reject, 3000);
} else {
resolve();
}
});
let _flush = function(_stream) {
return new Promise((resolve, reject) => {
setTimeout(() => { reject(new Error("timed out waiting for stdout/stderr streams to flush")) }, 30000);
_stream.on('error', (error) => reject(error));
_stream.write('', function() { resolve () });
});
};
let stderrFlushed = _flush(process.stderr);
let stdoutFlushed = _flush(process.stdout);

Promise.all([stdoutFlushed, stderrFlushed])
.then(
() => App.INTERNAL.mono_wasm_exit(exit_code),
reason => {
console.error(`flushing std* streams failed: ${reason}`);
App.INTERNAL.mono_wasm_exit(123);
});
Promise.all([ stdoutFlushed, stderrFlushed ])
.then(
() => App.INTERNAL.mono_wasm_exit(exit_code),
reason => {
console.error(`flushing std* streams failed: ${reason}`);
App.INTERNAL.mono_wasm_exit(123456);
});
} else {
App.INTERNAL.mono_wasm_exit(exit_code);
}
Expand Down
52 changes: 36 additions & 16 deletions src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,13 @@ protected string RunAndTestWasmApp(BuildArgs buildArgs,
}

string bundleDir = Path.Combine(GetBinDir(baseDir: buildDir, config: buildArgs.Config, targetFramework: targetFramework), "AppBundle");
(string testCommand, string extraXHarnessArgs) = host switch

// Use wasm-console.log to get the xharness output for non-browser cases
(string testCommand, string extraXHarnessArgs, bool useWasmConsoleOutput) = host switch
{
RunHost.V8 => ("wasm test", "--js-file=test-main.js --engine=V8 -v trace"),
RunHost.NodeJS => ("wasm test", "--js-file=test-main.js --engine=NodeJS -v trace"),
_ => ("wasm test-browser", $"-v trace -b {host} --web-server-use-cop")
RunHost.V8 => ("wasm test", "--js-file=test-main.js --engine=V8 -v trace", true),
RunHost.NodeJS => ("wasm test", "--js-file=test-main.js --engine=NodeJS -v trace", true),
_ => ("wasm test-browser", $"-v trace -b {host} --web-server-use-cop", false)
};

string testLogPath = Path.Combine(_logPath, host.ToString());
Expand All @@ -170,7 +172,8 @@ protected string RunAndTestWasmApp(BuildArgs buildArgs,
expectedAppExitCode: expectedExitCode,
extraXHarnessArgs: extraXHarnessArgs,
appArgs: args,
extraXHarnessMonoArgs: extraXHarnessMonoArgs
extraXHarnessMonoArgs: extraXHarnessMonoArgs,
useWasmConsoleOutput: useWasmConsoleOutput
);

if (buildArgs.AOT)
Expand All @@ -192,7 +195,8 @@ protected string RunAndTestWasmApp(BuildArgs buildArgs,

protected static string RunWithXHarness(string testCommand, string testLogPath, string projectName, string bundleDir,
ITestOutputHelper _testOutput, IDictionary<string, string>? envVars=null,
int expectedAppExitCode=0, int xharnessExitCode=0, string? extraXHarnessArgs=null, string? appArgs=null, string? extraXHarnessMonoArgs = null)
int expectedAppExitCode=0, int xharnessExitCode=0, string? extraXHarnessArgs=null,
string? appArgs=null, string? extraXHarnessMonoArgs = null, bool useWasmConsoleOutput = false)
{
_testOutput.WriteLine($"============== {testCommand} =============");
Directory.CreateDirectory(testLogPath);
Expand Down Expand Up @@ -230,6 +234,21 @@ protected static string RunWithXHarness(string testCommand, string testLogPath,
timeoutMs: s_defaultPerTestTimeoutMs);

File.WriteAllText(Path.Combine(testLogPath, $"xharness.log"), output);
if (useWasmConsoleOutput)
{
string wasmConsolePath = Path.Combine(testLogPath, "wasm-console.log");
try
{
if (File.Exists(wasmConsolePath))
output = File.ReadAllText(wasmConsolePath);
else
_testOutput.WriteLine($"Warning: Could not find {wasmConsolePath}. Ignoring.");
}
catch (IOException ioex)
{
_testOutput.WriteLine($"Warning: Could not read {wasmConsolePath}: {ioex}");
}
}

if (exitCode != xharnessExitCode)
{
Expand Down Expand Up @@ -746,9 +765,12 @@ public static (int exitCode, string buildOutput) RunProcess(string path,
process.BeginOutputReadLine();
process.BeginErrorReadLine();

// process.WaitForExit doesn't work if the process exits too quickly?
// resetEvent.WaitOne();
if (!process.WaitForExit(timeoutMs ?? s_defaultPerTestTimeoutMs))
using CancellationTokenSource cts = new();
cts.CancelAfter(timeoutMs ?? s_defaultPerTestTimeoutMs);

await process.WaitForExitAsync(cts.Token);

if (cts.IsCancellationRequested)
{
// process didn't exit
process.Kill(entireProcessTree: true);
Expand All @@ -758,13 +780,11 @@ public static (int exitCode, string buildOutput) RunProcess(string path,
throw new XunitException($"Process timed out. Last 20 lines of output:{Environment.NewLine}{string.Join(Environment.NewLine, lastLines)}");
}
}
else
{
// this will ensure that all the async event handling
// has completed
// https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.waitforexit?view=net-5.0#System_Diagnostics_Process_WaitForExit_System_Int32_
await process.WaitForExitAsync();
}

// this will ensure that all the async event handling has completed
// and should be called after process.WaitForExit(int)
// https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.waitforexit?view=net-5.0#System_Diagnostics_Process_WaitForExit_System_Int32_
process.WaitForExit();

process.ErrorDataReceived -= logStdErr;
process.OutputDataReceived -= logStdOut;
Expand Down
13 changes: 3 additions & 10 deletions src/tests/BuildWasmApps/Wasm.Build.Tests/NativeLibraryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ public static int Main()
}

[ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))]
[BuildAndRun(aot: false)]
[BuildAndRun(aot: true)]
[BuildAndRun(aot: false, host: RunHost.Chrome)]
[BuildAndRun(aot: true, host: RunHost.Chrome)]
public void ProjectUsingBrowserNativeCrypto(BuildArgs buildArgs, RunHost host, string id)
{
string projectName = $"AppUsingBrowserNativeCrypto";
Expand Down Expand Up @@ -140,14 +140,7 @@ public static int Main()
output);

string cryptoInitMsg = "MONO_WASM: Initializing Crypto WebWorker";
if (host == RunHost.V8 || host == RunHost.NodeJS)
{
Assert.DoesNotContain(cryptoInitMsg, output);
}
else
{
Assert.Contains(cryptoInitMsg, output);
}
Assert.Contains(cryptoInitMsg, output);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ public void ConsoleBuildAndRun(string config)
}

[ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))]
[ActiveIssue("https://github.com/dotnet/runtime/issues/70675", TestPlatforms.Windows)]
[InlineData("Debug", false)]
[InlineData("Debug", true)]
[InlineData("Release", false)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,21 @@ exit /b %EXIT_CODE%
REM Functions
:SetEnvVars
if [%TEST_USING_WORKLOADS%] == [true] (
set _DIR_NAME=dotnet-workload
set SDK_HAS_WORKLOAD_INSTALLED=true
robocopy /np /nfl /e %BASE_DIR%\dotnet-workload %EXECUTION_DIR%\dotnet-workload
set "SDK_FOR_WORKLOAD_TESTING_PATH=%EXECUTION_DIR%\dotnet-workload"
set "PATH=%EXECUTION_DIR%\dotnet-workload;%PATH%"
set "AppRefDir=%BASE_DIR%\microsoft.netcore.app.ref"
) else (
set _DIR_NAME=sdk-no-workload
set SDK_HAS_WORKLOAD_INSTALLED=false
robocopy /np /nfl /e %BASE_DIR%\sdk-no-workload %EXECUTION_DIR%\sdk-no-workload
set "SDK_FOR_WORKLOAD_TESTING_PATH=%EXECUTION_DIR%\sdk-no-workload"
set "PATH=%EXECUTION_DIR%\sdk-no-workload;%PATH%"
set "AppRefDir=%BASE_DIR%\microsoft.netcore.app.ref"
)

if [%HELIX_CORRELATION_PAYLOAD%] NEQ [] (
robocopy /np /nfl /NDL /NJH /NJS /nc /e %BASE_DIR%\%_DIR_NAME% %EXECUTION_DIR%\%_DIR_NAME%
set _SDK_DIR=%EXECUTION_DIR%\%_DIR_NAME%
) else (
set _SDK_DIR=%BASE_DIR%\%_DIR_NAME%
)

set "PATH=%_SDK_DIR%;%PATH%"
set "SDK_FOR_WORKLOAD_TESTING_PATH=%_SDK_DIR%"
set "AppRefDir=%BASE_DIR%\microsoft.netcore.app.ref"
EXIT /b 0
23 changes: 15 additions & 8 deletions src/tests/BuildWasmApps/Wasm.Build.Tests/data/RunScriptTemplate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,26 @@ echo XHARNESS_ARGS=$XHARNESS_ARGS

function set_env_vars()
{
local _DIR_NAME=
if [ "x$TEST_USING_WORKLOADS" = "xtrue" ]; then
cp -r $BASE_DIR/dotnet-workload $EXECUTION_DIR
export PATH=$EXECUTION_DIR/dotnet-workload:$PATH
_DIR_NAME=dotnet-workload
export SDK_HAS_WORKLOAD_INSTALLED=true
export SDK_FOR_WORKLOAD_TESTING_PATH=$EXECUTION_DIR/dotnet-workload
export AppRefDir=$BASE_DIR/microsoft.netcore.app.ref
else
cp -r $BASE_DIR/sdk-no-workload $EXECUTION_DIR
export PATH=$EXECUTION_DIR/sdk-no-workload:$PATH
_DIR_NAME=sdk-no-workload
export SDK_HAS_WORKLOAD_INSTALLED=false
export SDK_FOR_WORKLOAD_TESTING_PATH=$EXECUTION_DIR/sdk-no-workload
export AppRefDir=$BASE_DIR/microsoft.netcore.app.ref
fi

local _SDK_DIR=
if [[ -n "$HELIX_WORKITEM_UPLOAD_ROOT" ]]; then
cp -r $BASE_DIR/$_DIR_NAME $EXECUTION_DIR
_SDK_DIR=$EXECUTION_DIR/$_DIR_NAME
else
_SDK_DIR=$BASE_DIR/$_DIR_NAME
fi

export PATH=$_SDK_DIR:$PATH
export SDK_FOR_WORKLOAD_TESTING_PATH=$_SDK_DIR
export AppRefDir=$BASE_DIR/microsoft.netcore.app.ref
}

export TEST_LOG_PATH=${XHARNESS_OUT}/logs
Expand Down