public async Task When_Called_By_Multiple_Gateways_Should_Return_Closest() { var devEUI = TestEui.GenerateDevEui(); const uint fcntUp = 1; var req1 = new FunctionBundlerRequest() { GatewayId = "gateway1", ClientFCntUp = fcntUp, Rssi = -180 }; var pipeline1 = new FunctionBundlerPipelineExecuter(new IFunctionBundlerExecutionItem[] { this.preferredGatewayExecutionItem }, devEUI, req1); var t1 = Task.Run(() => this.preferredGatewayExecutionItem.ExecuteAsync(pipeline1)); var req2 = new FunctionBundlerRequest() { GatewayId = "gateway2", ClientFCntUp = fcntUp, Rssi = -179 }; var pipeline2 = new FunctionBundlerPipelineExecuter(new IFunctionBundlerExecutionItem[] { this.preferredGatewayExecutionItem }, devEUI, req2); var t2 = Task.Run(() => this.preferredGatewayExecutionItem.ExecuteAsync(pipeline2)); var req3 = new FunctionBundlerRequest() { GatewayId = "gateway3", ClientFCntUp = fcntUp, Rssi = -39 }; var pipeline3 = new FunctionBundlerPipelineExecuter(new IFunctionBundlerExecutionItem[] { this.preferredGatewayExecutionItem }, devEUI, req3); var t3 = Task.Run(() => this.preferredGatewayExecutionItem.ExecuteAsync(pipeline3)); await Task.WhenAll(t1, t2, t3); foreach (var reqAndPipeline in new[] { (t1, pipeline1), (t2, pipeline2), (t3, pipeline3) })
public async Task When_PerformNeededSyncs_Fails_Should_Release_Lock(string lockToTake) { var devAddrcache = new LoRaDevAddrCache(this.cache, null, null); await LockDevAddrHelper.PrepareLocksForTests(this.cache, lockToTake == null?null : new[] { lockToTake }); var managerInput = new List <DevAddrCacheInfo> { new DevAddrCacheInfo() { DevEUI = TestEui.GenerateDevEui(), DevAddr = CreateDevAddr() } }; var registryManagerMock = InitRegistryManager(managerInput); registryManagerMock.Setup(x => x.CreateQuery(It.IsAny <string>())).Throws(new RedisException(string.Empty)); await devAddrcache.PerformNeededSyncs(registryManagerMock.Object); // When doing a full update, the FullUpdateKey lock should be reset to 1min, the GlobalDevAddrUpdateKey should be gone // When doing a partial update, the GlobalDevAddrUpdateKey should be gone switch (lockToTake) { case FullUpdateKey: Assert.Null(await this.cache.GetObjectTTL(GlobalDevAddrUpdateKey)); break; case null: var nextFullUpdate = await this.cache.GetObjectTTL(FullUpdateKey); Assert.True(nextFullUpdate <= TimeSpan.FromMinutes(1)); Assert.Null(await this.cache.GetObjectTTL(GlobalDevAddrUpdateKey)); break; default: throw new InvalidOperationException("invalid test case"); } }
public async Task MessageDeduplication_DifferentDevices_Allowed() { var gateway1Id = NewUniqueEUI64(); var gateway2Id = NewUniqueEUI64(); var dev1EUI = TestEui.GenerateDevEui(); var dev2EUI = TestEui.GenerateDevEui(); var result = await this.deduplicationExecutionItem.GetDuplicateMessageResultAsync(dev1EUI, gateway1Id, 1, 1); Assert.False(result.IsDuplicate); Assert.Equal(gateway1Id, result.GatewayId); result = await this.deduplicationExecutionItem.GetDuplicateMessageResultAsync(dev1EUI, gateway2Id, 2, 1); Assert.False(result.IsDuplicate); Assert.Equal(gateway2Id, result.GatewayId); result = await this.deduplicationExecutionItem.GetDuplicateMessageResultAsync(dev2EUI, gateway1Id, 1, 1); Assert.False(result.IsDuplicate); Assert.Equal(gateway1Id, result.GatewayId); result = await this.deduplicationExecutionItem.GetDuplicateMessageResultAsync(dev2EUI, gateway2Id, 2, 1); Assert.False(result.IsDuplicate); Assert.Equal(gateway2Id, result.GatewayId); }
public async Task FrameCounter_Down_Initial() { var deviceEUI = TestEui.GenerateDevEui(); var gatewayId = NewUniqueEUI64(); var next = await this.fcntCheck.GetNextFCntDownAsync(deviceEUI, gatewayId, 1, 1); Assert.Equal(2U, next); }
// This test ensure that if the device has the key within the cache, it should not make any query to iot hub public async Task When_Device_Is_Not_Ours_Save_In_Cache_And_Dont_Query_Hub_Again() { var gatewayId = NewUniqueEUI64(); var dateTime = DateTime.UtcNow; // In this test we want no updates running // initialize locks for test to run correctly var lockToTake = new string[2] { FullUpdateKey, GlobalDevAddrUpdateKey }; await LockDevAddrHelper.PrepareLocksForTests(this.cache, lockToTake); var items = new List <IoTHubDeviceInfo>(); var primaryKey = Convert.ToBase64String(Encoding.UTF8.GetBytes(PrimaryKey)); var managerInput = new List <DevAddrCacheInfo>(); for (var i = 0; i < 2; i++) { managerInput.Add(new DevAddrCacheInfo() { DevEUI = TestEui.GenerateDevEui(), DevAddr = CreateDevAddr(), GatewayId = gatewayId, PrimaryKey = primaryKey, LastUpdatedTwins = dateTime }); } var devAddrJoining = CreateDevAddr(); InitCache(this.cache, managerInput); var registryManagerMock = InitRegistryManager(managerInput); var deviceGetter = new DeviceGetter(registryManagerMock.Object, this.cache); items = await deviceGetter.GetDeviceList(null, gatewayId, new DevNonce(0xABCD), devAddrJoining); Assert.Empty(items); var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, devAddrJoining)); Assert.Single(queryResult); var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value); Assert.Null(resultObject.DevEUI); Assert.Null(resultObject.PrimaryKey); Assert.Null(resultObject.GatewayId); var query2Result = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, devAddrJoining)); Assert.Single(query2Result); // Iot hub should never have been called. registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Never, "IoT Hub should not have been called, as the device was present in the cache."); registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never, "IoT Hub should not have been called, as the device was present in the cache."); // Should not query for the key as key is there registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Never); }
public async void DeviceGetter_OTAA_Join() { var devEui = TestEui.GenerateDevEui(); var gatewayId = NewUniqueEUI64(); var deviceGetter = new DeviceGetter(InitRegistryManager(devEui), new LoRaInMemoryDeviceStore()); var items = await deviceGetter.GetDeviceList(devEui, gatewayId, new DevNonce(0xABCD), null); Assert.Single(items); Assert.Equal(devEui, items[0].DevEUI); }
public async Task FunctionBundler_Multi() { var gatewayId1 = NewUniqueEUI64(); var gatewayId2 = NewUniqueEUI64(); var gatewayId3 = NewUniqueEUI64(); var gatewayId4 = NewUniqueEUI64(); var devEUI = TestEui.GenerateDevEui(); var requests = new FunctionBundlerRequest[] { CreateStandardBundlerRequest(gatewayId1), CreateStandardBundlerRequest(gatewayId2), CreateStandardBundlerRequest(gatewayId3), CreateStandardBundlerRequest(gatewayId4) }; foreach (var req in requests) { await PrepareADRFrames(devEUI, 20, req.AdrRequest); req.ClientFCntUp = req.AdrRequest.FCntUp; req.ClientFCntDown = req.AdrRequest.FCntDown; } var functionBundlerResults = await Task.WhenAll(from req in requests select ExecuteRequest(devEUI, req)); // only one request should be winning the race var winners = 0; var dups = 0; foreach (var res in functionBundlerResults) { if (!res.DeduplicationResult.IsDuplicate) { Assert.NotNull(res.AdrResult); Assert.True(res.AdrResult.CanConfirmToDevice); Assert.Equal(res.AdrResult.FCntDown, res.NextFCntDown); Assert.True(res.NextFCntDown.GetValueOrDefault() > 0); winners++; } else { Assert.NotNull(res.AdrResult); Assert.False(res.AdrResult.CanConfirmToDevice); Assert.Equal(0U, res.AdrResult.FCntDown.GetValueOrDefault()); Assert.Null(res.NextFCntDown); dups++; } } Assert.Equal(1, winners); Assert.Equal(functionBundlerResults.Length - 1, dups); }
// This test simulate a call received by multiple server. It ensures IoT Hub is only queried once. public async Task Multi_Gateway_When_DevAddr_Is_Not_In_Cache_Query_Iot_Hub_Only_Once_And_Save_In_Cache() { var gateway1 = NewUniqueEUI64(); var gateway2 = NewUniqueEUI64(); var dateTime = DateTime.UtcNow; var managerInput = new List <DevAddrCacheInfo>(); for (var i = 0; i < 2; i++) { managerInput.Add(new DevAddrCacheInfo() { DevEUI = TestEui.GenerateDevEui(), DevAddr = CreateDevAddr() }); } var devAddrJoining = managerInput[0].DevAddr; var registryManagerMock = InitRegistryManager(managerInput); // In this test we want no updates running // initialize locks for test to run correctly var lockToTake = new string[2] { FullUpdateKey, GlobalDevAddrUpdateKey }; await LockDevAddrHelper.PrepareLocksForTests(this.cache, lockToTake); var deviceGetter = new DeviceGetter(registryManagerMock.Object, this.cache); // Simulate three queries var tasks = from gw in new[] { gateway1, gateway2 } select Enumerable.Repeat(gw, 2) into gws // repeat each gateway twice from gw in gws select deviceGetter.GetDeviceList(null, gw, new DevNonce(0xABCD), devAddrJoining); await Task.WhenAll(tasks); // If a cache miss it should save it in the redisCache var devAddrcache = new LoRaDevAddrCache(this.cache, null, null); var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, devAddrJoining)); Assert.Single(queryResult); var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value); Assert.Equal(managerInput[0].DevAddr, resultObject.DevAddr); Assert.Equal(managerInput[0].GatewayId ?? string.Empty, resultObject.GatewayId); Assert.Equal(managerInput[0].DevEUI, resultObject.DevEUI); registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>(), It.IsAny <int>()), Times.Once); registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never); registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Once); }
// This test ensure that if a device is in cache without a key, it get the keys from iot hub and save it public async Task Multi_Gateway_When_DevAddr_Is_In_Cache_Without_Key_Should_Not_Query_Iot_Hub_For_Twin_But_Should_Get_Key_And_Update() { var gatewayId = NewUniqueEUI64(); var dateTime = DateTime.UtcNow; var managerInput = new List <DevAddrCacheInfo>(); for (var i = 0; i < 2; i++) { managerInput.Add(new DevAddrCacheInfo() { DevEUI = TestEui.GenerateDevEui(), DevAddr = CreateDevAddr(), GatewayId = gatewayId, LastUpdatedTwins = dateTime }); } var devAddrJoining = managerInput[0].DevAddr; InitCache(this.cache, managerInput); var registryManagerMock = InitRegistryManager(managerInput); // In this test we want no updates running // initialize locks for test to run correctly var lockToTake = new string[2] { FullUpdateKey, GlobalDevAddrUpdateKey }; await LockDevAddrHelper.PrepareLocksForTests(this.cache, lockToTake); var deviceGetter = new DeviceGetter(registryManagerMock.Object, this.cache); var tasks = from gw in Enumerable.Repeat(gatewayId, 3) select deviceGetter.GetDeviceList(null, gw, new DevNonce(0xABCD), devAddrJoining); await Task.WhenAll(tasks); // Iot hub should never have been called. registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Never, "IoT Hub should not have been called, as the device was present in the cache."); registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>(), It.IsAny <int>()), Times.Never, "IoT Hub should not have been called, as the device was present in the cache."); registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never, "IoT Hub should not have been called, as the device was present in the cache."); // Should query for the key as key is missing registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Once); var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, devAddrJoining)); Assert.Single(queryResult); // The key should have been saved var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value); Assert.NotNull(resultObject.PrimaryKey); }
// Check that the server perform a full reload if the locking key for full reload is not present public async Task When_FullUpdateKey_Is_Not_there_Should_Perform_Full_Reload() { var gatewayId = NewUniqueEUI64(); var dateTime = DateTime.UtcNow; var primaryKey = Convert.ToBase64String(Encoding.UTF8.GetBytes(PrimaryKey)); var managerInput = new List <DevAddrCacheInfo>(); for (var i = 0; i < 5; i++) { managerInput.Add(new DevAddrCacheInfo() { DevEUI = TestEui.GenerateDevEui(), DevAddr = CreateDevAddr(), GatewayId = gatewayId, }); } var devAddrJoining = managerInput[0].DevAddr; // The cache start as empty var registryManagerMock = InitRegistryManager(managerInput); // initialize locks for test to run correctly await LockDevAddrHelper.PrepareLocksForTests(this.cache); var items = new List <IoTHubDeviceInfo>(); var deviceGetter = new DeviceGetter(registryManagerMock.Object, this.cache); items = await deviceGetter.GetDeviceList(null, gatewayId, new DevNonce(0xABCD), devAddrJoining); Assert.Single(items); // Iot hub should never have been called. registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Once); registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never); // We expect to query for the key once (the device with an active connection) registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Once); // we expect the devices are saved for (var i = 1; i < 5; i++) { var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, managerInput[i].DevAddr)); Assert.Single(queryResult); var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value); Assert.Equal(managerInput[i].GatewayId, resultObject.GatewayId); Assert.Equal(managerInput[i].DevEUI, resultObject.DevEUI); } }
public async Task ADR_First_Entry_Device_Reset() { var deviceEUI = TestEui.GenerateDevEui(); var gatewayId = NewUniqueEUI64(); var req = CreateStandardADRRequest(gatewayId); var result = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req); Assert.NotNull(result); Assert.Equal(1, result.NumberOfFrames); Assert.True(result.CanConfirmToDevice); Assert.Equal(0, result.TxPower); Assert.Equal(req.DataRate, result.DataRate); Assert.Equal(1, result.NbRepetition); }
public async Task ADR_MultiGateway_Full_Frame() { var deviceEUI = TestEui.GenerateDevEui(); var gateway1Id = NewUniqueEUI64(); var gateway2Id = NewUniqueEUI64(); var req1 = CreateStandardADRRequest(gateway1Id, -10); var req2 = CreateStandardADRRequest(gateway2Id, -10); var rnd = new Random(); // add just 1 under the limit to the table for (var i = 0; i < LoRaADRTable.FrameCountCaptureCount - 1; i++) { var res1 = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req1); var res2 = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req2); var winner = req1.RequiredSnr < req2.RequiredSnr ? gateway2Id : gateway1Id; var last = await this.adrManager.GetLastEntryAsync(deviceEUI); Assert.Equal(winner, last.GatewayId); Assert.Equal(2U, last.GatewayCount); req1.RequiredSnr = rnd.Next(-20, 5); req2.RequiredSnr = rnd.Next(-20, 5); req2.FCntUp = ++req1.FCntUp; req1.FCntDown = res1.FCntDown.GetValueOrDefault() > 0 ? res1.FCntDown.Value : req1.FCntDown; req2.FCntDown = res2.FCntDown.GetValueOrDefault() > 0 ? res2.FCntDown.Value : req2.FCntDown; } req2.FCntUp = ++req1.FCntUp; // first one should win var result1 = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req1); var result2 = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req2); Assert.True(result1.CanConfirmToDevice); Assert.False(result2.CanConfirmToDevice); Assert.Equal(req1.FCntDown + 1, result1.FCntDown); Assert.Equal(0U, result2.FCntDown.GetValueOrDefault()); }
public async Task FunctionBundler_FCntDown_Only() { var gatewayId1 = NewUniqueEUI64(); var devEUI = TestEui.GenerateDevEui(); var req = CreateStandardBundlerRequest(gatewayId1); req.AdrRequest = null; req.FunctionItems = FunctionBundlerItemType.FCntDown; var resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req); Assert.NotNull(resp); Assert.Null(resp.AdrResult); Assert.Null(resp.DeduplicationResult); Assert.Equal(req.ClientFCntDown + 1, resp.NextFCntDown); }
public async Task ADR_MultiGateway_Entry_Update() { var deviceEUI = TestEui.GenerateDevEui(); var gateway1Id = NewUniqueEUI64(); var gateway2Id = NewUniqueEUI64(); var req = CreateStandardADRRequest(gateway1Id, -10); var req2 = CreateStandardADRRequest(gateway2Id, -10); _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req); _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req2); // last entry should have 2 and the id should be from gw1 var last = await this.adrManager.GetLastEntryAsync(deviceEUI); Assert.Equal(2U, last.GatewayCount); Assert.Equal(gateway1Id, last.GatewayId); // reply _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req); _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req2); last = await this.adrManager.GetLastEntryAsync(deviceEUI); Assert.Equal(4U, last.GatewayCount); // add new fcnt and change snr for gw2 req2.FCntUp = ++req.FCntUp; req2.RequiredSnr = -9; _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req); _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req2); last = await this.adrManager.GetLastEntryAsync(deviceEUI); Assert.Equal(2U, last.GatewayCount); Assert.Equal(gateway2Id, last.GatewayId); Assert.Equal(-9, last.Snr); }
public ADRTestData() { // First test not enough entries to send back an answer var tableentries = new List <LoRaADRTableEntry>(); var deviceEuiNotEnoughEntries = TestEui.GenerateDevEui(); for (uint i = 0; i < 10; i++) { tableentries.Add(new LoRaADRTableEntry() { DevEUI = deviceEuiNotEnoughEntries, FCnt = i, GatewayCount = 1, GatewayId = "mygateway", Snr = -20 }); } var radioMetadata = new RadioMetadata(DataRateIndex.DR5, TestUtils.TestRegion.GetDefaultRX2ReceiveWindow(default).Frequency, null);
public async Task FunctionBundler_All_Functions() { var gatewayId1 = NewUniqueEUI64(); var devEUI = TestEui.GenerateDevEui(); var req = CreateStandardBundlerRequest(gatewayId1); var resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req); Assert.NotNull(resp); Assert.NotNull(resp.AdrResult); Assert.False(resp.AdrResult.CanConfirmToDevice); Assert.Equal(1, resp.AdrResult.NumberOfFrames); Assert.NotNull(resp.DeduplicationResult); Assert.Equal(gatewayId1, resp.DeduplicationResult.GatewayId); Assert.False(resp.DeduplicationResult.IsDuplicate); Assert.Equal(req.ClientFCntDown + 1, resp.NextFCntDown); }
public async Task FunctionBundler_Adr_Only() { var gatewayId1 = NewUniqueEUI64(); var devEUI = TestEui.GenerateDevEui(); var req = CreateStandardBundlerRequest(gatewayId1); req.FunctionItems = FunctionBundlerItemType.ADR; var resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req); Assert.NotNull(resp); Assert.NotNull(resp.AdrResult); Assert.True(resp.AdrResult.CanConfirmToDevice); Assert.Equal(req.AdrRequest.DataRate, resp.AdrResult.DataRate); Assert.Equal(0, resp.AdrResult.TxPower); Assert.Equal(1, resp.AdrResult.NumberOfFrames); Assert.Null(resp.DeduplicationResult); Assert.Equal(2U, resp.NextFCntDown); }
// Trigger delta update correctly to see if it performs correctly on an empty cache public async Task Delta_Update_Perform_Correctly_On_Empty_Cache() { var gatewayId = NewUniqueEUI64(); var dateTime = DateTime.UtcNow; var managerInput = new List <DevAddrCacheInfo>(); for (var i = 0; i < 5; i++) { managerInput.Add(new DevAddrCacheInfo() { DevEUI = TestEui.GenerateDevEui(), DevAddr = CreateDevAddr(), GatewayId = gatewayId, LastUpdatedTwins = dateTime }); } var devAddrJoining = managerInput[0].DevAddr; // The cache start as empty var registryManagerMock = InitRegistryManager(managerInput); // initialize locks for test to run correctly var locksToTake = new string[1] { FullUpdateKey }; await LockDevAddrHelper.PrepareLocksForTests(this.cache, locksToTake); var devAddrCache = new LoRaDevAddrCache(this.cache, null, gatewayId); await devAddrCache.PerformNeededSyncs(registryManagerMock.Object); while (!string.IsNullOrEmpty(this.cache.StringGet(GlobalDevAddrUpdateKey))) { await Task.Delay(100); } var foundItem = 0; // we expect the devices are saved for (var i = 0; i < 5; i++) { var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, managerInput[i].DevAddr)); if (queryResult.Length > 0) { foundItem++; Assert.Single(queryResult); var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value); Assert.Equal(managerInput[i].GatewayId, resultObject.GatewayId); Assert.Equal(managerInput[i].DevEUI, resultObject.DevEUI); } } // Only two items should be updated by the delta updates Assert.Equal(2, foundItem); // Iot hub should never have been called. registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Once); registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never); // We expect to query for the key once (the device with an active connection) registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Never); }
public async System.Threading.Tasks.Task CheckADRReturnsDefaultValueIfCacheCrash() { var devEUI = TestEui.GenerateDevEui(); var region = RegionManager.EU868; ILoRaADRStrategyProvider provider = new LoRaADRStrategyProvider(NullLoggerFactory.Instance); var datarate = DataRateIndex.DR5; using var inMemoryStore = new LoRaADRInMemoryStore(); var loRaADRManager = new Mock <LoRaADRManagerBase>(MockBehavior.Loose, inMemoryStore, provider, NullLogger <LoRaADRManagerBase> .Instance) { CallBase = true }; _ = loRaADRManager.Setup(x => x.NextFCntDown(It.IsAny <DevEui>(), It.IsAny <string>(), It.IsAny <uint>(), It.IsAny <uint>())).ReturnsAsync(1U); // setup table with default value _ = await loRaADRManager.Object.CalculateADRResultAndAddEntryAsync(devEUI, string.Empty, 1, 1, (float)region.RequiredSnr(datarate), region.GetDownstreamDataRate(datarate), region.TXPowertoMaxEIRP.Count - 1, region.MaxADRDataRate, new LoRaADRTableEntry() { Snr = 0, FCnt = 1, DevEUI = devEUI, GatewayCount = 1, GatewayId = "gateway" }); // Add measurement and compute new ADR for (uint i = 0; i < 21; i++) { await loRaADRManager.Object.StoreADREntryAsync( new LoRaADRTableEntry() { DevEUI = devEUI, FCnt = i, GatewayCount = 1, GatewayId = "mygateway", Snr = 50 }); } var adrResult = await loRaADRManager.Object.CalculateADRResultAndAddEntryAsync(devEUI, string.Empty, 1, 1, (float)region.RequiredSnr(datarate), region.GetDownstreamDataRate(datarate), region.TXPowertoMaxEIRP.Count - 1, region.MaxADRDataRate); Assert.Equal(DR5, adrResult.DataRate); Assert.Equal(7, adrResult.TxPower); Assert.Equal(1, adrResult.NbRepetition); // reset cache and check we get default values _ = await loRaADRManager.Object.ResetAsync(devEUI); adrResult = await loRaADRManager.Object.CalculateADRResultAndAddEntryAsync(devEUI, string.Empty, 1, 1, (float)region.RequiredSnr(datarate), region.GetDownstreamDataRate(datarate), region.TXPowertoMaxEIRP.Count - 1, region.MaxADRDataRate, new LoRaADRTableEntry() { Snr = 0, FCnt = 1, DevEUI = devEUI, GatewayCount = 1, GatewayId = "gateway" }); Assert.Equal(DR5, adrResult.DataRate); Assert.Equal(0, adrResult.TxPower); Assert.Equal(1, adrResult.NbRepetition); loRaADRManager.Verify(x => x.NextFCntDown(It.IsAny <DevEui>(), It.IsAny <string>(), It.IsAny <uint>(), It.IsAny <uint>()), Times.AtLeastOnce, "NextFCntDown"); }
// This test perform a delta update and we check the following // primary key present in the cache is still here after a delta up // Items with save Devaddr are correctly saved (one old from cache, one from iot hub) // Gateway Id is correctly updated in old cache information. // Primary Key are kept as UpdateTime is similar public async Task Delta_Update_Perform_Correctly_On_Non_Empty_Cache_And_Keep_Old_Values() { var oldGatewayId = NewUniqueEUI64(); var newGatewayId = NewUniqueEUI64(); var dateTime = DateTime.UtcNow; var primaryKey = Convert.ToBase64String(Encoding.UTF8.GetBytes(PrimaryKey)); var managerInput = new List <DevAddrCacheInfo>(); var adressForDuplicateDevAddr = CreateDevAddr(); for (var i = 0; i < 5; i++) { managerInput.Add(new DevAddrCacheInfo() { DevEUI = TestEui.GenerateDevEui(), DevAddr = CreateDevAddr(), GatewayId = newGatewayId, LastUpdatedTwins = dateTime }); } managerInput.Add(new DevAddrCacheInfo() { DevEUI = TestEui.GenerateDevEui(), DevAddr = adressForDuplicateDevAddr, GatewayId = newGatewayId, LastUpdatedTwins = dateTime }); var devAddrJoining = managerInput[0].DevAddr; // The cache start as empty var registryManagerMock = InitRegistryManager(managerInput, managerInput.Count); // Set up the cache with expectation. var cacheInput = new List <DevAddrCacheInfo>(); for (var i = 0; i < 5; i++) { cacheInput.Add(new DevAddrCacheInfo() { DevEUI = managerInput[i].DevEUI, DevAddr = managerInput[i].DevAddr, GatewayId = oldGatewayId, LastUpdatedTwins = dateTime }); } cacheInput[2].PrimaryKey = primaryKey; cacheInput[3].PrimaryKey = primaryKey; var devEui = TestEui.GenerateDevEui(); cacheInput.Add(new DevAddrCacheInfo() { DevEUI = devEui, DevAddr = adressForDuplicateDevAddr, GatewayId = oldGatewayId, PrimaryKey = primaryKey, LastUpdatedTwins = dateTime }); InitCache(this.cache, cacheInput); // initialize locks for test to run correctly var locksToTake = new string[1] { FullUpdateKey }; await LockDevAddrHelper.PrepareLocksForTests(this.cache, locksToTake); var devAddrCache = new LoRaDevAddrCache(this.cache, null, newGatewayId); await devAddrCache.PerformNeededSyncs(registryManagerMock.Object); // we expect the devices are saved for (var i = 0; i < managerInput.Count; i++) { if (managerInput[i].DevAddr != adressForDuplicateDevAddr) { var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, managerInput[i].DevAddr)); Assert.Single(queryResult); var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value); Assert.Equal(managerInput[i].GatewayId, resultObject.GatewayId); Assert.Equal(managerInput[i].DevEUI, resultObject.DevEUI); Assert.Equal(cacheInput[i].PrimaryKey, resultObject.PrimaryKey); } } // let's check the devices with a double EUI var query2Result = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, adressForDuplicateDevAddr)); Assert.Equal(2, query2Result.Length); for (var i = 0; i < 2; i++) { var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(query2Result[0].Value); if (resultObject.DevEUI == devEui) { Assert.Equal(oldGatewayId, resultObject.GatewayId); Assert.Equal(primaryKey, resultObject.PrimaryKey); } else { Assert.Equal(newGatewayId, resultObject.GatewayId); Assert.True(string.IsNullOrEmpty(resultObject.PrimaryKey)); } } // Iot hub should never have been called. registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Once); registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never); // We expect to query for the key once (the device with an active connection) registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Never); registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>(), It.IsAny <int>()), Times.Never); }
public async Task FunctionBundler_Adr_and_Dedup() { var gatewayId1 = NewUniqueEUI64(); var gatewayId2 = NewUniqueEUI64(); var devEUI = TestEui.GenerateDevEui(); var req = CreateStandardBundlerRequest(gatewayId1); var req2 = CreateStandardBundlerRequest(gatewayId2); req.FunctionItems = FunctionBundlerItemType.ADR | FunctionBundlerItemType.Deduplication; req2.FunctionItems = FunctionBundlerItemType.ADR | FunctionBundlerItemType.Deduplication; var resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req); Assert.NotNull(resp); Assert.NotNull(resp.AdrResult); Assert.False(resp.AdrResult.CanConfirmToDevice); Assert.Equal(1, resp.AdrResult.NumberOfFrames); Assert.NotNull(resp.DeduplicationResult); Assert.Equal(gatewayId1, resp.DeduplicationResult.GatewayId); Assert.False(resp.DeduplicationResult.IsDuplicate); Assert.Null(resp.NextFCntDown); // with ADR frames await this.adrManager.ResetAsync(devEUI); await PrepareADRFrames(devEUI, LoRaADRTable.FrameCountCaptureCount - 1, req.AdrRequest); req.ClientFCntUp = req.AdrRequest.FCntUp; resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req); Assert.NotNull(resp); Assert.NotNull(resp.AdrResult); Assert.Equal(LoRaADRTable.FrameCountCaptureCount, resp.AdrResult.NumberOfFrames); Assert.NotNull(resp.DeduplicationResult); Assert.Equal(gatewayId1, resp.DeduplicationResult.GatewayId); Assert.False(resp.DeduplicationResult.IsDuplicate); Assert.True(resp.AdrResult.CanConfirmToDevice || resp.NextFCntDown == null); // multi request req.AdrRequest.FCntUp = req2.AdrRequest.FCntUp = req2.ClientFCntUp = ++req.ClientFCntUp; req.AdrRequest.FCntDown = req2.AdrRequest.FCntDown = req2.ClientFCntDown = req.ClientFCntDown = resp.NextFCntDown.GetValueOrDefault(); resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req); Assert.NotNull(resp); Assert.NotNull(resp.AdrResult); Assert.NotNull(resp.DeduplicationResult); Assert.Equal(gatewayId1, resp.DeduplicationResult.GatewayId); Assert.False(resp.DeduplicationResult.IsDuplicate); Assert.True(resp.AdrResult.CanConfirmToDevice || resp.NextFCntDown == null); resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req2); Assert.NotNull(resp); Assert.NotNull(resp.AdrResult); Assert.True(resp.AdrResult.CanConfirmToDevice || resp.NextFCntDown == null); Assert.NotNull(resp.DeduplicationResult); Assert.Equal(gatewayId1, resp.DeduplicationResult.GatewayId); Assert.True(resp.DeduplicationResult.IsDuplicate); }
// This test perform a full update and we check the following // primary key present in the cache is still here after a fullupdate // Items with same Devaddr are correctly saved (one old from cache, one from iot hub) // Old cache items sharing a devaddr not in the new update are correctly removed // Items with a devAddr not in the update are correctly still in cache // Gateway Id is correctly updated in old cache information. // Primary Key are not kept as UpdateTime is not similar public async Task Full_Update_Perform_Correctly_On_Non_Empty_Cache_And_Keep_Old_Values_Except_Primary_Keys() { var oldGatewayId = NewUniqueEUI64(); var newGatewayId = NewUniqueEUI64(); var dateTime = DateTime.UtcNow; var updateDateTime = DateTime.UtcNow.AddMinutes(3); var primaryKey = Convert.ToBase64String(Encoding.UTF8.GetBytes(PrimaryKey)); var newValues = new List <DevAddrCacheInfo>(); for (var i = 0; i < 5; i++) { newValues.Add(new DevAddrCacheInfo() { DevEUI = TestEui.GenerateDevEui(), DevAddr = CreateDevAddr(), GatewayId = newGatewayId, LastUpdatedTwins = updateDateTime }); } // The cache start as empty var registryManagerMock = InitRegistryManager(newValues, newValues.Count); // Set up the cache with expectation. var cacheInput = new List <DevAddrCacheInfo>(); for (var i = 0; i < 5; i++) { cacheInput.Add(new DevAddrCacheInfo() { DevEUI = newValues[i].DevEUI, DevAddr = newValues[i].DevAddr, GatewayId = oldGatewayId, LastUpdatedTwins = dateTime, PrimaryKey = primaryKey }); } InitCache(this.cache, cacheInput); // initialize locks for test to run correctly await LockDevAddrHelper.PrepareLocksForTests(this.cache); var devAddrCache = new LoRaDevAddrCache(this.cache, null, newGatewayId); await devAddrCache.PerformNeededSyncs(registryManagerMock.Object); // we expect the devices are saved, the double device id should not be there anymore for (var i = 0; i < newValues.Count; i++) { var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, newValues[i].DevAddr)); Assert.Single(queryResult); var result2Object = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value); Assert.Equal(newGatewayId, result2Object.GatewayId); Assert.Equal(newValues[i].DevEUI, result2Object.DevEUI); Assert.Equal(string.Empty, result2Object.PrimaryKey); } // Iot hub should never have been called. registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Once); registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never); // We expect to query for the key once (the device with an active connection) registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Never); }