added tests for kdb writing, fixed issue with syncing (keep UUIDs when loading again)
This commit is contained in:
@@ -23,14 +23,17 @@ namespace Kp2aUnitTests
|
||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("TestLoadKdb1WithKeyfileOnly"));
|
||||
|
||||
|
||||
runner.AddTests(new List<Type> { typeof(TestSelectStorageLocation) });
|
||||
//runner.AddTests(new List<Type> { typeof(TestSelectStorageLocation) });
|
||||
//runner.AddTests(new List<Type> { typeof(TestSynchronizeCachedDatabase)});
|
||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("LoadErrorWithCertificateTrustFailure"));
|
||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("LoadWithAcceptedCertificateTrustFailure"));
|
||||
|
||||
//runner.AddTests(new List<Type> { typeof(TestLoadDb) });
|
||||
//runner.AddTests(new List<Type> { typeof(TestSaveDb) });
|
||||
//runner.AddTests(new List<Type> { typeof(TestCachingFileStorage) });
|
||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("TestLoadKdb1"));
|
||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("TestLoadKdb1WithKeyfileOnly"));
|
||||
runner.AddTests(typeof(TestSaveDb).GetMethod("TestLoadEditSaveWithSyncKdb"));
|
||||
runner.AddTests(typeof(TestSaveDb).GetMethod("TestLoadAndSave_TestIdenticalFiles_kdb"));
|
||||
runner.AddTests(typeof(TestSaveDb).GetMethod("TestCreateSaveAndLoad_TestIdenticalFiles_kdb"));
|
||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("LoadAndSaveFromRemote1And1Ftp"));
|
||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("TestLoadKdbpWithPasswordOnly"));
|
||||
//runner.AddTests(typeof(TestSaveDb).GetMethod("TestLoadKdbxAndSaveKdbp_TestIdenticalFiles"));
|
||||
|
||||
@@ -136,6 +136,10 @@ namespace Kp2aUnitTests
|
||||
|
||||
IOConnectionInfo ioc = new IOConnectionInfo {Path = filename};
|
||||
Database db = app.CreateNewDatabase();
|
||||
if (filename.EndsWith(".kdb"))
|
||||
{
|
||||
db.DatabaseFormat = new KdbDatabaseFormat();
|
||||
}
|
||||
|
||||
db.KpDatabase = new PwDatabase();
|
||||
|
||||
|
||||
@@ -30,9 +30,12 @@ namespace Kp2aUnitTests
|
||||
bool createSuccesful = false;
|
||||
//create the task:
|
||||
CreateDb createDb = new CreateDb(app, Application.Context, ioc, new ActionOnFinish((success, message) =>
|
||||
{ createSuccesful = success;
|
||||
{ createSuccesful = success;
|
||||
if (!success)
|
||||
Android.Util.Log.Debug("KP2A_Test", message);
|
||||
}), false);
|
||||
//run it:
|
||||
|
||||
createDb.Run();
|
||||
//check expectations:
|
||||
Assert.IsTrue(createSuccesful);
|
||||
@@ -43,7 +46,7 @@ namespace Kp2aUnitTests
|
||||
|
||||
//ensure the the database can be loaded from file:
|
||||
PwDatabase loadedDb = new PwDatabase();
|
||||
loadedDb.Open(ioc, new CompositeKey(), null, new KdbxDatabaseLoader(KdbxFormat.Default));
|
||||
loadedDb.Open(ioc, new CompositeKey(), null, new KdbxDatabaseFormat(KdbxFormat.Default));
|
||||
|
||||
//Check whether the databases are equal
|
||||
AssertDatabasesAreEqual(loadedDb, app.GetDb().KpDatabase);
|
||||
|
||||
@@ -144,6 +144,11 @@ namespace Kp2aUnitTests
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void PrepareFileUsage(Context ctx, IOConnectionInfo ioc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnCreate(IFileStorageSetupActivity activity, Bundle savedInstanceState)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -187,8 +187,12 @@ namespace Kp2aUnitTests
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public bool CheckForDuplicateUuids
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
|
||||
public bool OnServerCertificateError(int sslPolicyErrors)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
@@ -15,6 +16,14 @@ using keepass2android;
|
||||
|
||||
namespace Kp2aUnitTests
|
||||
{
|
||||
static class StringExt
|
||||
{
|
||||
public static bool ContainsAny(this string haystack, IEnumerable<string> needles)
|
||||
{
|
||||
return needles.Any(haystack.Contains);
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
class TestSaveDb: TestBase
|
||||
{
|
||||
@@ -54,39 +63,83 @@ namespace Kp2aUnitTests
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void TestLoadEditSaveWithSyncKdb()
|
||||
{
|
||||
TestSync(DefaultDirectory + "savetest.kdb");
|
||||
}
|
||||
|
||||
private void TestSync(string filename)
|
||||
{
|
||||
//create the default database:
|
||||
IKp2aApp app = SetupAppWithDatabase(filename);
|
||||
DisplayGroups(app, "After create");
|
||||
//save it and reload it so we have a base version
|
||||
Android.Util.Log.Debug("KP2A", "-- Save first version -- ");
|
||||
SaveDatabase(app);
|
||||
Android.Util.Log.Debug("KP2A", "-- Load DB -- ");
|
||||
app = LoadDatabase(filename, DefaultPassword, DefaultKeyfile);
|
||||
DisplayGroups(app, "After reload");
|
||||
//load it once again:
|
||||
Android.Util.Log.Debug("KP2A", "-- Load DB to app 2-- ");
|
||||
IKp2aApp app2 = LoadDatabase(filename, DefaultPassword, DefaultKeyfile);
|
||||
DisplayGroups(app2, "After load to app2");
|
||||
|
||||
//modify the database by adding a group in both databases:
|
||||
app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true);
|
||||
var group2 = new PwGroup(true, true, "TestGroup2", PwIcon.Energy);
|
||||
app2.GetDb().KpDatabase.RootGroup.AddGroup(group2, true);
|
||||
//save the database from app 1:
|
||||
Android.Util.Log.Debug("KP2A", "-- Save from app 1 (with TestGroup) -- ");
|
||||
SaveDatabase(app);
|
||||
|
||||
|
||||
((TestKp2aApp) app2).SetYesNoCancelResult(TestKp2aApp.YesNoCancelResult.Yes);
|
||||
|
||||
//save the database from app 2: This save operation must detect the changes made from app 1 and ask if it should sync:
|
||||
Android.Util.Log.Debug("KP2A", "-- Save from app 2 (with TestGroup2, requires merge) -- ");
|
||||
SaveDatabase(app2);
|
||||
|
||||
DisplayGroups(app2, "After save with merge");
|
||||
//make sure the right question was asked
|
||||
Assert.AreEqual(UiStringKey.TitleSyncQuestion, ((TestKp2aApp) app2).LastYesNoCancelQuestionTitle);
|
||||
|
||||
//add group 2 to app 1:
|
||||
app.GetDb().KpDatabase.RootGroup.AddGroup(group2, true);
|
||||
app.GetDb().KpDatabase.RootGroup.SortSubGroups(true);
|
||||
|
||||
Android.Util.Log.Debug("KP2A", "-- Load DB to new app -- ");
|
||||
//load database to a new app instance:
|
||||
IKp2aApp resultApp = LoadDatabase(filename, DefaultPassword, DefaultKeyfile);
|
||||
|
||||
resultApp.GetDb().KpDatabase.RootGroup.SortSubGroups(true);
|
||||
//ensure the sync was successful:
|
||||
AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
|
||||
string kdbxXml = DatabaseToXml(app);
|
||||
string kdbxResultXml = DatabaseToXml(resultApp);
|
||||
|
||||
RemoveKdbLines(ref kdbxXml, true);
|
||||
RemoveKdbLines(ref kdbxResultXml, true);
|
||||
|
||||
Assert.AreEqual(kdbxXml, kdbxResultXml);
|
||||
|
||||
//AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
|
||||
}
|
||||
|
||||
private void DisplayGroups(IKp2aApp app, string name)
|
||||
{
|
||||
LogDebug("Groups display: " + name);
|
||||
DisplayGroupRecursive(0, app.GetDb().Root);
|
||||
}
|
||||
|
||||
private void DisplayGroupRecursive(int level, PwGroup g)
|
||||
{
|
||||
LogDebug("Group name="+g.Name+", exp: " + g.Expires+ ", expTime="+g.ExpiryTime.ToString(CultureInfo.InvariantCulture));
|
||||
foreach (var ch in g.Groups)
|
||||
DisplayGroupRecursive(level + 1, ch);
|
||||
|
||||
}
|
||||
|
||||
private static void LogDebug(string text, int indent=0)
|
||||
{
|
||||
Android.Util.Log.Debug("KP2A", text.PadLeft(indent*2));
|
||||
}
|
||||
|
||||
|
||||
@@ -293,10 +346,98 @@ namespace Kp2aUnitTests
|
||||
|
||||
Assert.AreEqual(kdbxXml,kdbxReloadedXml);
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestLoadAndSave_TestIdenticalFiles_kdb()
|
||||
{
|
||||
IKp2aApp app = LoadDatabase(DefaultDirectory + "complexDb.kdb", "test", null);
|
||||
app.GetDb().Root.SortSubGroups(true);
|
||||
string kdbxXml = DatabaseToXml(app);
|
||||
|
||||
newFilename = TestDbDirectory + "tmp_complexDb.kdb";
|
||||
if (File.Exists(newFilename))
|
||||
File.Delete(newFilename);
|
||||
app.GetDb().KpDatabase.IOConnectionInfo.Path = newFilename;
|
||||
app.GetDb().SaveData(Application.Context);
|
||||
|
||||
|
||||
IKp2aApp appReloaded = LoadDatabase(newFilename, "test", null);
|
||||
appReloaded.GetDb().Root.SortSubGroups(true);
|
||||
string kdbxReloadedXml = DatabaseToXml(appReloaded);
|
||||
|
||||
RemoveKdbLines(ref kdbxReloadedXml);
|
||||
RemoveKdbLines(ref kdbxXml);
|
||||
|
||||
Assert.AreEqual(kdbxXml, kdbxReloadedXml);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void TestCreateSaveAndLoad_TestIdenticalFiles_kdb()
|
||||
{
|
||||
string filename = DefaultDirectory + "createsaveandload.kdb";
|
||||
IKp2aApp app = SetupAppWithDatabase(filename);
|
||||
string kdbxXml = DatabaseToXml(app);
|
||||
//save it and reload it
|
||||
Android.Util.Log.Debug("KP2A", "-- Save DB -- ");
|
||||
SaveDatabase(app);
|
||||
Android.Util.Log.Debug("KP2A", "-- Load DB -- ");
|
||||
|
||||
|
||||
PwDatabase pwImp = new PwDatabase();
|
||||
PwDatabase pwDatabase = app.GetDb().KpDatabase;
|
||||
pwImp.New(new IOConnectionInfo(), pwDatabase.MasterKey);
|
||||
pwImp.MemoryProtection = pwDatabase.MemoryProtection.CloneDeep();
|
||||
pwImp.MasterKey = pwDatabase.MasterKey;
|
||||
|
||||
IOConnectionInfo ioc = new IOConnectionInfo() {Path = filename};
|
||||
using (Stream s = app.GetFileStorage(ioc).OpenFileForRead(ioc))
|
||||
{
|
||||
app.GetDb().DatabaseFormat.PopulateDatabaseFromStream(pwImp, s, null);
|
||||
}
|
||||
string kdbxReloadedXml = DatabaseToXml(app);
|
||||
|
||||
RemoveKdbLines(ref kdbxReloadedXml);
|
||||
RemoveKdbLines(ref kdbxXml);
|
||||
|
||||
Assert.AreEqual(kdbxXml, kdbxReloadedXml);
|
||||
|
||||
|
||||
|
||||
}
|
||||
private void RemoveKdbLines(ref string databaseXml, bool removeForAfterSync=false)
|
||||
{
|
||||
//these values are not part of .kdb and thus cannot be the same when comparing two .kdb files
|
||||
// -> remove them from the .xml
|
||||
var stuffToRemove = new string[] {"<DatabaseNameChanged>",
|
||||
"<DatabaseDescriptionChanged>",
|
||||
"<DefaultUserNameChanged>",
|
||||
"<MasterKeyChanged>",
|
||||
"<RecycleBinChanged>",
|
||||
"<EntryTemplatesGroupChanged>",
|
||||
"<Key>","<Key />" //key of attachments
|
||||
}.ToList();
|
||||
string[] moreStuffToRemove = new string[]
|
||||
{
|
||||
"<UUID>",
|
||||
"<ExpiryTime>",
|
||||
"<LocationChanged>"
|
||||
};
|
||||
if (removeForAfterSync)
|
||||
{
|
||||
stuffToRemove.AddRange(moreStuffToRemove);
|
||||
}
|
||||
string[] lines = databaseXml.Split(new char[] {'\n'});
|
||||
databaseXml = lines
|
||||
.Where(line => !line.ContainsAny(stuffToRemove))
|
||||
.Aggregate("", (current, line) => current + (line + "\n"));
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void TestLoadKdbxAndSaveKdbp_TestIdenticalFiles()
|
||||
{
|
||||
|
||||
@@ -99,6 +99,11 @@ namespace Kp2aUnitTests
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void PrepareFileUsage(Context ctx, IOConnectionInfo ioc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnCreate(IFileStorageSetupActivity activity, Bundle savedInstanceState)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
Reference in New Issue
Block a user