public async Task LessThanInvalidValuesTest()
        {
            //Arrange 
            var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "Trigger-LessThanInvalidValuesTest" };
            Database.SetInitializer(new CreateFreshDbInitializer());

            var logEntries = new List<LogEntry>();
            var ranstoredCommands = new List<int>();
            var log = new StubIFeedback<LogEntry>
            {
                ReportAsyncT0CancellationToken = (e, c) =>
                {
                    Console.WriteLine(e.ToString());
                    logEntries.Add(e);
                    return Task.FromResult(0);
                }
            };

            var commandProcessor = new StubICommandProcessor
            {
                RunCommandAsyncNullableOfInt32StringStringCancellationToken = ( commandId, argument, argument2, cancellationToken) =>
                {
                    if (commandId.HasValue) ranstoredCommands.Add(commandId.Value);
                    return Task.FromResult(Result.ReportSuccess());
                }
            };


            Database.SetInitializer(new CreateFreshDbInitializer());

            var cts = new CancellationTokenSource();
            var triggerManager = new TriggerRunner(log, commandProcessor, dbConnection);
            await triggerManager.StartAsync(cts.Token);

            var cmd = new Command();
            var dv = new DeviceValue
            {
                Value = "first value",
                ValueType = DataType.STRING,
                Triggers = new ObservableCollection<DeviceValueTrigger> { 
                    new DeviceValueTrigger
                {
                     Name = "trigger1",
                     IsEnabled = true,
                     Operator = TriggerOperator.LessThan,
                     Value = "a",
                     Command = cmd
                } }
            };

            var device = UnitTesting.CreateFakeDevice();
            device.Values.Add(dv);

            using (var context = new ZvsContext(dbConnection))
            {
                context.Devices.Add(device);
                var r = await context.TrySaveChangesAsync(cts.Token);
                Assert.IsFalse(r.HasError, r.Message);
                dv.Value = "3";

                //Act
                var r2 = await context.TrySaveChangesAsync(cts.Token);
                Assert.IsFalse(r2.HasError, r2.Message);
            }

            await Task.Delay(700, cts.Token);
            await triggerManager.StopAsync(cts.Token);

            //Assert
            Assert.IsTrue(logEntries.Any(o => o.Level == LogEntryLevel.Warn), "Expected some warning log entries");
            Assert.IsTrue(ranstoredCommands.Count == 0, "Trigger runner did not run the correct amount of commands.");
        }
        public async Task RunSceneAsyncMultipleCommandCancelRunTest()
        {
            //Arrange 
            var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "Scene-RunSceneAsyncMultipleCommandCancelRunTest" };
            Database.SetInitializer(new CreateFreshDbInitializer());

            var logEntries = new List<LogEntry>();
            var ranstoredCommands = new List<int>();

            var log = new StubIFeedback<LogEntry>
            {
                ReportAsyncT0CancellationToken = (e, c) =>
                {
                    Console.WriteLine(e);
                    logEntries.Add(e);
                    return Task.FromResult(0);
                }
            };
            var cts = new CancellationTokenSource();
            var commandProcessor = new StubICommandProcessor
            {
                RunCommandAsyncNullableOfInt32StringStringCancellationToken = ( commandId, argument, argument2, cancellationToken) =>
                {
                    if (commandId.HasValue) ranstoredCommands.Add(commandId.Value);
                    if (ranstoredCommands.Count == 2)
                    {
                        cts.Cancel();
                    }

                    return Task.FromResult(Result.ReportSuccessFormat("Ran command Id:{0}", commandId));
                }
            };
            var scene = new Scene
            {
                Name = "I have one command"
            };

            var cmd1 = new Command
            {
                Description = "Command 1"
            };
            var command1 = new SceneStoredCommand
            {
                SortOrder = 1,
                TargetObjectName = "Device 1",
                Description = "Turn On Device 1",
                Command = cmd1
            };

            var cmd2 = new Command
            {
                Description = "Command 2"
            };
            var command2 = new SceneStoredCommand
            {
                SortOrder = 2,
                Description = "TIME DELAY",
                Command = cmd2
            };

            var cmd3 = new Command
            {
                Description = "Command 3"
            };
            var command3 = new SceneStoredCommand
            {
                SortOrder = 3,
                TargetObjectName = "Device 3",
                Description = "Turn On Device 3",
                Command = cmd3
            };

            scene.Commands.Add(command3);
            scene.Commands.Add(command1);
            scene.Commands.Add(command2);

            using (var context = new ZvsContext(dbConnection))
            {
                context.Scenes.Add(scene);
                await context.SaveChangesAsync(CancellationToken.None);
            }

           
            var sceneRunner = new SceneRunner(log, commandProcessor, dbConnection);

            //Act
            var result = await sceneRunner.RunSceneAsync(scene.Id, cts.Token);

            Console.WriteLine(result.Message);

            //Assert
            Assert.IsFalse(result.HasError);
            Assert.IsTrue(logEntries.Count(o => o.Level == LogEntryLevel.Warn) == 0, "Expected one warning log entries");
            Assert.IsTrue(logEntries.Count(o => o.Level == LogEntryLevel.Error) == 0, "Expected zero error log entries");
            Assert.IsTrue(ranstoredCommands.Count == 2, "Scene runner did not run the correct amount of commands.");
        }
        public async Task QuickFireTriggerTest()
        {
            var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "Trigger-QuickFireTriggerTest" };
            Database.SetInitializer(new CreateFreshDbInitializer());

            var logEntries = new List<LogEntry>();
            var ranstoredCommands = new List<int>();

            //Arrange 
            var log = new StubIFeedback<LogEntry>
            {
                ReportAsyncT0CancellationToken = (e, c) =>
                {
                    Console.WriteLine(e.ToString());
                    logEntries.Add(e);
                    return Task.FromResult(0);
                }
            };

            var commandProcessor = new StubICommandProcessor
            {
                RunCommandAsyncNullableOfInt32StringStringCancellationToken = ( commandId, argument, argument2, cancellationToken) =>
                {
                    if (commandId.HasValue) ranstoredCommands.Add(commandId.Value);
                    return Task.FromResult(Result.ReportSuccess());
                }
            };

            var cts = new CancellationTokenSource();
            var triggerManager = new TriggerRunner(log, commandProcessor, dbConnection);
            await triggerManager.StartAsync(cts.Token);

            var cmd = new Command();
            var dv = new DeviceValue
            {
                Value = "first value",
                ValueType = DataType.STRING,
                Triggers = new ObservableCollection<DeviceValueTrigger> { 
                    new DeviceValueTrigger
                {
                     Name = "trigger1",
                     IsEnabled = true,
                     Operator = TriggerOperator.EqualTo,
                     Value = "some unique value",
                     Command = cmd
                } }
            };

            var device = UnitTesting.CreateFakeDevice();
            device.Values.Add(dv);

            //Act
            using (var context = new ZvsContext(dbConnection))
            {
                context.Devices.Add(device);
                await context.TrySaveChangesAsync(cts.Token);

                dv.Value = "Not It!";
                await context.TrySaveChangesAsync(cts.Token);

                dv.Value = "not this one";
                await context.TrySaveChangesAsync(cts.Token);

                dv.Value = "some unique value";
                await context.TrySaveChangesAsync(cts.Token);

                dv.Value = "not it";
                await context.TrySaveChangesAsync(cts.Token);

                dv.Value = "some unique value";
                await context.TrySaveChangesAsync(cts.Token);

                Console.WriteLine(context.DeviceValueTriggers.Count());
            }

            await Task.Delay(700, cts.Token);
            await triggerManager.StopAsync(cts.Token);

            //Assert
            Assert.IsTrue(logEntries.All(o => o.Level == LogEntryLevel.Info), "Expected only info type log entries");
            Assert.IsTrue(ranstoredCommands.Count == 2, "Trigger runner did not run the correct amount of commands.");
            Assert.IsTrue(ranstoredCommands.All(o => o == cmd.Id), "Scheduled task runner did not run the correct command.");
        }
        public async Task MultipleAsyncRequestsTest()
        {
            var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "MultipleAsyncRequestsTest" };
            Database.SetInitializer(new CreateFreshDbInitializer());

            var logEntries = new List<LogEntry>();
            var ranstoredCommands = new List<int>();

            //Arrange 
            var log = new StubIFeedback<LogEntry>
            {
                ReportAsyncT0CancellationToken = (e, c) =>
                {
                    Console.WriteLine(e.ToString());
                    logEntries.Add(e);
                    return Task.FromResult(0);
                }
            };

            var commandProcessor = new StubICommandProcessor
            {
                RunCommandAsyncNullableOfInt32StringStringCancellationToken = (commandId, argument, argument2, cancellationToken) =>
                {
                    if (commandId.HasValue) ranstoredCommands.Add(commandId.Value);
                    return Task.FromResult(Result.ReportSuccess());
                }
            };
            var currentTime = new StubITimeProvider { TimeGet = () => DateTime.Parse("5/21/14 15:02:20") };


            var cts = new CancellationTokenSource();
            var taskRunner = new ScheduledTaskRunner(log, commandProcessor, dbConnection, currentTime);

            await taskRunner.StartAsync(cts.Token);

            var command = new Command();
            var commandScheduledTask = new DataModel.ScheduledTask
            {
                IsEnabled = true,
                Name = "New Command added after start",
                Command = command
            };
            using (var context = new ZvsContext(dbConnection))
            {
                context.ScheduledTasks.Add(commandScheduledTask);
                var r2 = await context.TrySaveChangesAsync(cts.Token);
                Assert.IsFalse(r2.HasError, r2.Message);

                commandScheduledTask.StartTime = DateTime.Parse("5/20/14 15:02:20");
                var r = await context.TrySaveChangesAsync(cts.Token);
                Assert.IsFalse(r.HasError, r.Message);

                commandScheduledTask.StartTime = DateTime.Parse("5/20/14 15:02:21");
                var r3 = await context.TrySaveChangesAsync(cts.Token);
                Assert.IsFalse(r3.HasError, r.Message);
            }
            //Act
            await Task.Delay(2000, cts.Token);
            await taskRunner.StopAsync(cts.Token);

            //Assert
            Assert.IsTrue(logEntries.All(o => o.Level == LogEntryLevel.Info), "Expected only info type log entries");
            Assert.IsTrue(ranstoredCommands.Count == 0, "Scheduled task runner did not run the correct amount of commands.");
        }