示例#1
0
        public async Task TestCheckProcessExitedWhenExited()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, new MemoryStream(Resources.helloworld_key_a_txt));
            FakeDataStore.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            await New <KnownIdentities>().SetDefaultEncryptionIdentity(new LogOnIdentity(EmailAddress.Parse("*****@*****.**"), new Passphrase("test")));

            FakeLauncher fakeLauncher = new FakeLauncher();

            fakeLauncher.Launch(_decryptedFile1);
            ActiveFile activeFile = new ActiveFile(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), new LogOnIdentity("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);

            activeFile = new ActiveFile(activeFile, ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable);
            Resolve.FileSystemState.Add(activeFile, fakeLauncher);

            ((FakeNow)New <INow>()).TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange;
                return(Constant.CompletedTask);
            });
            SetupAssembly.FakeRuntimeEnvironment.Platform = Platform.WindowsDesktop;
            fakeLauncher.HasExited = true;
            await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext());

            activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_anAxxPath);
            Assert.That(changedWasRaised, Is.True, "A changed event should be raised because the process has exited.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The ActiveFile plain text should be deleted after the checking of active files because the launcher is no longer active.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotShareable), Is.False, "The file should be shareable after checking of active files because the launcher is no longer active.");
        }
示例#2
0
        public async Task TestCheckActiveFilesNotDecryptedAndDoesNotExist()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, new MemoryStream(Resources.helloworld_key_a_txt));
            FakeDataStore.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            ActiveFile activeFile = new ActiveFile(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), new LogOnIdentity("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().CryptoId);

            New <IDataStore>(_decryptedFile1).Delete();
            activeFile = new ActiveFile(activeFile, ActiveFileStatus.NotDecrypted);
            Resolve.FileSystemState.Add(activeFile);
            await Resolve.KnownIdentities.AddAsync(activeFile.Identity);

            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange;
                return(Constant.CompletedTask);
            });

            ((FakeNow)New <INow>()).TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext());

            Assert.That(changedWasRaised, Is.False, "The ActiveFile should be not be modified because it's already deleted.");
        }
示例#3
0
        public async Task TestPurgeActiveFilesWhenFileIsLocked()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, new MemoryStream(Resources.helloworld_key_a_txt));
            FakeDataStore.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            IDataStore encryptedFileInfo = New <IDataStore>(_anAxxPath);
            IDataStore decryptedFileInfo = New <IDataStore>(_decryptedFile1);
            ActiveFile activeFile        = new ActiveFile(encryptedFileInfo, decryptedFileInfo, new LogOnIdentity("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().CryptoId);

            Resolve.FileSystemState.Add(activeFile);

            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange;
                return(Constant.CompletedTask);
            });

            using (FileLock fileLock = New <FileLocker>().Acquire(decryptedFileInfo))
            {
                await Task.Run(() => New <ActiveFileAction>().PurgeActiveFiles(new ProgressContext()));
            }

            Assert.That(changedWasRaised, Is.False, "A changed event should not be raised because the decrypted file is locked.");
        }
示例#4
0
        internal static void TestOneFile(string resourceName, string password, string sha256HashValue)
        {
            string source      = Path.Combine(_rootPath, "source.axx");
            string destination = Path.Combine(_rootPath, "destination.file");
            Stream stream      = Assembly.GetAssembly(typeof(TestV2RegressionCompleteFiles)).GetManifestResourceStream("Axantum.AxCrypt.Core.Test.resources." + resourceName);

            FakeDataStore.AddFile(source, FakeDataStore.TestDate1Utc, FakeDataStore.TestDate2Utc, FakeDataStore.TestDate3Utc, stream);

            LogOnIdentity passphrase = new LogOnIdentity(password);

            bool ok = new AxCryptFile().Decrypt(New <IDataStore>(source), New <IDataStore>(destination), passphrase, AxCryptOptions.SetFileTimes, new ProgressContext());

            Assert.That(ok, Is.True, "The Decrypt() method should return true for ok.");

            byte[]        hash;
            HashAlgorithm hashAlgorithm = SHA256.Create();
            Stream        plainStream   = New <IDataStore>(destination).OpenRead();

            using (Stream cryptoStream = new CryptoStream(plainStream, hashAlgorithm, CryptoStreamMode.Read))
            {
                plainStream = null;
                cryptoStream.CopyTo(Stream.Null);
            }
            hash = hashAlgorithm.Hash;

            Assert.That(hash.IsEquivalentTo(sha256HashValue.FromHex()), "Wrong SHA-256.");
        }
