Exemple #1
0
        public async void ExposureStateUpdatedAsync_DeletesOldDatesAndAddsNewDates(string locale)
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo(locale);

            SystemTime.ResetDateTime();
            SecureStorageService.Delete(SecureStorageKeys.DAILY_SUMMARIES_OVER_THRESHOLD_TIMESTAMP_KEY);
            List <DateTime> previouslySavedDates = new List <DateTime>();

            previouslySavedDates.Add(SystemTime.Now().AddDays(-20).Date);
            previouslySavedDates.Add(SystemTime.Now().AddDays(-18).Date);
            previouslySavedDates.Add(SystemTime.Now().AddDays(-8).Date);
            SecureStorageService.SaveValue(
                SecureStorageKeys.DAILY_SUMMARIES_OVER_THRESHOLD_TIMESTAMP_KEY,
                JsonConvert.SerializeObject(previouslySavedDates));

            List <DateTime> datesToSave = createListOfDateTimesUpToXDaysInThePast(2);

            Assert.Single(ExposureDetectedHelper.DeleteDatesOfExposureOlderThan14DaysAndReturnNewList());

            await ExposureDetectedHelper.UpdateDatesOfExposures(datesToSave);

            List <DateTime> savedDates =
                JsonConvert.DeserializeObject <List <DateTime> >(
                    SecureStorageService.GetValue(SecureStorageKeys.DAILY_SUMMARIES_OVER_THRESHOLD_TIMESTAMP_KEY));

            Assert.Equal(datesToSave.Count + 1, savedDates.Count);
        }
Exemple #2
0
        public async void UpdateDatesOfExposures_AddsAllNewDatesToTheOld_WhenSomeDatesAreSavedInSecureStorage(
            string locale)
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo(locale);

            SystemTime.ResetDateTime();
            SecureStorageService.Delete(SecureStorageKeys.DAILY_SUMMARIES_OVER_THRESHOLD_TIMESTAMP_KEY);
            List <DateTime> previouslySavedDates = new List <DateTime>();

            previouslySavedDates.Add(SystemTime.Now().AddDays(-10).Date);
            previouslySavedDates.Add(SystemTime.Now().AddDays(-8).Date);
            SecureStorageService.SaveValue(
                SecureStorageKeys.DAILY_SUMMARIES_OVER_THRESHOLD_TIMESTAMP_KEY,
                JsonConvert.SerializeObject(previouslySavedDates));

            List <DateTime> datesToSave = createListOfDateTimesUpToXDaysInThePast(2);

            await ExposureDetectedHelper.UpdateDatesOfExposures(datesToSave);

            List <DateTime> savedDates =
                JsonConvert.DeserializeObject <List <DateTime> >(
                    SecureStorageService.GetValue(SecureStorageKeys.DAILY_SUMMARIES_OVER_THRESHOLD_TIMESTAMP_KEY));

            Assert.Equal(datesToSave.Count + previouslySavedDates.Count, savedDates.Count);
            datesToSave.Concat(previouslySavedDates).Should().BeEquivalentTo(savedDates);
        }
        public async void UntilNewTermsAreAccepted_NotificationResentNotOftenThan24h(
            int daysToPullForInFuture,
            int numberOfNotificationsExpectedToBeShown,
            int pullingIntervalInHours)
        {
            SystemTime.ResetDateTime();
            LocalPreferencesHelper.LastDateTimeTermsNotificationWasShown = DateTime.MinValue;
            LocalNotificationsManager.ResetHasBeenCalledMap();
            LocalNotificationsManager.HasBeenCalled[NotificationsEnum.ReApproveConsents] = false;
            LocalNotificationsManager.NewConsentsHasBeenCalledCount = 0;
            OnboardingStatusHelper.Status = OnboardingStatus.OnlyMainOnboardingCompleted;

            DateTime inXDays = SystemTime.Now().AddDays(daysToPullForInFuture);

            while (SystemTime.Now() < inXDays)
            {
                try
                {
                    await new FetchExposureKeysHelper().FetchExposureKeyBatchFilesFromServerAsync(null,
                                                                                                  CancellationToken.None);
                }
                catch (Exception)
                {
                    // ignore
                }
                SystemTime.SetDateTime(SystemTime.Now().AddHours(pullingIntervalInHours));
            }

            Assert.True(LocalNotificationsManager.HasBeenCalled[NotificationsEnum.ReApproveConsents]);
            Assert.Equal(numberOfNotificationsExpectedToBeShown, LocalNotificationsManager.NewConsentsHasBeenCalledCount);
        }
