mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-11-22 17:22:17 -05:00
More refactoring and introduction of further abstractions
Added further tests Fixed test loading with keyfile only
This commit is contained in:
parent
0435ad54ca
commit
903de8368a
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
|
using Android.OS;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
|
|
||||||
namespace keepass2android
|
namespace keepass2android
|
||||||
@ -49,5 +50,12 @@ namespace keepass2android
|
|||||||
EventHandler<DialogClickEventArgs> noHandler,
|
EventHandler<DialogClickEventArgs> noHandler,
|
||||||
EventHandler<DialogClickEventArgs> cancelHandler,
|
EventHandler<DialogClickEventArgs> cancelHandler,
|
||||||
Context ctx);
|
Context ctx);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a Handler object which can run tasks on the UI thread
|
||||||
|
/// </summary>
|
||||||
|
Handler UiThreadHandler { get; }
|
||||||
|
|
||||||
|
IProgressDialog CreateProgressDialog(Context ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
10
src/Kp2aBusinessLogic/IProgressDialog.cs
Normal file
10
src/Kp2aBusinessLogic/IProgressDialog.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace keepass2android
|
||||||
|
{
|
||||||
|
public interface IProgressDialog
|
||||||
|
{
|
||||||
|
void SetTitle(string title);
|
||||||
|
void SetMessage(string getResourceString);
|
||||||
|
void Dismiss();
|
||||||
|
void Show();
|
||||||
|
}
|
||||||
|
}
|
@ -41,6 +41,7 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="IProgressDialog.cs" />
|
||||||
<Compile Include="PreferenceKey.cs" />
|
<Compile Include="PreferenceKey.cs" />
|
||||||
<Compile Include="UiStringKey.cs" />
|
<Compile Include="UiStringKey.cs" />
|
||||||
<Compile Include="database\Database.cs" />
|
<Compile Include="database\Database.cs" />
|
||||||
|
@ -28,16 +28,17 @@ namespace keepass2android
|
|||||||
public class ProgressTask {
|
public class ProgressTask {
|
||||||
private readonly Handler _handler;
|
private readonly Handler _handler;
|
||||||
private readonly RunnableOnFinish _task;
|
private readonly RunnableOnFinish _task;
|
||||||
private readonly ProgressDialog _progressDialog;
|
private readonly IProgressDialog _progressDialog;
|
||||||
private readonly IKp2aApp _app;
|
private readonly IKp2aApp _app;
|
||||||
|
private Thread _thread;
|
||||||
|
|
||||||
public ProgressTask(IKp2aApp app, Context ctx, RunnableOnFinish task, UiStringKey messageKey) {
|
public ProgressTask(IKp2aApp app, Context ctx, RunnableOnFinish task, UiStringKey messageKey) {
|
||||||
_task = task;
|
_task = task;
|
||||||
_handler = new Handler();
|
_handler = app.UiThreadHandler;
|
||||||
_app = app;
|
_app = app;
|
||||||
|
|
||||||
// Show process dialog
|
// Show process dialog
|
||||||
_progressDialog = new ProgressDialog(ctx);
|
_progressDialog = app.CreateProgressDialog(ctx);
|
||||||
_progressDialog.SetTitle(_app.GetResourceString(UiStringKey.progress_title));
|
_progressDialog.SetTitle(_app.GetResourceString(UiStringKey.progress_title));
|
||||||
_progressDialog.SetMessage(_app.GetResourceString(messageKey));
|
_progressDialog.SetMessage(_app.GetResourceString(messageKey));
|
||||||
|
|
||||||
@ -53,15 +54,20 @@ namespace keepass2android
|
|||||||
|
|
||||||
|
|
||||||
// Start Thread to Run task
|
// Start Thread to Run task
|
||||||
Thread t = new Thread(_task.Run);
|
_thread = new Thread(_task.Run);
|
||||||
t.Start();
|
_thread.Start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterTask : OnFinish {
|
public void JoinWorkerThread()
|
||||||
readonly ProgressDialog _progressDialog;
|
{
|
||||||
|
_thread.Join();
|
||||||
|
}
|
||||||
|
|
||||||
public AfterTask (OnFinish finish, Handler handler, ProgressDialog pd): base(finish, handler)
|
private class AfterTask : OnFinish {
|
||||||
|
readonly IProgressDialog _progressDialog;
|
||||||
|
|
||||||
|
public AfterTask (OnFinish finish, Handler handler, IProgressDialog pd): base(finish, handler)
|
||||||
{
|
{
|
||||||
_progressDialog = pd;
|
_progressDialog = pd;
|
||||||
}
|
}
|
||||||
@ -69,8 +75,15 @@ namespace keepass2android
|
|||||||
public override void Run() {
|
public override void Run() {
|
||||||
base.Run();
|
base.Run();
|
||||||
|
|
||||||
|
if (Handler != null) //can be null in tests
|
||||||
|
{
|
||||||
// Remove the progress dialog
|
// Remove the progress dialog
|
||||||
Handler.Post(delegate { _progressDialog.Dismiss(); });
|
Handler.Post(delegate { _progressDialog.Dismiss(); });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_progressDialog.Dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ namespace keepass2android
|
|||||||
/// StatusLogger implementation which shows the progress in a progress dialog
|
/// StatusLogger implementation which shows the progress in a progress dialog
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UpdateStatus: IStatusLogger {
|
public class UpdateStatus: IStatusLogger {
|
||||||
private readonly ProgressDialog _progressDialog;
|
private readonly IProgressDialog _progressDialog;
|
||||||
readonly IKp2aApp _app;
|
readonly IKp2aApp _app;
|
||||||
private readonly Handler _handler;
|
private readonly Handler _handler;
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateStatus(IKp2aApp app, Handler handler, ProgressDialog pd) {
|
public UpdateStatus(IKp2aApp app, Handler handler, IProgressDialog pd) {
|
||||||
_app = app;
|
_app = app;
|
||||||
_progressDialog = pd;
|
_progressDialog = pd;
|
||||||
_handler = handler;
|
_handler = handler;
|
||||||
|
@ -19,6 +19,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using KeePassLib;
|
using KeePassLib;
|
||||||
|
using KeePassLib.Keys;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
|
|
||||||
namespace keepass2android
|
namespace keepass2android
|
||||||
@ -95,21 +96,36 @@ namespace keepass2android
|
|||||||
|
|
||||||
PwDatabase pwDatabase = new PwDatabase();
|
PwDatabase pwDatabase = new PwDatabase();
|
||||||
|
|
||||||
KeePassLib.Keys.CompositeKey key = new KeePassLib.Keys.CompositeKey();
|
CompositeKey compositeKey = new CompositeKey();
|
||||||
key.AddUserKey(new KeePassLib.Keys.KcpPassword(password));
|
compositeKey.AddUserKey(new KcpPassword(password));
|
||||||
if (!String.IsNullOrEmpty(keyfile))
|
if (!String.IsNullOrEmpty(keyfile))
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
key.AddUserKey(new KeePassLib.Keys.KcpKeyFile(keyfile));
|
compositeKey.AddUserKey(new KcpKeyFile(keyfile));
|
||||||
} catch (Exception)
|
} catch (Exception)
|
||||||
{
|
{
|
||||||
throw new KeyFileException();
|
throw new KeyFileException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pwDatabase.Open(iocInfo, key, status);
|
try
|
||||||
|
{
|
||||||
|
pwDatabase.Open(iocInfo, compositeKey, status);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
if ((password == "") && (keyfile != null))
|
||||||
|
{
|
||||||
|
//if we don't get a password, we don't know whether this means "empty password" or "no password"
|
||||||
|
//retry without password:
|
||||||
|
compositeKey.RemoveUserKey(compositeKey.GetUserKey(typeof (KcpPassword)));
|
||||||
|
pwDatabase.Open(iocInfo, compositeKey, status);
|
||||||
|
}
|
||||||
|
else throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (iocInfo.IsLocalFile())
|
if (iocInfo.IsLocalFile())
|
||||||
{
|
{
|
||||||
|
@ -41,15 +41,17 @@ namespace keepass2android
|
|||||||
|
|
||||||
public override void Run ()
|
public override void Run ()
|
||||||
{
|
{
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
_app.GetDb().LoadData (_app, _ioc, _pass, _key, Status);
|
_app.GetDb().LoadData (_app, _ioc, _pass, _key, Status);
|
||||||
|
|
||||||
SaveFileData (_ioc, _key);
|
SaveFileData (_ioc, _key);
|
||||||
|
|
||||||
} catch (KeyFileException) {
|
} catch (KeyFileException) {
|
||||||
|
Android.Util.Log.Debug("KP2ATest", "KeyFileException");
|
||||||
Finish(false, /*TODO Localize: use Keepass error text KPRes.KeyFileError (including "or invalid format")*/ _app.GetResourceString(UiStringKey.keyfile_does_not_exist));
|
Finish(false, /*TODO Localize: use Keepass error text KPRes.KeyFileError (including "or invalid format")*/ _app.GetResourceString(UiStringKey.keyfile_does_not_exist));
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
Android.Util.Log.Debug("KP2ATest", "Exception: "+e.Message);
|
||||||
Finish(false, "An error occured: " + e.Message);
|
Finish(false, "An error occured: " + e.Message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -85,6 +87,7 @@ namespace keepass2android
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
Android.Util.Log.Debug("KP2ATest", "LoadDB OK");
|
||||||
Finish(true);
|
Finish(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Run() {
|
public virtual void Run() {
|
||||||
if ( BaseOnFinish != null ) {
|
if (BaseOnFinish == null) return;
|
||||||
// Pass on result on call finish
|
// Pass on result on call finish
|
||||||
BaseOnFinish.SetResult(Success, Message);
|
BaseOnFinish.SetResult(Success, Message);
|
||||||
|
|
||||||
@ -68,7 +68,6 @@ namespace keepass2android
|
|||||||
BaseOnFinish.Run();
|
BaseOnFinish.Run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected void DisplayMessage(Context ctx) {
|
protected void DisplayMessage(Context ctx) {
|
||||||
DisplayMessage(ctx, Message);
|
DisplayMessage(ctx, Message);
|
||||||
|
@ -46,11 +46,16 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="ProgressDialogStub.cs" />
|
||||||
|
<Compile Include="TestBase.cs" />
|
||||||
<Compile Include="TestDrawableFactory.cs" />
|
<Compile Include="TestDrawableFactory.cs" />
|
||||||
<Compile Include="TestCreateDb.cs" />
|
<Compile Include="TestCreateDb.cs" />
|
||||||
<Compile Include="MainActivity.cs" />
|
<Compile Include="MainActivity.cs" />
|
||||||
<Compile Include="Resources\Resource.Designer.cs" />
|
<Compile Include="Resources\Resource.Designer.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="TestKp2aApp.cs" />
|
||||||
|
<Compile Include="TestLoadDb.cs" />
|
||||||
|
<Compile Include="TestSaveDb.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Resources\AboutResources.txt" />
|
<None Include="Resources\AboutResources.txt" />
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.Runtime;
|
using Android.Runtime;
|
||||||
@ -18,7 +18,9 @@ namespace Kp2aUnitTests
|
|||||||
{
|
{
|
||||||
TestRunner runner = new TestRunner();
|
TestRunner runner = new TestRunner();
|
||||||
// Run all tests from this assembly
|
// Run all tests from this assembly
|
||||||
runner.AddTests(Assembly.GetExecutingAssembly());
|
//runner.AddTests(Assembly.GetExecutingAssembly());
|
||||||
|
runner.AddTests(new List<Type> { typeof(TestLoadDb)});
|
||||||
|
//runner.AddTests(typeof(TestLoadDb).GetMethod("TestLoadWithPasswordOnly"));}}
|
||||||
return runner;
|
return runner;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
src/Kp2aUnitTests/ProgressDialogStub.cs
Normal file
34
src/Kp2aUnitTests/ProgressDialogStub.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using keepass2android;
|
||||||
|
|
||||||
|
namespace Kp2aUnitTests
|
||||||
|
{
|
||||||
|
class ProgressDialogStub : IProgressDialog
|
||||||
|
{
|
||||||
|
public void SetTitle(string title)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMessage(string getResourceString)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dismiss()
|
||||||
|
{
|
||||||
|
Dismissed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Show()
|
||||||
|
{
|
||||||
|
Showed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool Showed { get; set; }
|
||||||
|
|
||||||
|
public bool Dismissed { get; set; }
|
||||||
|
}
|
||||||
|
}
|
10
src/Kp2aUnitTests/Resources/Resource.Designer.cs
generated
10
src/Kp2aUnitTests/Resources/Resource.Designer.cs
generated
@ -93,14 +93,14 @@ namespace Kp2aUnitTests
|
|||||||
public partial class String
|
public partial class String
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// aapt resource value: 0x7f040002
|
||||||
|
public const int ApplicationName = 2130968578;
|
||||||
|
|
||||||
// aapt resource value: 0x7f040001
|
// aapt resource value: 0x7f040001
|
||||||
public const int ApplicationName = 2130968577;
|
public const int Hello = 2130968577;
|
||||||
|
|
||||||
// aapt resource value: 0x7f040000
|
// aapt resource value: 0x7f040000
|
||||||
public const int Hello = 2130968576;
|
public const int library_name = 2130968576;
|
||||||
|
|
||||||
// aapt resource value: 0x7f040002
|
|
||||||
public const int library_name = 2130968578;
|
|
||||||
|
|
||||||
static String()
|
static String()
|
||||||
{
|
{
|
||||||
|
131
src/Kp2aUnitTests/TestBase.cs
Normal file
131
src/Kp2aUnitTests/TestBase.cs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Android.App;
|
||||||
|
using Android.OS;
|
||||||
|
using KeePassLib;
|
||||||
|
using KeePassLib.Interfaces;
|
||||||
|
using KeePassLib.Keys;
|
||||||
|
using KeePassLib.Security;
|
||||||
|
using KeePassLib.Serialization;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using keepass2android;
|
||||||
|
|
||||||
|
namespace Kp2aUnitTests
|
||||||
|
{
|
||||||
|
internal class TestBase
|
||||||
|
{
|
||||||
|
private PwGroup mailGroup;
|
||||||
|
private PwEntry mailEntry;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares the two databases. uses Asserts
|
||||||
|
/// TODO: implement this with many more checks or use serialization?
|
||||||
|
/// </summary>
|
||||||
|
protected void AssertDatabasesAreEqual(PwDatabase db1, PwDatabase db2)
|
||||||
|
{
|
||||||
|
db1.RootGroup.GetObjects(true, null)
|
||||||
|
.ForEach(
|
||||||
|
item =>
|
||||||
|
{
|
||||||
|
IStructureItem foundItem = db2.RootGroup.FindObject(item.Uuid, true, null);
|
||||||
|
Assert.IsNotNull(foundItem);
|
||||||
|
Assert.IsTrue(item.ParentGroup.Uuid.EqualsValue(foundItem.ParentGroup.Uuid));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Assert.AreEqual(db1.RootGroup.GetObjects(true,null).Count(),db2.RootGroup.GetObjects(true,null).Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static string DefaultDirectory
|
||||||
|
{
|
||||||
|
get { return "/mnt/sdcard/kp2atest/"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static string DefaultFilename
|
||||||
|
{
|
||||||
|
get { return "/mnt/sdcard/kp2atest/savetest.kdbx"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string DefaultKeyfile
|
||||||
|
{
|
||||||
|
get { return DefaultDirectory + "keyfile.txt"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string DefaultPassword
|
||||||
|
{
|
||||||
|
get { return "secretpassword!"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IKp2aApp LoadDatabase(string defaultFilename, string password, string keyfile)
|
||||||
|
{
|
||||||
|
IKp2aApp app = new TestKp2aApp();
|
||||||
|
Handler handler = new Handler(Looper.MainLooper);
|
||||||
|
bool loadSuccesful = false;
|
||||||
|
LoadDb task = new LoadDb(app, new IOConnectionInfo() { Path = defaultFilename }, password, keyfile, new ActionOnFinish((success, message) =>
|
||||||
|
{
|
||||||
|
loadSuccesful = success; if (!success)
|
||||||
|
Assert.Fail(message);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
ProgressTask pt = new ProgressTask(app, Application.Context, task, UiStringKey.loading_database);
|
||||||
|
pt.Run();
|
||||||
|
Assert.IsTrue(loadSuccesful);
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SaveDatabase(IKp2aApp app)
|
||||||
|
{
|
||||||
|
bool saveSuccesful = false;
|
||||||
|
SaveDb save = new SaveDb(Application.Context, app.GetDb(), new ActionOnFinish((success, message) =>
|
||||||
|
{
|
||||||
|
saveSuccesful = success; if (!success)
|
||||||
|
Assert.Fail(message);
|
||||||
|
}), false);
|
||||||
|
save.Run();
|
||||||
|
|
||||||
|
Assert.IsTrue(saveSuccesful);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IKp2aApp SetupAppWithDefaultDatabase()
|
||||||
|
{
|
||||||
|
IKp2aApp app = new TestKp2aApp();
|
||||||
|
IOConnectionInfo ioc = new IOConnectionInfo {Path = DefaultFilename};
|
||||||
|
Database db = app.CreateNewDatabase();
|
||||||
|
|
||||||
|
db.KpDatabase = new PwDatabase();
|
||||||
|
//Key will be changed/created immediately after creation:
|
||||||
|
CompositeKey tempKey = new CompositeKey();
|
||||||
|
db.KpDatabase.New(ioc, tempKey);
|
||||||
|
|
||||||
|
|
||||||
|
db.KpDatabase.KeyEncryptionRounds = 3;
|
||||||
|
db.KpDatabase.Name = "Keepass2Android Testing Password Database";
|
||||||
|
|
||||||
|
|
||||||
|
// Set Database state
|
||||||
|
db.Root = db.KpDatabase.RootGroup;
|
||||||
|
db.Ioc = ioc;
|
||||||
|
db.Loaded = true;
|
||||||
|
db.SearchHelper = new SearchDbHelper(app);
|
||||||
|
|
||||||
|
// Add a couple default groups
|
||||||
|
db.KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "Internet", PwIcon.Key), true);
|
||||||
|
|
||||||
|
mailGroup = new PwGroup(true, true, "eMail", PwIcon.UserCommunication);
|
||||||
|
db.KpDatabase.RootGroup.AddGroup(mailGroup, true);
|
||||||
|
|
||||||
|
mailGroup.AddGroup(new PwGroup(true, true, "business", PwIcon.BlackBerry), true );
|
||||||
|
|
||||||
|
mailEntry = new PwEntry(true, true);
|
||||||
|
mailEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(
|
||||||
|
true, "me@there.com"));
|
||||||
|
mailEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(
|
||||||
|
true, "me@there.com Entry"));
|
||||||
|
mailGroup.AddEntry(mailEntry , true);
|
||||||
|
|
||||||
|
db.KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "eMail2", PwIcon.UserCommunication), true);
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Java.IO;
|
using Java.IO;
|
||||||
using KeePassLib;
|
using KeePassLib;
|
||||||
|
using KeePassLib.Interfaces;
|
||||||
using KeePassLib.Keys;
|
using KeePassLib.Keys;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
@ -12,15 +13,15 @@ using keepass2android;
|
|||||||
namespace Kp2aUnitTests
|
namespace Kp2aUnitTests
|
||||||
{
|
{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
class TestCreateDb
|
class TestCreateDb: TestBase
|
||||||
{
|
{
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void CreateAndSaveLocal()
|
public void CreateAndSaveLocal()
|
||||||
{
|
{
|
||||||
IKp2aApp app = new TestKp2aApp();
|
IKp2aApp app = new TestKp2aApp();
|
||||||
IOConnectionInfo ioc = new IOConnectionInfo {Path = "/mnt/sdcard/kp2atest/savetest.kdbx"};
|
IOConnectionInfo ioc = new IOConnectionInfo {Path = DefaultFilename};
|
||||||
|
|
||||||
File outputDir = new File("/mnt/sdcard/kp2atest/");
|
File outputDir = new File(DefaultDirectory);
|
||||||
outputDir.Mkdirs();
|
outputDir.Mkdirs();
|
||||||
File targetFile = new File(ioc.Path);
|
File targetFile = new File(ioc.Path);
|
||||||
if (targetFile.Exists())
|
if (targetFile.Exists())
|
||||||
@ -45,6 +46,10 @@ namespace Kp2aUnitTests
|
|||||||
PwDatabase loadedDb = new PwDatabase();
|
PwDatabase loadedDb = new PwDatabase();
|
||||||
loadedDb.Open(ioc, new CompositeKey(), null);
|
loadedDb.Open(ioc, new CompositeKey(), null);
|
||||||
|
|
||||||
|
//Check whether the databases are equal
|
||||||
|
AssertDatabasesAreEqual(loadedDb, app.GetDb().KpDatabase);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
|
using Android.OS;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
using keepass2android;
|
using keepass2android;
|
||||||
|
|
||||||
@ -50,5 +51,13 @@ namespace Kp2aUnitTests
|
|||||||
{
|
{
|
||||||
yesHandler(null, null);
|
yesHandler(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Handler UiThreadHandler {
|
||||||
|
get { return null; } //ensure everything runs in the same thread. Otherwise the OnFinish-callback would run after the test has already finished (with failure)
|
||||||
|
}
|
||||||
|
public IProgressDialog CreateProgressDialog(Context ctx)
|
||||||
|
{
|
||||||
|
return new ProgressDialogStub();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
78
src/Kp2aUnitTests/TestLoadDb.cs
Normal file
78
src/Kp2aUnitTests/TestLoadDb.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using Android.App;
|
||||||
|
using Android.OS;
|
||||||
|
using KeePassLib.Serialization;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using keepass2android;
|
||||||
|
|
||||||
|
namespace Kp2aUnitTests
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
internal class TestLoadDb : TestBase
|
||||||
|
{
|
||||||
|
private string TestDbDirectory
|
||||||
|
{
|
||||||
|
get { return DefaultDirectory + "savedWithDesktop/"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void RunLoadTest(string filenameWithoutDir, string password, string keyfile)
|
||||||
|
{
|
||||||
|
Android.Util.Log.Debug("KP2ATest", "Starting for " + filenameWithoutDir+" with " + password+"/"+keyfile);
|
||||||
|
|
||||||
|
IKp2aApp app = new TestKp2aApp();
|
||||||
|
app.CreateNewDatabase();
|
||||||
|
bool loadSuccesful = false;
|
||||||
|
LoadDb task = new LoadDb(app, new IOConnectionInfo() { Path = TestDbDirectory+filenameWithoutDir },
|
||||||
|
password, keyfile, new ActionOnFinish((success, message) =>
|
||||||
|
{
|
||||||
|
if (!success)
|
||||||
|
Android.Util.Log.Debug("KP2ATest", "error loading db: " + message);
|
||||||
|
loadSuccesful = success;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
ProgressTask pt = new ProgressTask(app, Application.Context, task, UiStringKey.loading_database);
|
||||||
|
Android.Util.Log.Debug("KP2ATest", "Running ProgressTask");
|
||||||
|
pt.Run();
|
||||||
|
pt.JoinWorkerThread();
|
||||||
|
Android.Util.Log.Debug("KP2ATest", "PT.run finished");
|
||||||
|
Assert.IsTrue(loadSuccesful, "didn't succesfully load database :-(");
|
||||||
|
|
||||||
|
Assert.AreEqual(6,app.GetDb().KpDatabase.RootGroup.Groups.Count());
|
||||||
|
Assert.AreEqual(2,app.GetDb().KpDatabase.RootGroup.Entries.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestLoadWithPasswordOnly()
|
||||||
|
{
|
||||||
|
RunLoadTest("passwordonly.kdbx", DefaultPassword, "");
|
||||||
|
}
|
||||||
|
[TestMethod]
|
||||||
|
public void TestLoadWithKeyfileOnly()
|
||||||
|
{
|
||||||
|
RunLoadTest("keyfileonly.kdbx", "", TestDbDirectory + "keyfile.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestLoadWithPasswordAndKeyfile()
|
||||||
|
{
|
||||||
|
RunLoadTest("PasswordAndKeyfile.kdbx", DefaultPassword, TestDbDirectory + "keyfile.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestLoadWithEmptyPassword()
|
||||||
|
{
|
||||||
|
RunLoadTest("EmptyPasswordAndKeyfile.kdbx", "", TestDbDirectory + "keyfile.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestLoadWithEmptyPasswordOnly()
|
||||||
|
{
|
||||||
|
RunLoadTest("EmptyPassword.kdbx", "", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
42
src/Kp2aUnitTests/TestSaveDb.cs
Normal file
42
src/Kp2aUnitTests/TestSaveDb.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Android.App;
|
||||||
|
using Android.OS;
|
||||||
|
using KeePassLib;
|
||||||
|
using KeePassLib.Serialization;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using keepass2android;
|
||||||
|
|
||||||
|
namespace Kp2aUnitTests
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
class TestSaveDb: TestBase
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void TestLoadEditSave()
|
||||||
|
{
|
||||||
|
//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);
|
||||||
|
//modify the database by adding a group:
|
||||||
|
app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true);
|
||||||
|
//save the database again:
|
||||||
|
// -> Ensure Assert below works! SaveDatabase(app, DefaultFilename);
|
||||||
|
|
||||||
|
//load database to a new app instance:
|
||||||
|
IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
|
||||||
|
|
||||||
|
//ensure the change was saved:
|
||||||
|
AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestLoadAndSave_TestIdenticalFiles()
|
||||||
|
{
|
||||||
|
Assert.Fail("Todo: implement");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -399,24 +399,24 @@ namespace keepass2android
|
|||||||
EntryEditActivity act = this;
|
EntryEditActivity act = this;
|
||||||
|
|
||||||
entry.Strings.Set(PwDefs.TitleField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectTitle,
|
entry.Strings.Set(PwDefs.TitleField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectTitle,
|
||||||
Util.getEditText(act, Resource.Id.entry_title)));
|
Util.GetEditText(act, Resource.Id.entry_title)));
|
||||||
entry.Strings.Set(PwDefs.UserNameField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectUserName,
|
entry.Strings.Set(PwDefs.UserNameField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectUserName,
|
||||||
Util.getEditText(act, Resource.Id.entry_user_name)));
|
Util.GetEditText(act, Resource.Id.entry_user_name)));
|
||||||
|
|
||||||
String pass = Util.getEditText(act, Resource.Id.entry_password);
|
String pass = Util.GetEditText(act, Resource.Id.entry_password);
|
||||||
byte[] password = StrUtil.Utf8.GetBytes(pass);
|
byte[] password = StrUtil.Utf8.GetBytes(pass);
|
||||||
entry.Strings.Set(PwDefs.PasswordField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectPassword,
|
entry.Strings.Set(PwDefs.PasswordField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectPassword,
|
||||||
password));
|
password));
|
||||||
MemUtil.ZeroByteArray(password);
|
MemUtil.ZeroByteArray(password);
|
||||||
|
|
||||||
entry.Strings.Set(PwDefs.UrlField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectUrl,
|
entry.Strings.Set(PwDefs.UrlField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectUrl,
|
||||||
Util.getEditText(act, Resource.Id.entry_url)));
|
Util.GetEditText(act, Resource.Id.entry_url)));
|
||||||
entry.Strings.Set(PwDefs.NotesField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectNotes,
|
entry.Strings.Set(PwDefs.NotesField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectNotes,
|
||||||
Util.getEditText(act, Resource.Id.entry_comment)));
|
Util.GetEditText(act, Resource.Id.entry_comment)));
|
||||||
|
|
||||||
// Validate expiry date
|
// Validate expiry date
|
||||||
DateTime newExpiry = new DateTime();
|
DateTime newExpiry = new DateTime();
|
||||||
if ((State.Entry.Expires) && (!DateTime.TryParse( Util.getEditText(this,Resource.Id.entry_expires), out newExpiry)))
|
if ((State.Entry.Expires) && (!DateTime.TryParse( Util.GetEditText(this,Resource.Id.entry_expires), out newExpiry)))
|
||||||
{
|
{
|
||||||
//ignore here
|
//ignore here
|
||||||
}
|
}
|
||||||
@ -454,9 +454,9 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
entry.OverrideUrl = Util.getEditText(this,Resource.Id.entry_override_url);
|
entry.OverrideUrl = Util.GetEditText(this,Resource.Id.entry_override_url);
|
||||||
|
|
||||||
List<string> vNewTags = StrUtil.StringToTags(Util.getEditText(this,Resource.Id.entry_tags));
|
List<string> vNewTags = StrUtil.StringToTags(Util.GetEditText(this,Resource.Id.entry_tags));
|
||||||
entry.Tags.Clear();
|
entry.Tags.Clear();
|
||||||
foreach(string strTag in vNewTags) entry.AddTag(strTag);
|
foreach(string strTag in vNewTags) entry.AddTag(strTag);
|
||||||
|
|
||||||
@ -850,15 +850,15 @@ namespace keepass2android
|
|||||||
|
|
||||||
protected bool ValidateBeforeSaving() {
|
protected bool ValidateBeforeSaving() {
|
||||||
// Require title
|
// Require title
|
||||||
String title = Util.getEditText(this, Resource.Id.entry_title);
|
String title = Util.GetEditText(this, Resource.Id.entry_title);
|
||||||
if ( title.Length == 0 ) {
|
if ( title.Length == 0 ) {
|
||||||
Toast.MakeText(this, Resource.String.error_title_required, ToastLength.Long).Show();
|
Toast.MakeText(this, Resource.String.error_title_required, ToastLength.Long).Show();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate password
|
// Validate password
|
||||||
String pass = Util.getEditText(this, Resource.Id.entry_password);
|
String pass = Util.GetEditText(this, Resource.Id.entry_password);
|
||||||
String conf = Util.getEditText(this, Resource.Id.entry_confpassword);
|
String conf = Util.GetEditText(this, Resource.Id.entry_confpassword);
|
||||||
if ( ! pass.Equals(conf) ) {
|
if ( ! pass.Equals(conf) ) {
|
||||||
Toast.MakeText(this, Resource.String.error_pass_match, ToastLength.Long).Show();
|
Toast.MakeText(this, Resource.String.error_pass_match, ToastLength.Long).Show();
|
||||||
return false;
|
return false;
|
||||||
@ -866,7 +866,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
// Validate expiry date
|
// Validate expiry date
|
||||||
DateTime newExpiry = new DateTime();
|
DateTime newExpiry = new DateTime();
|
||||||
if ((State.Entry.Expires) && (!DateTime.TryParse( Util.getEditText(this,Resource.Id.entry_expires), out newExpiry)))
|
if ((State.Entry.Expires) && (!DateTime.TryParse( Util.GetEditText(this,Resource.Id.entry_expires), out newExpiry)))
|
||||||
{
|
{
|
||||||
Toast.MakeText(this, Resource.String.error_invalid_expiry_date, ToastLength.Long).Show();
|
Toast.MakeText(this, Resource.String.error_invalid_expiry_date, ToastLength.Long).Show();
|
||||||
return false;
|
return false;
|
||||||
|
@ -517,7 +517,7 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String GetEditText(int resId) {
|
private String GetEditText(int resId) {
|
||||||
return Util.getEditText(this, resId);
|
return Util.GetEditText(this, resId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetEditText(int resId, String str) {
|
private void SetEditText(int resId, String str) {
|
||||||
|
@ -82,18 +82,18 @@ namespace keepass2android
|
|||||||
gotoUrl(context, donateUrl);
|
gotoUrl(context, donateUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getEditText(Activity act, int resId) {
|
public static String GetEditText(Activity act, int resId) {
|
||||||
TextView te = (TextView) act.FindViewById(resId);
|
TextView te = (TextView) act.FindViewById(resId);
|
||||||
System.Diagnostics.Debug.Assert(te != null);
|
System.Diagnostics.Debug.Assert(te != null);
|
||||||
|
|
||||||
if (te != null) {
|
if (te != null) {
|
||||||
return te.Text.ToString();
|
return te.Text;
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setEditText(Activity act, int resId, String str) {
|
public static void SetEditText(Activity act, int resId, String str) {
|
||||||
TextView te = (TextView) act.FindViewById(resId);
|
TextView te = (TextView) act.FindViewById(resId);
|
||||||
System.Diagnostics.Debug.Assert(te != null);
|
System.Diagnostics.Debug.Assert(te != null);
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||||||
using System;
|
using System;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
|
using Android.OS;
|
||||||
using Android.Runtime;
|
using Android.Runtime;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
using Android.Preferences;
|
using Android.Preferences;
|
||||||
@ -177,6 +178,48 @@ namespace keepass2android
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Handler UiThreadHandler
|
||||||
|
{
|
||||||
|
get { return new Handler(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Simple wrapper around ProgressDialog implementing IProgressDialog
|
||||||
|
/// </summary>
|
||||||
|
private class RealProgressDialog : IProgressDialog
|
||||||
|
{
|
||||||
|
private readonly ProgressDialog _pd;
|
||||||
|
|
||||||
|
public RealProgressDialog(Context ctx)
|
||||||
|
{
|
||||||
|
this._pd = new ProgressDialog(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTitle(string title)
|
||||||
|
{
|
||||||
|
_pd.SetTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMessage(string message)
|
||||||
|
{
|
||||||
|
_pd.SetMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dismiss()
|
||||||
|
{
|
||||||
|
_pd.Dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Show()
|
||||||
|
{
|
||||||
|
_pd.Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IProgressDialog CreateProgressDialog(Context ctx)
|
||||||
|
{
|
||||||
|
return new RealProgressDialog(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
internal void OnTerminate()
|
internal void OnTerminate()
|
||||||
|
@ -81,6 +81,7 @@ namespace MonoDroidUnitTesting {
|
|||||||
|
|
||||||
ISharedPreferencesEditor e = GetPreferences().Edit();
|
ISharedPreferencesEditor e = GetPreferences().Edit();
|
||||||
e.PutString(ACTIVITY_PREFS_NAME, typeof(TestClassResultActivity).Name);
|
e.PutString(ACTIVITY_PREFS_NAME, typeof(TestClassResultActivity).Name);
|
||||||
|
if (m_testClass != null)
|
||||||
e.PutString(INTENT_PARAM_NAME, this.m_testClass.Class.AssemblyQualifiedName);
|
e.PutString(INTENT_PARAM_NAME, this.m_testClass.Class.AssemblyQualifiedName);
|
||||||
e.Commit();
|
e.Commit();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user