示例#5
0
        public async Task TestFileWasCreatedWhereAKnownFolderWasExpected()
        {
            IDataContainer betterCloudInfo = New <IDataContainer>(@"C:\BetterCloud");
            IDataContainer fasterCloudInfo = New <IDataContainer>(@"C:\FasterCloud");
            KnownFolder    folder1         = new KnownFolder(betterCloudInfo, @"My AxCrypt", KnownFolderKind.GoogleDrive, null);
            KnownFolder    folder2         = new KnownFolder(fasterCloudInfo, @"My AxCrypt", KnownFolderKind.Dropbox, null);

            FakeDataStore.AddFile(@"C:\BetterCloud\My AxCrypt", Stream.Null);
            FakeDataStore.AddFolder(folder2.My.FullName);

            KnownIdentities       knownIdentities = new KnownIdentities(Resolve.FileSystemState, Resolve.SessionNotify);
            KnownFoldersViewModel vm = new KnownFoldersViewModel(Resolve.FileSystemState, Resolve.SessionNotify, knownIdentities);

            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(0));

            vm.KnownFolders = new KnownFolder[] { folder1, folder2 };
            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(2));
            Assert.That(vm.KnownFolders.First().Enabled, Is.False);
            Assert.That(vm.KnownFolders.Last().Enabled, Is.False);

            await knownIdentities.SetDefaultEncryptionIdentity(new LogOnIdentity("aaa"));

            Assert.That(Resolve.FileSystemState.WatchedFolders.Count(), Is.EqualTo(1));
            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(2));
            Assert.That(vm.KnownFolders.First().Enabled, Is.False);
            Assert.That(vm.KnownFolders.Last().Enabled, Is.True);
        }
        public void TestDragAndDropFilesPropertyBindSetsDragAndDropFileTypes()
        {
            using (MainViewModel mvm = New <MainViewModel>())
            {
                string encryptedFilePath = @"C:\Folder\File-txt.axx";
                mvm.DragAndDropFiles = new string[] { encryptedFilePath, };
                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.None));

                string decryptedFilePath = @"C:\Folder\File.txt";
                mvm.DragAndDropFiles = new string[] { decryptedFilePath, };
                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.None));

                FakeDataStore.AddFile(encryptedFilePath, null);
                mvm.DragAndDropFiles = new string[] { encryptedFilePath, decryptedFilePath, };
                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.EncryptedFile));

                FakeDataStore.AddFile(decryptedFilePath, null);
                mvm.DragAndDropFiles = new string[] { encryptedFilePath, decryptedFilePath, };
                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.EncryptableFile | FileInfoTypes.EncryptedFile));

                string folderPath = @"C:\Folder\";
                mvm.DragAndDropFiles = new string[] { encryptedFilePath, decryptedFilePath, folderPath };
                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.EncryptableFile | FileInfoTypes.EncryptedFile));

                FakeDataStore.AddFolder(folderPath);
                mvm.DragAndDropFiles = new string[] { encryptedFilePath, decryptedFilePath, folderPath };
                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.EncryptableFile | FileInfoTypes.EncryptedFile));
            }
        }
示例#7
0
        public static void Setup()
        {
            SetupAssembly.AssemblySetup();

            FakeDataStore.AddFile(_davidCopperfieldTxtPath, FakeDataStore.TestDate4Utc, FakeDataStore.TestDate5Utc, FakeDataStore.TestDate6Utc, FakeDataStore.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
            FakeDataStore.AddFile(_uncompressedAxxPath, FakeDataStore.ExpandableMemoryStream(Resources.uncompressable_zip));
            FakeDataStore.AddFile(_helloWorldAxxPath, FakeDataStore.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
        }
示例#8
0
        public void Setup()
        {
            SetupAssembly.AssemblySetup();
            SetupAssembly.AssemblySetupCrypto(_cryptoImplementation);

            FakeDataStore.AddFile(_testTextPath, FakeDataStore.TestDate1Utc, FakeDataStore.TestDate2Utc, FakeDataStore.TestDate3Utc, FakeDataStore.ExpandableMemoryStream(Encoding.UTF8.GetBytes("This is a short file")));
            FakeDataStore.AddFile(_davidCopperfieldTxtPath, FakeDataStore.TestDate4Utc, FakeDataStore.TestDate5Utc, FakeDataStore.TestDate6Utc, FakeDataStore.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
            FakeDataStore.AddFile(_uncompressedAxxPath, FakeDataStore.ExpandableMemoryStream(Resources.uncompressable_zip));
            FakeDataStore.AddFile(_helloWorldAxxPath, FakeDataStore.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
        }
示例#9
0
        public static void TestExtensions_FileFilter()
        {
            FakeDataStore.AddFile(@"c:\test.txt", null);
            IDataStore fileInfo = New <IDataStore>(@"c:\test.txt");

            Assert.That(New <FileFilter>().IsEncryptable(fileInfo), Is.True);

            New <FileFilter>().AddUnencryptableExtension("txt");

            Assert.That(New <FileFilter>().IsEncryptable(fileInfo), Is.False);
        }
        public void Setup()
        {
            SetupAssembly.AssemblySetup();
            SetupAssembly.AssemblySetupCrypto(_cryptoImplementation);

            FakeDataStore.AddFile(_davidCopperfieldTxtPath, FakeDataStore.TestDate4Utc, FakeDataStore.TestDate5Utc, FakeDataStore.TestDate6Utc, FakeDataStore.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
            FakeDataStore.AddFile(_uncompressedAxxPath, FakeDataStore.ExpandableMemoryStream(Resources.uncompressable_zip));
            FakeDataStore.AddFile(_helloWorldAxxPath, FakeDataStore.ExpandableMemoryStream(Resources.helloworld_key_a_txt));

            TypeMap.Register.Singleton <IUIThread>(() => new FakeUIThread());
        }
        public void TestValidateWrongButKnownPassphraseWithRealFile()
        {
            _identities.Add(new Passphrase("b"));

            FakeDataStore.AddFile(@"C:\My Folder\MyFile-txt.axx", new MemoryStream(Resources.helloworld_key_a_txt));
            FilePasswordViewModel npvm = new FilePasswordViewModel(@"C:\My Folder\MyFile-txt.axx");

            npvm.PasswordText = "b";

            Assert.That(npvm[nameof(FilePasswordViewModel.PasswordText)], Is.Not.EqualTo(String.Empty));
            Assert.That(npvm.ValidationError, Is.EqualTo((int)ValidationError.WrongPassphrase));
        }
示例#12
0
        public async Task TestCheckActiveFilesUpdateButWithTargetInaccessible()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, FakeDataStore.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
            LogOnIdentity passphrase = new LogOnIdentity("a");

            New <AxCryptFile>().Decrypt(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), passphrase, AxCryptOptions.None, new ProgressContext());

            ActiveFile activeFile = new ActiveFile(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), passphrase, ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().CryptoId);

            Resolve.FileSystemState.Add(activeFile);

            IDataStore decryptedFileInfo = New <IDataStore>(_decryptedFile1);

            decryptedFileInfo.SetFileTimes(utcNow.AddSeconds(30), utcNow.AddSeconds(30), utcNow.AddSeconds(30));

            ((FakeNow)New <INow>()).TimeFunction = (() => { return(utcNow.AddMinutes(1)); });

            await Resolve.KnownIdentities.AddAsync(passphrase);

            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange && notification.FullNames.Contains(_anAxxPath);
                return(Constant.CompletedTask);
            });

            EventHandler eventHandler = ((object sender, EventArgs e) =>
            {
                FakeDataStore fileInfo = (FakeDataStore)sender;
                if (fileInfo.FullName == Path.ChangeExtension(_anAxxPath, ".tmp"))
                {
                    throw new IOException("Faked access denied.");
                }
            });

            FakeDataStore.OpeningForWrite += eventHandler;
            try
            {
                Assert.ThrowsAsync <FileOperationException>(async() => await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext()));
            }
            finally
            {
                FakeDataStore.OpeningForWrite -= eventHandler;
            }

            Assert.That(changedWasRaised, Is.False, "The ActiveFile should not be modified because it was not accessible.");
            activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_anAxxPath);
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotShareable), Is.False, "The ActiveFile should not be marked as not shareable after the checking of active files.");
        }
