More refactoring and introduction of further abstractions

Added further tests
Fixed test loading with keyfile only
This commit is contained in:
Philipp Crocoll 2013-06-25 21:27:41 +02:00
parent 0435ad54ca
commit 903de8368a
22 changed files with 456 additions and 56 deletions

View File

@ -1,5 +1,6 @@
using System;
using Android.Content;
using Android.OS;
using KeePassLib.Serialization;
namespace keepass2android
@ -49,5 +50,12 @@ namespace keepass2android
EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler,
Context ctx);
/// <summary>
/// Returns a Handler object which can run tasks on the UI thread
/// </summary>
Handler UiThreadHandler { get; }
IProgressDialog CreateProgressDialog(Context ctx);
}
}

View File

@ -0,0 +1,10 @@
namespace keepass2android
{
public interface IProgressDialog
{
void SetTitle(string title);
void SetMessage(string getResourceString);
void Dismiss();
void Show();
}
}

View File

@ -41,6 +41,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="IProgressDialog.cs" />
<Compile Include="PreferenceKey.cs" />
<Compile Include="UiStringKey.cs" />
<Compile Include="database\Database.cs" />

View File

@ -28,16 +28,17 @@ namespace keepass2android
public class ProgressTask {
private readonly Handler _handler;
private readonly RunnableOnFinish _task;
private readonly ProgressDialog _progressDialog;
private readonly IProgressDialog _progressDialog;
private readonly IKp2aApp _app;
private Thread _thread;
public ProgressTask(IKp2aApp app, Context ctx, RunnableOnFinish task, UiStringKey messageKey) {
_task = task;
_handler = new Handler();
_handler = app.UiThreadHandler;
_app = app;
// Show process dialog
_progressDialog = new ProgressDialog(ctx);
_progressDialog = app.CreateProgressDialog(ctx);
_progressDialog.SetTitle(_app.GetResourceString(UiStringKey.progress_title));
_progressDialog.SetMessage(_app.GetResourceString(messageKey));
@ -53,25 +54,37 @@ namespace keepass2android
// Start Thread to Run task
Thread t = new Thread(_task.Run);
t.Start();
_thread = new Thread(_task.Run);
_thread.Start();
}
public void JoinWorkerThread()
{
_thread.Join();
}
private class AfterTask : OnFinish {
readonly ProgressDialog _progressDialog;
readonly IProgressDialog _progressDialog;
public AfterTask (OnFinish finish, Handler handler, ProgressDialog pd): base(finish, handler)
public AfterTask (OnFinish finish, Handler handler, IProgressDialog pd): base(finish, handler)
{
_progressDialog = pd;
}
public override void Run() {
base.Run();
// Remove the progress dialog
Handler.Post(delegate {_progressDialog.Dismiss();});
if (Handler != null) //can be null in tests
{
// Remove the progress dialog
Handler.Post(delegate { _progressDialog.Dismiss(); });
}
else
{
_progressDialog.Dismiss();
}
}
}

View File

@ -26,7 +26,7 @@ namespace keepass2android
/// StatusLogger implementation which shows the progress in a progress dialog
/// </summary>
public class UpdateStatus: IStatusLogger {
private readonly ProgressDialog _progressDialog;
private readonly IProgressDialog _progressDialog;
readonly IKp2aApp _app;
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;
_progressDialog = pd;
_handler = handler;

View File

@ -19,6 +19,7 @@ using System;
using System.Collections.Generic;
using Android.Content;
using KeePassLib;
using KeePassLib.Keys;
using KeePassLib.Serialization;
namespace keepass2android
@ -95,21 +96,36 @@ namespace keepass2android
PwDatabase pwDatabase = new PwDatabase();
KeePassLib.Keys.CompositeKey key = new KeePassLib.Keys.CompositeKey();
key.AddUserKey(new KeePassLib.Keys.KcpPassword(password));
CompositeKey compositeKey = new CompositeKey();
compositeKey.AddUserKey(new KcpPassword(password));
if (!String.IsNullOrEmpty(keyfile))
{
try
{
key.AddUserKey(new KeePassLib.Keys.KcpKeyFile(keyfile));
compositeKey.AddUserKey(new KcpKeyFile(keyfile));
} catch (Exception)
{
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())
{

View File

@ -41,15 +41,17 @@ namespace keepass2android
public override void Run ()
{
try {
try
{
_app.GetDb().LoadData (_app, _ioc, _pass, _key, Status);
SaveFileData (_ioc, _key);
} 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));
}
catch (Exception e) {
Android.Util.Log.Debug("KP2ATest", "Exception: "+e.Message);
Finish(false, "An error occured: " + e.Message);
return;
}
@ -85,6 +87,7 @@ namespace keepass2android
return;
}
*/
Android.Util.Log.Debug("KP2ATest", "LoadDB OK");
Finish(true);
}

View File

@ -58,15 +58,14 @@ namespace keepass2android
}
public virtual void Run() {
if ( BaseOnFinish != null ) {
// Pass on result on call finish
BaseOnFinish.SetResult(Success, Message);
if (BaseOnFinish == null) return;
// Pass on result on call finish
BaseOnFinish.SetResult(Success, Message);
if ( Handler != null ) {
Handler.Post(BaseOnFinish.Run);
} else {
BaseOnFinish.Run();
}
if ( Handler != null ) {
Handler.Post(BaseOnFinish.Run);
} else {
BaseOnFinish.Run();
}
}

View File

@ -46,11 +46,16 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ProgressDialogStub.cs" />
<Compile Include="TestBase.cs" />
<Compile Include="TestDrawableFactory.cs" />
<Compile Include="TestCreateDb.cs" />
<Compile Include="MainActivity.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestKp2aApp.cs" />
<Compile Include="TestLoadDb.cs" />
<Compile Include="TestSaveDb.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\AboutResources.txt" />

View File

@ -1,5 +1,5 @@
using System;
using System.Collections.Generic;
using Android.App;
using Android.Content;
using Android.Runtime;
@ -18,7 +18,9 @@ namespace Kp2aUnitTests
{
TestRunner runner = new TestRunner();
// 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;
}
}

