From 5120c8177b0b7ec4e883458ac99406f3159dc4bb Mon Sep 17 00:00:00 2001 From: BONNEVILLE Geoffroy Date: Wed, 22 Nov 2017 18:54:03 +0100 Subject: [PATCH] Adding tests for App WIP make VMs app agnostic --- ModernKeePass.sln | 26 +++ ModernKeePass/Common/DatabaseHelper.cs | 46 +++-- ModernKeePass/Interfaces/IDatabase.cs | 20 ++ ModernKeePass/ModernKeePassApp.csproj | 1 + ModernKeePass/ViewModels/CompositeKeyVm.cs | 23 ++- ModernKeePass/ViewModels/EntryVm.cs | 26 ++- ModernKeePass/ViewModels/MainVm.cs | 8 +- ModernKeePass/ViewModels/OpenVm.cs | 4 +- ModernKeePassApp.Test/DatabaseTests.cs | 64 ++++++ .../Databases/TestDatabase.kdbx | Bin 0 -> 1838 bytes .../Images/UnitTestLogo.scale-100.png | Bin 0 -> 5789 bytes .../Images/UnitTestSmallLogo.scale-100.png | Bin 0 -> 745 bytes .../Images/UnitTestSplashScreen.scale-100.png | Bin 0 -> 9381 bytes .../Images/UnitTestStoreLogo.scale-100.png | Bin 0 -> 2005 bytes .../ModernKeePassApp.Test.csproj | 191 ++++++++++++++++++ .../ModernKeePassApp.Test_TemporaryKey.pfx | Bin 0 -> 2446 bytes ModernKeePassApp.Test/Package.appxmanifest | 56 +++++ .../Properties/AssemblyInfo.cs | 28 +++ ModernKeePassApp.Test/packages.config | 14 ++ 19 files changed, 467 insertions(+), 40 deletions(-) create mode 100644 ModernKeePass/Interfaces/IDatabase.cs create mode 100644 ModernKeePassApp.Test/DatabaseTests.cs create mode 100644 ModernKeePassApp.Test/Databases/TestDatabase.kdbx create mode 100644 ModernKeePassApp.Test/Images/UnitTestLogo.scale-100.png create mode 100644 ModernKeePassApp.Test/Images/UnitTestSmallLogo.scale-100.png create mode 100644 ModernKeePassApp.Test/Images/UnitTestSplashScreen.scale-100.png create mode 100644 ModernKeePassApp.Test/Images/UnitTestStoreLogo.scale-100.png create mode 100644 ModernKeePassApp.Test/ModernKeePassApp.Test.csproj create mode 100644 ModernKeePassApp.Test/ModernKeePassApp.Test_TemporaryKey.pfx create mode 100644 ModernKeePassApp.Test/Package.appxmanifest create mode 100644 ModernKeePassApp.Test/Properties/AssemblyInfo.cs create mode 100644 ModernKeePassApp.Test/packages.config diff --git a/ModernKeePass.sln b/ModernKeePass.sln index 376d44d..a5cfa75 100644 --- a/ModernKeePass.sln +++ b/ModernKeePass.sln @@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassLib.Test", "Mo EndProject Project("{F5034706-568F-408A-B7B3-4D38C6DB8A32}") = "Scripts", "Scripts\Scripts.pssproj", "{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassApp.Test", "ModernKeePassApp.Test\ModernKeePassApp.Test.csproj", "{7E80F5E7-724A-4668-9333-B10F5D75C6D0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -103,6 +105,30 @@ Global {6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|x64.Build.0 = Release|Any CPU {6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|x86.ActiveCfg = Release|Any CPU {6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|x86.Build.0 = Release|Any CPU + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|ARM.ActiveCfg = Debug|ARM + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|ARM.Build.0 = Debug|ARM + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|ARM.Deploy.0 = Debug|ARM + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x64.ActiveCfg = Debug|x64 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x64.Build.0 = Debug|x64 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x64.Deploy.0 = Debug|x64 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x86.ActiveCfg = Debug|x86 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x86.Build.0 = Debug|x86 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x86.Deploy.0 = Debug|x86 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|Any CPU.Build.0 = Release|Any CPU + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|Any CPU.Deploy.0 = Release|Any CPU + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|ARM.ActiveCfg = Release|ARM + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|ARM.Build.0 = Release|ARM + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|ARM.Deploy.0 = Release|ARM + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x64.ActiveCfg = Release|x64 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x64.Build.0 = Release|x64 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x64.Deploy.0 = Release|x64 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x86.ActiveCfg = Release|x86 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x86.Build.0 = Release|x86 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x86.Deploy.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ModernKeePass/Common/DatabaseHelper.cs b/ModernKeePass/Common/DatabaseHelper.cs index 9afae3d..668e728 100644 --- a/ModernKeePass/Common/DatabaseHelper.cs +++ b/ModernKeePass/Common/DatabaseHelper.cs @@ -1,6 +1,7 @@ using System; using Windows.Storage; using Windows.UI.Xaml.Controls; +using ModernKeePass.Interfaces; using ModernKeePass.ViewModels; using ModernKeePassLib; using ModernKeePassLib.Cryptography.KeyDerivation; @@ -10,7 +11,7 @@ using ModernKeePassLib.Serialization; namespace ModernKeePass.Common { - public class DatabaseHelper + public class DatabaseHelper: IDatabase { public enum DatabaseStatus { @@ -37,7 +38,7 @@ namespace ModernKeePass.Common } } - public DatabaseStatus Status { get; private set; } = DatabaseStatus.Closed; + public int Status { get; set; } = (int)DatabaseStatus.Closed; public string Name => DatabaseFile?.Name; public bool RecycleBinEnabled @@ -52,7 +53,7 @@ namespace ModernKeePass.Common set { _databaseFile = value; - Status = DatabaseStatus.Opening; + Status = (int)DatabaseStatus.Opening; } } @@ -84,24 +85,26 @@ namespace ModernKeePass.Common { try { - if (key == null) Status = DatabaseStatus.NoCompositeKey; + if (key == null) + { + Status = (int)DatabaseStatus.NoCompositeKey; + return; + } var ioConnection = IOConnectionInfo.FromFile(DatabaseFile); if (createNew) _pwDatabase.New(ioConnection, key); else _pwDatabase.Open(ioConnection, key, new NullStatusLogger()); - if (_pwDatabase.IsOpen) - { - Status = DatabaseStatus.Opened; - RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null); - } + if (!_pwDatabase.IsOpen) return; + Status = (int)DatabaseStatus.Opened; + RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null); } catch (InvalidCompositeKeyException) { - Status = DatabaseStatus.CompositeKeyError; + Status = (int)DatabaseStatus.CompositeKeyError; } catch (Exception ex) { - Status = DatabaseStatus.Error; + Status = (int)DatabaseStatus.Error; } } @@ -109,11 +112,19 @@ namespace ModernKeePass.Common /// Save the current database to another file and open it /// /// The new database file - internal void Save(StorageFile file) + public bool Save(StorageFile file) { DatabaseFile = file; - _pwDatabase.SaveAs(IOConnectionInfo.FromFile(DatabaseFile), true, new NullStatusLogger()); - Status = DatabaseStatus.Opened; + try + { + _pwDatabase.SaveAs(IOConnectionInfo.FromFile(DatabaseFile), true, new NullStatusLogger()); + Status = (int)DatabaseStatus.Opened; + return true; + } + catch (Exception ex) + { + return false; + } } /// @@ -129,9 +140,10 @@ namespace ModernKeePass.Common } catch (Exception ex) { + return false; + // TODO: put this at a better place (e.g. in views) MessageDialogHelper.ShowErrorDialog(ex); } - return false; } /// @@ -140,7 +152,7 @@ namespace ModernKeePass.Common public void Close() { _pwDatabase?.Close(); - Status = DatabaseStatus.Closed; + Status = (int)DatabaseStatus.Closed; } public void AddDeletedItem(PwUuid id) @@ -150,7 +162,7 @@ namespace ModernKeePass.Common public void CreateRecycleBin() { - RecycleBin = RootGroup.AddNewGroup("Recycle bin"); + RecycleBin = ((GroupVm)RootGroup).AddNewGroup("Recycle bin"); RecycleBin.IsSelected = true; RecycleBin.IconSymbol = Symbol.Delete; } diff --git a/ModernKeePass/Interfaces/IDatabase.cs b/ModernKeePass/Interfaces/IDatabase.cs new file mode 100644 index 0000000..e005b46 --- /dev/null +++ b/ModernKeePass/Interfaces/IDatabase.cs @@ -0,0 +1,20 @@ +using ModernKeePass.ViewModels; +using ModernKeePassLib; +using ModernKeePassLib.Keys; + +namespace ModernKeePass.Interfaces +{ + public interface IDatabase + { + bool RecycleBinEnabled { get; set; } + int Status { get; set; } + GroupVm RootGroup { get; set; } + GroupVm RecycleBin { get; set; } + + void Open(CompositeKey key, bool createNew); + void UpdateCompositeKey(CompositeKey key); + bool Save(); + void CreateRecycleBin(); + void AddDeletedItem(PwUuid id); + } +} \ No newline at end of file diff --git a/ModernKeePass/ModernKeePassApp.csproj b/ModernKeePass/ModernKeePassApp.csproj index 8683979..05c66f5 100644 --- a/ModernKeePass/ModernKeePassApp.csproj +++ b/ModernKeePass/ModernKeePassApp.csproj @@ -123,6 +123,7 @@ + diff --git a/ModernKeePass/ViewModels/CompositeKeyVm.cs b/ModernKeePass/ViewModels/CompositeKeyVm.cs index 70ec127..2a7d91f 100644 --- a/ModernKeePass/ViewModels/CompositeKeyVm.cs +++ b/ModernKeePass/ViewModels/CompositeKeyVm.cs @@ -2,6 +2,7 @@ using Windows.Storage; using Windows.UI.Xaml; using ModernKeePass.Common; +using ModernKeePass.Interfaces; using ModernKeePassLib.Cryptography; using ModernKeePassLib.Keys; using ModernKeePassLib.Serialization; @@ -18,7 +19,7 @@ namespace ModernKeePass.ViewModels Success = 5 } - private readonly App _app = Application.Current as App; + //private readonly App _app = Application.Current as App; private bool _hasPassword; private bool _hasKeyFile; private string _password = string.Empty; @@ -27,6 +28,8 @@ namespace ModernKeePass.ViewModels private StorageFile _keyFile; private string _keyFileText = "Select key file from disk..."; + public IDatabase Database { get; set; } + public bool HasPassword { get { return _hasPassword; } @@ -90,15 +93,23 @@ namespace ModernKeePass.ViewModels } public GroupVm RootGroup { get; set; } + public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password?.ToCharArray()); - + + public CompositeKeyVm() : this((Application.Current as App)?.Database) { } + + public CompositeKeyVm(IDatabase database) + { + Database = database; + } + public bool OpenDatabase(bool createNew) { - _app.Database.Open(CreateCompositeKey(), createNew); - switch (_app.Database.Status) + Database.Open(CreateCompositeKey(), createNew); + switch ((DatabaseHelper.DatabaseStatus)Database.Status) { case DatabaseHelper.DatabaseStatus.Opened: - RootGroup = _app.Database.RootGroup; + RootGroup = Database.RootGroup; return true; case DatabaseHelper.DatabaseStatus.CompositeKeyError: var errorMessage = new StringBuilder("Error: wrong "); @@ -113,7 +124,7 @@ namespace ModernKeePass.ViewModels public void UpdateKey() { - _app.Database.UpdateCompositeKey(CreateCompositeKey()); + Database.UpdateCompositeKey(CreateCompositeKey()); UpdateStatus("Database composite key updated.", StatusTypes.Success); } diff --git a/ModernKeePass/ViewModels/EntryVm.cs b/ModernKeePass/ViewModels/EntryVm.cs index 83813fb..2c2e7f5 100644 --- a/ModernKeePass/ViewModels/EntryVm.cs +++ b/ModernKeePass/ViewModels/EntryVm.cs @@ -14,6 +14,7 @@ namespace ModernKeePass.ViewModels { public class EntryVm : INotifyPropertyChanged, IPwEntity { + public IDatabase Database { get; set; } public GroupVm ParentGroup { get; private set; } public GroupVm PreviousGroup { get; private set; } @@ -150,7 +151,6 @@ namespace ModernKeePass.ViewModels public event PropertyChangedEventHandler PropertyChanged; private readonly PwEntry _pwEntry; - private readonly App _app = Application.Current as App; private bool _isEditMode; private bool _isRevealPassword; private double _passwordLength = 25; @@ -160,16 +160,20 @@ namespace ModernKeePass.ViewModels PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } - public EntryVm() { } - public EntryVm(PwEntry entry, GroupVm parent) + public EntryVm() : this(null, null) { } + + internal EntryVm(PwEntry entry, GroupVm parent) : this(entry, parent, (Application.Current as App)?.Database) { } + + public EntryVm(PwEntry entry, GroupVm parent, IDatabase database) { + Database = database; _pwEntry = entry; ParentGroup = parent; } public void GeneratePassword() { - var pwProfile = new PwProfile() + var pwProfile = new PwProfile { GeneratorType = PasswordGeneratorType.CharSet, Length = (uint)PasswordLength, @@ -208,9 +212,9 @@ namespace ModernKeePass.ViewModels public void MarkForDelete() { - if (_app.Database.RecycleBinEnabled && _app.Database.RecycleBin?.IdUuid == null) - _app.Database.CreateRecycleBin(); - Move(_app.Database.RecycleBinEnabled && !ParentGroup.IsSelected ? _app.Database.RecycleBin : null); + if (Database.RecycleBinEnabled && Database.RecycleBin?.IdUuid == null) + Database.CreateRecycleBin(); + Move(Database.RecycleBinEnabled && !ParentGroup.IsSelected ? Database.RecycleBin : null); } public void UndoDelete() @@ -225,7 +229,7 @@ namespace ModernKeePass.ViewModels PreviousGroup.RemovePwEntry(_pwEntry); if (destination == null) { - _app.Database.AddDeletedItem(IdUuid); + Database.AddDeletedItem(IdUuid); return; } ParentGroup = destination; @@ -236,13 +240,13 @@ namespace ModernKeePass.ViewModels public void CommitDelete() { _pwEntry.ParentGroup.Entries.Remove(_pwEntry); - if (_app.Database.RecycleBinEnabled && !PreviousGroup.IsSelected) _app.Database.RecycleBin.AddPwEntry(_pwEntry); - else _app.Database.AddDeletedItem(IdUuid); + if (Database.RecycleBinEnabled && !PreviousGroup.IsSelected) Database.RecycleBin.AddPwEntry(_pwEntry); + else Database.AddDeletedItem(IdUuid); } public void Save() { - _app.Database.Save(); + Database.Save(); } } } diff --git a/ModernKeePass/ViewModels/MainVm.cs b/ModernKeePass/ViewModels/MainVm.cs index f83890f..ae18a81 100644 --- a/ModernKeePass/ViewModels/MainVm.cs +++ b/ModernKeePass/ViewModels/MainVm.cs @@ -49,14 +49,14 @@ namespace ModernKeePass.ViewModels { var app = (App)Application.Current; var mru = StorageApplicationPermissions.MostRecentlyUsedList; - var isDatabaseOpen = app.Database != null && app.Database.Status == DatabaseHelper.DatabaseStatus.Opened; + var isDatabaseOpen = app.Database != null && app.Database.Status == (int) DatabaseHelper.DatabaseStatus.Opened; var mainMenuItems = new ObservableCollection { new MainMenuItemVm { Title = "Open", PageType = typeof(OpenDatabasePage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Page2, - IsSelected = app.Database.Status == DatabaseHelper.DatabaseStatus.Opening + IsSelected = app.Database.Status == (int) DatabaseHelper.DatabaseStatus.Opening }, new MainMenuItemVm { @@ -69,7 +69,7 @@ namespace ModernKeePass.ViewModels }, new MainMenuItemVm { Title = "Recent" , PageType = typeof(RecentDatabasesPage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Copy, - IsSelected = (app.Database == null || app.Database.Status == DatabaseHelper.DatabaseStatus.Closed) && mru.Entries.Count > 0, IsEnabled = mru.Entries.Count > 0 + IsSelected = (app.Database == null || app.Database.Status == (int) DatabaseHelper.DatabaseStatus.Closed) && mru.Entries.Count > 0, IsEnabled = mru.Entries.Count > 0 }, new MainMenuItemVm { @@ -78,7 +78,7 @@ namespace ModernKeePass.ViewModels }; // Auto-select the Recent Items menu item if the conditions are met SelectedItem = mainMenuItems.FirstOrDefault(m => m.IsSelected); - if (app.Database != null && app.Database.Status == DatabaseHelper.DatabaseStatus.Opened) + if (app.Database != null && app.Database.Status == (int) DatabaseHelper.DatabaseStatus.Opened) mainMenuItems.Add(new MainMenuItemVm { Title = app.Database.Name, diff --git a/ModernKeePass/ViewModels/OpenVm.cs b/ModernKeePass/ViewModels/OpenVm.cs index 3f94b00..2987237 100644 --- a/ModernKeePass/ViewModels/OpenVm.cs +++ b/ModernKeePass/ViewModels/OpenVm.cs @@ -10,7 +10,7 @@ namespace ModernKeePass.ViewModels { public bool ShowPasswordBox { - get { return ((App)Application.Current).Database.Status == DatabaseHelper.DatabaseStatus.Opening; } + get { return ((App)Application.Current).Database.Status == (int) DatabaseHelper.DatabaseStatus.Opening; } } public string Name @@ -21,7 +21,7 @@ namespace ModernKeePass.ViewModels public OpenVm() { var app = Application.Current as App; - if (app?.Database == null || app.Database.Status != DatabaseHelper.DatabaseStatus.Opening) return; + if (app?.Database == null || app.Database.Status != (int) DatabaseHelper.DatabaseStatus.Opening) return; OpenFile(app.Database.DatabaseFile); } diff --git a/ModernKeePassApp.Test/DatabaseTests.cs b/ModernKeePassApp.Test/DatabaseTests.cs new file mode 100644 index 0000000..3ca6687 --- /dev/null +++ b/ModernKeePassApp.Test/DatabaseTests.cs @@ -0,0 +1,64 @@ +using System; +using Windows.ApplicationModel; +using Windows.Storage; +using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; +using ModernKeePass.Common; +using ModernKeePass.ViewModels; +using ModernKeePassLib.Keys; + +namespace ModernKeePassApp.Test +{ + [TestClass] + public class DatabaseTests + { + private readonly DatabaseHelper _database = new DatabaseHelper(); + + [TestMethod] + public void TestCreate() + { + Assert.AreEqual(_database.Status, (int) DatabaseHelper.DatabaseStatus.Closed); + _database.DatabaseFile = ApplicationData.Current.TemporaryFolder.CreateFileAsync("NewDatabase.kdbx").GetAwaiter().GetResult(); + Assert.AreEqual(_database.Status, (int)DatabaseHelper.DatabaseStatus.Opening); + OpenOrCreateDatabase(true); + _database.Close(); + Assert.AreEqual(_database.Status, (int)DatabaseHelper.DatabaseStatus.Closed); + } + + [TestMethod] + public void TestOpen() + { + Assert.AreEqual(_database.Status, (int)DatabaseHelper.DatabaseStatus.Closed); + _database.DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Databases\TestDatabase.kdbx").GetAwaiter().GetResult(); + Assert.AreEqual(_database.Status, (int)DatabaseHelper.DatabaseStatus.Opening); + OpenOrCreateDatabase(false); + } + + [TestMethod] + public void TestSave() + { + TestOpen(); + Assert.IsTrue(_database.Save(ApplicationData.Current.TemporaryFolder.CreateFileAsync("SaveDatabase.kdbx").GetAwaiter().GetResult())); + _database.Close(); + Assert.AreEqual(_database.Status, (int)DatabaseHelper.DatabaseStatus.Closed); + TestOpen(); + } + + private void OpenOrCreateDatabase(bool createNew) + { + _database.Open(null, createNew); + Assert.AreEqual(_database.Status, (int)DatabaseHelper.DatabaseStatus.NoCompositeKey); + var compositeKey = new CompositeKey(); + if (!createNew) + { + _database.Open(compositeKey); + Assert.AreEqual(_database.Status, (int)DatabaseHelper.DatabaseStatus.CompositeKeyError); + } + compositeKey.AddUserKey(new KcpPassword("test")); + + _database.Open(compositeKey, createNew); + /*var compositeKey = new CompositeKeyVm(_database); + compositeKey.OpenDatabase(createNew);*/ + Assert.AreEqual(_database.Status, (int)DatabaseHelper.DatabaseStatus.Opened); + } + } +} diff --git a/ModernKeePassApp.Test/Databases/TestDatabase.kdbx b/ModernKeePassApp.Test/Databases/TestDatabase.kdbx new file mode 100644 index 0000000000000000000000000000000000000000..da44db51a360802a58ab02061dca9ad022f5f273 GIT binary patch literal 1838 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 literal 0 HcmV?d00001 diff --git a/ModernKeePassApp.Test/Images/UnitTestSmallLogo.scale-100.png b/ModernKeePassApp.Test/Images/UnitTestSmallLogo.scale-100.png new file mode 100644 index 0000000000000000000000000000000000000000..92dd1058fbfb70c4491d934fe5f60ff2bacd41e9 GIT binary patch literal 745 zcmVGVQpR4ciyoglSwB91#GhGhn{+`40 zKOYZLtJUy5M#Hz+??BTuEf5G^US9q^+F&rqWU^c?_f@o5EFKPriyn{1Bb7>Dq2Gpm zj6OIx0Dx2~HJwfYfY0ae?(T|2B8f!u{QL|62qB-(r&KC$Z*SK_*J?F}VN52|>FMcU zFfbSl3WWjytX69-my^roXJ=<#ua{)79{TC&>GAP#Z*OmVdpj13x!rDr5V@9aw;PYg zH#axi?RKlx`izXlVo|Hrs#L0EGRd+maoTJ)o6W}O^8uh-F3h|y@YSS;jQC=}8(jWHGo1n>Siolbo|pUdSMkH^GQuh+}v@;m@7 z&Jc>C4i68Hj*hr+T!t~ezP`S?y22R0k0z$q>n|=YHa0d^OdOHmY;9-&aER;zuc8|`*G;bM$g zmK6$x05F+MNKYb!91h14^s=n;`Mg%E?Q}Y^Sj_A71_A*9C=?2bL}EUktX3=67~#xX zqtR?_Z50ZIlarIdV8G+?{C+<<@8RKLe}A70Rh>@PY&O@+Iv5NhgzoO{=BuF5Xoy6j zot>Spu7XS^v$&ZilS!#ml1in7OJvMsGGeiKZ5iKgy!-omnN0R!*h(_~++zV_yx462 b>BH;~a9|}kOw?>(00000NkvXXu0mjfaI93Z literal 0 HcmV?d00001 diff --git a/ModernKeePassApp.Test/Images/UnitTestSplashScreen.scale-100.png b/ModernKeePassApp.Test/Images/UnitTestSplashScreen.scale-100.png new file mode 100644 index 0000000000000000000000000000000000000000..193187f108f50dd242cb5c589b02a29691b7432a GIT binary patch literal 9381 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 + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {7E80F5E7-724A-4668-9333-B10F5D75C6D0} + Library + Properties + ModernKeePassApp.Test + ModernKeePassApp.Test + en-US + 8.1 + 14 + 512 + {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ModernKeePassApp.Test_TemporaryKey.pfx + Never + False + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE;NETFX_CORE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE;NETFX_CORE + prompt + 4 + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + ARM + false + prompt + true + + + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + x64 + false + prompt + true + + + bin\x64\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + x64 + false + prompt + true + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + x86 + false + prompt + true + + + True + true + + + + + + + + + + + + + Designer + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + {A0CFC681-769B-405A-8482-0CDEE595A91F} + ModernKeePassApp + + + + + ..\packages\Portable.BouncyCastle.1.8.1.3\lib\netstandard1.0\BouncyCastle.Crypto.dll + True + + + ..\packages\ModernKeePassLib.2.37.7000\lib\netstandard1.2\ModernKeePassLib.dll + True + + + ..\packages\Splat.2.0.0\lib\Portable-Win81+Wpa81\Splat.dll + True + + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\win8\System.Runtime.InteropServices.RuntimeInformation.dll + True + + + ..\packages\Validation.2.4.18\lib\portable-net45+win8+wp8+wpa81\Validation.dll + True + + + + 14.0 + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/ModernKeePassApp.Test/ModernKeePassApp.Test_TemporaryKey.pfx b/ModernKeePassApp.Test/ModernKeePassApp.Test_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..78d6a18d307d57bfd1c46c89d2a4f3834fede62e GIT binary patch literal 2446 zcmZuz2{=^!8b330W|&ddER8LtObnedG1k$SFeOVd))petrDP~-qK;xLS;{1(W^Ab` z($GT7Cs`wWlH?C_JNI7_b{K@Q0|?!VST|1MUs)>%C^R1i7a{w2R{Z(cdO-eGWwY={%c3nl z_@Z3CjYRmVOPh8$3vVgj?Fjz7bGM**IO(eRYD)UI3l@bX>pDghKiMrdvn%x|=Jo+~~X!gwnM4pzF#7q!l~ckGipHUbtSXJM(N(<@y`{(MPHIs!eGQ zk`_MJ8KL#)L7;N%yllKOL9DAfH$}-#CBHbql_@W6wRfm5FdHJa@0vHKJJGM9a~I;b ze=SsqDyI35j^GP%3jz%rVdaGiSkXSAYv|Q$o58SklCMhJ=z5Ya+MTWmRLijZYsvG*3H3maYOty$0TC zAt8jRFl!U#d)u?GKACD;d){G&u{0&O^*PxtP)$%$6xtpF;D6LMOXvoyGi$*ZFs( zU(7k~xs-7jv_R$X7 zYI5d|Z{{a!S=2_%e=r_s8VyxGhc7#IqNzAyqGXe)!!-L*l4awkn*6rJXR ziEoZ z4%&KANxZR$_2jT8T(^ITZfyJVHqaOVPehbc4sG* zA|+IvYbFiaKLYpA4{IVP>)M5sf?WA^^>j}y9z&$%XhbV6uJw&m>e}#b4{I(#)y&o` zfGhRYd1H#A&U1hNcH)=Pe%ko@e83dBWb?s(j?85 z_hePZFPxr?o7w2-r|~M*+9|{F=7Lz#^S4L73Q-FxfyI~e#@poc8)8Tr?fb04 zZWU&}-3k_2m>jN&r&X}W1A9I+?Q^@hc=o~kz~!Fqg7oWt+`P=)N*&pr-cA?Cz;yUf zU|d|!j(O#YMYiD}h@;)upHm^(a7HUc+Y@infMc4uyfP$0(<_xi3I#nF07ptUd|_qz zlGSN$Ub=UNSwI|v>o7%9TuuSy>}yEw*SN&XQ*a=N0ssJV{SUc{vO|plcmw)?F<^*X zDTqe}bb-x)A7BI={OK9|)N~Qm8_||IUnK4TV1UFNK%xwggMw&2&|Vx~2ZsVtFii$U zaa6Mh?0^8k2M7U<0xZP*fKXr!;Dnr)nInKdf-Dg~0tiO9qX-T`$^-+4erBx!9Dl|g zN02YFYzPEnbbsx9`NM!w17Qpip%oC5{eAjl_%Qkl1f%TAq0!R*&i$WiiBVrfjA_9tbpAh7^OJ@PFcA)Y{)mqObr4Mo9t44hU!%g#!AY_*blk`Ma8I^HXgW zvc<1^C;A=C`%>EFNJ$=OnGdx{lKfm5?6xJWhLFN9Th+bBMK^J7Hxzkmc$U<+VEUzN z%$O7qtl-x3C8Pdr63A$(R=nYHhS&dYiQC+8I$veJ5!>0;eQ#o4!AJp4ETSTayrtA)N%W3TC+63cs^ zcr!);U%OEG9lQN`OYnEn(HeDLURHdU@h7b$QA^>|J$U$4D9PWGzV+{d@Y_yHh1zb> z>P)7QgXXuP{W_wQ>{H_oucxt%W)7=@e-O^E*>+hbK|c!zTaso4$4865ijHXwvs@Ay z_6l&xnHYYo`g_SgY{acKw&ir2^^osZixz{!=Ja2_(^-?y*GzRHn|8NQ|3Xt;M<$>C zRl)F04dN7+gnXOOEzOGlxT5BE>ycS~bBg@`f6+}Lbw~_{)se)YiQuZovE}66T}s*s p;ztY%ShgC0vf+=xRh2v0)n{e6DYk_%UN*BcH+#s|^~--o{{)y%1ik + + + + + + ModernKeePassApp.Test + GBE + Images\UnitTestStoreLogo.png + ModernKeePassApp.Test + + + + 6.3.0 + 6.3.0 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePassApp.Test/Properties/AssemblyInfo.cs b/ModernKeePassApp.Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9678477 --- /dev/null +++ b/ModernKeePassApp.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,28 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ModernKeePassApp.Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ModernKeePassApp.Test")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ModernKeePassApp.Test/packages.config b/ModernKeePassApp.Test/packages.config new file mode 100644 index 0000000..7e8fa7e --- /dev/null +++ b/ModernKeePassApp.Test/packages.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file