示例#13
0
        public static void TestValidateWrongPassphraseWithRealFile(CryptoImplementation cryptoImplementation)
        {
            SetupAssembly.AssemblySetupCrypto(cryptoImplementation);

            FakeDataStore.AddFile(@"C:\My Folder\MyFile-txt.axx", new MemoryStream(Resources.helloworld_key_a_txt));
            NewPasswordViewModel npvm = new NewPasswordViewModel(String.Empty, @"C:\My Folder\MyFile-txt.axx");

            npvm.PasswordText = "b";
            npvm.Verification = "b";

            Assert.That(npvm[nameof(NewPasswordViewModel.PasswordText)], Is.Not.EqualTo(""));
            Assert.That(npvm.ValidationError, Is.EqualTo((int)ValidationError.WrongPassphrase));
        }
        public void TestSetRecentFilesComparer()
        {
            string file1      = @"C:\Folder\File3-txt.axx";
            string decrypted1 = @"C:\Folder\File2.txt";
            string file2      = @"C:\Folder\File2-txt.axx";
            string decrypted2 = @"C:\Folder\File1.txt";
            string file3      = @"C:\Folder\File1-txt.axx";
            string decrypted3 = @"C:\Folder\File3.txt";

            ActiveFile activeFile;

            ((FakeNow)New <INow>()).TimeFunction = () => new DateTime(2001, 1, 1);
            FakeDataStore.AddFile(file1, new MemoryStream(Resources.helloworld_key_a_txt));
            activeFile = new ActiveFile(New <IDataStore>(file1), New <IDataStore>(decrypted1), new LogOnIdentity("passphrase1"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);
            Resolve.FileSystemState.Add(activeFile);

            ((FakeNow)New <INow>()).TimeFunction = () => new DateTime(2002, 2, 2);
            FakeDataStore.AddFile(file2, new MemoryStream(Resources.helloworld_key_a_txt));
            activeFile = new ActiveFile(New <IDataStore>(file2), New <IDataStore>(decrypted2), new LogOnIdentity("passphrase2"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);
            Resolve.FileSystemState.Add(activeFile);

            ((FakeNow)New <INow>()).TimeFunction = () => new DateTime(2003, 3, 3);
            FakeDataStore.AddFile(file3, new MemoryStream(Resources.helloworld_key_a_txt));
            activeFile = new ActiveFile(New <IDataStore>(file3), New <IDataStore>(decrypted3), new LogOnIdentity("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);
            Resolve.FileSystemState.Add(activeFile);

            ActiveFileComparer comparer;
            List <ActiveFile>  recentFiles;

            comparer = ActiveFileComparer.DateComparer;
            using (MainViewModel mvm = New <MainViewModel>())
            {
                mvm.RecentFiles         = Resolve.FileSystemState.ActiveFiles;
                mvm.RecentFilesComparer = comparer;
                recentFiles             = mvm.RecentFiles.ToList();

                Assert.That(recentFiles[0].EncryptedFileInfo.FullName, Is.EqualTo(file1.NormalizeFilePath()), "Sorted by Date, this should be number 1.");
                Assert.That(recentFiles[1].EncryptedFileInfo.FullName, Is.EqualTo(file2.NormalizeFilePath()), "Sorted by Date, this should be number 2.");
                Assert.That(recentFiles[2].EncryptedFileInfo.FullName, Is.EqualTo(file3.NormalizeFilePath()), "Sorted by Date, this should be number 3.");

                comparer                = ActiveFileComparer.DateComparer;
                comparer.ReverseSort    = true;
                mvm.RecentFilesComparer = comparer;
                recentFiles             = mvm.RecentFiles.ToList();
            }

            Assert.That(recentFiles[0].EncryptedFileInfo.FullName, Is.EqualTo(file3.NormalizeFilePath()), "Sorted by Date in reverse, this should be number 1.");
            Assert.That(recentFiles[1].EncryptedFileInfo.FullName, Is.EqualTo(file2.NormalizeFilePath()), "Sorted by Date, this should be number 2.");
            Assert.That(recentFiles[2].EncryptedFileInfo.FullName, Is.EqualTo(file1.NormalizeFilePath()), "Sorted by Date, this should be number 3.");
        }
        public async Task TestSetFilesArePending()
        {
            await Resolve.KnownIdentities.SetDefaultEncryptionIdentity(new LogOnIdentity("passphrase"));

            FakeDataStore.AddFolder(@"C:\MyFolders\Folder1");
            using (MainViewModel mvm = New <MainViewModel>())
            {
                Assert.That(mvm.FilesArePending, Is.False);
                await Resolve.FileSystemState.AddWatchedFolderAsync(new WatchedFolder(@"C:\MyFolders\Folder1", Resolve.KnownIdentities.DefaultEncryptionIdentity.Tag));

                FakeDataStore.AddFile(@"C:\MyFolders\Folder1\Encryptable.txt", Stream.Null);
                Assert.That(mvm.FilesArePending, Is.True);
            }
        }
示例#16
0
        public async Task TestCheckActiveFilesKeyIsNotSetWithoutKnownKey()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, FakeDataStore.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
            LogOnIdentity passphrase = new LogOnIdentity("a");

            New <AxCryptFile>().Decrypt(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), passphrase, AxCryptOptions.None, new ProgressContext());

            ActiveFile activeFile = new ActiveFile(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), passphrase, ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().CryptoId);

            Resolve.FileSystemState.Add(activeFile);
            await Resolve.FileSystemState.Save();

            TypeMap.Register.Singleton <FileSystemState>(() => FileSystemState.Create(New <IDataStore>(_fileSystemStateFilePath)));

            IDataStore decryptedFileInfo = New <IDataStore>(_decryptedFile1);

            decryptedFileInfo.SetFileTimes(utcNow.AddSeconds(30), utcNow.AddSeconds(30), utcNow.AddSeconds(30));

            ((FakeNow)New <INow>()).TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange;
                return(Constant.CompletedTask);
            });

            activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_anAxxPath);
            Assert.That(activeFile.Identity == LogOnIdentity.Empty, "The key should be null after loading of new FileSystemState");

            await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext());

            Assert.That(changedWasRaised, Is.False, "The ActiveFile should be not be modified because the file was modified as well and thus cannot be deleted.");

            await Resolve.KnownIdentities.AddAsync(new LogOnIdentity("x"));

            await Resolve.KnownIdentities.AddAsync(new LogOnIdentity("y"));

            await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext());

            Assert.That(changedWasRaised, Is.False, "The ActiveFile should be not be modified because the file was modified as well and thus cannot be deleted.");

            activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_anAxxPath);
            Assert.That(activeFile.Identity == LogOnIdentity.Empty, "The key should still be null after the checking of active files.");

            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted), Is.True, "The file should still be there.");
            Assert.That(activeFile.ThumbprintMatch(passphrase.Passphrase), Is.True, "The active file should still be known to be decryptable with the original passphrase.");
        }
