Skip to content

Commit

Permalink
Merge pull request #9 from cozzyy2002/bugfix-0008-move-native-callback
Browse files Browse the repository at this point in the history
Bugfix 0008 move native callback
  • Loading branch information
cozzyy2002 committed Jan 5, 2020
2 parents 71cd4d5 + 8fef9af commit bb21536
Show file tree
Hide file tree
Showing 38 changed files with 900 additions and 363 deletions.
6 changes: 6 additions & 0 deletions StateMachine.NET.TestConsole/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
126 changes: 126 additions & 0 deletions StateMachine.NET.TestConsole/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using tsm_NET.Generic;

namespace StateMachine.NET.TestConsole
{
class Program
{
static void Main(string[] args)
{
State.MemoryWeight = Event.MemoryWeight = 100;

var context = new Context();
context.setup(new State());
context.StateMonitor = new StateMonitor();

while (true)
{
var str = Console.ReadLine();
if (string.IsNullOrEmpty(str)) { break; }

int nextGeneration;
if (int.TryParse(str, out nextGeneration))
{
var e = new Event(nextGeneration);
context.triggerEvent(e);
}
else
{

}
}
}
}

class Context : tsm_NET.Generic.Context<Event, State>
{
}

class State : tsm_NET.Generic.State<Context, Event, State>
{
public State(State masterState = null) : base(masterState)
{
generation = (masterState != null) ? masterState.generation + 1 : 0;
}

public override HResult entry(Context context, Event @event, State previousState)
{
Console.WriteLine(string.Format("{0}: {1}", @event, this));
return HResult.Ok;
}

public override HResult handleEvent(Context context, Event @event, ref State nextState)
{
if(generation < @event.NextGeneration)
{
// Go to next State with current State as master state.
// This path continues until generation equals to Event.NextGeneration.
nextState = new State(this);
context.triggerEvent(new Event(@event.NextGeneration));
}
else if(@event.NextGeneration < generation)
{
// Go to master state whose generation is Event.NextGeneration.
var state = this;
while ((state != null) && (@event.NextGeneration < state.generation)) { state = state.MasterState; }
nextState = state;
}

return HResult.Ok;
}

public override HResult exit(Context context, Event @event, State nextState)
{
if(MasterState.generation == @event.NextGeneration)
{
Console.WriteLine("Force a garbage collection.");
GC.Collect();
}
return HResult.Ok;
}

public override string ToString()
{
return string.Format("State({0}): generation={1}", SequenceNumber, generation);
}

int generation;
}

class Event : tsm_NET.Generic.Event<Context>
{
public Event(int nextGeneration)
{
NextGeneration = nextGeneration;
}

public override string ToString()
{
return string.Format("Event({0}): NextGeneration={1}", SequenceNumber, NextGeneration);
}

public readonly int NextGeneration;
}

class StateMonitor : IStateMonitor<Event, State>
{
public void onEventHandling(Context<Event, State> context, Event @event, State current) { }

public void onEventTriggered(Context<Event, State> context, Event @event) { }

public void onIdle(Context<Event, State> context)
{
Console.Write("{0} > ", GC.GetTotalMemory(true));
}

public void onStateChanged(Context<Event, State> context, Event @event, State previous, State next) { }

public void onTimerStarted(Context<Event, State> context, Event @event) { }

public void onWorkerThreadExit(Context<Event, State> context, HResult exitCode) { }
}
}
36 changes: 36 additions & 0 deletions StateMachine.NET.TestConsole/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("StateMachine.NET.TestConsole")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("StateMachine.NET.TestConsole")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c5db67fe-9b51-4035-a6a5-a38613f30424")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
58 changes: 58 additions & 0 deletions StateMachine.NET.TestConsole/StateMachine.NET.TestConsole.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C5DB67FE-9B51-4035-A6A5-A38613F30424}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>StateMachine.NET.TestConsole</RootNamespace>
<AssemblyName>StateMachine.NET.TestConsole</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StateMachine.NET\StateMachine.NET.vcxproj">
<Project>{de14c539-5986-4ad3-8dad-e3f966304787}</Project>
<Name>StateMachine.NET</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
73 changes: 70 additions & 3 deletions StateMachine.NET.UnitTest/Class1.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using NSubstitute;
using NUnit.Framework;
using System;
using System.Diagnostics;
using System.Threading;
using tsm_NET.Generic;
Expand All @@ -8,6 +9,8 @@ namespace StateMachine.NET.UnitTest.Generic
{
public class Context : Context<Event, State>
{
public Context() : base(true) { }
public Context(bool isAsync) : base(isAsync) { }
}

public class Event : Event<Context>
Expand All @@ -23,6 +26,70 @@ public class State : State<Context, Event, State>
[TestFixture]
public class GenericTestCase
{
[Test]
public void SyncContextTest()
{
var mockEvent = Substitute.For<Event>();
var mockInitialState = Substitute.For<State>();
var mockNextState = Substitute.For<State>();
var mockStateMonitor = Substitute.For<IStateMonitor<Event, State>>();

// Create synchronous Context object.
var c = new Context(false);
c.StateMonitor = mockStateMonitor;
Assert.That(c.CurrentState, Is.EqualTo(null), "Context has no initial state when created.");

// mockInitialState handles mockEvent and changes state to nextState.
mockInitialState
.handleEvent(Arg.Is(c), Arg.Is(mockEvent), ref Arg.Is(State.Null))
.Returns(x =>
{
Console.WriteLine($"{mockInitialState.GetType()}.handleEvent({x[0]}) is called.");
x[2] = mockNextState;
return HResult.Ok;
});

Assert.That(c.setup(mockInitialState), Is.EqualTo(HResult.Ok));
Assert.That(c.handleEvent(mockEvent), Is.EqualTo(HResult.Ok));

// Current state should be mockNextState.
Assume.That(c.CurrentState, Is.EqualTo(mockNextState));

// Shutdown
mockNextState.IsExitCalledOnShutdown = true;
Assume.That(c.shutdown(TimeSpan.FromSeconds(1)), Is.EqualTo(HResult.Ok));

// Check calls to methods of State.
Received.InOrder(() =>
{
mockInitialState.Received()
.entry(Arg.Is(c), Arg.Is(Event.Null), Arg.Is(State.Null));
mockInitialState.Received()
.handleEvent(Arg.Is(c), Arg.Is(mockEvent), ref Arg.Is(State.Null));
mockInitialState.Received()
.exit(Arg.Is(c), Arg.Is(mockEvent), mockNextState);
mockNextState.Received()
.entry(Arg.Is(c), Arg.Is(mockEvent), Arg.Is(mockInitialState));
mockNextState.Received()
.exit(Arg.Is(c), Arg.Is(Event.Null), Arg.Is(State.Null));
});
mockNextState.DidNotReceive().handleEvent(Arg.Any<Context>(), Arg.Any<Event>(), ref Arg.Any<State>());

// Check calls to methods of IStateMonitor.
Received.InOrder(() =>
{
mockStateMonitor.Received()
.onStateChanged(Arg.Is(c), Arg.Is(Event.Null), Arg.Is(State.Null), Arg.Is(mockInitialState));
mockStateMonitor.Received()
.onEventHandling(Arg.Is(c), Arg.Is(mockEvent), Arg.Is(mockInitialState));
mockStateMonitor.Received()
.onStateChanged(Arg.Is(c), Arg.Is(mockEvent), Arg.Is(mockInitialState), Arg.Is(mockNextState));
});
mockStateMonitor.DidNotReceive().onEventTriggered(Arg.Any<Context>(), Arg.Any<Event>());
mockStateMonitor.DidNotReceive().onIdle(Arg.Any<Context>());
mockStateMonitor.DidNotReceive().onWorkerThreadExit(Arg.Any<Context>(), Arg.Any<HResult>());
}

[Test]
public void BasicTest()
{
Expand All @@ -40,7 +107,7 @@ public void BasicTest()
.handleEvent(Arg.Is(c), Arg.Is(mockEvent), ref Arg.Is(State.Null))
.Returns(x =>
{
Trace.WriteLine($"{mockInitialState.GetType()}.handleEvent({x[0]}) is called.");
Console.WriteLine($"{mockInitialState.GetType()}.handleEvent({x[0]}) is called.");
x[2] = mockNextState;
return HResult.Ok;
});
Expand All @@ -54,8 +121,8 @@ public void BasicTest()

// Shutdown
mockNextState.IsExitCalledOnShutdown = true;
Assume.That(c.shutdown(), Is.EqualTo(HResult.Ok));
Thread.Sleep(100);
Assume.That(c.shutdown(TimeSpan.FromSeconds(1)), Is.EqualTo(HResult.Ok));
Thread.Sleep(1000);

// Check calls to methods of State.
Received.InOrder(() =>
Expand Down
11 changes: 9 additions & 2 deletions StateMachine.NET.UnitTest/StateMachine.NET.UnitTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.7.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
Expand Down Expand Up @@ -83,4 +83,11 @@
<Error Condition="!Exists('..\packages\NUnit.3.12.0\build\NUnit.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit.3.12.0\build\NUnit.props'))" />
<Error Condition="!Exists('..\packages\NUnit3TestAdapter.3.15.1\build\net35\NUnit3TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit3TestAdapter.3.15.1\build\net35\NUnit3TestAdapter.props'))" />
</Target>
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>xcopy /D /Y "$(SolutionDir)packages\NUnit.ConsoleRunner.3.10.0\tools\*.*" "$(TargetDir)"</PostBuildEvent>
</PropertyGroup>
</Project>
2 changes: 1 addition & 1 deletion StateMachine.NET.UnitTest/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Expand Down
2 changes: 1 addition & 1 deletion StateMachine.NET.UnitTest/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
<package id="NUnit.Extension.TeamCityEventListener" version="1.0.7" targetFramework="net45" />
<package id="NUnit.Extension.VSProjectLoader" version="3.8.0" targetFramework="net45" />
<package id="NUnit3TestAdapter" version="3.15.1" targetFramework="net45" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.6.0" targetFramework="net45" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.7.0" targetFramework="net45" />
<package id="System.Threading.Tasks.Extensions" version="4.5.3" targetFramework="net45" />
</packages>
Loading

0 comments on commit bb21536

Please sign in to comment.