Skip to content

Commit

Permalink
Adding tests (#25)
Browse files Browse the repository at this point in the history
* add compiled rust tests
split buildTask test to theory
invalid json error test

* trigger tests on all commits
  • Loading branch information
JanProvaznik authored Aug 15, 2024
1 parent a1b0d4e commit d5dab70
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 60 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ name: compile and test

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
test:
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ obj/
Playground/
/MSBuildWasmLocal.sln
/examples/go
templates/src
templates/src
/test/WasmTasksTests/GeneratedRustTests
4 changes: 2 additions & 2 deletions src/WasmTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -301,11 +301,11 @@ private void ReflectOutputJsonToClassProperties(string taskOutputJson)
}
catch (JsonException ex)
{
Log.LogError($"Error parsing JSON: {ex.Message}");
Log.LogError($"Error parsing output JSON: {ex.Message}");
}
catch (Exception ex)
{
Log.LogError($"Error Reflecting properties from Json to Class: {ex.Message}");
Log.LogError($"Error Reflecting properties from Json to Class after task run: {ex.Message}");
}
}

Expand Down
26 changes: 16 additions & 10 deletions src/WasmTaskFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ namespace MSBuildWasm
/// </summary>
public class WasmTaskFactory : ITaskFactory2
{
// TODO avoid hardcoded when possible
/// <summary>
/// Name displayed in the MSBuild log.
/// </summary>
public string FactoryName => nameof(WasmTaskFactory);
public TaskLoggingHelper Log { get; set; }
private TaskPropertyInfo[] _taskProperties;
private TaskLoggingHelper _log;
private bool _taskInfoReceived = false;
private string _taskName;
private string _taskPath;
Expand All @@ -45,7 +47,7 @@ public TaskPropertyInfo[] GetTaskParameters()

public bool Initialize(string taskName, IDictionary<string, string> factoryIdentityParameters, IDictionary<string, TaskPropertyInfo> parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost)
{
_log = new TaskLoggingHelper(taskFactoryLoggingHost, taskName)
Log = new TaskLoggingHelper(taskFactoryLoggingHost, taskName)
{
HelpKeywordPrefix = $"WasmTask.{taskName}."
};
Expand Down Expand Up @@ -74,7 +76,7 @@ private void GetCustomWasmTaskProperties()
{
using var engine = new Engine();
using var module = Wasmtime.Module.FromFile(engine, _taskPath);
using var linker = new WasmTaskLinker(engine, _log);
using var linker = new WasmTaskLinker(engine, Log);
using var store = new Store(engine);
linker.DefineWasi();
linker.LinkLogFunctions(store);
Expand All @@ -84,35 +86,39 @@ private void GetCustomWasmTaskProperties()
Action getTaskInfo = instance.GetAction(WasmTask.GetTaskInfoFunctionName);
if (getTaskInfo == null)
{
_log.LogError("Function 'GetTaskInfo' not found in the WebAssembly module.");
Log.LogError("Function 'GetTaskInfo' not found in the WebAssembly module.");
return;
}

getTaskInfo.Invoke();
}
catch (WasmtimeException ex)
{
_log.LogErrorFromException(ex, true);
Log.LogErrorFromException(ex, true);
}
if (!_taskInfoReceived)
{
_log.LogError("Task info was not received from the WebAssembly module.");
Log.LogError("Task info was not received from the WebAssembly module.");
}
}

/// <summary>
/// Handling callback with Task Info JSON.
/// </summary>
/// <remarks>WASIp2: get structured info from GetTaskInfo function output and parse it via classes from wit-bindgen and convert them to properties, this event scheme unnecessary</remarks>
private void OnTaskInfoReceived(object sender, string taskInfoJson)
internal void OnTaskInfoReceived(object sender, string taskInfoJson)
{
try
{
_taskProperties = Serializer.DeserializeTaskInfoJson(taskInfoJson);
}
catch (Exception ex) when (ex is JsonException || ex is KeyNotFoundException || ex is ArgumentException)
catch (Exception ex) when (ex is JsonException || ex is KeyNotFoundException || ex is ArgumentException || ex is InvalidOperationException)
{
Log.LogError("Could not deserialize Task Info JSON. {0}:{1}", ex.GetType().ToString(), ex.Message);
}
catch (Exception ex)
{
_log.LogErrorFromException(ex);
Log.LogError("Unknown error in Task Info JSON deserialization. {0}", ex.Message);
}
_taskInfoReceived = true;
}
Expand Down
61 changes: 42 additions & 19 deletions test/WasmTasksTests/WasmTaskFactory_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,29 +50,47 @@ public void BuildTaskType_CreatesTypeWithCorrectProperties(Type propType)
Assert.NotNull(resultType.GetProperty(prop1name));
Assert.Null(resultType.GetProperty(prop2name));
}
// split/theory
[Fact]
public void BuildTaskType_CreatesTypeWithCorrectAttributes()