示例#17
0
        public async Task TestTryDeleteButDecryptedSharingLocked()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, new MemoryStream(Resources.helloworld_key_a_txt));
            FakeDataStore.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            ActiveFile activeFile = new ActiveFile(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), new LogOnIdentity("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().CryptoId);

            Resolve.FileSystemState.Add(activeFile);

            ((FakeNow)New <INow>()).TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange;
                return(Constant.CompletedTask);
            });
            SetupAssembly.FakeRuntimeEnvironment.Platform = Platform.WindowsDesktop;

            EventHandler eventHandler = ((object sender, EventArgs e) =>
            {
                FakeDataStore fileInfo = (FakeDataStore)sender;
                if (fileInfo.FullName == _decryptedFile1)
                {
                    throw new IOException("Faked sharing violation.");
                }
            });

            FakeDataStore.Moving          += eventHandler;
            FakeDataStore.Deleting        += eventHandler;
            FakeDataStore.OpeningForWrite += eventHandler;
            try
            {
                await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext());
            }
            finally
            {
                FakeDataStore.Deleting        -= eventHandler;
                FakeDataStore.OpeningForWrite -= eventHandler;
                FakeDataStore.Moving          -= eventHandler;
            }

            activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_anAxxPath);
            Assert.That(changedWasRaised, Is.True, "A changed event should be raised because it should now be NotShareable.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted), Is.True, "The ActiveFile plain text should still be there after the checking of active files because the file is NotShareable.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotShareable), Is.True, "The ActiveFile plain text should be NotShareable after the checking of active files because the file could not be deleted.");
        }
        public async Task TestStatusMaskAtLoad()
        {
            using (FileSystemState state = FileSystemState.Create(Resolve.WorkFolder.FileInfo.FileItemInfo("mystate.txt")))
            {
                FakeDataStore.AddFile(_encryptedAxxPath, FakeDataStore.TestDate1Utc, FakeDataStore.TestDate2Utc, FakeDataStore.TestDate3Utc, new MemoryStream(Resources.helloworld_key_a_txt));
                ActiveFile activeFile = new ActiveFile(New <IDataStore>(_encryptedAxxPath), New <IDataStore>(_decryptedTxtPath), new LogOnIdentity("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().CryptoId);
                state.Add(activeFile);
                await state.Save();

                FileSystemState reloadedState = FileSystemState.Create(Resolve.WorkFolder.FileInfo.FileItemInfo("mystate.txt"));
                Assert.That(reloadedState, Is.Not.Null, "An instance should always be instantiated.");
                Assert.That(reloadedState.ActiveFiles.Count(), Is.EqualTo(1), "The reloaded state should have one active file.");
                Assert.That(reloadedState.ActiveFiles.First().Status, Is.EqualTo(ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NoProcessKnown), "When reloading saved state, some statuses should be masked away and NoProcessKnown added.");
            }
        }
示例#19
0
        public async Task TestPurgeActiveFilesWhenFileIsModified()
        {
            DateTime utcNow    = New <INow>().Utc;
            Stream   axxStream = new MemoryStream();

            axxStream.Write(Resources.helloworld_key_a_txt, 0, Resources.helloworld_key_a_txt.Length);
            axxStream.Position = 0;
            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, axxStream);
            FakeDataStore.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            Mock <AxCryptFactory> axCryptFactoryMock = new Mock <AxCryptFactory>()
            {
                CallBase = true
            };

            axCryptFactoryMock.Setup <DecryptionParameter>(m => m.FindDecryptionParameter(It.IsAny <IEnumerable <DecryptionParameter> >(), It.IsAny <IDataStore>())).Returns((Func <IEnumerable <DecryptionParameter>, IDataStore, DecryptionParameter>)((IEnumerable <DecryptionParameter> decryptionParameters, IDataStore fileInfo) =>
            {
                return(new DecryptionParameter(Passphrase.Empty, new V1Aes128CryptoFactory().CryptoId));
            }));
            TypeMap.Register.New <AxCryptFactory>(() => axCryptFactoryMock.Object);

            IDataStore encryptedFileInfo = New <IDataStore>(_anAxxPath);
            IDataStore decryptedFileInfo = New <IDataStore>(_decryptedFile1);
            ActiveFile activeFile        = new ActiveFile(encryptedFileInfo, decryptedFileInfo, new LogOnIdentity("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().CryptoId);

            Resolve.FileSystemState.Add(activeFile);

            int timeCalls = 0;

            ((FakeNow)New <INow>()).TimeFunction = (() => { return(utcNow.AddMinutes(1).AddMilliseconds(100 * timeCalls++)); });
            DateTime utcLater = New <INow>().Utc;

            decryptedFileInfo.SetFileTimes(utcLater, utcLater, utcLater);

            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange;
                return(Constant.CompletedTask);
            });

            await New <ActiveFileAction>().PurgeActiveFiles(new ProgressContext());

            activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_anAxxPath);
            Assert.That(changedWasRaised, Is.True, "A changed event should be raised because the decrypted file is modified.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The NotShareable not withstanding, the purge should have updated the file and removed the decrypted file.");
        }
