public ConcentratorDeduplicationJoinRequestsIntegrationTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
        {
            this.simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateOTAADevice(0));
            this.deviceMock      = new Mock <LoRaDevice>(MockBehavior.Default,
                                                         this.simulatedDevice.DevAddr,
                                                         this.simulatedDevice.DevEUI,
                                                         ConnectionManager)
            {
                CallBase = true
            };
            this.deviceMock.Object.AppKey      = this.simulatedDevice.AppKey;
            this.deviceMock.Object.AppEui      = this.simulatedDevice.AppEui;
            this.deviceMock.Object.IsOurDevice = true;
            this.testOutputLoggerFactory       = new TestOutputLoggerFactory(testOutputHelper);

            this.cache = new MemoryCache(new MemoryCacheOptions());
            var concentratorDeduplication = new ConcentratorDeduplication(this.cache, this.testOutputLoggerFactory.CreateLogger <IConcentratorDeduplication>());
            var deviceRegistryMock        = new Mock <ILoRaDeviceRegistry>();

            _ = deviceRegistryMock.Setup(x => x.GetDeviceForJoinRequestAsync(It.IsAny <DevEui>(), It.IsAny <DevNonce>()))
                .ReturnsAsync(this.deviceMock.Object);

            var clientMock = new Mock <ILoRaDeviceClient>();

            _ = clientMock.Setup(x => x.UpdateReportedPropertiesAsync(It.IsAny <TwinCollection>(), It.IsAny <CancellationToken>())).ReturnsAsync(true);
            ConnectionManager.Register(this.deviceMock.Object, clientMock.Object);

            this.joinRequestHandler = new JoinRequestMessageHandler(
                ServerConfiguration,
                concentratorDeduplication,
                deviceRegistryMock.Object,
                this.testOutputLoggerFactory.CreateLogger <JoinRequestMessageHandler>(),
                null);
        }
        public ConcentratorDeduplicationDataMessagesIntegrationTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
        {
            this.cache = new MemoryCache(new MemoryCacheOptions());
            this.testOutputLoggerFactory = new TestOutputLoggerFactory(testOutputHelper);
            var concentratorDeduplication = new ConcentratorDeduplication(this.cache, this.testOutputLoggerFactory.CreateLogger <IConcentratorDeduplication>());

            this.frameCounterStrategyMock = new Mock <ILoRaDeviceFrameCounterUpdateStrategy>();
            this.frameCounterProviderMock = new Mock <ILoRaDeviceFrameCounterUpdateStrategyProvider>();

            this.dataRequestHandlerMock = new Mock <TestDefaultLoRaRequestHandler>(MockBehavior.Default,
                                                                                   ServerConfiguration,
                                                                                   this.frameCounterProviderMock.Object,
                                                                                   concentratorDeduplication,
                                                                                   PayloadDecoder,
                                                                                   new DeduplicationStrategyFactory(this.testOutputLoggerFactory, this.testOutputLoggerFactory.CreateLogger <DeduplicationStrategyFactory>()),
                                                                                   new LoRaADRStrategyProvider(this.testOutputLoggerFactory),
                                                                                   new LoRAADRManagerFactory(LoRaDeviceApi.Object, this.testOutputLoggerFactory),
                                                                                   new FunctionBundlerProvider(LoRaDeviceApi.Object, this.testOutputLoggerFactory, this.testOutputLoggerFactory.CreateLogger <FunctionBundlerProvider>()),
                                                                                   testOutputHelper)
            {
                CallBase = true
            };

            this.dataRequestHandlerMock
            .Setup(d => d.DownlinkMessageBuilderResponseAssert(It.IsAny <LoRaRequest>(),
                                                               It.IsAny <LoRaDevice>(),
                                                               It.IsAny <LoRaOperationTimeWatcher>(),
                                                               It.IsAny <LoRaADRResult>(),
                                                               It.IsAny <IReceivedLoRaCloudToDeviceMessage>(),
                                                               It.IsAny <uint?>(),
                                                               It.IsAny <bool>()))
            .Returns((LoRaRequest request, LoRaDevice device, LoRaOperationTimeWatcher _, LoRaADRResult _, IReceivedLoRaCloudToDeviceMessage _, uint?_, bool _) => new
                     DownlinkMessageBuilderResponse(new DownlinkMessage(((LoRaPayloadData)request.Payload).Serialize(device.AppSKey.Value, device.NwkSKey.Value), default, default, default, default, default, default, default, default),
        public MessageProcessorMultipleGatewayBase(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
        {
            SecondServerConfiguration = new NetworkServerConfiguration
            {
                GatewayID    = SecondServerGatewayID,
                LogToConsole = true,
                LogLevel     = ((int)LogLevel.Debug).ToString(CultureInfo.InvariantCulture),
            };

            SecondDownstreamMessageSender            = new TestDownstreamMessageSender();
            SecondLoRaDeviceApi                      = new Mock <LoRaDeviceAPIServiceBase>(MockBehavior.Strict);
            SecondFrameCounterUpdateStrategyProvider = new LoRaDeviceFrameCounterUpdateStrategyProvider(SecondServerConfiguration, SecondLoRaDeviceApi.Object);
            this.cache = new MemoryCache(new MemoryCacheOptions()
            {
                ExpirationScanFrequency = TimeSpan.FromSeconds(5)
            });

            this.testOutputLoggerFactory = new TestOutputLoggerFactory(testOutputHelper);
            var deduplicationStrategyFactory = new DeduplicationStrategyFactory(this.testOutputLoggerFactory, this.testOutputLoggerFactory.CreateLogger <DeduplicationStrategyFactory>());
            var loRaAdrManagerFactory        = new LoRAADRManagerFactory(SecondLoRaDeviceApi.Object, this.testOutputLoggerFactory);
            var adrStrategyProvider          = new LoRaADRStrategyProvider(this.testOutputLoggerFactory);
            var functionBundlerProvider      = new FunctionBundlerProvider(SecondLoRaDeviceApi.Object, this.testOutputLoggerFactory, this.testOutputLoggerFactory.CreateLogger <FunctionBundlerProvider>());

            SecondConcentratorDeduplication = new ConcentratorDeduplication(this.cache, this.testOutputLoggerFactory.CreateLogger <IConcentratorDeduplication>());

            SecondRequestHandlerImplementation = new DefaultLoRaDataRequestHandler(SecondServerConfiguration,
                                                                                   SecondFrameCounterUpdateStrategyProvider,
                                                                                   SecondConcentratorDeduplication,
                                                                                   new LoRaPayloadDecoder(this.testOutputLoggerFactory.CreateLogger <LoRaPayloadDecoder>()),
                                                                                   deduplicationStrategyFactory,
                                                                                   adrStrategyProvider,
                                                                                   loRaAdrManagerFactory,
                                                                                   functionBundlerProvider,
                                                                                   this.testOutputLoggerFactory.CreateLogger <DefaultLoRaDataRequestHandler>(),
                                                                                   null);
            SecondLoRaDeviceClient = new Mock <ILoRaDeviceClient>(MockBehavior.Strict);
            this.cache             = new MemoryCache(new MemoryCacheOptions()
            {
                ExpirationScanFrequency = TimeSpan.FromSeconds(5)
            });

            var defaultRequestHandler = new DefaultLoRaDataRequestHandler(SecondServerConfiguration,
                                                                          SecondFrameCounterUpdateStrategyProvider,
                                                                          SecondConcentratorDeduplication,
                                                                          new LoRaPayloadDecoder(this.testOutputLoggerFactory.CreateLogger <LoRaPayloadDecoder>()),
                                                                          deduplicationStrategyFactory,
                                                                          adrStrategyProvider,
                                                                          loRaAdrManagerFactory,
                                                                          functionBundlerProvider,
                                                                          this.testOutputLoggerFactory.CreateLogger <DefaultLoRaDataRequestHandler>(),
                                                                          meter: null);

            SecondConnectionManager = new LoRaDeviceClientConnectionManager(this.cache, this.testOutputLoggerFactory.CreateLogger <LoRaDeviceClientConnectionManager>());
            SecondLoRaDeviceFactory = new TestLoRaDeviceFactory(SecondServerConfiguration, SecondLoRaDeviceClient.Object, SecondConnectionManager, DeviceCache, defaultRequestHandler);
        }
        public void When_Data_Message_Encountered_Should_Find_Duplicates_For_Different_Deduplication_Strategies(string station1, string station2, DeduplicationMode deduplicationMode, ConcentratorDeduplicationResult expectedResult)
        {
            // arrange
            var station1Eui = StationEui.Parse(station1);

            this.dataRequest.SetStationEui(station1Eui);
            _ = this.concentratorDeduplication.CheckDuplicateData(this.dataRequest, this.loRaDevice);

            this.dataRequest.SetStationEui(StationEui.Parse(station2));
            this.loRaDevice.Deduplication = deduplicationMode;

            // act/assert
            Assert.Equal(expectedResult, this.concentratorDeduplication.CheckDuplicateData(this.dataRequest, this.loRaDevice));
            Assert.Equal(1, this.cache.Count);
            var key = ConcentratorDeduplication.CreateCacheKey(this.dataPayload, this.loRaDevice);

            Assert.True(this.cache.TryGetValue(key, out var foundStation));
            Assert.Equal(station1Eui, foundStation);
        }
        public void When_Data_Message_Not_Encountered_Should_Not_Find_Duplicates_And_Should_Add_To_Cache(bool isCacheEmpty)
        {
            // arrange
            if (!isCacheEmpty)
            {
                using var testDevice = new LoRaDevice(this.simulatedABPDevice.DevAddr, new DevEui(0x1111111111111111UL), this.connectionManager);
                _ = this.concentratorDeduplication.CheckDuplicateData(this.dataRequest, testDevice);
            }

            // act
            var result = this.concentratorDeduplication.CheckDuplicateData(this.dataRequest, this.loRaDevice);

            // assert
            Assert.Equal(ConcentratorDeduplicationResult.NotDuplicate, result);
            var key = ConcentratorDeduplication.CreateCacheKey(this.dataPayload, this.loRaDevice);

            Assert.True(this.cache.TryGetValue(key, out var addedStation));
            Assert.Equal(this.dataRequest.StationEui, addedStation);
        }
        public ConcentratorDeduplicationTest()
        {
            this.cache             = new MemoryCache(new MemoryCacheOptions());
            this.connectionManager = new LoRaDeviceClientConnectionManager(this.cache, NullLogger <LoRaDeviceClientConnectionManager> .Instance);

            this.simulatedABPDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(0));
            this.dataPayload        = this.simulatedABPDevice.CreateConfirmedDataUpMessage("payload");
            this.dataRequest        = WaitableLoRaRequest.Create(this.dataPayload);
            this.loRaDevice         = new LoRaDevice(this.simulatedABPDevice.DevAddr, this.simulatedABPDevice.DevEUI, this.connectionManager);

            this.simulatedOTAADevice = new SimulatedDevice(TestDeviceInfo.CreateOTAADevice(0));
            this.joinPayload         = this.simulatedOTAADevice.CreateJoinRequest(appkey: this.simulatedOTAADevice.AppKey);
            this.joinRequest         = WaitableLoRaRequest.Create(this.joinPayload);
            this.joinRequest.SetPayload(this.joinPayload);

            this.concentratorDeduplication = new ConcentratorDeduplication(
                this.cache,
                NullLogger <IConcentratorDeduplication> .Instance);
        }