* Introduced IFileStorage interface: Better abstraction than current IOConnection (suitable for cloud support). Currently only implemented by the built-in IOConnection (local/http/ftp)
* Implemented Merge functionality for SaveDB. UI is not yet implemented! * Added tests for merge functionality
This commit is contained in:
@@ -20,7 +20,8 @@ namespace Kp2aUnitTests
|
||||
// Run all tests from this assembly
|
||||
runner.AddTests(Assembly.GetExecutingAssembly());
|
||||
//runner.AddTests(new List<Type> { typeof(TestSaveDb)});
|
||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("TestLoadWithPasswordOnly"));}}
|
||||
//runner.AddTests(typeof(TestSaveDb).GetMethod("TestLoadEditSaveWithSyncConflict"));
|
||||
//runner.AddTests(typeof(TestSaveDb).GetMethod("TestLoadEditSave"));
|
||||
return runner;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ namespace Kp2aUnitTests
|
||||
|
||||
}
|
||||
|
||||
public void SetMessage(string getResourceString)
|
||||
public void SetMessage(string resourceString)
|
||||
{
|
||||
|
||||
Kp2aLog.Log("Progress message: " + resourceString);
|
||||
}
|
||||
|
||||
public void Dismiss()
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Kp2aUnitTests
|
||||
|
||||
})
|
||||
);
|
||||
ProgressTask pt = new ProgressTask(app, Application.Context, task, UiStringKey.loading_database);
|
||||
ProgressTask pt = new ProgressTask(app, Application.Context, task);
|
||||
pt.Run();
|
||||
pt.JoinWorkerThread();
|
||||
Assert.IsTrue(loadSuccesful);
|
||||
@@ -83,16 +83,27 @@ namespace Kp2aUnitTests
|
||||
|
||||
protected void SaveDatabase(IKp2aApp app)
|
||||
{
|
||||
bool saveSuccesful = false;
|
||||
SaveDb save = new SaveDb(Application.Context, app.GetDb(), new ActionOnFinish((success, message) =>
|
||||
{
|
||||
saveSuccesful = success;
|
||||
}), false);
|
||||
save.Run();
|
||||
bool saveSuccesful = TrySaveDatabase(app);
|
||||
|
||||
Assert.IsTrue(saveSuccesful);
|
||||
}
|
||||
|
||||
public static bool TrySaveDatabase(IKp2aApp app)
|
||||
{
|
||||
bool saveSuccesful = false;
|
||||
SaveDb save = new SaveDb(Application.Context, app, new ActionOnFinish((success, message) =>
|
||||
{
|
||||
saveSuccesful = success;
|
||||
if (!success)
|
||||
{
|
||||
Kp2aLog.Log("Error during TestBase.SaveDatabase: " + message);
|
||||
}
|
||||
}), false);
|
||||
save.Run();
|
||||
save.JoinWorkerThread();
|
||||
return saveSuccesful;
|
||||
}
|
||||
|
||||
protected IKp2aApp SetupAppWithDefaultDatabase()
|
||||
{
|
||||
IKp2aApp app = new TestKp2aApp();
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using KeePassLib.Serialization;
|
||||
using keepass2android;
|
||||
using keepass2android.Io;
|
||||
|
||||
namespace Kp2aUnitTests
|
||||
{
|
||||
@@ -11,7 +13,14 @@ namespace Kp2aUnitTests
|
||||
/// </summary>
|
||||
internal class TestKp2aApp : IKp2aApp
|
||||
{
|
||||
internal enum YesNoCancelResult
|
||||
{
|
||||
Yes, No, Cancel
|
||||
}
|
||||
|
||||
private Database _db;
|
||||
private YesNoCancelResult _yesNoCancelResult = YesNoCancelResult.Yes;
|
||||
private Dictionary<PreferenceKey, bool> _preferences = new Dictionary<PreferenceKey, bool>();
|
||||
|
||||
public void SetShutdown()
|
||||
{
|
||||
@@ -43,13 +52,32 @@ namespace Kp2aUnitTests
|
||||
|
||||
public bool GetBooleanPreference(PreferenceKey key)
|
||||
{
|
||||
if (_preferences.ContainsKey(key))
|
||||
return _preferences[key];
|
||||
return true;
|
||||
}
|
||||
|
||||
public UiStringKey? LastYesNoCancelQuestionTitle { get; set; }
|
||||
|
||||
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey, EventHandler<DialogClickEventArgs> yesHandler, EventHandler<DialogClickEventArgs> noHandler,
|
||||
EventHandler<DialogClickEventArgs> cancelHandler, Context ctx)
|
||||
{
|
||||
yesHandler(null, null);
|
||||
LastYesNoCancelQuestionTitle = titleKey;
|
||||
switch (_yesNoCancelResult)
|
||||
{
|
||||
case YesNoCancelResult.Yes:
|
||||
yesHandler(null, null);
|
||||
break;
|
||||
case YesNoCancelResult.No:
|
||||
noHandler(null, null);
|
||||
break;
|
||||
case YesNoCancelResult.Cancel:
|
||||
cancelHandler(null, null);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("unexpected case!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Handler UiThreadHandler {
|
||||
@@ -59,5 +87,20 @@ namespace Kp2aUnitTests
|
||||
{
|
||||
return new ProgressDialogStub();
|
||||
}
|
||||
|
||||
public IFileStorage GetFileStorage(IOConnectionInfo iocInfo)
|
||||
{
|
||||
return new BuiltInFileStorage();
|
||||
}
|
||||
|
||||
public void SetYesNoCancelResult(YesNoCancelResult yesNoCancelResult)
|
||||
{
|
||||
_yesNoCancelResult = yesNoCancelResult;
|
||||
}
|
||||
|
||||
public void SetPreference(PreferenceKey key, bool value)
|
||||
{
|
||||
_preferences[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ namespace Kp2aUnitTests
|
||||
loadSuccesful = success;
|
||||
})
|
||||
);
|
||||
ProgressTask pt = new ProgressTask(app, Application.Context, task, UiStringKey.loading_database);
|
||||
ProgressTask pt = new ProgressTask(app, Application.Context, task);
|
||||
Android.Util.Log.Debug("KP2ATest", "Running ProgressTask");
|
||||
pt.Run();
|
||||
pt.JoinWorkerThread();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Android.App;
|
||||
using Android.OS;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Keys;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
@@ -23,6 +25,7 @@ namespace Kp2aUnitTests
|
||||
{
|
||||
//create the default database:
|
||||
IKp2aApp app = SetupAppWithDefaultDatabase();
|
||||
IOConnection.DeleteFile(new IOConnectionInfo { Path = DefaultFilename });
|
||||
//save it and reload it so we have a base version
|
||||
SaveDatabase(app);
|
||||
app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
@@ -56,9 +59,14 @@ namespace Kp2aUnitTests
|
||||
//save the database from app 1:
|
||||
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:
|
||||
SaveDatabase(app2);
|
||||
|
||||
//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);
|
||||
|
||||
@@ -68,7 +76,162 @@ namespace Kp2aUnitTests
|
||||
//ensure the sync was successful:
|
||||
AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
|
||||
|
||||
Assert.IsTrue(false, "todo: test for sync question, test overwrite or cancel!");
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void TestLoadEditSaveWithSyncOverwrite()
|
||||
{
|
||||
//create the default database:
|
||||
IKp2aApp app = SetupAppWithDefaultDatabase();
|
||||
//save it and reload it so we have a base version
|
||||
SaveDatabase(app);
|
||||
app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
//load it once again:
|
||||
IKp2aApp app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
|
||||
//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:
|
||||
SaveDatabase(app);
|
||||
|
||||
//the user clicks the "no" button when asked if the sync should be performed -> overwrite expected!
|
||||
((TestKp2aApp)app2).SetYesNoCancelResult(TestKp2aApp.YesNoCancelResult.No);
|
||||
|
||||
//save the database from app 2: This save operation must detect the changes made from app 1 and ask if it should sync:
|
||||
SaveDatabase(app2);
|
||||
|
||||
//make sure the right question was asked
|
||||
Assert.AreEqual(UiStringKey.TitleSyncQuestion, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle);
|
||||
|
||||
//load database to a new app instance:
|
||||
IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
|
||||
//ensure the sync was NOT performed (overwrite expected!):
|
||||
AssertDatabasesAreEqual(app2.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
|
||||
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void TestLoadEditSaveWithSyncOverwriteBecauseOfNoCheck()
|
||||
{
|
||||
//create the default database:
|
||||
IKp2aApp app = SetupAppWithDefaultDatabase();
|
||||
//save it and reload it so we have a base version
|
||||
SaveDatabase(app);
|
||||
app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
//load it once again:
|
||||
IKp2aApp app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
|
||||
//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:
|
||||
SaveDatabase(app);
|
||||
|
||||
//the user doesn't want to perform check for file change:
|
||||
((TestKp2aApp) app2).SetPreference(PreferenceKey.CheckForFileChangesOnSave, false);
|
||||
|
||||
//save the database from app 2: This save operation must detect the changes made from app 1 and ask if it should sync:
|
||||
SaveDatabase(app2);
|
||||
|
||||
//make sure no question was asked
|
||||
Assert.AreEqual(null, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle);
|
||||
|
||||
//load database to a new app instance:
|
||||
IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
|
||||
//ensure the sync was NOT performed (overwrite expected!):
|
||||
AssertDatabasesAreEqual(app2.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestLoadEditSaveWithSyncCancel()
|
||||
{
|
||||
//create the default database:
|
||||
IKp2aApp app = SetupAppWithDefaultDatabase();
|
||||
//save it and reload it so we have a base version
|
||||
SaveDatabase(app);
|
||||
app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
//load it once again:
|
||||
IKp2aApp app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
|
||||
//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:
|
||||
SaveDatabase(app);
|
||||
|
||||
//the user clicks the "cancel" button when asked if the sync should be performed
|
||||
((TestKp2aApp)app2).SetYesNoCancelResult(TestKp2aApp.YesNoCancelResult.Cancel);
|
||||
|
||||
//save the database from app 2: This save operation must detect the changes made from app 1 and ask if it should sync:
|
||||
Assert.AreEqual(false, TrySaveDatabase(app2));
|
||||
|
||||
//make sure the right question was asked
|
||||
Assert.AreEqual(UiStringKey.TitleSyncQuestion, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle);
|
||||
|
||||
//load database to a new app instance:
|
||||
IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
|
||||
//ensure the sync was NOT performed (cancel expected!):
|
||||
AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
|
||||
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void TestLoadEditSaveWithSyncConflict()
|
||||
{
|
||||
|
||||
//create the default database:
|
||||
IKp2aApp app = SetupAppWithDefaultDatabase();
|
||||
//save it and reload it so we have a base version
|
||||
SaveDatabase(app);
|
||||
app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
//load it once again:
|
||||
IKp2aApp app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||
|
||||
//modify the database by renaming the same group in both databases:
|
||||
app.GetDb().KpDatabase.RootGroup.Groups.Single(g => g.Name == "Internet").Name += "abc";
|
||||
app2.GetDb().KpDatabase.RootGroup.Groups.Single(g => g.Name == "Internet").Name += "abcde";
|
||||
//app1 also changes the master password:
|
||||
var compositeKey = app.GetDb().KpDatabase.MasterKey;
|
||||
compositeKey.RemoveUserKey(compositeKey.GetUserKey(typeof (KcpPassword)));
|
||||
compositeKey.AddUserKey(new KcpPassword("abc"));
|
||||
|
||||
//save the database from app 1:
|
||||
SaveDatabase(app);
|
||||
|
||||
|
||||
((TestKp2aApp)app2).SetYesNoCancelResult(TestKp2aApp.YesNoCancelResult.Yes);
|
||||
|
||||
//save the database from app 2: This save operation must fail because the target file cannot be loaded:
|
||||
Assert.IsFalse(TrySaveDatabase(app2));
|
||||
|
||||
//make sure the right question was asked
|
||||
Assert.AreEqual(UiStringKey.TitleSyncQuestion, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void TestSaveAsWhenReadOnly()
|
||||
{
|
||||
Assert.Fail("TODO: Test ");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestSaveAsWhenSyncError()
|
||||
{
|
||||
Assert.Fail("TODO: Test ");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -119,4 +282,6 @@ namespace Kp2aUnitTests
|
||||
return sOutput.Text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user