示例#20
0
        public void Setup()
        {
            SetupAssembly.AssemblySetup();
            SetupAssembly.AssemblySetupCrypto(_cryptoImplementation);

            _rootPath                = Path.GetPathRoot(Environment.CurrentDirectory);
            _testTextPath            = _rootPath.PathCombine("test.txt");
            _davidCopperfieldTxtPath = _rootPath.PathCombine("Users", "AxCrypt", "David Copperfield.txt");
            _uncompressedAxxPath     = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments).PathCombine("Uncompressed.axx");
            _helloWorldAxxPath       = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments).PathCombine("HelloWorld.axx");

            FakeDataStore.AddFile(_testTextPath, FakeDataStore.TestDate1Utc, FakeDataStore.TestDate2Utc, FakeDataStore.TestDate1Utc, FakeDataStore.ExpandableMemoryStream(Encoding.UTF8.GetBytes("This is a short file")));
            FakeDataStore.AddFile(_davidCopperfieldTxtPath, FakeDataStore.TestDate4Utc, FakeDataStore.TestDate5Utc, FakeDataStore.TestDate6Utc, FakeDataStore.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
            FakeDataStore.AddFile(_uncompressedAxxPath, FakeDataStore.ExpandableMemoryStream(Resources.uncompressable_zip));
            FakeDataStore.AddFile(_helloWorldAxxPath, FakeDataStore.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
        }
示例#21
0
        public async Task TestCheckActiveFilesKeyIsSet()
        {
            DateTime utcNow     = New <INow>().Utc;
            DateTime utcJustNow = utcNow.AddMinutes(-1);

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, new MemoryStream(Resources.helloworld_key_a_txt));
            FakeDataStore.AddFile(_decryptedFile1, utcJustNow, utcJustNow, utcJustNow, Stream.Null);

            Mock <AxCryptFactory> axCryptFactoryMock = new Mock <AxCryptFactory>()
            {
                CallBase = true
            };

            axCryptFactoryMock.Setup <DecryptionParameter>(m => m.FindDecryptionParameter(It.IsAny <IEnumerable <DecryptionParameter> >(), It.IsAny <IDataStore>())).Returns((Func <IEnumerable <DecryptionParameter>, IDataStore, DecryptionParameter>)((IEnumerable <DecryptionParameter> decryptionParameters, IDataStore fileInfo) =>
            {
                return(new DecryptionParameter(Passphrase.Empty, new V1Aes128CryptoFactory().CryptoId));
            }));
            TypeMap.Register.New <AxCryptFactory>(() => axCryptFactoryMock.Object);

            ActiveFile activeFile;

            activeFile = new ActiveFile(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), new LogOnIdentity("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().CryptoId);
            Resolve.FileSystemState.Add(activeFile);
            await Resolve.KnownIdentities.AddAsync(activeFile.Identity);

            IDataStore decryptedFileInfo = New <IDataStore>(_decryptedFile1);

            decryptedFileInfo.SetFileTimes(utcNow, utcNow, utcNow);

            ((FakeNow)New <INow>()).TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange;
                return(Constant.CompletedTask);
            });
            ((FakeNow)New <INow>()).TimeFunction = () => DateTime.UtcNow;
            await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext());

            Assert.That(changedWasRaised, Is.True, "The file should be detected as modified, because it is considered open and decrypted, has a proper key, is modified, no running process so it should be re-encrypted and deleted.");
            activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_anAxxPath);
            Assert.That(activeFile, Is.Not.Null, "The encrypted file should be found.");
            Assert.That(activeFile.IsModified, Is.False, "The file should no longer be flagged as modified.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The file should no longer be decrypted, since it was re-encrypted and deleted.");
        }
