public void GetImageAsByteArray_NoParamsAndImageCacheHasNoData_ReturnsNull()
        {
            // Arrange
            var imageCache = new CacheUpdateService();

            // Act
            var imgCacheSvc = new ImageFromCacheService(imageCache);

            // Assert
            Assert.IsNull(imgCacheSvc.GetCurrentImageAsByteArray());
        }
        public void Constructor_ValidParams_HappyPath(int expiration, int fps)
        {
            // Arrange
            var imageCache = new CacheUpdateService();

            // Act
            var imgCacheSvc = new ImageFromCacheService(imageCache, null, expiration, fps);

            // Assert
            Assert.IsNotNull(imgCacheSvc);
        }
        public void GetImageAsByteArray_NoParamsImageCacheHasData_ReturnsNotNull()
        {
            // Arrange
            var imageCache = new CacheUpdateService();

            imageCache.UpdateImage(new byte[2], 1, DateTime.MaxValue);

            // Act
            var imgCacheSvc = new ImageFromCacheService(imageCache);


            // Assert
            Assert.IsNotNull(imgCacheSvc.GetCurrentImageAsByteArray());
        }
        [TestCase(1, StrCacheLastUpdate, 2000, 5, true, 99, 5000, false)]  // Failure: readerDelay > lifetime
        public void GetNewImageAsByteArray_WithParamsAndFreshData_ReturnNotNull(int cacheUpdaterUserId, string strCacheLastUpdate, int cacheLifeTime,
                                                                                int cacheFps, bool cacheHasData,
                                                                                int cacheReaderUserId, int cacheReaderDelay, bool expectedSuccess)
        {
            // Arrange
            DateTime cacheLastUpdate     = DateTime.ParseExact(s: strCacheLastUpdate, format: "yyyy-MM-dd HH:mm:ss.fff", provider: null);
            DateTime timeWhenCacheIsRead = cacheLastUpdate.AddMilliseconds(cacheReaderDelay);

            byte[]             imageBytes = cacheHasData ? new byte[2] : null;
            CacheUpdateService imageCache = CreateImageCache(imageBytes, cacheUpdaterUserId, cacheLastUpdate);
            var cachingService            = new ImageFromCacheService(cacheUpdateService: imageCache, logger: null, cacheLifeTimeMilliSec: cacheLifeTime, framesPerSecond: cacheFps);

            // Act
            byte[] imgBytes        = cachingService.GetNewImageAsByteArray(userId: cacheReaderUserId, timeRequested: timeWhenCacheIsRead);
            bool   resultIsNotNull = imgBytes != null;

            // Assert
            Assert.AreEqual(resultIsNotNull, expectedSuccess);
        }
        [TestCase(10, StrCacheLastUpdate, 2000, 5, true, 99, -1, 0)]                    // No wait time:  cacheReaderDelay < 0 ms
        public void WaitBeforeGettingNextImageTest_AnyParameters_ReturnExpectedResult(int cacheUpdaterUserId, string strCacheLastUpdate, int cacheLifeTime,
                                                                                      int cacheFps, bool cacheHasData,
                                                                                      int cacheReaderUserId, int cacheReaderDelay, int expectedWaitTimeMilliSec)
        {
            // Arrange
            DateTime cacheLastUpdate     = DateTime.ParseExact(s: strCacheLastUpdate, format: "yyyy-MM-dd HH:mm:ss.fff", provider: null);
            DateTime timeWhenCacheIsRead = cacheLastUpdate.AddMilliseconds(cacheReaderDelay);

            byte[] imageBytes = cacheHasData ? new byte[2] : null;

            CacheUpdateService imageCache       = CreateImageCache(imageBytes, cacheUpdaterUserId, cacheLastUpdate);
            var cachingService                  = new ImageFromCacheService(cacheUpdateService: imageCache, logger: null, cacheLifeTimeMilliSec: cacheLifeTime, framesPerSecond: cacheFps);
            int fpsTimeBetweenTwoFramesMilliSec = 1000 / cacheFps;

            // Act
            (int waitTimeMilliSec, string reason) = cachingService.WaitBeforeGettingNextImage(userId: cacheReaderUserId, timeRequested: timeWhenCacheIsRead);

            // Assert
            Assert.That(waitTimeMilliSec, Is.EqualTo(expectedWaitTimeMilliSec));

            Assert.That(waitTimeMilliSec, Is.LessThanOrEqualTo(fpsTimeBetweenTwoFramesMilliSec));
        }
        [TestCase(10, StrCacheLastUpdate, 2000, 5, true, 99, -1, false)] // Cannot update = new date is in the past
        public void UpdateCachedImage_AnyParameters_ReturnExpectedResult(int oldUpdaterUserId, string strCacheLastUpdate, int cacheLifeTime,
                                                                         int cacheFps, bool cacheHasData,
                                                                         int newCacheUpdaterUserId, int newCacheUpdaterDelay, bool expectedSuccess)
        {
            // Arrange
            DateTime cacheLastUpdate     = DateTime.ParseExact(s: strCacheLastUpdate, format: "yyyy-MM-dd HH:mm:ss.fff", provider: null);
            DateTime timeWhenCacheIsRead = cacheLastUpdate.AddMilliseconds(newCacheUpdaterDelay);
            var      oldImageArraySize   = 2;

            byte[] imageBytes = cacheHasData ? new byte[oldImageArraySize] : null;

            CacheUpdateService imageCache = CreateImageCache(imageBytes, oldUpdaterUserId, cacheLastUpdate);
            var cachingService            = new ImageFromCacheService(cacheUpdateService: imageCache, logger: null, cacheLifeTimeMilliSec: cacheLifeTime, framesPerSecond: cacheFps);
            var newImageArraySize         = 44;

            // Act
            cachingService.UpdateCachedImage(new byte[newImageArraySize], newCacheUpdaterUserId, timeWhenCacheIsRead);

            // Assert
            bool cacheHasBeenUpdated = cachingService.GetCurrentImageAsByteArray().Length == newImageArraySize;

            Assert.That(cacheHasBeenUpdated, Is.EqualTo(expectedSuccess));
        }