diff --git a/src/Linker.cs b/src/Linker.cs index 69c6ad9..2e36b29 100644 --- a/src/Linker.cs +++ b/src/Linker.cs @@ -13,8 +13,6 @@ namespace Wasmtime /// public partial class Linker : IDisposable { - private const int StackallocThreshold = 256; - /// /// Constructs a new linker from the given engine. /// @@ -304,9 +302,11 @@ public Function GetDefaultFunction(Store store, string name) public Function? GetFunction(Store store, string module, string name) { if (store is null) - { throw new ArgumentNullException(nameof(store)); - } + if (module is null) + throw new ArgumentNullException(nameof(module)); + if (name is null) + throw new ArgumentNullException(nameof(name)); var context = store.Context; if (!TryGetExtern(context, module, name, out var ext) || ext.kind != ExternKind.Func) @@ -329,9 +329,11 @@ public Function GetDefaultFunction(Store store, string name) public Table? GetTable(Store store, string module, string name) { if (store is null) - { throw new ArgumentNullException(nameof(store)); - } + if (module is null) + throw new ArgumentNullException(nameof(module)); + if (name is null) + throw new ArgumentNullException(nameof(name)); var context = store.Context; if (!TryGetExtern(context, module, name, out var ext) || ext.kind != ExternKind.Table) @@ -354,9 +356,11 @@ public Function GetDefaultFunction(Store store, string name) public Memory? GetMemory(Store store, string module, string name) { if (store is null) - { throw new ArgumentNullException(nameof(store)); - } + if (module is null) + throw new ArgumentNullException(nameof(module)); + if (name is null) + throw new ArgumentNullException(nameof(name)); var context = store.Context; if (!TryGetExtern(context, module, name, out var ext) || ext.kind != ExternKind.Memory) @@ -379,9 +383,11 @@ public Function GetDefaultFunction(Store store, string name) public Global? GetGlobal(Store store, string module, string name) { if (store is null) - { throw new ArgumentNullException(nameof(store)); - } + if (module is null) + throw new ArgumentNullException(nameof(module)); + if (name is null) + throw new ArgumentNullException(nameof(name)); var context = store.Context; if (!TryGetExtern(context, module, name, out var ext) || ext.kind != ExternKind.Global) @@ -412,19 +418,15 @@ public void Dispose() public void DefineFunction(string module, string name, Function.UntypedCallbackDelegate callback, IReadOnlyList parameterKinds, IReadOnlyList resultKinds) { if (module is null) - { throw new ArgumentNullException(nameof(module)); - } - if (name is null) - { throw new ArgumentNullException(nameof(name)); - } - if (callback is null) - { throw new ArgumentNullException(nameof(callback)); - } + if (parameterKinds is null) + throw new ArgumentNullException(nameof(parameterKinds)); + if (resultKinds is null) + throw new ArgumentNullException(nameof(resultKinds)); unsafe { diff --git a/tests/ExternTests.cs b/tests/ExternTests.cs new file mode 100644 index 0000000..9ca4c6f --- /dev/null +++ b/tests/ExternTests.cs @@ -0,0 +1,57 @@ +using System.Diagnostics; +using Xunit; + +namespace Wasmtime.Tests; + +public class ExternTests +{ + [Fact] + public void ExternFunc_StaticCheck() + { + // An assertion is made in the static constructor. Doing this forces the static constructor to run + Assert.Equal(default(ExternFunc), default); + } + + [Fact] + public void ExternTable_StaticCheck() + { + // An assertion is made in the static constructor. Doing this forces the static constructor to run + Assert.Equal(default(ExternTable), default); + } + + [Fact] + public void ExternMemory_StaticCheck() + { + // An assertion is made in the static constructor. Doing this forces the static constructor to run + Assert.Equal(default(ExternMemory), default); + } + + [Fact] + public void ExternInstance_StaticCheck() + { + // An assertion is made in the static constructor. Doing this forces the static constructor to run + Assert.Equal(default(ExternInstance), default); + } + + [Fact] + public void ExternGlobal_StaticCheck() + { + // An assertion is made in the static constructor. Doing this forces the static constructor to run + Assert.Equal(default(ExternGlobal), default); + } + + [Fact] + public void ExternUnion_StaticCheck() + { + // An assertion is made in the static constructor. Doing this forces the static constructor to run + Assert.Equal(default(ExternUnion), default); + Assert.Equal(default(Extern), default); + } + + [Fact] + public void Extern_StaticCheck() + { + // An assertion is made in the static constructor. Doing this forces the static constructor to run + Assert.Equal(default(Extern), default); + } +} \ No newline at end of file diff --git a/tests/LinkerFunctionsTests.cs b/tests/LinkerFunctionsTests.cs index 07a70f9..e8b169e 100644 --- a/tests/LinkerFunctionsTests.cs +++ b/tests/LinkerFunctionsTests.cs @@ -237,15 +237,61 @@ public void ItReturnsNullForUndefinedFunctions() } [Fact] - public void ItBindsComplexFunction() + public void GetFunctionThrowsWithNullStore() + { + Assert.Throws(() => Linker.GetFunction(null!, "module", "name")); + } + + [Fact] + public void GetFunctionThrowsWithNullName() + { + Assert.Throws(() => Linker.GetFunction(Store, "module", null!)); + } + + [Fact] + public void GetFunctionThrowsWithNullModule() + { + Assert.Throws(() => Linker.GetFunction(Store, null!, "name")); + } + + [Fact] + public void DefineFunctionThrowsWithNullModule() + { + Assert.Throws(() => Linker.DefineFunction(null!, "name", (c, p, r) => { }, [ ValueKind.Int32 ], [])); + } + + [Fact] + public void DefineFunctionThrowsWithNullName() + { + Assert.Throws(() => Linker.DefineFunction("", null!, (c, p, r) => { }, [ValueKind.Int32], [])); + } + + [Fact] + public void DefineFunctionThrowsWithNullCallback() + { + Assert.Throws(() => Linker.DefineFunction("", "name", null!, [ValueKind.Int32], [])); + } + + [Fact] + public void DefineFunctionThrowsWithNullParameters() { - using var store = new Store(Fixture.Engine); + Assert.Throws(() => Linker.DefineFunction("", "name", (c, p, r) => { }, null!, [])); + } + + [Fact] + public void DefineFunctionThrowsWithNullResults() + { + Assert.Throws(() => Linker.DefineFunction("", "name", (c, p, r) => { }, [ValueKind.Int32], null!)); + } + [Fact] + public void ItBindsComplexFunction() + { Linker.DefineFunction("", "complex", (c, p, r) => { p.Length.Should().Be(0); r.Length.Should().Be(19); - for (int i = 0; i < r.Length; ++i) + for (var i = 0; i < r.Length; ++i) { r[i] = i + 1; } @@ -254,7 +300,7 @@ public void ItBindsComplexFunction() Enumerable.Repeat(ValueKind.Int32, 19).ToArray() ); - var func = Linker.GetFunction(store, "", "complex"); + var func = Linker.GetFunction(Store, "", "complex"); func.Should().NotBeNull(); } diff --git a/tests/LinkerTests.cs b/tests/LinkerTests.cs new file mode 100644 index 0000000..6bab78e --- /dev/null +++ b/tests/LinkerTests.cs @@ -0,0 +1,160 @@ +using System; +using Xunit; + +namespace Wasmtime.Tests; + +public sealed class LinkerFixture : ModuleFixture +{ + protected override string ModuleFileName => "FunctionExports.wat"; +} + +public sealed class LinkerTests + : IClassFixture, IDisposable +{ + private Store Store { get; } + private Linker Linker { get; } + + public LinkerTests(LinkerFixture fixture) + { + Fixture = fixture; + Linker = new Linker(Fixture.Engine); + Store = new Store(Fixture.Engine); + } + + public LinkerFixture Fixture { get; } + + public void Dispose() + { + Linker.Dispose(); + Store.Dispose(); + } + + [Fact] + public void ItThrowsWithNullEngine() + { + Assert.Throws(() => new Linker(null!)); + } + + [Fact] + public void DefineThrowsWithNullStore() + { + Assert.Throws(() => Linker.Define("module", "name", Function.Null)); + } + + [Fact] + public void DefineThrowsWithNullModule() + { + Assert.Throws(() => Linker.Define(null!, "name", new Global(Store, ValueKind.Int32, 1, Mutability.Immutable))); + } + + [Fact] + public void DefineThrowsWithNullName() + { + Assert.Throws(() => Linker.Define("module", null!, new Global(Store, ValueKind.Int32, 1, Mutability.Immutable))); + } + + [Fact] + public void DefineModuleThrowsWithNullModule() + { + Assert.Throws(() => Linker.DefineModule(Store, null!)); + } + + [Fact] + public void DefineModuleThrowsWithNullStore() + { + Assert.Throws(() => Linker.DefineModule(null!, Fixture.Module)); + } + + [Fact] + public void DefineWasiTwiceThrows() + { + Linker.DefineWasi(); + Assert.Throws(() => Linker.DefineWasi()); + } + + [Fact] + public void GetDefaultFunctionThrowsWithNullStore() + { + Assert.Throws(() => Linker.GetDefaultFunction(null!, "name")); + } + + [Fact] + public void GetDefaultFunctionThrowsWithNullName() + { + Assert.Throws(() => Linker.GetDefaultFunction(Store, null!)); + } + + [Fact] + public void GetTableThrowsWithNullStore() + { + Assert.Throws(() => Linker.GetTable(null!, "module", "name")); + } + + [Fact] + public void GetTableThrowsWithNullModule() + { + Assert.Throws(() => Linker.GetTable(Store, null!, "name")); + } + + [Fact] + public void GetTableThrowsWithNullName() + { + Assert.Throws(() => Linker.GetTable(Store, "module", null!)); + } + + [Fact] + public void GetMemoryThrowsWithNullStore() + { + Assert.Throws(() => Linker.GetMemory(null!, "module", "name")); + } + + [Fact] + public void GetMemoryThrowsWithNullModule() + { + Assert.Throws(() => Linker.GetMemory(Store, null!, "name")); + } + + [Fact] + public void GetMemoryThrowsWithNullName() + { + Assert.Throws(() => Linker.GetMemory(Store, "module", null!)); + } + + [Fact] + public void GetGlobalThrowsWithNullStore() + { + Assert.Throws(() => Linker.GetGlobal(null!, "module", "name")); + } + + [Fact] + public void GetGlobalThrowsWithNullModule() + { + Assert.Throws(() => Linker.GetGlobal(Store, null!, "name")); + } + + [Fact] + public void GetGlobalThrowsWithNullName() + { + Assert.Throws(() => Linker.GetGlobal(Store, "module", null!)); + } + + [Fact] + public void DefineInstanceThrowsWithNullStore() + { + var instance = new Instance(Store, Fixture.Module); + Assert.Throws(() => Linker.DefineInstance(null!, "name", instance)); + } + + [Fact] + public void DefineInstanceThrowsWithNullName() + { + var instance = new Instance(Store, Fixture.Module); + Assert.Throws(() => Linker.DefineInstance(Store, null!, instance)); + } + + [Fact] + public void DefineInstanceThrowsWithNullInstance() + { + Assert.Throws(() => Linker.DefineInstance(Store, "name", null!)); + } +} \ No newline at end of file