Exemple #4
0
        public async void SystemDateTimeIsIncorrect_NtpIsEqualToPersisted_ShouldUseDefault()
        {
            SystemTime.ResetDateTime();
            DateTime currentTime = DateTime.UtcNow.AddYears(-3);

            SystemTime.SetDateTime(currentTime);

            NTPUtcDateTime ntpUtcDateTime =
                Mock.Of <NTPUtcDateTime>(ntp =>
                                         ntp.GetNTPUtcDateTime() == Task.FromResult(LocalPreferencesHelper.LastNTPUtcDateTime));

            try
            {
                new FetchExposureKeysHelper().UpdateLastNTPDateTime(ntpUtcDateTime);
            }
            catch
            {
                // ignore as ZipDownloader is not mocked in this test
            }
            LogDeviceDetails logModel =
                new LogDeviceDetails(
                    LogSeverity.WARNING,
                    "message",
                    "additionalInfo");

            Assert.Equal(Conf.DATE_TIME_REPLACEMENT, logModel.ReportedTime);

            SystemTime.ResetDateTime();
        }
Exemple #5
0
        public async void SystemDateTimeIsIncorrectInTheFuture_ShouldUseNTP()
        {
            SystemTime.ResetDateTime();
            DateTime currentTime = DateTime.UtcNow.AddYears(3);

            SystemTime.SetDateTime(currentTime);

            try
            {
                await new FetchExposureKeysHelper()
                .FetchExposureKeyBatchFilesFromServerAsync(
                    null,
                    CancellationToken.None);
            }
            catch
            {
                // ignore as ZipDownloader is not mocked in this test
            }

            LogDeviceDetails logModel =
                new LogDeviceDetails(
                    LogSeverity.WARNING,
                    "message",
                    "additionalInfo");

            Assert.True(currentTime > logModel.ReportedTime);

            SystemTime.ResetDateTime();
        }
Exemple #6
0
        public async void SystemDateTimeIsCorrect_ShouldUseSystemDateTime()
        {
            SystemTime.ResetDateTime();
            DateTime currentTime = DateTime.UtcNow;

            SystemTime.SetDateTime(currentTime);

            try
            {
                new FetchExposureKeysHelper()
                .UpdateLastNTPDateTime();
            }
            catch
            {
                // ignore as ZipDownloader is not mocked in this test
            }

            LogDeviceDetails logModel =
                new LogDeviceDetails(
                    LogSeverity.WARNING,
                    "message",
                    "additionalInfo");

            Assert.Equal(currentTime, logModel.ReportedTime);

            SystemTime.ResetDateTime();
        }
Exemple #7
0
        public void TimeSpanOffsetFromGivenTimeToCurrentTime(int diffHours)
        {
            var smart = GetFormatter();
            // test will work in any TimeZone
            var now            = DateTimeOffset.Now;
            var dateTimeOffset = now.AddHours(diffHours);

            SystemTime.SetDateTimeOffset(now);

            // This notation - using formats as formatter options - was allowed in Smart.Format v2.x, but is now depreciated.
            // It is still detected and working, as long as the format part is left empty
            var formatDepreciated = "{0:time(abbr hours noless)}";

            // This format string is recommended for Smart.Format v3 and later
            var format = "{0:time:abbr hours noless:}";

            // The difference to current time with a DateTimeOffset as an argument
            var actual = smart.Format(format, dateTimeOffset);

            Assert.That(actual, Is.EqualTo(smart.Format(formatDepreciated, dateTimeOffset)));
            Assert.That(actual, Is.EqualTo($"{diffHours * -1}h"));

            // Make sure that logic for TimeSpan and DateTime arguments are the same
            Assert.That(actual, Is.EqualTo(smart.Format(format, now - dateTimeOffset)));

            SystemTime.ResetDateTime();
        }
 private void ResetData()
 {
     SystemTime.ResetDateTime();
     PermissionsHelper.BluetoothEnabled = true;
     PermissionsHelper.LocationEnabled  = true;
     LocalNotificationsManager.ResetHasBeenCalledMap();
 }
