diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ecf315b..64b590a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,4 +54,4 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Run Tests - run: dotnet test --configuration Release --no-build --verbosity normal \ No newline at end of file + run: dotnet test --configuration Release --no-build --verbosity normal Spec.Test/Spec.Test.csproj \ No newline at end of file diff --git a/Feature.Detect/DetectFeatures.cs b/Feature.Detect/DetectFeatures.cs new file mode 100644 index 0000000..fe8232b --- /dev/null +++ b/Feature.Detect/DetectFeatures.cs @@ -0,0 +1,43 @@ +using Spec.Test; +using Wacs.Core; +using Wacs.Core.Runtime; +using Wacs.Core.Types; +using Xunit; + +namespace Feature.Detect; + +public class DetectFeatures +{ + [Theory] + [ClassData(typeof(FeatureDetectTestData))] + public void Detect(FeatureJson.FeatureJson file) + { + if (!string.IsNullOrEmpty(file.Module)) + { + try + { + var runtime = new WasmRuntime(); + + //Mutable globals + var mutableGlobal = new GlobalType(ValType.I32, Mutability.Mutable); + runtime.BindHostGlobal(("a", "b"), mutableGlobal, 1); + + var filepath = Path.Combine(file.Path, file.Module); + using var fileStream = new FileStream(filepath, FileMode.Open); + var module = BinaryModuleParser.ParseWasm(fileStream); + var modInst = runtime.InstantiateModule(module); + var moduleName = !string.IsNullOrEmpty(file.Name)?file.Name:$"{filepath}"; + module.SetName(moduleName); + } + catch (Exception e) + { + Assert.Fail($"{file.Name} support not detected.\n{e}"); + } + + } + else + { + Assert.Fail($"{file.Name} not supported."); + } + } +} \ No newline at end of file diff --git a/Feature.Detect/Feature.Detect.csproj b/Feature.Detect/Feature.Detect.csproj index a155a49..f91be62 100644 --- a/Feature.Detect/Feature.Detect.csproj +++ b/Feature.Detect/Feature.Detect.csproj @@ -11,4 +11,25 @@ + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + Always + + + + + + + diff --git a/Feature.Detect/FeatureDetectTestData.cs b/Feature.Detect/FeatureDetectTestData.cs new file mode 100644 index 0000000..4387785 --- /dev/null +++ b/Feature.Detect/FeatureDetectTestData.cs @@ -0,0 +1,73 @@ +// /* +// * Copyright 2024 Kelvin Nishikawa +// * +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// */ + +using System.Collections; +using System.Text.Json; +using System.Text.Json.Serialization; +using Feature.Detect.FeatureJson; +using Microsoft.Extensions.Configuration; + +namespace Spec.Test +{ + public class FeatureDetectTestData : IEnumerable + { + private static readonly IConfiguration Configuration; + + static FeatureDetectTestData() + { + // Use ConfigurationFixture to get the JSON directory path + Configuration = new ConfigurationBuilder() + .SetBasePath(AppContext.BaseDirectory) // Set to current directory + .AddJsonFile("testsettings.json", optional: false, reloadOnChange: true) + .Build(); + } + + private static string JsonDirectory => Path.Combine(AppContext.BaseDirectory, Configuration["JsonDirectory"] ?? ""); + + public IEnumerator GetEnumerator() + { + var files = Directory.GetFiles(JsonDirectory, "*.json", SearchOption.AllDirectories).OrderBy(path => path); + foreach (var file in files) + { + var testData = LoadFeatureDefinition(file); + yield return new object[] { testData }; + } + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + static FeatureJson LoadFeatureDefinition(string jsonPath) + { + string json = File.ReadAllText(jsonPath); + + var options = new JsonSerializerOptions + { + Converters = + { + new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) + }, + PropertyNameCaseInsensitive = true + }; + + var testDefinition = JsonSerializer.Deserialize(json, options); + if (testDefinition == null) + throw new JsonException($"Error while parsing {jsonPath}"); + + testDefinition.Path = Path.GetDirectoryName(jsonPath)!; + return testDefinition; + } + } +} \ No newline at end of file diff --git a/Feature.Detect/FeatureJson/FeatureJson.cs b/Feature.Detect/FeatureJson/FeatureJson.cs new file mode 100644 index 0000000..d62079e --- /dev/null +++ b/Feature.Detect/FeatureJson/FeatureJson.cs @@ -0,0 +1,54 @@ +// /* +// * Copyright 2024 Kelvin Nishikawa +// * +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// */ + +using System.Text.Json.Serialization; + +namespace Feature.Detect.FeatureJson; + +public class FeatureJson +{ + [JsonPropertyName("source")] + public string? Source { get; set; } + + public string? Path { get; set; } + + [JsonPropertyName("module")] + public string? Module { get; set; } + + [JsonPropertyName("options")] + public Options? Options { get; set; } + + [JsonPropertyName("name")] + public string? Name { get; set; } + + [JsonPropertyName("proposal")] + public string? Proposal { get; set; } + + [JsonPropertyName("features")] + public List? Features { get; set; } // New property for features list + + public override string ToString() + { + return $"Name: {Name}\n Proposal: {Proposal}\n Features: {string.Join(", ", Features ?? new List())}\n Module: {Module}\n Options: {Options}"; + } + +} + +public class Options +{ + [JsonPropertyName("builtins")] + public List? Builtins { get; set; } +} \ No newline at end of file diff --git a/Feature.Detect/testsettings.json b/Feature.Detect/testsettings.json new file mode 100644 index 0000000..f8e3efa --- /dev/null +++ b/Feature.Detect/testsettings.json @@ -0,0 +1,3 @@ +{ + "JsonDirectory": "../../../generated-wasm" +} \ No newline at end of file