public void TestInvalidTicketResponse()
        {
            FakeDeviceClient   fakeDeviceClient = new FakeDeviceClient();
            FakeEventScheduler fakeScheduler    = new FakeEventScheduler();

            TestContext.WriteLine(">> Testing the Device's Ticket Validation failed notification..");

            ValidateTicketResponse approvePurchaseMethodkRequest = new ValidateTicketResponse()
            {
                DeviceId   = deviceconfig.DeviceId,
                DeviceType = deviceconfig.DeviceType,
                IsApproved = false
            };

            // create our test device
            GateReaderDevice device = new GateReaderDevice(deviceconfig, fakeDeviceClient, fakeScheduler);

            device.InitializeAsync().Wait();

            // send a ticket NOT approved event to the callback method
            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> validating ticket, shouldn't throw event");
            string        requestString = JsonConvert.SerializeObject(approvePurchaseMethodkRequest);
            MethodRequest methodRequest = new MethodRequest("ReceivePurchaseTicketResponse", Encoding.UTF8.GetBytes(requestString));

            MethodResponse myresult = fakeDeviceClient.directMethods[0](methodRequest, null).Result;

            // ticket validation failed, so no "gate opened" message sent
            Assert.AreEqual(0, fakeDeviceClient.sendMessageLog.Count);
        }
        public void TestGateReaderTicketValidation()
        {
            FakeDeviceClient   fakeDeviceClient = new FakeDeviceClient();
            FakeEventScheduler fakeScheduler    = new FakeEventScheduler();

            deviceconfig.PercentOfWrongWay = 0; // make sure we don't have any wrong way swipes

            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Testing the purchase ticket simulated event..");

            GateReaderDevice device = new GateReaderDevice(deviceconfig, fakeDeviceClient, fakeScheduler);

            device.InitializeAsync().Wait();

            // execute a validate ticket event and check the result, it should always be false
            Assert.IsFalse(fakeScheduler.EventList[0].EventDelegate());
            // that delegate should have sent one message to the cloud
            Assert.AreEqual(1, fakeDeviceClient.sendMessageLog.Count);

            // check the message sent to make sure its correct
            // create a sample request for comparison
            ValidateTicketRequest expectedRequest = new ValidateTicketRequest()
            {
                DeviceId      = deviceconfig.DeviceId,
                DeviceType    = deviceconfig.DeviceType,
                TransactionId = "fakeId",
                CreateTime    = System.DateTime.UtcNow,
                MethodName    = "ReceiveTicketValidationResponse"
            };
            // get request message into an object so we can compare it
            ValidateTicketRequest actualRequest = JsonConvert.DeserializeObject <ValidateTicketRequest>(fakeDeviceClient.sendMessageLog[0]);

            // compare properties to make sure they're valid.
            Assert.AreEqual(expectedRequest.DeviceId, actualRequest.DeviceId);
            Assert.AreEqual(expectedRequest.DeviceType, actualRequest.DeviceType);
            Assert.AreEqual(expectedRequest.MessageType, actualRequest.MessageType);
            Assert.AreEqual(expectedRequest.MethodName, actualRequest.MethodName);

            //
            /// test the CloudToEvent PurchaseResponse call we expect back
            //
            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Testing the ticket successfully validated direct method..");

            // test the direct method itself
            ValidateTicketResponse approvePurchaseMethodkRequest = new ValidateTicketResponse()
            {
                IsApproved  = true,
                DeviceId    = expectedRequest.DeviceId,
                DeviceType  = expectedRequest.DeviceType,
                MessageType = expectedRequest.MessageType,
            };
            string requestString = JsonConvert.SerializeObject(approvePurchaseMethodkRequest);
            // execute the method
            MethodRequest  methodRequest = new MethodRequest(expectedRequest.MethodName, Encoding.UTF8.GetBytes(requestString));
            MethodResponse methodresult  = fakeDeviceClient.directMethods[0](methodRequest, null).Result;

            // check results
            Assert.AreEqual(200, methodresult.Status); // got back an ok
        }
        public void TestKioskPurchaseTicket()
        {
            FakeDeviceClient   fakeDeviceClient = new FakeDeviceClient();
            FakeEventScheduler fakeScheduler    = new FakeEventScheduler();

            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Testing the purchase ticket simulated event..");

            KioskDevice device = new KioskDevice(deviceconfig, fakeDeviceClient, fakeScheduler);

            // execute a purchase ticket event and check the result, it should always be false
            Assert.IsFalse(fakeScheduler.EventList[0].EventDelegate());
            // that delegate should have sent one message to the cloud
            Assert.AreEqual(fakeDeviceClient.sendMessageLog.Count, 1);

            // check the message sent to make sure its correct
            // create a sample request for comparison
            PurchaseTicketRequest expectedRequest = new PurchaseTicketRequest()
            {
                DeviceId      = deviceconfig.DeviceId,
                DeviceType    = deviceconfig.DeviceType,
                TransactionId = "fakeId",
                CreateTime    = System.DateTime.UtcNow,
                Price         = 1,
                MethodName    = "ReceivePurchaseTicketResponse"
            };
            // get request message into an object so we can compare it
            PurchaseTicketRequest actualRequest = JsonConvert.DeserializeObject <PurchaseTicketRequest>(fakeDeviceClient.sendMessageLog[0]);

            // compare properties to make sure they're valid.
            Assert.AreEqual(actualRequest.DeviceId, expectedRequest.DeviceId);
            Assert.AreEqual(actualRequest.DeviceType, expectedRequest.DeviceType);
            Assert.AreEqual(actualRequest.MessageType, expectedRequest.MessageType);
            // skipping the TransactionID and CreationTime
            Assert.IsTrue(actualRequest.Price > 2);
            Assert.IsTrue(actualRequest.Price < 100);
            Assert.AreEqual(actualRequest.MethodName, expectedRequest.MethodName);

            //
            /// test the CloudToEvent PurchaseResponse call we expect back
            //
            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Testing the ticket approval direct method..");

            // test the direct method itself
            PurchaseTicketPayload approvePurchaseMethodkRequest = new PurchaseTicketPayload()
            {
                IsApproved  = true,
                DeviceId    = expectedRequest.DeviceId,
                DeviceType  = expectedRequest.DeviceType,
                MessageType = expectedRequest.MessageType,
            };
            string requestString = JsonConvert.SerializeObject(approvePurchaseMethodkRequest);
            // execute the method
            MethodRequest  methodRequest = new MethodRequest(expectedRequest.MethodName, Encoding.UTF8.GetBytes(requestString));
            MethodResponse methodresult  = fakeDeviceClient.directMethods[0](methodRequest, null).Result;

            // check results
            Assert.AreEqual(methodresult.Status, 200); // got back an ok
        }
        public void TestPurchaseDenied()
        {
            FakeDeviceClient   fakeDeviceClient = new FakeDeviceClient();
            FakeEventScheduler fakeScheduler    = new FakeEventScheduler();

            TestContext.WriteLine(">> Testing the Kiosk Device's Low Stock notification..");

            PurchaseTicketPayload approvePurchaseMethodkRequest = new PurchaseTicketPayload()
            {
                DeviceId    = deviceconfig.DeviceId,
                DeviceType  = deviceconfig.DeviceType,
                MessageType = "Purchase",
                IsApproved  = false
            };

            // create our test device
            KioskDevice device = new KioskDevice(deviceconfig, fakeDeviceClient, fakeScheduler);

            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Purchasing tickets, shouldn't throw event");
            string        requestString = JsonConvert.SerializeObject(approvePurchaseMethodkRequest);
            MethodRequest methodRequest = new MethodRequest("ReceivePurchaseTicketResponse", Encoding.UTF8.GetBytes(requestString));


            MethodResponse myresult = fakeDeviceClient.directMethods[0](methodRequest, null).Result;

            // no ticket was issued, count remained the same and no message sent to cloud
            Assert.AreEqual(device.CurrentStockLevel, deviceconfig.InitialStockCount);
            Assert.AreEqual(fakeDeviceClient.sendMessageLog.Count, 0);
        }
        public void TestBaseKioskDevice()
        {
            FakeDeviceClient   fakeDeviceClient = new FakeDeviceClient();
            FakeEventScheduler fakeScheduler    = new FakeEventScheduler();

            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Testing the Kiosk Device's base functionality..");

            KioskDevice device = new KioskDevice(deviceconfig, fakeDeviceClient, fakeScheduler);

            // should only have 1 scheduled event
            Assert.AreEqual(fakeScheduler.EventList.Count, 1, "Incorrect number of scheduled events");

            // should only have 1 callback method
            Assert.AreEqual(fakeDeviceClient.directMethods.Count, 1, "Incorrect number of callback methods");
        }
        public void TestWrongWaySwipe()
        {
            TestContext.WriteLine(">> Testing the Device's wrong way swipe..");

            FakeDeviceClient   fakeDeviceClient = new FakeDeviceClient();
            FakeEventScheduler fakeScheduler    = new FakeEventScheduler();

            deviceconfig.PercentOfWrongWay = 100; // gurantee a wrong way swipe

            // create our test device
            GateReaderDevice device = new GateReaderDevice(deviceconfig, fakeDeviceClient, fakeScheduler);

            device.InitializeAsync().Wait();

            // check the ticket, should return false so we can restart the timer
            Assert.IsTrue(fakeScheduler.EventList[0].EventDelegate());
            // that delegate should have sent NO messages to the cloud
            Assert.AreEqual(0, fakeDeviceClient.sendMessageLog.Count);
        }
        public void TestBaseGateReaderDevice()
        {
            FakeDeviceClient   fakeDeviceClient = new FakeDeviceClient();
            FakeEventScheduler fakeScheduler    = new FakeEventScheduler();

            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Testing the GateReader Device's base functionality..");

            GateReaderDevice device = new GateReaderDevice(deviceconfig, fakeDeviceClient, fakeScheduler);

            // initialize the device, setting up initial connections
            device.InitializeAsync().Wait();

            // should only have 1 scheduled event
            Assert.AreEqual(1, fakeScheduler.EventList.Count, "Incorrect number of scheduled events");

            // should only have 1 callback method
            Assert.AreEqual(2, fakeDeviceClient.directMethods.Count, "Incorrect number of callback methods");

            // gate direction should be "In"
            Assert.AreEqual(GateDirection.In, device.Direction, $"Device gate direction is not correct, expected 'In', found {device.Direction}");
        }
        public void TestGateReaderGateDirection()
        {
            FakeDeviceClient   fakeDeviceClient = new FakeDeviceClient(fakeTwin);
            FakeEventScheduler fakeScheduler    = new FakeEventScheduler();

            TestContext.WriteLine(">> Testing the Device's Gate Direction initialization ..");

            // create our test device
            GateReaderDevice device = new GateReaderDevice(deviceconfig, fakeDeviceClient, fakeScheduler);

            device.InitializeAsync().Wait();

            // gate direction should be "Out" as fakeTwin properties should override device config
            Assert.AreEqual(GateDirection.Out, device.Direction, $"Device gate direction is not correct, expected 'In', found {device.Direction}");

            TestContext.WriteLine(">> Testing the Device's Gate Direction change commands..");

            cmdGateDirectionUpdate commandGateDirectionUpdate = new cmdGateDirectionUpdate()
            {
                Direction = GateDirection.Out
            };

            // call the gate change direction
            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Sending command to change gate direction when its already pointed that way, shouldn't log event");
            string        requestString = JsonConvert.SerializeObject(commandGateDirectionUpdate);
            MethodRequest methodRequest = new MethodRequest("ReceiveCommandGateChange", Encoding.UTF8.GetBytes(requestString));

            MethodResponse myresult = fakeDeviceClient.directMethods[1](methodRequest, null).Result;

            // gate direction should be "In" now
            Assert.AreEqual(GateDirection.Out, device.Direction, $"Device gate direction is not correct, expected 'Out', found {device.Direction}");

            // check the device twin properties
            // ensures that the device is using the device client SetDigitalTwinPropertyAsync method for twin property updates
            GateDirection twinDirection = (GateDirection)Enum.Parse(typeof(GateDirection), fakeTwin.Properties.Reported["GateDirection"].ToString());

            Assert.AreEqual(GateDirection.Out, twinDirection, $"Device gate direction in the device twin is not correct, expected 'Out', found {twinDirection}");
        }
        public void TestLowStock()
        {
            FakeDeviceClient   fakeDeviceClient = new FakeDeviceClient();
            FakeEventScheduler fakeScheduler    = new FakeEventScheduler();

            TestContext.WriteLine(">> Testing the Kiosk Device's Low Stock notification..");

            PurchaseTicketPayload approvePurchaseMethodkRequest = new PurchaseTicketPayload()
            {
                DeviceId    = deviceconfig.DeviceId,
                DeviceType  = deviceconfig.DeviceType,
                MessageType = MessageType.cmdPurchaseTicket,
                IsApproved  = true
            };

            // create our test device
            KioskDevice device = new KioskDevice(deviceconfig, fakeDeviceClient, fakeScheduler);

            device.InitializeAsync().Wait();

            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Purchasing tickets, shouldn't throw event");
            string        requestString = JsonConvert.SerializeObject(approvePurchaseMethodkRequest);
            MethodRequest methodRequest = new MethodRequest("ReceivePurchaseTicketResponse", Encoding.UTF8.GetBytes(requestString));

            // fire events to bring the count down to right at threshold
            for (long count = this.deviceconfig.InitialStockCount; count > this.deviceconfig.LowStockThreshold; count--)
            {
                MethodResponse myresult = fakeDeviceClient.directMethods[0](methodRequest, null).Result;
                TestContext.WriteLine(">> Current stock level: " + device.CurrentStockLevel);
            }

            // now that we're at the threshold, lets clear all previous events
            fakeDeviceClient.sendMessageLog.Clear(); // clear out all messages to this point

            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Purchasing 1 more ticket. Should send low stock notification");
            // purchase one more ticket.
            MethodResponse methodresult = fakeDeviceClient.directMethods[0](methodRequest, null).Result;

            // we expect 2 messages to have been sent
            Assert.AreEqual(fakeDeviceClient.sendMessageLog.Count, 2);
            // second message should make expected result
            LowStockRequest expectedRequest = new LowStockRequest()
            {
                DeviceId   = deviceconfig.DeviceId,
                DeviceType = deviceconfig.DeviceType,
                StockLevel = (deviceconfig.LowStockThreshold - 1),
            };
            // get actual message into an object so we can compare it
            LowStockRequest actualRequest = JsonConvert.DeserializeObject <LowStockRequest>(fakeDeviceClient.sendMessageLog[1]);

            TestContext.WriteLine(fakeDeviceClient.sendMessageLog[1]);
            // compare properties to make sure they're valid.
            Assert.AreEqual(actualRequest.DeviceId, expectedRequest.DeviceId);
            Assert.AreEqual(actualRequest.DeviceType, expectedRequest.DeviceType);
            Assert.AreEqual(actualRequest.MessageType, expectedRequest.MessageType);
            Assert.AreEqual(actualRequest.StockLevel, expectedRequest.StockLevel);

            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Testing to make sure we don't have a second low stock warning ..");
            // make sure we don't throw the low stock warning again
            fakeDeviceClient.sendMessageLog.Clear(); // clear out all messages to this point
            // purchase one more ticket.
            methodresult = fakeDeviceClient.directMethods[0](methodRequest, null).Result;
            // we expect 2 messages to have been sent
            Assert.AreEqual(fakeDeviceClient.sendMessageLog.Count, 1);

            // reset the device to make sure ticket stock is reset using the desired property callback option
            device.SetDeviceStatusAsync(DeviceStatus.disabled).Wait(); // disable the device
            device.SetDeviceStatusAsync(DeviceStatus.enabled).Wait();  // enable the device
            // check the stock level
            Assert.AreEqual(deviceconfig.InitialStockCount, device.CurrentStockLevel, "Device stock levels were not reset back to initial after device rest");
        }