Exemple #9
0
        public static IEnumerable <TestQuote> CreateFakeDayMinuteQuotes(TestCompany company, int numDaysSkipped, TimeSpan endTime)
        {
            SystemTime.SetDateTime(DateTime.Now.AddDays(-1 * numDaysSkipped));

            var dayQuotes    = CreateFakeDayQuotes(null, 7);
            var minuteQuotes = CreateFakeMinuteQuotes(null, endTime);

            var quoteCounter = 1;

            foreach (var dayQuote in dayQuotes)
            {
                dayQuote.Id        = quoteCounter++;
                dayQuote.Company   = company;
                dayQuote.CompanyId = company.Id;
                yield return(dayQuote);
            }
            foreach (var minQuote in minuteQuotes)
            {
                minQuote.Id        = quoteCounter++;
                minQuote.Company   = company;
                minQuote.CompanyId = company.Id;
                yield return(minQuote);
            }

            SystemTime.ResetDateTime();
        }
        public void AssertThatAfterAnAppropriateAmountofTimeHasPassedTheAppetiteOfThePetHasDecayedAccordingly()
        {
            testPetDataAccess.SavePetStatus(petOne);

            SystemTime.SetDateTime(DateTime.Now.AddHours(10));             // mock a day passing so the decay can be calcuated

            testPetDataAccess.GetPetStatus(petOne.Id).CurrentAppetiteRating.Should().Be(25);

            SystemTime.ResetDateTime();
        }
Exemple #11
0
 private void ResetData()
 {
     SystemTime.ResetDateTime();
     MessageUtils.RemoveAll();
     Permissions.BluetoothEnabled = true;
     Permissions.LocationEnabled  = true;
     LocalNotificationsManager.ResetHasBeenCalledMap();
     foreach (string key in SecureStorageKeys.GetAllKeysForCleaningDevice())
     {
         _secureStorageService.Delete(key);
     }
 }
Exemple #12
0
        public void DeleteDatesOfExposureOlderThan14DaysAndReturnNewList_ReturnsEmptyListWhenNothingIsSavedYet(
            string locale)
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo(locale);

            SystemTime.ResetDateTime();
            SecureStorageService.Delete(SecureStorageKeys.DAILY_SUMMARIES_OVER_THRESHOLD_TIMESTAMP_KEY);

            List <DateTime> validDates = ExposureDetectedHelper.DeleteDatesOfExposureOlderThan14DaysAndReturnNewList();

            Assert.Empty(validDates);
        }
        public void ResetDateTime_ResetsDateTime()
        {
            // Arrange
            var fakeTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 12, 30, 0);

            SystemTime.SetDateTime(fakeTime);

            // Act
            SystemTime.ResetDateTime();

            // Assert
            Assert.IsTrue(SystemTime.Now() != fakeTime);
        }
Exemple #14
0
        public void LastDownloadZipsTooRecent_ShouldReturnTrue()
        {
            // Given
            PullRules pullRules = new PullRules();

            SystemTime.ResetDateTime();

            // When
            _preferences.Set(PreferencesKeys.LAST_PULL_KEYS_SUCCEEDED_DATE_TIME, SystemTime.Now().AddMinutes(-1));
            bool lastDownloadZipsTooRecent = pullRules.LastDownloadZipsTooRecent();

            // Then
            Assert.True(lastDownloadZipsTooRecent);
        }
Exemple #15
0
        public void Setup()
        {
            SystemTime.ResetDateTime();
            var clientBuilder1 = new ClientBuilder();

            _client1 = clientBuilder1
                       .AddName("Huy")
                       .AddSurname("Li")
                       .AddAddress("R13")
                       .AddPassportDetails("432342")
                       .Build();
            _client1.ChooseBank
            .FirstBank()
            .CreateBankAccount
            .CreatCreditAccount(_client1, new CreditAccountInformation(-3000, 300, 5000));
        }
Exemple #16
0
        public void Setup()
        {
            SystemTime.ResetDateTime();
            var clientBuilder = new ClientBuilder();

            _client = clientBuilder
                      .AddName("Nikita")
                      .AddSurname("Dunaev")
                      .AddAddress("ABC123")
                      .AddPassportDetails("727272")
                      .Build();
            _client.ChooseBank
            .FirstBank()
            .CreateBankAccount
            .CreatDebitAccount(_client, new DebitAccountInformation(12, 200));
        }