示例#22
0
        public async Task TestDoNotDeleteModifiedIfNotSignedIn()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, new MemoryStream(Resources.helloworld_key_a_txt));
            FakeDataStore.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            ActiveFile activeFile = new ActiveFile(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), LogOnIdentity.Empty, ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);

            activeFile = new ActiveFile(activeFile, utcNow.AddMinutes(-1), ActiveFileStatus.AssumedOpenAndDecrypted);
            Resolve.FileSystemState.Add(activeFile);

            await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext());

            activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_anAxxPath);
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted), Is.True, "The ActiveFile plain text should not be deleted after the checking of active files because the user is not signed in.");
        }
        public static void TestMoveCurrentLogFileContentToPreviousLogFile()
        {
            FakeDataStore.AddFile(@"c:\test\ReportSnapshot.txt", new MemoryStream());
            FakeDataStore.AddFile(@"c:\test\ReportSnapshot.1.txt", new MemoryStream());

            IReport report          = new Report(@"c:\test\", 100);
            string  previousLogText = new StreamReader(New <IDataStore>(@"c:\test\ReportSnapshot.1.txt").OpenRead(), Encoding.UTF8).ReadToEnd();

            Assert.That(previousLogText.Length == 0, "Previous log file contain data.");

            for (int i = 0; i < 5; i++)
            {
                report.Exception(new Exception("This is a test " + i));
            }
            previousLogText = new StreamReader(New <IDataStore>(@"c:\test\ReportSnapshot.1.txt").OpenRead(), Encoding.UTF8).ReadToEnd();
            Assert.That(previousLogText.Length > 0, "Data not been coppied to pPrevious log file.");
        }
        public async Task TestRemoveRecentFiles()
        {
            var mockFileSystemState = new Mock <FileSystemState>()
            {
                CallBase = true
            };

            mockFileSystemState.Setup(x => x.Save()).Returns(Constant.CompletedTask);

            TypeMap.Register.Singleton <FileSystemState>(() => mockFileSystemState.Object);

            string file1      = @"C:\Folder\File3-txt.axx";
            string decrypted1 = @"C:\Folder\File2.txt";
            string file2      = @"C:\Folder\File2-txt.axx";
            string decrypted2 = @"C:\Folder\File1.txt";
            string file3      = @"C:\Folder\File1-txt.axx";
            string decrypted3 = @"C:\Folder\File3.txt";

            ActiveFile activeFile;

            FakeDataStore.AddFile(file1, new MemoryStream(Resources.helloworld_key_a_txt));
            activeFile = new ActiveFile(New <IDataStore>(file1), New <IDataStore>(decrypted1), new LogOnIdentity("passphrase1"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);
            Resolve.FileSystemState.Add(activeFile);

            FakeDataStore.AddFile(file2, new MemoryStream(Resources.helloworld_key_a_txt));
            activeFile = new ActiveFile(New <IDataStore>(file2), New <IDataStore>(decrypted2), new LogOnIdentity("passphrase2"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);
            Resolve.FileSystemState.Add(activeFile);

            FakeDataStore.AddFile(file3, new MemoryStream(Resources.helloworld_key_a_txt));
            activeFile = new ActiveFile(New <IDataStore>(file3), New <IDataStore>(decrypted3), new LogOnIdentity("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);
            Resolve.FileSystemState.Add(activeFile);

            using (MainViewModel mvm = New <MainViewModel>())
            {
                Assert.That(await mvm.RemoveRecentFiles.CanExecuteAsync(null), Is.True, "RemoveRecentFiles should be executable by default.");

                await mvm.RemoveRecentFiles.ExecuteAsync(new string[] { file2 });

                mockFileSystemState.Verify(x => x.RemoveActiveFile(It.IsAny <ActiveFile>()), Times.Once, "Exactly one recent file should be removed.");

                mockFileSystemState.ResetCalls();
                await mvm.RemoveRecentFiles.ExecuteAsync(new string[] { file2 });
            }
            mockFileSystemState.Verify(x => x.RemoveActiveFile(It.IsAny <ActiveFile>()), Times.Never, "There is no longer any matching file, so no call to remove should happen.");
        }
示例#25
0
        public async Task TestUpdateActiveFileWithKeyIfKeyMatchesThumbprintWithMatchingThumbprint()
        {
            IDataStore    encryptedFileInfo = New <IDataStore>(_anAxxPath);
            IDataStore    decryptedFileInfo = New <IDataStore>(_decryptedFile1);
            LogOnIdentity key = new LogOnIdentity("passphrase");

            FakeDataStore.AddFile(_anAxxPath, FakeDataStore.TestDate1Utc, FakeDataStore.TestDate2Utc, FakeDataStore.TestDate3Utc, new MemoryStream(Resources.helloworld_key_a_txt));
            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().CryptoId);

            Resolve.FileSystemState.Add(activeFile);
            await Resolve.FileSystemState.Save();

            TypeMap.Register.Singleton <FileSystemState>(() => FileSystemState.Create(New <IDataStore>(_fileSystemStateFilePath)));

            bool updateWasMade = await New <ActiveFileAction>().UpdateActiveFileWithKeyIfKeyMatchesThumbprint(key);

            Assert.That(updateWasMade, Is.True, "Since there is an ActiveFile with the right thumbprint in the list, an update should be made.");
        }
示例#26
0
        public async Task TestDeleteModifiedWhenSignedIn()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, FakeDataStore.ExpandableMemoryStream(Resources.david_copperfield_key__aa_ae_oe__ulu_txt));
            FakeDataStore.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            ActiveFile activeFile = new ActiveFile(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), LogOnIdentity.Empty, ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);

            activeFile = new ActiveFile(activeFile, utcNow.AddMinutes(-1), ActiveFileStatus.AssumedOpenAndDecrypted);
            Resolve.FileSystemState.Add(activeFile);

            await New <KnownIdentities>().SetDefaultEncryptionIdentity(new LogOnIdentity(EmailAddress.Parse("*****@*****.**"), new Passphrase("test")));
            await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext());

            activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_anAxxPath);
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The ActiveFile plain text should be deleted after the checking of active files because the user is signed in.");
        }
