Skip to content

Commit

Permalink
Merge dca67f2 into b782135
Browse files Browse the repository at this point in the history
  • Loading branch information
helto4real committed Aug 28, 2020
2 parents b782135 + dca67f2 commit 9731fdc
Show file tree
Hide file tree
Showing 11 changed files with 750 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/tags_nuget.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,7 @@ jobs:
run: dotnet pack src/App/NetDaemon.App/NetDaemon.App.csproj --configuration Release -p:PackageVersion=${GIT_TAG_NAME}-beta
- name: pack Daemon
run: dotnet pack src/Daemon/NetDaemon.Daemon/NetDaemon.Daemon.csproj --configuration Release -p:PackageVersion=${GIT_TAG_NAME}-beta
- name: pack Test
run: dotnet pack tests/NetDaemon.Test/NetDaemon.Test.csproj --configuration Release -p:PackageVersion=${GIT_TAG_NAME}-beta
- name: push to nuget
run: dotnet nuget push **/*.nupkg --api-key ${{secrets.NUGET_API_KEY}} --source https://api.nuget.org/v3/index.json --no-symbols true
17 changes: 17 additions & 0 deletions NetDaemon.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DaemonRunner", "src\DaemonR
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DaemonRunner", "DaemonRunner", "{A7F8279D-A148-48B8-8492-BDD96CE1E676}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{32E20E48-2F62-447B-83A2-DB2EA7F61AB3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetDaemon.Test", "tests\NetDaemon.Test\NetDaemon.Test.csproj", "{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -94,6 +98,18 @@ Global
{E79D336A-0BA1-4662-A840-CAB24B3145B9}.Release|x64.Build.0 = Release|Any CPU
{E79D336A-0BA1-4662-A840-CAB24B3145B9}.Release|x86.ActiveCfg = Release|Any CPU
{E79D336A-0BA1-4662-A840-CAB24B3145B9}.Release|x86.Build.0 = Release|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Debug|x64.ActiveCfg = Debug|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Debug|x64.Build.0 = Debug|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Debug|x86.ActiveCfg = Debug|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Debug|x86.Build.0 = Debug|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Release|Any CPU.Build.0 = Release|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Release|x64.ActiveCfg = Release|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Release|x64.Build.0 = Release|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Release|x86.ActiveCfg = Release|Any CPU
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -104,6 +120,7 @@ Global
{1DF9E750-9308-4E12-8A48-CAABE68FF30A} = {42718370-2C75-4708-8C40-DD59D633C96E}
{E73BF13E-A17F-4B0B-8504-C2A299B83DEE} = {42718370-2C75-4708-8C40-DD59D633C96E}
{E79D336A-0BA1-4662-A840-CAB24B3145B9} = {A7F8279D-A148-48B8-8492-BDD96CE1E676}
{E1844E4F-2711-4A04-B70C-D67D5D2C8F31} = {32E20E48-2F62-447B-83A2-DB2EA7F61AB3}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7C5FBB7F-654C-4CAC-964F-6D71AF3D62F8}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,25 @@ public static IObservable<(EntityState Old, EntityState New)> NDSameStateFor(thi
{
return observable.Throttle(span);
}

/// <summary>
/// Wait for state the specified time
/// </summary>
/// <param name="observable"></param>
/// <param name="timeout">Timeout waiting for state</param>
public static IObservable<(EntityState Old, EntityState New)> NDWaitForState(this IObservable<(EntityState Old, EntityState New)> observable, TimeSpan timeout)
{
return observable.Timeout(timeout, Observable.Return((new NetDaemon.Common.EntityState() { State = "TimeOut" }, new NetDaemon.Common.EntityState() { State = "TimeOut" }))).Take(1);
}

/// <summary>
/// Wait for state the default time
/// </summary>
/// <param name="observable"></param>
public static IObservable<(EntityState Old, EntityState New)> NDWaitForState(this IObservable<(EntityState Old, EntityState New)> observable)
{
return observable.Timeout(TimeSpan.FromSeconds(5), Observable.Return((new NetDaemon.Common.EntityState() { State = "TimeOut" }, new NetDaemon.Common.EntityState() { State = "TimeOut" }))).Take(1);
}

}
}
1 change: 1 addition & 0 deletions src/Daemon/NetDaemon.Daemon/Daemon/NetDaemonHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using NetDaemon.Mapping;

[assembly: InternalsVisibleTo("NetDaemon.Daemon.Tests")]
[assembly: InternalsVisibleTo("NetDaemon.Test")]

namespace NetDaemon.Daemon
{
Expand Down
241 changes: 241 additions & 0 deletions tests/NetDaemon.Test/DaemonHostTestBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
using System.Threading;
using System.Threading.Tasks;
using JoySoftware.HomeAssistant.Client;
using Moq;
using NetDaemon.Common;
using NetDaemon.Common.Reactive;
using NetDaemon.Daemon.Storage;
using Xunit;

namespace NetDaemon.Daemon.Test
{

public partial class DaemonHostTestBase : IAsyncLifetime
{
private readonly NetDaemonHost _defaultDaemonHost;
private readonly Mock<IDataRepository> _defaultDataRepositoryMock;
private readonly HassClientMock _defaultHassClientMock;
private readonly HttpHandlerMock _defaultHttpHandlerMock;
private readonly LoggerMock _loggerMock;

internal DaemonHostTestBase()
{
_loggerMock = new LoggerMock();
_defaultHassClientMock = HassClientMock.DefaultMock;
_defaultDataRepositoryMock = new Mock<IDataRepository>();

_defaultHttpHandlerMock = new HttpHandlerMock();
_defaultDaemonHost = new NetDaemonHost(
_defaultHassClientMock.Object,
_defaultDataRepositoryMock.Object,
_loggerMock.LoggerFactory,
_defaultHttpHandlerMock.Object);

}

public NetDaemonHost DefaultDaemonHost => _defaultDaemonHost;
public Mock<IDataRepository> DefaultDataRepositoryMock => _defaultDataRepositoryMock;
public HassClientMock DefaultHassClientMock => _defaultHassClientMock;
public HttpHandlerMock DefaultHttpHandlerMock => _defaultHttpHandlerMock;
public LoggerMock LoggerMock => _loggerMock;

Task IAsyncLifetime.DisposeAsync()
{
return Task.CompletedTask;
}

/// <summary>
/// Gets a object as dynamic
/// </summary>
/// <param name="testData">The object to turn into dynamic</param>
public dynamic GetDynamicDataObject(string testData = "testdata")
{
var expandoObject = new ExpandoObject();
dynamic dynamicData = expandoObject;
dynamicData.Test = testData;
return dynamicData;
}

/// <summary>
/// Converts parameters to dynamics
/// </summary>
public (dynamic, ExpandoObject) GetDynamicObject(params (string, object)[] dynamicParameters)
{
var expandoObject = new ExpandoObject();
var dict = expandoObject as IDictionary<string, object>;

foreach (var (name, value) in dynamicParameters)
{
dict[name] = value;
}
return (expandoObject, expandoObject);
}

/// <summary>
/// Override for test init function
/// </summary>
public virtual Task InitializeAsync()
{
return Task.CompletedTask;
}

/// <summary>
/// Adds an new instance of app
/// </summary>
/// <param name="app">The instance of the app to add</param>
public void AddAppInstance(INetDaemonAppBase app)
{
if (string.IsNullOrEmpty(app.Id))
throw new ArgumentException("Application needs an unique id, please provide it!");
DefaultDaemonHost.InternalAllAppInstances[app.Id] = app;
DefaultDaemonHost.InternalRunningAppInstances[app.Id] = app;
}

/// <summary>
/// Adds an simple state change event to NetDaemon to trigger apps
/// </summary>
/// <param name="entityId">Unique id of the entity</param>
/// <param name="fromState">From state</param>
/// <param name="toState">To state</param>
public void AddChangedEvent(string entityId, object fromState, object toState)
{
DefaultHassClientMock.AddChangedEvent(entityId, fromState, toState);
}

/// <summary>
/// Adds a full home assistant fake event
/// </summary>
/// <param name="hassEvent">Event to fake</param>
public void AddChangedEvent(HassEvent hassEvent)
{
DefaultHassClientMock.FakeEvents.Enqueue(hassEvent);
}

/// <summary>
/// Add a fake event
/// </summary>
/// <param name="eventType">The id of the event</param>
/// <param name="data">any custom data provided</param>
public void AddCustomEvent(string eventType, dynamic? data)
{
DefaultHassClientMock.FakeEvents.Enqueue(new HassEvent
{
EventType = eventType,
Data = data
});
}

/// <summary>
/// Add a face service call event
/// </summary>
/// <param name="domain">Domain of event</param>
/// <param name="service">Service to call</param>
/// <param name="data">Custom data</param>
public void AddCallServiceEvent(string domain, string service, dynamic data)
{
DefaultHassClientMock.AddCallServiceEvent(domain, service, data);
}

/// <summary>
/// Verify that a service has been called
/// </summary>
/// <param name="domain">Domain of service</param>
/// <param name="service">The service name</param>
/// <param name="attributesTuples">Attributes</param>
public void VerifyCallService(string domain, string service,
params (string attribute, object value)[] attributesTuples)
{
DefaultHassClientMock.VerifyCallService(domain, service, attributesTuples);
}

/// <summary>
/// Verify that a service been called specific number of times
/// </summary>
/// <param name="service">Service name</param>
/// <param name="times">Times called</param>
public void VerifyCallServiceTimes(string service, Times times)
{
DefaultHassClientMock.VerifyCallServiceTimes(service, times);
}

public async Task<(Task, CancellationTokenSource)> ReturnRunningDefauldDaemonHostTask(short milliSeconds = 100, bool overrideDebugNotCancel = false)
{
await InitApps();
var cancelSource = Debugger.IsAttached && !overrideDebugNotCancel
? new CancellationTokenSource()
: new CancellationTokenSource(milliSeconds);
return (_defaultDaemonHost.Run("host", 8123, false, "token", cancelSource.Token), cancelSource);
}

public async Task RunDefauldDaemonUntilCanceled(short milliSeconds = 100, bool overrideDebugNotCancel = false)
{
var cancelSource = Debugger.IsAttached && !overrideDebugNotCancel
? new CancellationTokenSource()
: new CancellationTokenSource(milliSeconds);
try
{
await InitApps();
await _defaultDaemonHost.Run("host", 8123, false, "token", cancelSource.Token).ConfigureAwait(false);
}
catch (TaskCanceledException)
{
// Expected behaviour
}
}

public async Task WaitUntilCanceled(Task task)
{
try
{
await task.ConfigureAwait(false);
}
catch (TaskCanceledException)
{
// Expected behaviour
}
}

public async Task InitApps()
{
foreach (var inst in DefaultDaemonHost.InternalAllAppInstances)
{
await inst.Value.StartUpAsync(_defaultDaemonHost);
}

foreach (var inst in DefaultDaemonHost.InternalRunningAppInstances)
{
await inst.Value.InitializeAsync();
inst.Value.Initialize();
}
}

protected async Task<Task> GetConnectedNetDaemonTask(short milliSeconds = 100, bool overrideDebugNotCancel = false)
{
var cancelSource = Debugger.IsAttached && !overrideDebugNotCancel
? new CancellationTokenSource()
: new CancellationTokenSource(milliSeconds);

await InitApps();

var daemonTask = _defaultDaemonHost.Run("host", 8123, false, "token", cancelSource.Token);
await WaitForDefaultDaemonToConnect(DefaultDaemonHost, cancelSource.Token);
return daemonTask;
}

protected async Task WaitForDefaultDaemonToConnect(NetDaemonHost daemonHost, CancellationToken stoppingToken)
{
var nrOfTimesCheckForConnectedState = 0;

while (!daemonHost.Connected && !stoppingToken.IsCancellationRequested)
{
await Task.Delay(50, stoppingToken).ConfigureAwait(false);
if (nrOfTimesCheckForConnectedState++ > 100)
break;
}
}
}
}
Loading

0 comments on commit 9731fdc

Please sign in to comment.