Exemple #17
0
        public void TimeSpanOffsetFromGivenTimeToCurrentTime(int diffHours)
        {
            // test will work in any TimeZone
            var now            = DateTimeOffset.Now;
            var dateTimeOffset = now.AddHours(diffHours);

            SystemTime.SetDateTimeOffset(now);
            var format = "{0:time(abbr hours noless)}";
            // The difference to current time with a DateTimeOffset as an argument
            var actual = m_Smart.Format(format, dateTimeOffset);

            Assert.AreEqual($"{diffHours * -1}h", actual);
            // Make sure that logic for TimeSpan and DateTime arguments are the same
            Assert.AreEqual(actual, m_Smart.Format(format, now - dateTimeOffset));
            Console.WriteLine("Success: \"{0}\" => \"{1}\"", format, actual);
            SystemTime.ResetDateTime();
        }
Exemple #18
0
        public void DeleteDatesOfExposureOlderThan14DaysAndReturnNewList_DeletesNoDaysOlderThan14DaysOld(string locale)
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo(locale);

            SystemTime.ResetDateTime();
            SecureStorageService.Delete(SecureStorageKeys.DAILY_SUMMARIES_OVER_THRESHOLD_TIMESTAMP_KEY);

            List <DateTime> previouslySavedDates = createListOfDateTimesUpToXDaysInThePast(14);

            SecureStorageService.SaveValue(
                SecureStorageKeys.DAILY_SUMMARIES_OVER_THRESHOLD_TIMESTAMP_KEY,
                JsonConvert.SerializeObject(previouslySavedDates));

            List <DateTime> validDates = ExposureDetectedHelper.DeleteDatesOfExposureOlderThan14DaysAndReturnNewList();

            Assert.Equal(14, validDates.Count);
        }
        public void PullKeysParams_PullFirstTime_ConsentGiven()
        {
            //Given the app never pulled before, but consent was given to pull EU keys.
            _preferences.Clear();
            OnboardingStatusHelper.Status = OnboardingStatus.CountriesOnboardingCompleted;

            //When the app pulls for the first time
            PullKeysParams pullParams = PullKeysParams.GenerateParams();

            //We will request all keys for today but only NO keys (consent was not given yet)
            Assert.Equal(SystemTime.Now().Date, pullParams.Date);
            Assert.Equal(1, pullParams.BatchNumber);
            Assert.Equal(BatchType.ALL, pullParams.BatchType);

            //Reset
            SystemTime.ResetDateTime();
        }
Exemple #20
0
        public async void UpdateDatesOfExposures_AddsAllNewDates_WhenNothingIsSavedYet(string locale)
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo(locale);

            SystemTime.ResetDateTime();
            SecureStorageService.Delete(SecureStorageKeys.DAILY_SUMMARIES_OVER_THRESHOLD_TIMESTAMP_KEY);

            List <DateTime> datesToSave = createListOfDateTimesUpToXDaysInThePast(2);

            await ExposureDetectedHelper.UpdateDatesOfExposures(datesToSave);

            List <DateTime> savedDates =
                JsonConvert.DeserializeObject <List <DateTime> >(
                    SecureStorageService.GetValue(SecureStorageKeys.DAILY_SUMMARIES_OVER_THRESHOLD_TIMESTAMP_KEY));

            datesToSave.Should().BeEquivalentTo(savedDates);
            Assert.Equal(datesToSave.Count, savedDates.Count);
        }
        public void createAValidListOfTemporaryExposureKeys_Have15Keys_Only14ShouldBeKept()
        {
            SystemTime.ResetDateTime();

            // Create a list of 15 keys
            IEnumerable <ExposureKeyModel> temporaryExposureKeys = new List <ExposureKeyModel>();

            for (int i = 0; i < 15; i++)
            {
                temporaryExposureKeys = temporaryExposureKeys.Append(new ExposureKeyModel(new byte[i + 1], SystemTime.Now().AddDays(0 - i), TimeSpan.FromDays(1), RiskLevel.Medium));
            }

            // Process them
            IEnumerable <ExposureKeyModel> processedKeys = UploadDiagnosisKeysHelper.CreateAValidListOfTemporaryExposureKeys(temporaryExposureKeys);

            // There should be 14 left
            Assert.Equal(14, processedKeys.Count());
        }
        public void PullKeysParams_PullFirstTime()
        {
            //Given the app never pulled before (preferences will be empty)
            _preferences.Clear();
            DateTime today = new DateTime(2020, 4, 4, 8, 8, 8);

            SystemTime.SetDateTime(today);

            //When the app pulls for the first time
            PullKeysParams pullParams = PullKeysParams.GenerateParams();

            //We will request all keys for today
            Assert.Equal(today.Date, pullParams.Date);
            Assert.Equal(1, pullParams.BatchNumber);
            Assert.Equal(BatchType.ALL, pullParams.BatchType);

            //Reset
            SystemTime.ResetDateTime();
        }
        public void PullKeysParams_LastPullWas15DaysAgo()
        {
            //Given that last time we pulled keys was 20 days ago and the last batch was number 2 for that day
            DateTime lastPullDate = SystemTime.Now().AddDays(-20).Date;

            _preferences.Clear();
            _preferences.Set(PULL_DATE_KEY, lastPullDate.ToUniversalTime());
            _preferences.Set(PULL_BATCH_KEY, 2);

            //When the app pulls
            PullKeysParams pullParams = PullKeysParams.GenerateParams();

            //Then it pulls only for the last 14 days, incl. today.
            Assert.Equal(SystemTime.Now().AddDays(-13).Date, pullParams.Date);
            Assert.Equal(1, pullParams.BatchNumber);
            Assert.Equal(BatchType.ALL, pullParams.BatchType);

            //Reset
            SystemTime.ResetDateTime();
        }