View 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; }
}
}

View File

@ -93,14 +93,14 @@ namespace Kp2aUnitTests
public partial class String
{
// aapt resource value: 0x7f040002
public const int ApplicationName = 2130968578;
// aapt resource value: 0x7f040001
public const int ApplicationName = 2130968577;
public const int Hello = 2130968577;
// aapt resource value: 0x7f040000
public const int Hello = 2130968576;
// aapt resource value: 0x7f040002
public const int library_name = 2130968578;
public const int library_name = 2130968576;
static String()
{

View 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;
}
}
}

View File

@ -1,9 +1,10 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Java.IO;
using KeePassLib;
using KeePassLib.Interfaces;
using KeePassLib.Keys;
using KeePassLib.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@ -12,15 +13,15 @@ using keepass2android;
namespace Kp2aUnitTests
{
[TestClass]
class TestCreateDb
class TestCreateDb: TestBase
{
[TestMethod]
public void CreateAndSaveLocal()
{
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();
File targetFile = new File(ioc.Path);
if (targetFile.Exists())
@ -45,6 +46,10 @@ namespace Kp2aUnitTests
PwDatabase loadedDb = new PwDatabase();
loadedDb.Open(ioc, new CompositeKey(), null);
//Check whether the databases are equal
AssertDatabasesAreEqual(loadedDb, app.GetDb().KpDatabase);
}
}

View File

@ -1,5 +1,6 @@
using System;
using Android.Content;
using Android.OS;
using KeePassLib.Serialization;
using keepass2android;
@ -50,5 +51,13 @@ namespace Kp2aUnitTests
{
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();
}
}
}

View 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", "", "");
}
}
}

View 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");
}
}
}

View File

@ -399,24 +399,24 @@ namespace keepass2android
EntryEditActivity act = this;
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,
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);
entry.Strings.Set(PwDefs.PasswordField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectPassword,
password));
MemUtil.ZeroByteArray(password);
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,
Util.getEditText(act, Resource.Id.entry_comment)));
Util.GetEditText(act, Resource.Id.entry_comment)));
// Validate expiry date
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
}
@ -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();
foreach(string strTag in vNewTags) entry.AddTag(strTag);
@ -850,15 +850,15 @@ namespace keepass2android
protected bool ValidateBeforeSaving() {
// Require title
String title = Util.getEditText(this, Resource.Id.entry_title);
String title = Util.GetEditText(this, Resource.Id.entry_title);
if ( title.Length == 0 ) {
Toast.MakeText(this, Resource.String.error_title_required, ToastLength.Long).Show();
return false;
}
// Validate password
String pass = Util.getEditText(this, Resource.Id.entry_password);
String conf = Util.getEditText(this, Resource.Id.entry_confpassword);
String pass = Util.GetEditText(this, Resource.Id.entry_password);
String conf = Util.GetEditText(this, Resource.Id.entry_confpassword);
if ( ! pass.Equals(conf) ) {
Toast.MakeText(this, Resource.String.error_pass_match, ToastLength.Long).Show();
return false;
@ -866,7 +866,7 @@ namespace keepass2android
// Validate expiry date
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();
return false;

View File

@ -517,7 +517,7 @@ namespace keepass2android
}
private String GetEditText(int resId) {
return Util.getEditText(this, resId);
return Util.GetEditText(this, resId);
}
private void SetEditText(int resId, String str) {

View File

@ -82,18 +82,18 @@ namespace keepass2android
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);
System.Diagnostics.Debug.Assert(te != null);
if (te != null) {
return te.Text.ToString();
return te.Text;
} else {
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);
System.Diagnostics.Debug.Assert(te != null);

View File

@ -18,6 +18,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using KeePassLib.Serialization;
using Android.Preferences;
@ -177,9 +178,51 @@ 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()
{
if (_db != null)
{

View File

@ -81,7 +81,8 @@ namespace MonoDroidUnitTesting {
ISharedPreferencesEditor e = GetPreferences().Edit();
e.PutString(ACTIVITY_PREFS_NAME, typeof(TestClassResultActivity).Name);
e.PutString(INTENT_PARAM_NAME, this.m_testClass.Class.AssemblyQualifiedName);
if (m_testClass != null)
e.PutString(INTENT_PARAM_NAME, this.m_testClass.Class.AssemblyQualifiedName);
e.Commit();
}