示例#27
0
        public async Task TestCheckActiveFilesUpdateButWithTargetLockedForSharing()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, FakeDataStore.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
            LogOnIdentity passphrase = new LogOnIdentity("a");

            New <AxCryptFile>().Decrypt(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), passphrase, AxCryptOptions.None, new ProgressContext());

            ActiveFile activeFile = new ActiveFile(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), passphrase, ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().CryptoId);

            Resolve.FileSystemState.Add(activeFile);

            IDataStore decryptedFileInfo = New <IDataStore>(_decryptedFile1);

            decryptedFileInfo.SetFileTimes(utcNow.AddSeconds(30), utcNow.AddSeconds(30), utcNow.AddSeconds(30));

            ((FakeNow)New <INow>()).TimeFunction = (() => { return(utcNow.AddMinutes(1)); });

            await Resolve.KnownIdentities.AddAsync(passphrase);

            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange;
                return(Constant.CompletedTask);
            });

            try
            {
                FakeDataStore.IsLockedFunc = (fds) => fds.FullName == _decryptedFile1;

                await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext());
            }
            finally
            {
                FakeDataStore.IsLockedFunc = (fds) => false;
            }

            Assert.That(changedWasRaised, Is.True, "The ActiveFile should be modified because it should now be marked as not shareable.");
            activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_anAxxPath);
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotShareable), Is.True, "The ActiveFile should be marked as not shareable after the checking of active files.");
        }
        public async Task TestWatchedFolderChanged()
        {
            using (FileSystemState state = FileSystemState.Create(Resolve.WorkFolder.FileInfo.FileItemInfo("mystate.txt")))
            {
                FakeDataStore.AddFolder(_rootPath);
                await state.AddWatchedFolderAsync(new WatchedFolder(_rootPath, IdentityPublicTag.Empty));

                Assert.That(state.ActiveFileCount, Is.EqualTo(0));

                FakeDataStore.AddFile(_encryptedAxxPath, new MemoryStream(Resources.helloworld_key_a_txt));
                Assert.That(state.ActiveFileCount, Is.EqualTo(0));

                state.Add(new ActiveFile(New <IDataStore>(_encryptedAxxPath), New <IDataStore>(_decryptedTxtPath), new LogOnIdentity("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId));
                Assert.That(state.ActiveFileCount, Is.EqualTo(1));

                New <IDataStore>(_encryptedAxxPath).Delete();
                Assert.That(state.ActiveFileCount, Is.EqualTo(0), "When deleted, the active file count should be zero.");
            }
        }
        public static void TestWorkFolderWatcherSimple()
        {
            TypeMap.Register.Singleton <SessionNotify>(() => new Mock <SessionNotify>().Object);

            using (WorkFolderWatcher wfw = new WorkFolderWatcher())
            {
                string fileName = Resolve.WorkFolder.FileInfo.FileItemInfo("New File.txt").FullName;
                FakeDataStore.AddFile(fileName, null);

                Mock.Get(Resolve.SessionNotify).Verify(s => s.NotifyAsync(It.Is <SessionNotification>(n => n.NotificationType == SessionNotificationType.WorkFolderChange && n.FullNames.SequenceEqual(new string[] { fileName }))), Times.Once);

                New <IDataStore>(fileName).Delete();
                Mock.Get(Resolve.SessionNotify).Verify(s => s.NotifyAsync(It.Is <SessionNotification>(n => n.NotificationType == SessionNotificationType.WorkFolderChange && n.FullNames.SequenceEqual(new string[] { fileName }))), Times.Exactly(2));

                IDataStore fileSystemStateInfo = Resolve.WorkFolder.FileInfo.FileItemInfo("FileSystemState.txt");
                fileSystemStateInfo.Delete();
                Mock.Get(Resolve.SessionNotify).Verify(s => s.NotifyAsync(It.Is <SessionNotification>(n => n.NotificationType == SessionNotificationType.WorkFolderChange && n.FullNames.SequenceEqual(new string[] { fileSystemStateInfo.FullName }))), Times.Never);
            }
        }
        public async Task TestOpenFiles()
        {
            string file1      = @"C:\Folder\File3-txt.axx";
            string decrypted1 = @"C:\Folder\File2.txt";
            string file2      = @"C:\Folder\File2-txt.axx";
            string decrypted2 = @"C:\Folder\File1.txt";
            string file3      = @"C:\Folder\File1-txt.axx";
            string decrypted3 = @"C:\Folder\File3.txt";

            ActiveFile activeFile;

            using (MainViewModel mvm = New <MainViewModel>())
            {
                ((FakeNow)New <INow>()).TimeFunction = () => new DateTime(2001, 1, 1);
                FakeDataStore.AddFile(file1, new MemoryStream(Resources.helloworld_key_a_txt));
                activeFile = new ActiveFile(New <IDataStore>(file1), New <IDataStore>(decrypted1), new LogOnIdentity("passphrase1"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().CryptoId);
                Resolve.FileSystemState.Add(activeFile);

                ((FakeNow)New <INow>()).TimeFunction = () => new DateTime(2002, 2, 2);
                FakeDataStore.AddFile(file2, new MemoryStream(Resources.helloworld_key_a_txt));
                activeFile = new ActiveFile(New <IDataStore>(file2), New <IDataStore>(decrypted2), new LogOnIdentity("passphrase2"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);
                Resolve.FileSystemState.Add(activeFile);

                ((FakeNow)New <INow>()).TimeFunction = () => new DateTime(2003, 3, 3);
                FakeDataStore.AddFile(file3, new MemoryStream(Resources.helloworld_key_a_txt));
                activeFile = new ActiveFile(New <IDataStore>(file3), New <IDataStore>(decrypted3), new LogOnIdentity("passphrase3"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);
                Resolve.FileSystemState.Add(activeFile);
                await Resolve.FileSystemState.Save();

                Assert.That(mvm.FilesArePending, Is.True);

                activeFile = new ActiveFile(New <IDataStore>(file1), New <IDataStore>(decrypted1), new LogOnIdentity("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);
                Resolve.FileSystemState.Add(activeFile);
                await Resolve.FileSystemState.Save();

                Assert.That(mvm.FilesArePending, Is.False);
            }
        }