Exemple #24
0
        public void PullKeysParams_LastPullWasThreeDaysAgo()
        {
            //Given that last time we pulled keys was three days ago and the last batch was number 2 for that day
            DateTime lastPullDate = SystemTime.Now().AddDays(-3).Date;

            _preferences.Clear();
            _preferences.Set(PULL_DATE_KEY, lastPullDate.ToUniversalTime());
            _preferences.Set(PULL_BATCH_KEY, 2);

            //When the app pulls
            PullKeysParams pullParams = PullKeysParams.GenerateParams();

            //Then the next batch number for three days ago will be requested
            Assert.Equal(lastPullDate, pullParams.Date);
            Assert.Equal(3, pullParams.BatchNumber);
            Assert.Equal(BatchType.NO, pullParams.BatchType);

            //Reset
            SystemTime.ResetDateTime();
        }
Exemple #25
0
        public void PullKeysParams_NotFirstPullOfDay()
        {
            //Given that we previously successfully pulled keys today and the last batch was number 3.
            DateTime lastPullDate = SystemTime.Now().Date;

            _preferences.Clear();
            _preferences.Set(PULL_DATE_KEY, lastPullDate.ToUniversalTime());
            _preferences.Set(PULL_BATCH_KEY, 3);

            //When the app pulls
            PullKeysParams pullParams = PullKeysParams.GenerateParams();

            //Then the next batch number for today will be requested
            Assert.Equal(lastPullDate, pullParams.Date);
            Assert.Equal(4, pullParams.BatchNumber);
            Assert.Equal(BatchType.NO, pullParams.BatchType);

            //Reset
            SystemTime.ResetDateTime();
        }
        public async void createAValidListOfTemporaryExposureKeys_HaveDateGap_AllShouldBeKept()
        {
            SystemTime.ResetDateTime();

            // Create keys
            ExposureKeyModel tek1 = new ExposureKeyModel(new byte[1], SystemTime.Now(), TimeSpan.FromDays(1), RiskLevel.Medium);
            ExposureKeyModel tek2 = new ExposureKeyModel(new byte[2], SystemTime.Now().AddDays(-1), TimeSpan.FromDays(1), RiskLevel.Medium);
            ExposureKeyModel tek3 = new ExposureKeyModel(new byte[3], SystemTime.Now().AddDays(-3), TimeSpan.FromDays(1), RiskLevel.Medium);

            // Process a list of copies
            IEnumerable <ExposureKeyModel> temporaryExposureKeys = new List <ExposureKeyModel>()
            {
                CopyTek(tek1), CopyTek(tek2), CopyTek(tek3)
            };
            IEnumerable <ExposureKeyModel> processedKeys = UploadDiagnosisKeysHelper.CreateAValidListOfTemporaryExposureKeys(temporaryExposureKeys);

            // No keys should be filtered out
            Assert.Equal(processedKeys.Count(), temporaryExposureKeys.Count());
            Assert.True(ContainsTek(tek3, processedKeys));
            Assert.False((await _logManager.GetLogs(10)).Any());
        }
        public void PullKeysParams_NotFirstPull()
        {
            //App was just updated to pull EU keys, and the last pull was NO keys.
            DateTime lastPullDate = SystemTime.Now().Date;

            _preferences.Clear();
            _preferences.Set(PULL_DATE_KEY, lastPullDate.ToUniversalTime());
            _preferences.Set(PULL_BATCH_KEY, 3);
            _preferences.Set(PULL_BATCH_TYPE, "no");

            //When the app pulls for the first time
            PullKeysParams pullParams = PullKeysParams.GenerateParams();

            //We will request all keys for today
            Assert.Equal(SystemTime.Now().Date, pullParams.Date);
            Assert.Equal(1, pullParams.BatchNumber);
            Assert.Equal(BatchType.ALL, pullParams.BatchType);

            //Reset
            SystemTime.ResetDateTime();
        }
        public async void createAValidListOfTemporaryExposureKeys_GeneratesProperLogIfKeysAreFiltered(int ExtraKeys)
        {
            SystemTime.ResetDateTime();
            await _logManager.DeleteAll();

            // Create a list of 15 keys
            IEnumerable <ExposureKeyModel> temporaryExposureKeys = new List <ExposureKeyModel>();

            for (int i = 0; i < 14 + ExtraKeys; i++)
            {
                temporaryExposureKeys = temporaryExposureKeys.Append(new ExposureKeyModel(new byte[i + 1], SystemTime.Now().AddDays(0 - i), TimeSpan.FromDays(1), RiskLevel.Medium));
            }

            // Process them
            IEnumerable <ExposureKeyModel> processedKeys = UploadDiagnosisKeysHelper.CreateAValidListOfTemporaryExposureKeys(temporaryExposureKeys);

            // Check if log is generated
            string logStatement = _logManager.GetLogs(1).Result.ElementAt(0).Description;

            Assert.Equal(ExtraKeys.ToString(), logStatement.Last().ToString());
        }
        public void createAValidListOfTemporaryExposureKeys_HaveMultipleWithSameDate_AllShouldBeKept()
        {
            SystemTime.ResetDateTime();

            // Create keys
            ExposureKeyModel tek1 = new ExposureKeyModel(new byte[1], SystemTime.Now(), TimeSpan.FromDays(0.7), RiskLevel.Medium);
            ExposureKeyModel tek2 = new ExposureKeyModel(new byte[2], SystemTime.Now(), TimeSpan.FromDays(0.3), RiskLevel.Medium);
            ExposureKeyModel tek3 = new ExposureKeyModel(new byte[3], SystemTime.Now().AddDays(-1), TimeSpan.FromDays(1), RiskLevel.Medium);

            // Process a list of copies
            IEnumerable <ExposureKeyModel> temporaryExposureKeys = new List <ExposureKeyModel>()
            {
                CopyTek(tek1), CopyTek(tek2), CopyTek(tek3)
            };
            IEnumerable <ExposureKeyModel> processedKeys = UploadDiagnosisKeysHelper.CreateAValidListOfTemporaryExposureKeys(temporaryExposureKeys);

            // No keys should be filtered out
            Assert.True(ContainsTek(tek1, processedKeys));
            Assert.True(ContainsTek(tek2, processedKeys));
            Assert.True(ContainsTek(tek3, processedKeys));
        }
Exemple #30
0
        public void HasNotShownExposureNotificationForDate_ReturnsTrueIfTimeStampHasNotYetBeenSaved(string locale)
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo(locale);

            SystemTime.ResetDateTime();
            List <DateTime> previouslySavedDates = new List <DateTime>();

            previouslySavedDates.Add(SystemTime.Now().AddDays(0).Date);
            previouslySavedDates.Add(SystemTime.Now().AddDays(-1).Date);
            previouslySavedDates.Add(SystemTime.Now().AddDays(-2).Date);

            bool savedBefore =
                ExposureDetectedHelper.HasNotShownExposureNotificationForDate(SystemTime.Now().AddDays(-1),
                                                                              previouslySavedDates);
            bool neverSaved =
                ExposureDetectedHelper.HasNotShownExposureNotificationForDate(SystemTime.Now().AddDays(-3),
                                                                              previouslySavedDates);

            Assert.False(savedBefore);
            Assert.True(neverSaved);
        }