[Theory]
[InlineData("StringProp", typeof(string), true, false)]
[InlineData("BoolProp", typeof(bool), false, true)]
[InlineData("TaskItemProp", typeof(ITaskItem), false, false)]
[InlineData("StringArrayProp", typeof(string[]), true, true)]
public void BuildTaskType_CreatesTypeWithCorrectAttributes(string propertyName, Type propertyType, bool isOutput, bool isRequired)
{
// Arrange
const string taskName = "TestTask";
const string prop1name = "p1";
const string prop2name = "p2";
TaskPropertyInfo[] properties = new[]
{
new TaskPropertyInfo(prop1name, typeof(string), output: true, required: false),
new TaskPropertyInfo(prop2name, typeof(bool), false, true)
};
new TaskPropertyInfo(propertyName, propertyType, isOutput, isRequired)
};

// Act
Type resultType = WasmTaskReflectionBuilder.BuildTaskType(taskName, properties);

// Assert
Assert.NotNull(resultType.GetProperty(prop1name)!.GetCustomAttribute<OutputAttribute>());
Assert.Null(resultType.GetProperty(prop1name)!.GetCustomAttribute<RequiredAttribute>());
Assert.NotNull(resultType.GetProperty(prop2name)!.GetCustomAttribute<RequiredAttribute>());
Assert.Null(resultType.GetProperty(prop2name)!.GetCustomAttribute<OutputAttribute>());
PropertyInfo? property = resultType.GetProperty(propertyName);
Assert.NotNull(property);

if (isOutput)
{
Assert.NotNull(property!.GetCustomAttribute<OutputAttribute>());
}
else
{
Assert.Null(property!.GetCustomAttribute<OutputAttribute>());
}

if (isRequired)
{
Assert.NotNull(property!.GetCustomAttribute<RequiredAttribute>());
}
else
{
Assert.Null(property!.GetCustomAttribute<RequiredAttribute>());
}
}

[Fact]
public void ConvertJsonTaskInfoToProperties_ShouldParseProperties()
{
Expand All @@ -90,16 +108,21 @@ public void ConvertJsonTaskInfoToProperties_ShouldParseProperties()
propsExpected.ShouldBeEquivalentTo(propsParsed);
}

// the task returns undeserializable json, should error
//[Fact]
//public void GetTaskInfo_InvalidJson_ShouldError()
//{
// const string invalidJson = "{ \"Properties\": { \"Dirs\": { \"type\": \"ITaskItem[]\", \"required\": true, \"output\": false }, \"MergedDir\": { \"type\": \"ITaskItem\", \"required\": false, \"output\": true }, \"MergedName\": { \"type\": \"string\", \"required\": false, \"output\": false } ";
[Fact]
public void GetTaskInfo_InvalidJson_ShouldError()
{
const string invalidJson = "{ \"Properties\": { \"Dirs\": { \"type\": \"ITaskItem[]\", \"required\": true, \"output\": false }, \"MergedDir\": { \"type\": \"ITaskItem\", \"required\": false, \"output\": true }, \"MergedName\": { \"type\": \"string\", \"required\": false, \"output\": false {} ";

// WasmTaskFactory factory = new WasmTaskFactory();
MockEngine m = new MockEngine();

// factory.OnTaskInfoReceived(null, invalidJson);
WasmTaskFactory factory = new WasmTaskFactory
{
Log = new Microsoft.Build.Utilities.TaskLoggingHelper(m, "TestTask")
};

factory.OnTaskInfoReceived(null, invalidJson);
m.AssertLogContains("Error");
}



Expand Down
Loading

0 comments on commit d5dab70

Please sign in to comment.