/* * Copyright (c) 2024 Proton AG * * This file is part of ProtonVPN. * * ProtonVPN is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ProtonVPN is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ProtonVPN. If not, see . */ using NSubstitute; using ProtonVPN.Client.EventMessaging.Contracts; using ProtonVPN.Client.Logic.Connection.Contracts.Messages; using ProtonVPN.Client.Logic.Connection.NetworkingTraffic; using ProtonVPN.Common.Core.Networking; namespace ProtonVPN.Client.Logic.Connection.Tests.NetworkingTraffic; [TestClass] public class NetworkTrafficManagerTest { private IEventMessageSender? _eventMessageSender; private MockOfNetworkTrafficScheduler? _mockOfNetworkTrafficScheduler; private NetworkTrafficManager? _networkTrafficManager; [TestInitialize] public virtual void Initialize() { _eventMessageSender = Substitute.For(); _mockOfNetworkTrafficScheduler = new MockOfNetworkTrafficScheduler(); _networkTrafficManager = new(_eventMessageSender, _mockOfNetworkTrafficScheduler); } [TestCleanup] public virtual void Cleanup() { _eventMessageSender = null; _mockOfNetworkTrafficScheduler = null; _networkTrafficManager = null; } [TestMethod] public void Test_WhenFirstNetworkTrafficResponseIsZero() { NetworkTraffic networkTraffic = NetworkTraffic.Zero; _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic); _eventMessageSender!.Received(1).Send(Arg.Any()); AssertEqualNetworkTrafficWithoutDate(NetworkTraffic.Zero, _networkTrafficManager!.GetSpeed()); AssertEqualNetworkTrafficWithoutDate(NetworkTraffic.Zero, _networkTrafficManager.GetVolume()); AssertSpeedHistoryIsEmpty(); } private void AssertEqualNetworkTrafficWithoutDate(NetworkTraffic expectedNetworkTraffic, NetworkTraffic networkTraffic) { Assert.AreEqual(expectedNetworkTraffic.BytesDownloaded, networkTraffic.BytesDownloaded); Assert.AreEqual(expectedNetworkTraffic.BytesUploaded, networkTraffic.BytesUploaded); } private void AssertSpeedHistoryIsEmpty() { IReadOnlyList speedHistory = _networkTrafficManager!.GetSpeedHistory(); Assert.HasCount(NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS, speedHistory); for (int i = 0; i < NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS; i++) { AssertEqualNetworkTrafficWithoutDate(NetworkTraffic.Zero, speedHistory[i]); } } [TestMethod] public void Test_WhenFirstNetworkTrafficResponseIsNonZero() { NetworkTraffic networkTraffic = new(12345, 23456); _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic); _eventMessageSender!.Received(1).Send(Arg.Any()); AssertEqualNetworkTrafficWithoutDate(NetworkTraffic.Zero, _networkTrafficManager!.GetSpeed()); Assert.AreEqual(networkTraffic, _networkTrafficManager.GetVolume()); AssertSpeedHistoryIsEmpty(); } [TestMethod] public void Test_NetworkTrafficResponses_TooOldIncrement() { DateTime utcNow = DateTime.UtcNow; NetworkTraffic networkTraffic1 = new(100, 200, utcNow); NetworkTraffic networkTraffic2 = new(300, 300, utcNow.AddSeconds(1).AddTicks(-1)); NetworkTraffic expectedSpeed = NetworkTraffic.Zero; _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic1); _eventMessageSender!.Received(1).Send(Arg.Any()); _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic2); _eventMessageSender!.Received(1).Send(Arg.Any()); AssertEqualNetworkTrafficWithoutDate(expectedSpeed, _networkTrafficManager!.GetSpeed()); Assert.AreEqual(networkTraffic1, _networkTrafficManager.GetVolume()); AssertSpeedHistoryIsEmpty(); } [TestMethod] public void Test_NetworkTrafficResponses_FromZero_OneSecondIncrement() { DateTime utcNow = DateTime.UtcNow; NetworkTraffic networkTraffic1 = new(0, 0, utcNow); NetworkTraffic networkTraffic2 = new(100, 200, utcNow.AddSeconds(1)); NetworkTraffic expectedSpeed = networkTraffic2; _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic1); _eventMessageSender!.Received(1).Send(Arg.Any()); _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic2); _eventMessageSender!.Received(2).Send(Arg.Any()); AssertEqualNetworkTrafficWithoutDate(expectedSpeed, _networkTrafficManager!.GetSpeed()); Assert.AreEqual(networkTraffic2, _networkTrafficManager.GetVolume()); AssertLastSpeedHistoryItems(expectedSpeed, 1); } [TestMethod] public void Test_NetworkTrafficResponses_FromNonZero_OneSecondIncrement() { DateTime utcNow = DateTime.UtcNow; NetworkTraffic networkTraffic1 = new(100, 200, utcNow); NetworkTraffic networkTraffic2 = new(500, 300, utcNow.AddSeconds(1)); NetworkTraffic expectedSpeed = new(400, 100); _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic1); _eventMessageSender!.Received(1).Send(Arg.Any()); _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic2); _eventMessageSender!.Received(2).Send(Arg.Any()); AssertEqualNetworkTrafficWithoutDate(expectedSpeed, _networkTrafficManager!.GetSpeed()); Assert.AreEqual(networkTraffic2, _networkTrafficManager.GetVolume()); AssertLastSpeedHistoryItems(expectedSpeed, 1); } [TestMethod] public void Test_NetworkTrafficResponses_FromZero_HighIncrementButBelowLength() { DateTime utcNow = DateTime.UtcNow; ulong timeDifferenceInSeconds = NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS / 2; ulong downloadVolume = NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS * 20; ulong uploadVolume = NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS * 40; NetworkTraffic networkTraffic1 = new(0, 0, utcNow); NetworkTraffic networkTraffic2 = new(downloadVolume, uploadVolume, utcNow.AddSeconds(timeDifferenceInSeconds)); NetworkTraffic expectedSpeed = new(downloadVolume / timeDifferenceInSeconds, uploadVolume / timeDifferenceInSeconds); _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic1); _eventMessageSender!.Received(1).Send(Arg.Any()); _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic2); _eventMessageSender!.Received(2).Send(Arg.Any()); AssertEqualNetworkTrafficWithoutDate(expectedSpeed, _networkTrafficManager!.GetSpeed()); Assert.AreEqual(networkTraffic2, _networkTrafficManager.GetVolume()); AssertLastSpeedHistoryItems(expectedSpeed, (int)timeDifferenceInSeconds); } private void AssertLastSpeedHistoryItems(NetworkTraffic expectedSpeed, int numOfItems) { IReadOnlyList speedHistory = _networkTrafficManager!.GetSpeedHistory(); Assert.HasCount(NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS, speedHistory); int numOfEmptyItems = NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS - numOfItems; for (int i = 0; i < NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS; i++) { NetworkTraffic innerExpectedSpeed = i < numOfEmptyItems ? NetworkTraffic.Zero : expectedSpeed; AssertEqualNetworkTrafficWithoutDate(innerExpectedSpeed, speedHistory[i]); } } [TestMethod] public void Test_NetworkTrafficResponses_FromZero_HighIncrementAboveLength() { DateTime utcNow = DateTime.UtcNow; ulong timeDifferenceInSeconds = NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS * 2; ulong downloadVolume = NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS * 20; ulong uploadVolume = NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS * 40; NetworkTraffic networkTraffic1 = new(0, 0, utcNow); NetworkTraffic networkTraffic2 = new(downloadVolume, uploadVolume, utcNow.AddSeconds(timeDifferenceInSeconds)); NetworkTraffic expectedSpeed = new(downloadVolume / timeDifferenceInSeconds, uploadVolume / timeDifferenceInSeconds); _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic1); _eventMessageSender!.Received(1).Send(Arg.Any()); _mockOfNetworkTrafficScheduler!.InvokeEvent(networkTraffic2); _eventMessageSender!.Received(2).Send(Arg.Any()); AssertEqualNetworkTrafficWithoutDate(expectedSpeed, _networkTrafficManager!.GetSpeed()); Assert.AreEqual(networkTraffic2, _networkTrafficManager.GetVolume()); AssertLastSpeedHistoryItems(expectedSpeed, NetworkTrafficManager.HISTORY_LENGTH_IN_SECONDS); } }