Merge branch 'mainline' into remove-old-msgs-beyond-storage-pref

This commit is contained in:
Chris Heywood 2020-04-30 18:08:19 +10:00
commit 4ff783b231
265 changed files with 43565 additions and 27582 deletions

View file

@ -40,15 +40,9 @@ class Accounts.ManagerTest : TestCase {
// engine without creating all of these dirs.
this.tmp = GLib.File.new_for_path(
GLib.DirUtils.make_tmp("geary-engine-test-XXXXXX")
GLib.DirUtils.make_tmp("accounts-manager-test-XXXXXX")
);
GLib.File config = this.tmp.get_child("config");
config.make_directory();
GLib.File data = this.tmp.get_child("data");
data.make_directory();
this.primary_mailbox = new Geary.RFC822.MailboxAddress(
null, "test1@example.com"
);
@ -60,7 +54,7 @@ class Accounts.ManagerTest : TestCase {
this.mediator,
this.primary_mailbox
);
this.test = new Manager(this.mediator, config, data);
this.test = new Manager(this.mediator, this.tmp, this.tmp);
}
public override void tear_down() throws GLib.Error {
@ -82,7 +76,7 @@ class Accounts.ManagerTest : TestCase {
this.test.create_account.begin(
account, new GLib.Cancellable(),
(obj, res) => { async_complete(res); }
this.async_completion
);
this.test.create_account.end(async_result());
@ -95,7 +89,7 @@ class Accounts.ManagerTest : TestCase {
public void create_orphan_account() throws GLib.Error {
this.test.new_orphan_account.begin(
Geary.ServiceProvider.OTHER, this.primary_mailbox, null,
(obj, res) => { async_complete(res); }
this.async_completion
);
Geary.AccountInformation account1 =
this.test.new_orphan_account.end(async_result());
@ -103,13 +97,13 @@ class Accounts.ManagerTest : TestCase {
this.test.create_account.begin(
account1, new GLib.Cancellable(),
(obj, res) => { async_complete(res); }
this.async_completion
);
this.test.create_account.end(async_result());
this.test.new_orphan_account.begin(
Geary.ServiceProvider.OTHER, this.primary_mailbox, null,
(obj, res) => { async_complete(res); }
this.async_completion
);
Geary.AccountInformation account2 =
this.test.new_orphan_account.end(async_result());
@ -119,13 +113,13 @@ class Accounts.ManagerTest : TestCase {
public void create_orphan_account_with_legacy() throws GLib.Error {
this.test.create_account.begin(
account, new GLib.Cancellable(),
(obj, res) => { async_complete(res); }
this.async_completion
);
this.test.create_account.end(async_result());
this.test.new_orphan_account.begin(
Geary.ServiceProvider.OTHER, this.primary_mailbox, null,
(obj, res) => { async_complete(res); }
this.async_completion
);
Geary.AccountInformation account1 =
this.test.new_orphan_account.end(async_result());
@ -133,13 +127,13 @@ class Accounts.ManagerTest : TestCase {
this.test.create_account.begin(
account1, new GLib.Cancellable(),
(obj, res) => { async_complete(res); }
this.async_completion
);
this.test.create_account.end(async_result());
this.test.new_orphan_account.begin(
Geary.ServiceProvider.OTHER, this.primary_mailbox, null,
(obj, res) => { async_complete(res); }
this.async_completion
);
Geary.AccountInformation account2 =
this.test.new_orphan_account.end(async_result());
@ -154,7 +148,7 @@ class Accounts.ManagerTest : TestCase {
this.test.new_orphan_account.begin(
Geary.ServiceProvider.OTHER, this.primary_mailbox, null,
(obj, res) => { async_complete(res); }
this.async_completion
);
Geary.AccountInformation account =
this.test.new_orphan_account.end(async_result());
@ -169,12 +163,13 @@ class Accounts.ManagerTest : TestCase {
this.account.save_sent = false;
this.account.signature = "blarg";
this.account.use_signature = false;
Accounts.AccountConfigV1 config = new Accounts.AccountConfigV1(false);
Geary.ConfigFile file =
new Geary.ConfigFile(this.tmp.get_child("config"));
new Geary.ConfigFile(this.tmp.get_child("config.ini"));
Accounts.AccountConfigV1 config = new Accounts.AccountConfigV1(false);
config.save(this.account, file);
Geary.AccountInformation copy = config.load(
file, TEST_ID, this.mediator, null, null
);
@ -194,7 +189,7 @@ class Accounts.ManagerTest : TestCase {
new Accounts.AccountConfigLegacy();
Geary.ConfigFile file =
new Geary.ConfigFile(this.tmp.get_child("config"));
new Geary.ConfigFile(this.tmp.get_child("config.ini"));
config.save(this.account, file);
Geary.AccountInformation copy = config.load(
@ -221,7 +216,7 @@ class Accounts.ManagerTest : TestCase {
Geary.Credentials.Requirement.NONE;
Accounts.ServiceConfigV1 config = new Accounts.ServiceConfigV1();
Geary.ConfigFile file =
new Geary.ConfigFile(this.tmp.get_child("config"));
new Geary.ConfigFile(this.tmp.get_child("config.ini"));
config.save(this.account, this.account.outgoing, file);
config.load(file, copy, copy.outgoing);
@ -246,7 +241,7 @@ class Accounts.ManagerTest : TestCase {
Geary.Credentials.Requirement.NONE;
Accounts.ServiceConfigLegacy config = new Accounts.ServiceConfigLegacy();
Geary.ConfigFile file =
new Geary.ConfigFile(this.tmp.get_child("config"));
new Geary.ConfigFile(this.tmp.get_child("config.ini"));
config.save(this.account, this.account.outgoing, file);
config.load(file, copy, copy.outgoing);

View file

@ -6,42 +6,35 @@
*/
public abstract class Components.WebViewTestCase<V> : TestCase {
public abstract class ClientWebViewTestCase<V> : TestCase {
protected V? test_view = null;
protected Application.Configuration? config = null;
protected WebViewTestCase(string name) {
protected ClientWebViewTestCase(string name) {
base(name);
}
public override void set_up() {
this.config = new Application.Configuration(Application.Client.SCHEMA_ID);
this.config.enable_debug = true;
WebView.init_web_context(
ClientWebView.init_web_context(
this.config,
File.new_for_path(_BUILD_ROOT_DIR).get_child("src"),
File.new_for_path("/tmp") // XXX use something better here
);
try {
WebView.load_resources(GLib.File.new_for_path("/tmp"));
ClientWebView.load_resources(GLib.File.new_for_path("/tmp"));
} catch (GLib.Error err) {
assert_not_reached();
}
this.test_view = set_up_test_view();
}
protected override void tear_down() {
this.config = null;
this.test_view = null;
public override void set_up() {
this.test_view = set_up_test_view();
}
protected abstract V set_up_test_view();
protected virtual void load_body_fixture(string html = "") {
WebView client_view = (WebView) this.test_view;
ClientWebView client_view = (ClientWebView) this.test_view;
client_view.load_html(html);
while (!client_view.is_content_loaded) {
Gtk.main_iteration();
@ -49,11 +42,8 @@ public abstract class Components.WebViewTestCase<V> : TestCase {
}
protected WebKit.JavascriptResult run_javascript(string command) throws Error {
WebView view = (WebView) this.test_view;
view.run_javascript.begin(
command, null, (obj, res) => { async_complete(res); }
);
ClientWebView view = (ClientWebView) this.test_view;
view.run_javascript.begin(command, null, this.async_completion);
return view.run_javascript.end(async_result());
}

View file

@ -5,10 +5,10 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
public class Components.WebViewTest : TestCase {
public class ClientWebViewTest : TestCase {
public WebViewTest() {
base("Components.WebViewTest");
public ClientWebViewTest() {
base("ClientWebViewTest");
add_test("init_web_context", init_web_context);
add_test("load_resources", load_resources);
}
@ -18,7 +18,7 @@ public class Components.WebViewTest : TestCase {
Application.Client.SCHEMA_ID
);
config.enable_debug = true;
WebView.init_web_context(
ClientWebView.init_web_context(
config,
File.new_for_path(_BUILD_ROOT_DIR).get_child("src"),
File.new_for_path("/tmp") // XXX use something better here
@ -27,7 +27,7 @@ public class Components.WebViewTest : TestCase {
public void load_resources() throws GLib.Error {
try {
WebView.load_resources(GLib.File.new_for_path("/tmp"));
ClientWebView.load_resources(GLib.File.new_for_path("/tmp"));
} catch (GLib.Error err) {
assert_not_reached();
}

View file

@ -5,7 +5,7 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
public class Composer.WebViewTest : Components.WebViewTestCase<Composer.WebView> {
public class Composer.WebViewTest : ClientWebViewTestCase<Composer.WebView> {
public WebViewTest() {
@ -54,7 +54,7 @@ public class Composer.WebViewTest : Components.WebViewTestCase<Composer.WebView>
public void get_html() throws GLib.Error {
string BODY = "<p>para</p>";
load_body_fixture(BODY);
this.test_view.get_html.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_html.begin(this.async_completion);
string html = this.test_view.get_html.end(async_result());
assert_string(PageStateTest.CLEAN_BODY_TEMPLATE.printf(BODY), html);
}
@ -62,14 +62,14 @@ public class Composer.WebViewTest : Components.WebViewTestCase<Composer.WebView>
public void get_html_for_draft() throws GLib.Error {
string BODY = "<p>para</p>";
load_body_fixture(BODY);
this.test_view.get_html_for_draft.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_html_for_draft.begin(this.async_completion);
string html = this.test_view.get_html.end(async_result());
assert_string(PageStateTest.COMPLETE_BODY_TEMPLATE.printf(BODY), html);
}
public void get_text() throws Error {
load_body_fixture("<p>para</p>");
this.test_view.get_text.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_text.begin(this.async_completion);
try {
assert(this.test_view.get_text.end(async_result()) == "para\n\n\n\n\n");
} catch (Error err) {
@ -80,7 +80,7 @@ public class Composer.WebViewTest : Components.WebViewTestCase<Composer.WebView>
public void get_text_with_quote() throws Error {
load_body_fixture("<p>pre</p> <blockquote><p>quote</p></blockquote> <p>post</p>");
this.test_view.get_text.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_text.begin(this.async_completion);
try {
assert(this.test_view.get_text.end(async_result()) ==
"pre\n\n> quote\n> \npost\n\n\n\n\n");
@ -92,7 +92,7 @@ public class Composer.WebViewTest : Components.WebViewTestCase<Composer.WebView>
public void get_text_with_nested_quote() throws Error {
load_body_fixture("<p>pre</p> <blockquote><p>quote1</p> <blockquote><p>quote2</p></blockquote></blockquote> <p>post</p>");
this.test_view.get_text.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_text.begin(this.async_completion);
try {
assert(this.test_view.get_text.end(async_result()) ==
"pre\n\n> quote1\n> \n>> quote2\n>> \npost\n\n\n\n\n");
@ -107,7 +107,7 @@ public class Composer.WebViewTest : Components.WebViewTestCase<Composer.WebView>
<p>A long, long, long, long, long, long para. Well, longer than MAX_BREAKABLE_LEN
at least. Really long, long, long, long, long long, long long, long long, long.</p>
""");
this.test_view.get_text.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_text.begin(this.async_completion);
try {
assert(this.test_view.get_text.end(async_result()) ==
"""A long, long, long, long, long, long para. Well, longer than
@ -130,7 +130,7 @@ long long, long long, long.
<p>A long, long, long, long, long, long para. Well, longer than MAX_BREAKABLE_LEN
at least. Really long, long, long, long, long long, long long, long long, long.</p>""");
this.test_view.get_text.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_text.begin(this.async_completion);
try {
assert(this.test_view.get_text.end(async_result()) ==
"""> A long, long, long, long, long, long line. Well, longer than
@ -157,7 +157,7 @@ long long, long long, long.
</div>
""");
this.test_view.get_text.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_text.begin(this.async_completion);
try {
assert(this.test_view.get_text.end(async_result()) ==
"""On Sun, Jan 1, 2017 at 9:55 PM, Michael Gratton <mike@vee.net> wrote:
@ -185,7 +185,7 @@ long, long, long, long, long, long, long, long, long, long,
public void get_text_with_named_link() throws Error {
load_body_fixture("Check out <a href=\"https://wiki.gnome.org/Apps/Geary\">Geary</a>!");
this.test_view.get_text.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_text.begin(this.async_completion);
try {
assert(this.test_view.get_text.end(async_result()) ==
"Check out Geary <https://wiki.gnome.org/Apps/Geary>!\n\n\n\n");
@ -197,7 +197,7 @@ long, long, long, long, long, long, long, long, long, long,
public void get_text_with_url_link() throws Error {
load_body_fixture("Check out <a href=\"https://wiki.gnome.org/Apps/Geary\">https://wiki.gnome.org/Apps/Geary</a>!");
this.test_view.get_text.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_text.begin(this.async_completion);
try {
assert(this.test_view.get_text.end(async_result()) ==
"Check out <https://wiki.gnome.org/Apps/Geary>!\n\n\n\n");
@ -209,7 +209,7 @@ long, long, long, long, long, long, long, long, long, long,
public void get_text_with_surrounding_nbsps() throws Error {
load_body_fixture("&nbsp;&nbsp;I like my space&nbsp;&nbsp;");
this.test_view.get_text.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_text.begin(this.async_completion);
try {
assert(this.test_view.get_text.end(async_result()) ==
" I like my space\n\n\n\n");
@ -226,21 +226,21 @@ long, long, long, long, long, long, long, long, long, long,
const string SIG1 = "signature text 1";
this.test_view.update_signature(SIG1);
this.test_view.get_html.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_html.begin(this.async_completion);
html = this.test_view.get_html.end(async_result());
assert_true(BODY in html, "Body not present");
assert_true(SIG1 in html, "Signature 1 not present");
const string SIG2 = "signature text 2";
this.test_view.update_signature(SIG2);
this.test_view.get_html.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_html.begin(this.async_completion);
html = this.test_view.get_html.end(async_result());
assert_true(BODY in html, "Body not present");
assert_false(SIG1 in html, "Signature 1 still present");
assert_true(SIG2 in html, "Signature 2 not present");
this.test_view.update_signature("");
this.test_view.get_html.begin((obj, ret) => { async_complete(ret); });
this.test_view.get_html.begin(this.async_completion);
html = this.test_view.get_html.end(async_result());
assert_true(BODY in html, "Body not present");
assert_false(SIG1 in html, "Signature 1 still present");

View file

@ -22,6 +22,8 @@ public class Util.Avatar.Test : TestCase {
assert_string("AB", extract_initials_from_name("aardvark !baardvark"));
assert_string("AC", extract_initials_from_name("aardvark baardvark !caardvark"));
assert_string("Ó", extract_initials_from_name("óvári"));
assert_true(extract_initials_from_name("") == null);
assert_true(extract_initials_from_name(" ") == null);
assert_true(extract_initials_from_name(" ") == null);

View file

@ -107,6 +107,18 @@ public class Geary.MockAccount : Account, MockObject {
}
}
public override async Folder create_personal_folder(
string name,
Folder.SpecialUse use = NONE,
GLib.Cancellable? cancellable = null
) throws GLib.Error {
return object_call<Folder>(
"create_personal_folder",
{ box_arg(name), box_arg(use), cancellable },
new MockFolder(null, null, null, use, null)
);
}
public override EmailIdentifier to_email_identifier(GLib.Variant serialised)
throws EngineError.BAD_PARAMETERS {
try {
@ -148,7 +160,7 @@ public class Geary.MockAccount : Account, MockObject {
} catch (EngineError.NOT_FOUND err) {
throw err;
} catch (GLib.Error err) {
return new MockFolder(null, null, null, SpecialFolderType.NONE, null);
return new MockFolder(null, null, null, NONE, null);
}
}
@ -162,7 +174,7 @@ public class Geary.MockAccount : Account, MockObject {
}
}
public override Folder? get_special_folder(SpecialFolderType special) {
public override Folder? get_special_folder(Folder.SpecialUse special) {
try {
return object_call<Folder?>(
"get_special_folder", {box_arg(special)}, null
@ -172,7 +184,7 @@ public class Geary.MockAccount : Account, MockObject {
}
}
public override async Folder get_required_special_folder_async(SpecialFolderType special,
public override async Folder get_required_special_folder_async(Folder.SpecialUse special,
Cancellable? cancellable = null)
throws Error {
return object_or_throw_call<Folder>(

View file

@ -83,9 +83,7 @@ class Geary.AttachmentTest : TestCase {
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
test.get_safe_file_name.begin(null, this.async_completion);
assert(test.get_safe_file_name.end(async_result()) == TEST_FILENAME);
}
@ -102,9 +100,7 @@ class Geary.AttachmentTest : TestCase {
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
test.get_safe_file_name.begin(null, this.async_completion);
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
@ -121,9 +117,7 @@ class Geary.AttachmentTest : TestCase {
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
test.get_safe_file_name.begin(null, this.async_completion);
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
@ -139,9 +133,7 @@ class Geary.AttachmentTest : TestCase {
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
test.get_safe_file_name.begin(null, this.async_completion);
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
@ -157,9 +149,7 @@ class Geary.AttachmentTest : TestCase {
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
test.get_safe_file_name.begin(null, this.async_completion);
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
@ -176,9 +166,7 @@ class Geary.AttachmentTest : TestCase {
this.file
);
test.get_safe_file_name.begin(ALT_TEXT, (obj, ret) => {
async_complete(ret);
});
test.get_safe_file_name.begin(ALT_TEXT, this.async_completion);
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
@ -194,9 +182,7 @@ class Geary.AttachmentTest : TestCase {
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
test.get_safe_file_name.begin(null, this.async_completion);
assert(test.get_safe_file_name.end(async_result()) == TEST_FILENAME);
}
@ -214,9 +200,7 @@ class Geary.AttachmentTest : TestCase {
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
test.get_safe_file_name.begin(null, this.async_completion);
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
@ -233,9 +217,7 @@ class Geary.AttachmentTest : TestCase {
File.new_for_path(TEST_FILENAME)
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
test.get_safe_file_name.begin(null, this.async_completion);
assert_string(TEST_FILENAME, test.get_safe_file_name.end(async_result()));
}

View file

@ -20,8 +20,8 @@ public class Geary.MockFolder : Folder, MockObject {
get { return this._path; }
}
public override SpecialFolderType special_folder_type {
get { return this._type; }
public override Folder.SpecialUse used_as {
get { return this._used_as; }
}
public override ProgressMonitor opening_monitor {
@ -36,19 +36,19 @@ public class Geary.MockFolder : Folder, MockObject {
private Account _account;
private FolderProperties _properties;
private FolderPath _path;
private SpecialFolderType _type;
private Folder.SpecialUse _used_as;
private ProgressMonitor _opening_monitor;
public MockFolder(Account? account,
FolderProperties? properties,
FolderPath? path,
SpecialFolderType type,
Folder.SpecialUse used_as,
ProgressMonitor? monitor) {
this._account = account;
this._properties = properties ?? new MockFolderPoperties();
this._path = path;
this._type = type;
this._used_as = used_as;
this._opening_monitor = monitor;
}
@ -58,8 +58,8 @@ public class Geary.MockFolder : Folder, MockObject {
public override async bool open_async(Folder.OpenFlags open_flags,
Cancellable? cancellable = null)
throws Error {
return boolean_call(
throws GLib.Error {
return yield boolean_call_async(
"open_async",
{ int_arg(open_flags), cancellable },
false
@ -67,14 +67,14 @@ public class Geary.MockFolder : Folder, MockObject {
}
public override async bool close_async(Cancellable? cancellable = null)
throws Error {
return boolean_call(
throws GLib.Error {
return yield boolean_call_async(
"close_async", { cancellable }, false
);
}
public override async void wait_for_close_async(Cancellable? cancellable = null)
throws Error {
throws GLib.Error {
throw new EngineError.UNSUPPORTED("Mock method");
}
@ -89,8 +89,8 @@ public class Geary.MockFolder : Folder, MockObject {
Geary.Email.Field required_fields,
Folder.ListFlags flags,
Cancellable? cancellable = null)
throws Error {
return object_call<Gee.List<Email>?>(
throws GLib.Error {
return yield object_call_async<Gee.List<Email>?>(
"list_email_by_id_async",
{initial_id, int_arg(count), box_arg(required_fields), box_arg(flags), cancellable},
null
@ -102,8 +102,8 @@ public class Geary.MockFolder : Folder, MockObject {
Geary.Email.Field required_fields,
Folder.ListFlags flags,
Cancellable? cancellable = null)
throws Error {
return object_call<Gee.List<Email>?>(
throws GLib.Error {
return yield object_call_async<Gee.List<Email>?>(
"list_email_by_sparse_id_async",
{ids, box_arg(required_fields), box_arg(flags), cancellable},
null
@ -115,7 +115,12 @@ public class Geary.MockFolder : Folder, MockObject {
Geary.Email.Field required_fields,
Folder.ListFlags flags,
Cancellable? cancellable = null)
throws Error {
throws GLib.Error {
throw new EngineError.UNSUPPORTED("Mock method");
}
public override void set_used_as_custom(bool enabled)
throws EngineError.UNSUPPORTED {
throw new EngineError.UNSUPPORTED("Mock method");
}

View file

@ -20,6 +20,8 @@ class Geary.App.ConversationMonitorTest : TestCase {
base("Geary.App.ConversationMonitorTest");
add_test("start_stop_monitoring", start_stop_monitoring);
add_test("open_error", open_error);
add_test("close_during_open_error", close_during_open_error);
add_test("close_after_open_error", close_after_open_error);
add_test("load_single_message", load_single_message);
add_test("load_multiple_messages", load_multiple_messages);
add_test("load_related_message", load_related_message);
@ -42,14 +44,14 @@ class Geary.App.ConversationMonitorTest : TestCase {
this.account,
null,
this.folder_root.get_child("base"),
SpecialFolderType.NONE,
NONE,
null
);
this.other_folder = new MockFolder(
this.account,
null,
this.folder_root.get_child("other"),
SpecialFolderType.NONE,
NONE,
null
);
}
@ -78,7 +80,7 @@ class Geary.App.ConversationMonitorTest : TestCase {
this.base_folder.expect_call("close_async");
monitor.start_monitoring.begin(
NONE, test_cancellable, (obj, res) => { async_complete(res); }
NONE, test_cancellable, this.async_completion
);
monitor.start_monitoring.end(async_result());
@ -88,7 +90,7 @@ class Geary.App.ConversationMonitorTest : TestCase {
}
monitor.stop_monitoring.begin(
test_cancellable, (obj, res) => { async_complete(res); }
test_cancellable, this.async_completion
);
monitor.stop_monitoring.end(async_result());
@ -108,7 +110,7 @@ class Geary.App.ConversationMonitorTest : TestCase {
.throws(new EngineError.SERVER_UNAVAILABLE("Mock error"));
monitor.start_monitoring.begin(
NONE, null, (obj, res) => { async_complete(res); }
NONE, null, this.async_completion
);
try {
monitor.start_monitoring.end(async_result());
@ -117,9 +119,69 @@ class Geary.App.ConversationMonitorTest : TestCase {
assert_error(open.throw_error, err);
}
assert_false(monitor.is_monitoring, "is monitoring");
this.base_folder.assert_expectations();
}
public void close_during_open_error() throws GLib.Error {
ConversationMonitor monitor = new ConversationMonitor(
this.base_folder, Email.Field.NONE, 10
);
ExpectedCall open = this.base_folder
.expect_call("open_async")
.async_call(PAUSE)
.throws(new GLib.IOError.CANCELLED("Mock error"));
this.base_folder
.expect_call("close_async")
.throws(new EngineError.ALREADY_CLOSED("Mock error"));
var start_waiter = new AsyncResultWaiter(this.main_loop);
monitor.start_monitoring.begin(NONE, null, start_waiter.async_completion);
var stop_waiter = new AsyncResultWaiter(this.main_loop);
monitor.stop_monitoring.begin(null, stop_waiter.async_completion);
open.async_resume();
try {
monitor.start_monitoring.end(start_waiter.async_result());
assert_not_reached();
} catch (GLib.Error err) {
assert_error(open.throw_error, err);
}
// base_folder.close_async should not be called, so should not
// throw an error
monitor.stop_monitoring.end(stop_waiter.async_result());
}
public void close_after_open_error() throws GLib.Error {
ConversationMonitor monitor = new ConversationMonitor(
this.base_folder, Email.Field.NONE, 10
);
ExpectedCall open = this.base_folder
.expect_call("open_async")
.throws(new EngineError.SERVER_UNAVAILABLE("Mock error"));
this.base_folder
.expect_call("close_async")
.throws(new EngineError.ALREADY_CLOSED("Mock error"));
monitor.start_monitoring.begin(NONE, null, this.async_completion);
try {
monitor.start_monitoring.end(async_result());
assert_not_reached();
} catch (GLib.Error err) {
assert_error(open.throw_error, err);
}
// base_folder.close_async should not be called, so should not
// throw an error
monitor.stop_monitoring.begin(null, this.async_completion);
monitor.stop_monitoring.end(async_result());
}
public void load_single_message() throws Error {
Email e1 = setup_email(1);
@ -246,7 +308,7 @@ class Geary.App.ConversationMonitorTest : TestCase {
// error out during later tests
this.base_folder.expect_call("close_async");
monitor.stop_monitoring.begin(
null, (obj, res) => { async_complete(res); }
null, this.async_completion
);
monitor.stop_monitoring.end(async_result());
}
@ -477,7 +539,7 @@ class Geary.App.ConversationMonitorTest : TestCase {
}
monitor.start_monitoring.begin(
NONE, test_cancellable, (obj, res) => { async_complete(res); }
NONE, test_cancellable, this.async_completion
);
monitor.start_monitoring.end(async_result());

View file

@ -33,7 +33,7 @@ class Geary.App.ConversationSetTest : TestCase {
null,
null,
this.folder_root.get_child("test"),
SpecialFolderType.NONE,
NONE,
null
);
this.test = new ConversationSet(this.base_folder);

View file

@ -33,7 +33,7 @@ class Geary.App.ConversationTest : TestCase {
null,
null,
this.folder_root.get_child("test"),
SpecialFolderType.NONE,
NONE,
null
);
this.test = new Conversation(this.base_folder);

View file

@ -54,7 +54,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
public void whitelisted_folder_type() throws GLib.Error {
ContactHarvesterImpl whitelisted = new ContactHarvesterImpl(
this.store,
SpecialFolderType.INBOX,
INBOX,
this.senders
);
this.store.expect_call("get_by_rfc822");
@ -64,9 +64,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
);
whitelisted.harvest_from_email.begin(
Collection.single(this.email), null,
(obj, ret) => { async_complete(ret); }
);
Collection.single(this.email), null, this.async_completion);
whitelisted.harvest_from_email.end(async_result());
this.store.assert_expectations();
@ -84,7 +82,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
public void blacklisted_folder_type() throws GLib.Error {
ContactHarvesterImpl whitelisted = new ContactHarvesterImpl(
this.store,
SpecialFolderType.SPAM,
JUNK,
this.senders
);
this.email.set_receivers(
@ -92,9 +90,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
);
whitelisted.harvest_from_email.begin(
Collection.single(this.email), null,
(obj, ret) => { async_complete(ret); }
);
Collection.single(this.email), null, this.async_completion);
whitelisted.harvest_from_email.end(async_result());
this.store.assert_expectations();
@ -103,7 +99,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
public void seen_priority() throws GLib.Error {
ContactHarvesterImpl whitelisted = new ContactHarvesterImpl(
this.store,
SpecialFolderType.INBOX,
INBOX,
this.senders
);
this.store.expect_call("get_by_rfc822");
@ -113,9 +109,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
);
whitelisted.harvest_from_email.begin(
Collection.single(this.email), null,
(obj, ret) => { async_complete(ret); }
);
Collection.single(this.email), null, this.async_completion);
whitelisted.harvest_from_email.end(async_result());
this.store.assert_expectations();
@ -132,7 +126,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
public void sent_priority() throws GLib.Error {
ContactHarvesterImpl whitelisted = new ContactHarvesterImpl(
this.store,
SpecialFolderType.SENT,
SENT,
this.senders
);
this.store.expect_call("get_by_rfc822");
@ -142,9 +136,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
);
whitelisted.harvest_from_email.begin(
Collection.single(this.email), null,
(obj, ret) => { async_complete(ret); }
);
Collection.single(this.email), null, this.async_completion);
whitelisted.harvest_from_email.end(async_result());
this.store.assert_expectations();
@ -161,7 +153,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
public void received_priority() throws GLib.Error {
ContactHarvesterImpl whitelisted = new ContactHarvesterImpl(
this.store,
SpecialFolderType.SENT,
SENT,
this.senders
);
this.store.expect_call("get_by_rfc822");
@ -171,9 +163,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
);
whitelisted.harvest_from_email.begin(
Collection.single(this.email), null,
(obj, ret) => { async_complete(ret); }
);
Collection.single(this.email), null, this.async_completion);
whitelisted.harvest_from_email.end(async_result());
this.store.assert_expectations();

View file

@ -42,7 +42,7 @@ class Geary.ContactStoreImplTest : TestCase {
);
this.db.open.begin(
Geary.Db.DatabaseFlags.CREATE_FILE, null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.db.open.end(async_result());
@ -79,7 +79,7 @@ class Geary.ContactStoreImplTest : TestCase {
test_article.get_by_rfc822.begin(
new RFC822.MailboxAddress(null, "Test@example.com"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Contact? existing = test_article.get_by_rfc822.end(async_result());
assert_non_null(existing, "Existing contact");
@ -92,7 +92,7 @@ class Geary.ContactStoreImplTest : TestCase {
test_article.get_by_rfc822.begin(
new RFC822.MailboxAddress(null, "test@example.com"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Contact? missing = test_article.get_by_rfc822.end(async_result());
assert_null(missing, "Missing contact");
@ -104,7 +104,7 @@ class Geary.ContactStoreImplTest : TestCase {
0,
10,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Collection<Contact> results = test_article.search.end(
async_result()
@ -118,7 +118,7 @@ class Geary.ContactStoreImplTest : TestCase {
0,
10,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Collection<Contact> results = test_article.search.end(
async_result()
@ -139,7 +139,7 @@ class Geary.ContactStoreImplTest : TestCase {
0,
10,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Collection<Contact> results = test_article.search.end(
async_result()
@ -173,7 +173,7 @@ class Geary.ContactStoreImplTest : TestCase {
0,
10,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Collection<Contact> results = test_article.search.end(
async_result()
@ -204,7 +204,7 @@ class Geary.ContactStoreImplTest : TestCase {
0,
10,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Collection<Contact> results = test_article.search.end(
async_result()
@ -226,14 +226,14 @@ class Geary.ContactStoreImplTest : TestCase {
test_article.update_contacts.begin(
Collection.single(not_persisted),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
test_article.update_contacts.end(async_result());
test_article.get_by_rfc822.begin(
new RFC822.MailboxAddress(null, "New@example.com"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Contact? persisted = test_article.get_by_rfc822.end(async_result());
assert_non_null(persisted, "persisted");
@ -255,13 +255,13 @@ class Geary.ContactStoreImplTest : TestCase {
test_article.update_contacts.begin(
Collection.single(not_updated),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
test_article.update_contacts.end(async_result());
test_article.get_by_rfc822.begin(
new RFC822.MailboxAddress(null, "Test@example.com"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Contact? updated = test_article.get_by_rfc822.end(async_result());
assert_non_null(updated, "updated");
@ -276,13 +276,13 @@ class Geary.ContactStoreImplTest : TestCase {
test_article.update_contacts.begin(
Collection.single(not_updated),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
test_article.update_contacts.end(async_result());
test_article.get_by_rfc822.begin(
new RFC822.MailboxAddress(null, "Test@example.com"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Contact? updated_again = test_article.get_by_rfc822.end(async_result());
assert_false(updated_again.flags.always_load_remote_images(), "Removed flags");

View file

@ -21,10 +21,7 @@ class Geary.Db.DatabaseTest : TestCase {
public void transient_open() throws Error {
Database db = new Geary.Db.Database.transient();
db.open.begin(
Geary.Db.DatabaseFlags.NONE, null,
(obj, ret) => { async_complete(ret); }
);
db.open.begin(Geary.Db.DatabaseFlags.NONE, null, this.async_completion);
db.open.end(async_result());
// Need to get a connection since the database doesn't
@ -39,10 +36,7 @@ class Geary.Db.DatabaseTest : TestCase {
);
Database db = new Geary.Db.Database.persistent(tmp_file);
db.open.begin(
Geary.Db.DatabaseFlags.NONE, null,
(obj, ret) => { async_complete(ret); }
);
db.open.begin(Geary.Db.DatabaseFlags.NONE, null, this.async_completion);
db.open.end(async_result());
// Need to get a connection since the database doesn't
@ -61,8 +55,7 @@ class Geary.Db.DatabaseTest : TestCase {
tmp_dir.get_child("test.db")
);
db.open.begin(
Geary.Db.DatabaseFlags.CREATE_FILE, null,
(obj, ret) => { async_complete(ret); }
Geary.Db.DatabaseFlags.CREATE_FILE, null, this.async_completion
);
db.open.end(async_result());
@ -86,7 +79,7 @@ class Geary.Db.DatabaseTest : TestCase {
Geary.Db.DatabaseFlags.CREATE_DIRECTORY |
Geary.Db.DatabaseFlags.CREATE_FILE,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
db.open.end(async_result());
@ -111,7 +104,7 @@ class Geary.Db.DatabaseTest : TestCase {
Geary.Db.DatabaseFlags.CREATE_DIRECTORY |
Geary.Db.DatabaseFlags.CREATE_FILE,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
db.open.end(async_result());
@ -135,7 +128,7 @@ class Geary.Db.DatabaseTest : TestCase {
Geary.Db.DatabaseFlags.CREATE_FILE |
Geary.Db.DatabaseFlags.CHECK_CORRUPTION,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
db.open.end(async_result());
@ -160,7 +153,7 @@ class Geary.Db.DatabaseTest : TestCase {
Geary.Db.DatabaseFlags.CREATE_FILE |
Geary.Db.DatabaseFlags.CHECK_CORRUPTION,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
db.open.end(async_result());

View file

@ -34,8 +34,7 @@ class Geary.Db.VersionedDatabaseTest : TestCase {
);
db.open.begin(
Geary.Db.DatabaseFlags.CREATE_FILE, null,
(obj, ret) => { async_complete(ret); }
Geary.Db.DatabaseFlags.CREATE_FILE, null, this.async_completion
);
db.open.end(async_result());

View file

@ -48,7 +48,7 @@ class Geary.ImapDB.AccountTest : TestCase {
);
this.account.open_async.begin(
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.account.open_async.end(async_result());
@ -59,7 +59,7 @@ class Geary.ImapDB.AccountTest : TestCase {
this.root = null;
this.account.close_async.begin(
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.account.close_async.end(async_result());
this.account = null;
@ -84,14 +84,14 @@ class Geary.ImapDB.AccountTest : TestCase {
new Imap.UIDValidity(7),
6 //unseen
),
new Imap.Capabilities(1)
new Imap.Capabilities.empty(0)
)
);
this.account.clone_folder_async.begin(
folder,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.account.clone_folder_async.end(async_result());
@ -123,14 +123,14 @@ class Geary.ImapDB.AccountTest : TestCase {
new Imap.UIDValidity(7),
6 //unseen
),
new Imap.Capabilities(1)
new Imap.Capabilities.empty(0)
)
);
this.account.clone_folder_async.begin(
folder,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.account.clone_folder_async.end(async_result());
@ -155,7 +155,7 @@ class Geary.ImapDB.AccountTest : TestCase {
this.account.list_folders_async.begin(
this.account.imap_folder_root,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Collection<Geary.ImapDB.Folder> result =
this.account.list_folders_async.end(async_result());
@ -167,7 +167,7 @@ class Geary.ImapDB.AccountTest : TestCase {
this.account.list_folders_async.begin(
test1.get_path(),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
result = this.account.list_folders_async.end(async_result());
@ -178,7 +178,7 @@ class Geary.ImapDB.AccountTest : TestCase {
this.account.list_folders_async.begin(
test2.get_path(),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
result = this.account.list_folders_async.end(async_result());
@ -198,14 +198,14 @@ class Geary.ImapDB.AccountTest : TestCase {
this.account.delete_folder_async.begin(
this.root.get_child("test1").get_child("test2"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.account.delete_folder_async.end(async_result());
this.account.delete_folder_async.begin(
this.root.get_child("test1"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.account.delete_folder_async.end(async_result());
}
@ -221,7 +221,7 @@ class Geary.ImapDB.AccountTest : TestCase {
this.account.delete_folder_async.begin(
this.root.get_child("test1"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
try {
this.account.delete_folder_async.end(async_result());
@ -242,7 +242,7 @@ class Geary.ImapDB.AccountTest : TestCase {
this.account.delete_folder_async.begin(
this.root.get_child("test3"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
try {
this.account.delete_folder_async.end(async_result());
@ -263,7 +263,7 @@ class Geary.ImapDB.AccountTest : TestCase {
this.account.fetch_folder_async.begin(
this.root.get_child("test1"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Folder? result = this.account.fetch_folder_async.end(async_result());
@ -282,7 +282,7 @@ class Geary.ImapDB.AccountTest : TestCase {
this.account.fetch_folder_async.begin(
this.root.get_child("test1").get_child("test2"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Folder? result = this.account.fetch_folder_async.end(async_result());
@ -301,7 +301,7 @@ class Geary.ImapDB.AccountTest : TestCase {
this.account.fetch_folder_async.begin(
this.root.get_child("test3"),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
try {
this.account.fetch_folder_async.end(async_result());
@ -330,7 +330,7 @@ class Geary.ImapDB.AccountTest : TestCase {
}).to_linked_list(),
Email.Field.RECEIVERS,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.List<Email> result = this.account.list_email.end(
async_result()
@ -344,7 +344,7 @@ class Geary.ImapDB.AccountTest : TestCase {
Collection.single(new EmailIdentifier(3, null)),
Email.Field.RECEIVERS,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
try {
this.account.list_email.end(async_result());
@ -357,7 +357,7 @@ class Geary.ImapDB.AccountTest : TestCase {
Collection.single(new EmailIdentifier(1, null)),
Email.Field.BODY,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
try {
this.account.list_email.end(async_result());

View file

@ -119,7 +119,7 @@ class Geary.ImapDB.AttachmentIoTest : TestCase {
this.db = new Geary.Db.Database.transient();
this.db.open.begin(
Geary.Db.DatabaseFlags.NONE, null,
(obj, res) => { async_complete(res); }
this.async_completion
);
this.db.open.end(async_result());
this.db.exec("""
@ -150,7 +150,7 @@ CREATE TABLE MessageAttachmentTable (
Files.recursive_delete_async.begin(
this.tmp_dir, GLib.Priority.DEFAULT, null,
(obj, res) => { async_complete(res); }
this.async_completion
);
Files.recursive_delete_async.end(async_result());
this.tmp_dir = null;

View file

@ -42,7 +42,7 @@ class Geary.ImapDB.DatabaseTest : TestCase {
db.open.begin(
Geary.Db.DatabaseFlags.CREATE_FILE, null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
db.open.end(async_result());
@ -102,7 +102,7 @@ class Geary.ImapDB.DatabaseTest : TestCase {
db.open.begin(
Geary.Db.DatabaseFlags.CREATE_FILE, null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
db.open.end(async_result());
@ -136,7 +136,7 @@ class Geary.ImapDB.DatabaseTest : TestCase {
db.open.begin(
Geary.Db.DatabaseFlags.CREATE_FILE, null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
db.open.end(async_result());

View file

@ -48,7 +48,7 @@ class Geary.ImapDB.FolderTest : TestCase {
);
this.account.open_async.begin(
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.account.open_async.end(async_result());
@ -59,7 +59,7 @@ class Geary.ImapDB.FolderTest : TestCase {
this.account.list_folders_async.begin(
this.account.imap_folder_root,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.folder = traverse<Folder>(
this.account.list_folders_async.end(async_result())
@ -70,7 +70,7 @@ class Geary.ImapDB.FolderTest : TestCase {
this.folder = null;
this.account.close_async.begin(
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.account.close_async.end(async_result());
this.account = null;
@ -88,7 +88,7 @@ class Geary.ImapDB.FolderTest : TestCase {
true,
new MockContactHarvester(),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Map<Email,bool> results =
this.folder.create_or_merge_email_async.end(async_result());
@ -108,7 +108,7 @@ class Geary.ImapDB.FolderTest : TestCase {
true,
new MockContactHarvester(),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Map<Email,bool> results =
this.folder.create_or_merge_email_async.end(async_result());
@ -128,7 +128,7 @@ class Geary.ImapDB.FolderTest : TestCase {
false,
new MockContactHarvester(),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Map<Email,bool> results =
this.folder.create_or_merge_email_async.end(async_result());
@ -158,7 +158,7 @@ class Geary.ImapDB.FolderTest : TestCase {
true,
new MockContactHarvester(),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Map<Email,bool> results =
this.folder.create_or_merge_email_async.end(async_result());
@ -173,7 +173,7 @@ class Geary.ImapDB.FolderTest : TestCase {
fixture_fields | mock.fields,
Folder.ListFlags.NONE,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Email? merged = null;
try {
@ -209,7 +209,7 @@ class Geary.ImapDB.FolderTest : TestCase {
true,
new MockContactHarvester(),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Map<Email,bool> results =
this.folder.create_or_merge_email_async.end(async_result());
@ -243,7 +243,7 @@ class Geary.ImapDB.FolderTest : TestCase {
true,
new MockContactHarvester(),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Gee.Map<Email,bool> results =
this.folder.create_or_merge_email_async.end(async_result());
@ -281,7 +281,7 @@ class Geary.ImapDB.FolderTest : TestCase {
this.folder.set_email_flags_async.begin(
Collection.single_map(test, test_flags),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.folder.set_email_flags_async.end(async_result());
@ -317,7 +317,7 @@ class Geary.ImapDB.FolderTest : TestCase {
this.folder.set_email_flags_async.begin(
Collection.single_map(test, test_flags),
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.folder.set_email_flags_async.end(async_result());
@ -369,7 +369,7 @@ class Geary.ImapDB.FolderTest : TestCase {
this.folder.detach_emails_before_timestamp.begin(
threshold,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
this.folder.detach_emails_before_timestamp.end(async_result());
@ -412,7 +412,7 @@ class Geary.ImapDB.FolderTest : TestCase {
Email.Field.FLAGS,
Folder.ListFlags.INCLUDE_MARKED_FOR_REMOVE,
null,
(obj, ret) => { async_complete(ret); }
this.async_completion
);
Email? merged = null;
try {

View file

@ -57,18 +57,12 @@ public class Geary.ImapEngine.GenericAccountTest : TestCase {
this.tmp_dir,
GLib.File.new_for_path(_SOURCE_ROOT_DIR).get_child("sql")
);
this.local_account.open_async.begin(
null,
(obj, ret) => { async_complete(ret); }
);
this.local_account.open_async.begin(null, this.async_completion);
this.local_account.open_async.end(async_result());
}
public override void tear_down() throws GLib.Error {
this.local_account.close_async.begin(
null,
(obj, ret) => { async_complete(ret); }
);
this.local_account.close_async.begin(null, this.async_completion);
this.local_account.close_async.end(async_result());
this.local_account = null;
this.config = null;

View file

@ -26,7 +26,7 @@ class Geary.Imap.CreateCommandTest : TestCase {
"---- create Everything (use (\\All))",
new CreateCommand.special_use(
new MailboxSpecifier("Everything"),
SpecialFolderType.ALL_MAIL
ALL_MAIL
).to_string()
);
}

View file

@ -0,0 +1,160 @@
/*
* Copyright 2019 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
class Geary.Imap.ClientConnectionTest : TestCase {
private class TestCommand : Command {
public TestCommand() {
base("TEST");
}
}
private TestServer? server = null;
public ClientConnectionTest() {
base("Geary.Imap.ClientConnectionTest");
add_test("connect_disconnect", connect_disconnect);
if (GLib.Test.slow()) {
add_test("idle", idle);
add_test("command_timeout", command_timeout);
}
}
protected override void set_up() throws GLib.Error {
this.server = new TestServer();
}
protected override void tear_down() {
this.server.stop();
this.server = null;
}
public void connect_disconnect() throws GLib.Error {
var test_article = new ClientConnection(new_endpoint());
test_article.connect_async.begin(null, this.async_completion);
test_article.connect_async.end(async_result());
assert_non_null(test_article.get_remote_address());
assert_non_null(test_article.get_local_address());
test_article.disconnect_async.begin(null, this.async_completion);
test_article.disconnect_async.end(async_result());
assert_null(test_article.get_remote_address());
assert_null(test_article.get_local_address());
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert(result.succeeded);
}
public void idle() throws GLib.Error {
this.server.add_script_line(RECEIVE_LINE, "a001 IDLE");
this.server.add_script_line(SEND_LINE, "+ idling");
this.server.add_script_line(RECEIVE_LINE, "DONE");
this.server.add_script_line(SEND_LINE, "a001 OK Completed");
this.server.add_script_line(RECEIVE_LINE, "a002 TEST");
this.server.add_script_line(SEND_LINE, "a002 OK Looks good");
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
const int COMMAND_TIMEOUT = 1;
const int IDLE_TIMEOUT = 1;
var test_article = new ClientConnection(
new_endpoint(), COMMAND_TIMEOUT, IDLE_TIMEOUT
);
test_article.connect_async.begin(null, this.async_completion);
test_article.connect_async.end(async_result());
assert_false(test_article.is_in_idle(), "Initial idle state");
test_article.enable_idle_when_quiet(true);
assert_false(test_article.is_in_idle(), "Post-enabled idle state");
// Wait for idle to kick in
GLib.Timer timer = new GLib.Timer();
timer.start();
while (!test_article.is_in_idle() &&
timer.elapsed() < IDLE_TIMEOUT * 2) {
this.main_loop.iteration(false);
}
assert_true(test_article.is_in_idle(), "Entered idle");
// Ensure idle outlives command timeout
timer.start();
while (timer.elapsed() < COMMAND_TIMEOUT * 2) {
this.main_loop.iteration(false);
}
assert_true(test_article.is_in_idle(), "Post idle command timeout");
var command = new TestCommand();
test_article.send_command(command);
command.wait_until_complete.begin(null, this.async_completion);
command.wait_until_complete.end(async_result());
assert_false(test_article.is_in_idle(), "Post test command");
test_article.disconnect_async.begin(null, this.async_completion);
test_article.disconnect_async.end(async_result());
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert(result.succeeded);
}
public void command_timeout() throws GLib.Error {
this.server.add_script_line(
SEND_LINE, "* OK localhost test server ready"
);
this.server.add_script_line(RECEIVE_LINE, "a001 TEST");
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
const int TIMEOUT = 2;
bool sent = false;
bool recv_fail = false;
bool timed_out = false;
var test_article = new ClientConnection(new_endpoint(), TIMEOUT);
test_article.sent_command.connect(() => { sent = true; });
test_article.receive_failure.connect(() => { recv_fail = true; });
test_article.connect_async.begin(null, this.async_completion);
test_article.connect_async.end(async_result());
var command = new TestCommand();
command.response_timed_out.connect(() => { timed_out = true; });
test_article.send_command(command);
GLib.Timer timer = new GLib.Timer();
timer.start();
while (!timed_out && timer.elapsed() < TIMEOUT * 2) {
this.main_loop.iteration(false);
}
test_article.disconnect_async.begin(null, this.async_completion);
test_article.disconnect_async.end(async_result());
assert_true(sent, "connection.sent_command");
assert_true(recv_fail, "command.receive_failure");
assert_true(timed_out, "command.response_timed_out");
debug("Waiting for server...");
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert_true(result.succeeded);
}
protected Endpoint new_endpoint() {
return new Endpoint(this.server.get_client_address(), NONE, 10);
}
}

View file

@ -0,0 +1,415 @@
/*
* Copyright 2019 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
class Geary.Imap.ClientSessionTest : TestCase {
private const uint CONNECT_TIMEOUT = 2;
private TestServer? server = null;
public ClientSessionTest() {
base("Geary.Imap.ClientSessionTest");
add_test("connect_disconnect", connect_disconnect);
add_test("connect_with_capabilities", connect_with_capabilities);
if (GLib.Test.slow()) {
add_test("connect_timeout", connect_timeout);
}
add_test("login", login);
add_test("login_with_capabilities", login_with_capabilities);
add_test("logout", logout);
add_test("login_logout", login_logout);
add_test("initiate_request_capabilities", initiate_request_capabilities);
add_test("initiate_implicit_capabilities", initiate_implicit_capabilities);
add_test("initiate_namespace", initiate_namespace);
}
protected override void set_up() throws GLib.Error {
this.server = new TestServer();
}
protected override void tear_down() {
this.server.stop();
this.server = null;
}
public void connect_disconnect() throws GLib.Error {
this.server.add_script_line(
SEND_LINE, "* OK localhost test server ready"
);
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
var test_article = new ClientSession(new_endpoint());
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
test_article.connect_async.begin(
CONNECT_TIMEOUT, null, this.async_completion
);
test_article.connect_async.end(async_result());
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
test_article.disconnect_async.begin(null, this.async_completion);
test_article.disconnect_async.end(async_result());
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert_true(
result.succeeded,
result.error != null ? result.error.message : "Server result failed"
);
}
public void connect_with_capabilities() throws GLib.Error {
this.server.add_script_line(
SEND_LINE, "* OK [CAPABILITY IMAP4rev1] localhost test server ready"
);
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
var test_article = new ClientSession(new_endpoint());
test_article.connect_async.begin(
CONNECT_TIMEOUT, null, this.async_completion
);
test_article.connect_async.end(async_result());
assert_true(test_article.capabilities.supports_imap4rev1());
test_article.disconnect_async.begin(null, this.async_completion);
test_article.disconnect_async.end(async_result());
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert_true(result.succeeded);
}
public void connect_timeout() throws GLib.Error {
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
var test_article = new ClientSession(new_endpoint());
GLib.Timer timer = new GLib.Timer();
timer.start();
test_article.connect_async.begin(
CONNECT_TIMEOUT, null, this.async_completion
);
try {
test_article.connect_async.end(async_result());
assert_not_reached();
} catch (GLib.IOError.TIMED_OUT err) {
assert_double(timer.elapsed(), CONNECT_TIMEOUT, CONNECT_TIMEOUT * 0.5);
}
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert_true(result.succeeded);
}
public void login_with_capabilities() throws GLib.Error {
this.server.add_script_line(
SEND_LINE, "* OK localhost test server ready"
);
this.server.add_script_line(RECEIVE_LINE, "a001 login test password");
this.server.add_script_line(
SEND_LINE, "a001 OK [CAPABILITY IMAP4rev1] ohhai"
);
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
var test_article = new ClientSession(new_endpoint());
test_article.connect_async.begin(
CONNECT_TIMEOUT, null, this.async_completion
);
test_article.connect_async.end(async_result());
test_article.login_async.begin(
new Credentials(PASSWORD, "test", "password"),
null,
this.async_completion
);
test_article.login_async.end(async_result());
assert_true(test_article.capabilities.supports_imap4rev1());
test_article.disconnect_async.begin(null, this.async_completion);
test_article.disconnect_async.end(async_result());
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert_true(
result.succeeded,
result.error != null ? result.error.message : "Server result failed"
);
}
public void login() throws GLib.Error {
this.server.add_script_line(
SEND_LINE, "* OK localhost test server ready"
);
this.server.add_script_line(RECEIVE_LINE, "a001 login test password");
this.server.add_script_line(SEND_LINE, "a001 OK ohhai");
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
var test_article = new ClientSession(new_endpoint());
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
test_article.connect_async.begin(
CONNECT_TIMEOUT, null, this.async_completion
);
test_article.connect_async.end(async_result());
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
test_article.login_async.begin(
new Credentials(PASSWORD, "test", "password"),
null,
this.async_completion
);
test_article.login_async.end(async_result());
assert_true(test_article.get_protocol_state() == AUTHORIZED);
test_article.disconnect_async.begin(null, this.async_completion);
test_article.disconnect_async.end(async_result());
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert_true(
result.succeeded,
result.error != null ? result.error.message : "Server result failed"
);
}
public void logout() throws GLib.Error {
this.server.add_script_line(
SEND_LINE, "* OK localhost test server ready"
);
this.server.add_script_line(RECEIVE_LINE, "a001 logout");
this.server.add_script_line(SEND_LINE, "* BYE fine");
this.server.add_script_line(SEND_LINE, "a001 OK laters");
this.server.add_script_line(DISCONNECT, "");
var test_article = new ClientSession(new_endpoint());
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
test_article.connect_async.begin(
CONNECT_TIMEOUT, null, this.async_completion
);
test_article.connect_async.end(async_result());
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
test_article.logout_async.begin(null, this.async_completion);
test_article.logout_async.end(async_result());
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert_true(
result.succeeded,
result.error != null ? result.error.message : "Server result failed"
);
}
public void login_logout() throws GLib.Error {
this.server.add_script_line(
SEND_LINE, "* OK localhost test server ready"
);
this.server.add_script_line(RECEIVE_LINE, "a001 login test password");
this.server.add_script_line(SEND_LINE, "a001 OK ohhai");
this.server.add_script_line(RECEIVE_LINE, "a002 logout");
this.server.add_script_line(SEND_LINE, "* BYE fine");
this.server.add_script_line(SEND_LINE, "a002 OK laters");
this.server.add_script_line(DISCONNECT, "");
var test_article = new ClientSession(new_endpoint());
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
test_article.connect_async.begin(
CONNECT_TIMEOUT, null, this.async_completion
);
test_article.connect_async.end(async_result());
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
test_article.login_async.begin(
new Credentials(PASSWORD, "test", "password"),
null,
this.async_completion
);
test_article.login_async.end(async_result());
assert_true(test_article.get_protocol_state() == AUTHORIZED);
test_article.logout_async.begin(null, this.async_completion);
test_article.logout_async.end(async_result());
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert_true(
result.succeeded,
result.error != null ? result.error.message : "Server result failed"
);
}
public void initiate_request_capabilities() throws GLib.Error {
this.server.add_script_line(
SEND_LINE, "* OK localhost test server ready"
);
this.server.add_script_line(RECEIVE_LINE, "a001 capability");
this.server.add_script_line(SEND_LINE, "* CAPABILITY IMAP4rev1 LOGIN");
this.server.add_script_line(SEND_LINE, "a001 OK enjoy");
this.server.add_script_line(RECEIVE_LINE, "a002 login test password");
this.server.add_script_line(SEND_LINE, "a002 OK ohhai");
this.server.add_script_line(RECEIVE_LINE, "a003 capability");
this.server.add_script_line(SEND_LINE, "* CAPABILITY IMAP4rev1");
this.server.add_script_line(SEND_LINE, "a003 OK thanks");
this.server.add_script_line(RECEIVE_LINE, "a004 LIST \"\" INBOX");
this.server.add_script_line(SEND_LINE, "* LIST (\\HasChildren) \".\" Inbox");
this.server.add_script_line(SEND_LINE, "a004 OK there");
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
var test_article = new ClientSession(new_endpoint());
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
test_article.connect_async.begin(
CONNECT_TIMEOUT, null, this.async_completion
);
test_article.connect_async.end(async_result());
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
test_article.initiate_session_async.begin(
new Credentials(PASSWORD, "test", "password"),
null,
this.async_completion
);
test_article.initiate_session_async.end(async_result());
assert_true(test_article.capabilities.supports_imap4rev1());
assert_false(test_article.capabilities.has_capability("AUTH"));
assert_int(2, test_article.capabilities.revision);
assert_string("Inbox", test_article.inbox.mailbox.name);
assert_true(test_article.inbox.mailbox.is_inbox);
test_article.disconnect_async.begin(null, this.async_completion);
test_article.disconnect_async.end(async_result());
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert_true(
result.succeeded,
result.error != null ? result.error.message : "Server result failed"
);
}
public void initiate_implicit_capabilities() throws GLib.Error {
this.server.add_script_line(
SEND_LINE, "* OK [CAPABILITY IMAP4rev1 LOGIN] localhost test server ready"
);
this.server.add_script_line(RECEIVE_LINE, "a001 login test password");
this.server.add_script_line(SEND_LINE, "a001 OK [CAPABILITY IMAP4rev1] ohhai");
this.server.add_script_line(RECEIVE_LINE, "a002 LIST \"\" INBOX");
this.server.add_script_line(SEND_LINE, "* LIST (\\HasChildren) \".\" Inbox");
this.server.add_script_line(SEND_LINE, "a002 OK there");
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
var test_article = new ClientSession(new_endpoint());
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
test_article.connect_async.begin(
CONNECT_TIMEOUT, null, this.async_completion
);
test_article.connect_async.end(async_result());
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
test_article.initiate_session_async.begin(
new Credentials(PASSWORD, "test", "password"),
null,
this.async_completion
);
test_article.initiate_session_async.end(async_result());
assert_true(test_article.capabilities.supports_imap4rev1());
assert_false(test_article.capabilities.has_capability("AUTH"));
assert_int(2, test_article.capabilities.revision);
assert_string("Inbox", test_article.inbox.mailbox.name);
assert_true(test_article.inbox.mailbox.is_inbox);
test_article.disconnect_async.begin(null, this.async_completion);
test_article.disconnect_async.end(async_result());
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert_true(
result.succeeded,
result.error != null ? result.error.message : "Server result failed"
);
}
public void initiate_namespace() throws GLib.Error {
this.server.add_script_line(
SEND_LINE,
"* OK [CAPABILITY IMAP4rev1 LOGIN] localhost test server ready"
);
this.server.add_script_line(
RECEIVE_LINE, "a001 login test password"
);
this.server.add_script_line(
SEND_LINE, "a001 OK [CAPABILITY IMAP4rev1 NAMESPACE] ohhai"
);
this.server.add_script_line(
RECEIVE_LINE, "a002 LIST \"\" INBOX"
);
this.server.add_script_line(
SEND_LINE, "* LIST (\\HasChildren) \".\" Inbox"
);
this.server.add_script_line(
SEND_LINE, "a002 OK there"
);
this.server.add_script_line(
RECEIVE_LINE, "a003 NAMESPACE"
);
this.server.add_script_line(
SEND_LINE,
"""* NAMESPACE (("INBOX." ".")) (("user." ".")) (("shared." "."))"""
);
this.server.add_script_line(SEND_LINE, "a003 OK there");
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
var test_article = new ClientSession(new_endpoint());
assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
test_article.connect_async.begin(
CONNECT_TIMEOUT, null, this.async_completion
);
test_article.connect_async.end(async_result());
assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
test_article.initiate_session_async.begin(
new Credentials(PASSWORD, "test", "password"),
null,
this.async_completion
);
test_article.initiate_session_async.end(async_result());
assert_int(1, test_article.get_personal_namespaces().size);
assert_string(
"INBOX.", test_article.get_personal_namespaces()[0].prefix
);
assert_int(1, test_article.get_shared_namespaces().size);
assert_string(
"shared.", test_article.get_shared_namespaces()[0].prefix
);
assert_int(1, test_article.get_other_users_namespaces().size);
assert_string(
"user.", test_article.get_other_users_namespaces()[0].prefix
);
test_article.disconnect_async.begin(null, this.async_completion);
test_article.disconnect_async.end(async_result());
TestServer.Result result = this.server.wait_for_script(this.main_loop);
assert_true(
result.succeeded,
result.error != null ? result.error.message : "Server result failed"
);
}
protected Endpoint new_endpoint() {
return new Endpoint(this.server.get_client_address(), NONE, 10);
}
}

View file

@ -51,7 +51,7 @@ class Geary.Imap.DeserializerTest : TestCase {
}
public override void tear_down() {
this.deser.stop_async.begin((obj, ret) => { async_complete(ret); });
this.deser.stop_async.begin(this.async_completion);
async_result();
this.stream = null;
}
@ -62,7 +62,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(bytes.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert_int(2, message.size);
@ -76,7 +76,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(bytes.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert_int(2, message.size);
@ -90,7 +90,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(bytes.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert_int(2, message.size);
@ -104,7 +104,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(bytes.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert_int(2, message.size);
@ -118,7 +118,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(bytes.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert_int(2, message.size);
@ -136,7 +136,7 @@ class Geary.Imap.DeserializerTest : TestCase {
// deserializer currently silently ignores lines with
// malformed lists and continues parsing, so we get to the end
// of the stream.
this.process.begin(Expect.EOS, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.EOS, this.async_completion);
this.process.end(async_result());
}
@ -150,7 +150,7 @@ class Geary.Imap.DeserializerTest : TestCase {
// deserializer currently silently ignores lines with
// malformed lists and continues parsing, so we get to the end
// of the stream.
this.process.begin(Expect.EOS, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.EOS, this.async_completion);
this.process.end(async_result());
}
@ -159,7 +159,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(greeting.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert(message.to_string() == greeting);
@ -170,7 +170,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(greeting.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert(message.to_string() == greeting);
@ -182,7 +182,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(greeting.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert(message.to_string() == parsed);
@ -193,7 +193,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(flags.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.DESER_FAIL, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.DESER_FAIL, this.async_completion);
this.process.end(async_result());
}
@ -202,7 +202,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(flags.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert(message.to_string() == flags);
@ -213,7 +213,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(flags.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert(message.to_string() == flags);
@ -224,7 +224,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(flags.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert(message.to_string() == flags);
@ -239,7 +239,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(flags.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert(message.to_string() == expected);
@ -250,12 +250,12 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(flags.data);
this.stream.add_data(EOL.data);
this.process.begin(Expect.DESER_FAIL, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.DESER_FAIL, this.async_completion);
this.process.end(async_result());
}
public void instant_eos() throws Error {
this.process.begin(Expect.EOS, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.EOS, this.async_completion);
this.process.end(async_result());
assert(this.deser.is_halted());
}
@ -265,12 +265,16 @@ class Geary.Imap.DeserializerTest : TestCase {
this.stream.add_data(bye.data);
bool eos = false;
this.deser.eos.connect(() => { eos = true; });
this.deser.end_of_stream.connect(() => { eos = true; });
this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); });
this.process.begin(Expect.MESSAGE, this.async_completion);
RootParameters? message = this.process.end(async_result());
assert(message.to_string() == bye);
assert(eos);
assert_false(eos);
this.process.begin(Expect.EOS, this.async_completion);
assert_true(eos);
assert(this.deser.is_halted());
}
@ -283,7 +287,7 @@ class Geary.Imap.DeserializerTest : TestCase {
this.deser.parameters_ready.connect((param) => { message = param; });
this.deser.bytes_received.connect((count) => { bytes_received += count; });
this.deser.eos.connect((param) => { eos = true; });
this.deser.end_of_stream.connect((param) => { eos = true; });
this.deser.deserialize_failure.connect(() => { deserialize_failure = true; });
this.deser.receive_failure.connect((err) => { receive_failure = true;});

View file

@ -57,8 +57,11 @@ This is the second line.
add_test("get_recipients", get_recipients);
add_test("get_searchable_body", get_searchable_body);
add_test("get_searchable_recipients", get_searchable_recipients);
add_test("get_network_buffer", get_network_buffer);
add_test("from_composed_email", from_composed_email);
add_test("from_composed_email_inline_attachments", from_composed_email_inline_attachments);
add_test("get_network_buffer", get_network_buffer);
add_test("get_network_buffer_dot_stuff", get_network_buffer_dot_stuff);
add_test("get_network_buffer_long_ascii_line", get_network_buffer_long_ascii_line);
}
public void basic_message_from_buffer() throws Error {
@ -209,10 +212,112 @@ This is the second line.
public void get_network_buffer() throws Error {
Message test = resource_to_message(BASIC_TEXT_PLAIN);
Memory.Buffer buffer = test.get_network_buffer(true);
Memory.Buffer buffer = test.get_network_buffer(true);
assert_true(buffer.to_string() == NETWORK_BUFFER_EXPECTED, "Network buffer differs");
}
public void get_network_buffer_dot_stuff() throws GLib.Error {
RFC822.MailboxAddress to = new RFC822.MailboxAddress(
"Test", "test@example.com"
);
RFC822.MailboxAddress from = new RFC822.MailboxAddress(
"Sender", "sender@example.com"
);
Geary.ComposedEmail composed = new Geary.ComposedEmail(
new GLib.DateTime.now_local(),
new Geary.RFC822.MailboxAddresses.single(from)
).set_to(new Geary.RFC822.MailboxAddresses.single(to));
composed.body_text = ".newline\n.\n";
this.message_from_composed_email.begin(
composed,
this.async_completion
);
Geary.RFC822.Message message = message_from_composed_email.end(async_result());
string message_data = message.get_network_buffer(true).to_string();
assert_true(message_data.has_suffix("..newline\r\n..\r\n"));
}
public void get_network_buffer_long_ascii_line() throws GLib.Error {
RFC822.MailboxAddress to = new RFC822.MailboxAddress(
"Test", "test@example.com"
);
RFC822.MailboxAddress from = new RFC822.MailboxAddress(
"Sender", "sender@example.com"
);
Geary.ComposedEmail composed = new Geary.ComposedEmail(
new GLib.DateTime.now_local(),
new Geary.RFC822.MailboxAddresses.single(from)
).set_to(new Geary.RFC822.MailboxAddresses.single(to));
GLib.StringBuilder buf = new GLib.StringBuilder();
for (int i = 0; i < 2000; i++) {
buf.append("long ");
}
//composed.body_text = buf.str;
composed.body_html = "<p>%s<p>".printf(buf.str);
this.message_from_composed_email.begin(
composed,
this.async_completion
);
Geary.RFC822.Message message = message_from_composed_email.end(async_result());
string message_data = message.get_network_buffer(true).to_string();
foreach (var line in message_data.split("\n")) {
assert_true(line.length < 1000, line);
}
}
public void from_composed_email() throws GLib.Error {
RFC822.MailboxAddress to = new RFC822.MailboxAddress(
"Test", "test@example.com"
);
RFC822.MailboxAddress from = new RFC822.MailboxAddress(
"Sender", "sender@example.com"
);
Geary.ComposedEmail composed = new Geary.ComposedEmail(
new GLib.DateTime.now_local(),
new Geary.RFC822.MailboxAddresses.single(from)
).set_to(new Geary.RFC822.MailboxAddresses.single(to));
composed.body_text = "hello";
this.message_from_composed_email.begin(
composed,
this.async_completion
);
Geary.RFC822.Message message = message_from_composed_email.end(async_result());
assert_non_null(message.to, "to");
assert_non_null(message.from, "from");
assert_non_null(message.date, "date");
assert_non_null(message.message_id, "message_id");
string message_data = message.to_string();
assert_true(
message_data.contains("To: Test <test@example.com>\n"),
"to data"
);
assert_true(
message_data.contains("From: Sender <sender@example.com>\n"),
"from data"
);
assert_true(
message_data.contains("Message-Id: "),
"message-id data"
);
assert_true(
message_data.contains("Date: "),
"date data"
);
assert_true(
message_data.contains("hello\n"),
"body data"
);
}
public void from_composed_email_inline_attachments() throws Error {
RFC822.MailboxAddress to = new RFC822.MailboxAddress(
"Test", "test@example.com"
@ -238,7 +343,7 @@ This is the second line.
this.message_from_composed_email.begin(
composed,
async_complete_full
this.async_completion
);
Geary.RFC822.Message message = message_from_composed_email.end(async_result());

View file

@ -10,6 +10,9 @@ class Geary.RFC822.Utils.Test : TestCase {
public Test() {
base("Geary.RFC822.Utils.Test");
add_test("to_preview_text", to_preview_text);
add_test("best_encoding_default", best_encoding_default);
add_test("best_encoding_long_line", best_encoding_long_line);
add_test("best_encoding_binary", best_encoding_binary);
}
public void to_preview_text() throws Error {
@ -21,6 +24,34 @@ class Geary.RFC822.Utils.Test : TestCase {
HTML_BODY_EXPECTED);
}
public void best_encoding_default() throws GLib.Error {
string test = "abc";
var stream = new GMime.StreamMem.with_buffer(test.data);
get_best_encoding.begin(stream, 7BIT, null, this.async_completion);
var encoding = get_best_encoding.end(async_result());
assert_true(encoding == DEFAULT);
}
public void best_encoding_long_line() throws GLib.Error {
GLib.StringBuilder buf = new GLib.StringBuilder();
for (int i = 0; i < 2000; i++) {
buf.append("long ");
}
var stream = new GMime.StreamMem.with_buffer(buf.str.data);
get_best_encoding.begin(stream, 7BIT, null, this.async_completion);
var encoding = get_best_encoding.end(async_result());
assert_true(encoding == QUOTEDPRINTABLE);
}
public void best_encoding_binary() throws GLib.Error {
uint8 test[] = { 0x20, 0x00, 0x20 };
var stream = new GMime.StreamMem.with_buffer(test);
get_best_encoding.begin(stream, 7BIT, null, this.async_completion);
var encoding = get_best_encoding.end(async_result());
assert_true(encoding == BASE64);
}
public static string PLAIN_BODY_ENCODED = "-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA512\n\n=============================================================================\nFreeBSD-EN-16:11.vmbus Errata Notice\n The FreeBSD Project\n\nTopic: Avoid using spin locks for channel message locks\n\nCategory: core\nModule: vmbus\nAnnounced: 2016-08-12\nCredits: Microsoft OSTC\nAffects: FreeBSD 10.3\nCorrected: 2016-06-15 09:52:01 UTC (stable/10, 10.3-STABLE)\n 2016-08-12 04:01:16 UTC (releng/10.3, 10.3-RELEASE-p7)\n\nFor general information regarding FreeBSD Errata Notices and Security\nAdvisories, including descriptions of the fields above, security\nbranches, and the following sections, please visit\n<URL:https://security.FreeBSD.org/>.\n";
public static string PLAIN_BODY_EXPECTED = "FreeBSD-EN-16:11.vmbus Errata Notice The FreeBSD Project Topic: Avoid using spin locks for channel message locks Category: core Module: vmbus Announced: 2016-08-12 Credits: Microsoft OSTC Affects: FreeBSD 10.3 Corrected: 2016-06-15 09:52:01 UTC (stable/10, 10.3-STABLE) 2016-08-12 04:01:16 UTC (releng/10.3, 10.3-RELEASE-p7) For general information regarding FreeBSD Errata Notices and Security Advisories, including descriptions of the fields above, security branches, and the following sections, please visit <URL:https://security.FreeBSD.org/>.";

View file

@ -87,7 +87,7 @@ class Geary.TimeoutManagerTest : TestCase {
this.main_loop.iteration(true);
}
assert_epsilon(timer.elapsed(), 1.0, SECONDS_EPSILON);
assert_double(timer.elapsed(), 1.0, SECONDS_EPSILON);
}
public void milliseconds() throws Error {
@ -101,7 +101,7 @@ class Geary.TimeoutManagerTest : TestCase {
this.main_loop.iteration(true);
}
assert_epsilon(timer.elapsed(), 0.1, MILLISECONDS_EPSILON);
assert_double(timer.elapsed(), 0.1, MILLISECONDS_EPSILON);
}
public void repeat_forever() throws Error {
@ -118,11 +118,7 @@ class Geary.TimeoutManagerTest : TestCase {
}
timer.stop();
assert_epsilon(timer.elapsed(), 2.0, SECONDS_EPSILON * 2);
}
private inline void assert_epsilon(double actual, double expected, double epsilon) {
assert(actual + epsilon >= expected && actual - epsilon <= expected);
assert_double(timer.elapsed(), 2.0, SECONDS_EPSILON * 2);
}
}

View file

@ -33,18 +33,18 @@ class Integration.Imap.ClientSession : TestCase {
}
public override void tear_down() throws GLib.Error {
if (this.session.get_protocol_state(null) != NOT_CONNECTED) {
this.session.disconnect_async.begin(null, async_complete_full);
if (this.session.get_protocol_state() != NOT_CONNECTED) {
this.session.disconnect_async.begin(null, this.async_completion);
this.session.disconnect_async.end(async_result());
}
this.session = null;
}
public void session_connect() throws GLib.Error {
this.session.connect_async.begin(null, async_complete_full);
this.session.connect_async.begin(2, null, this.async_completion);
this.session.connect_async.end(async_result());
this.session.disconnect_async.begin(null, async_complete_full);
this.session.disconnect_async.begin(null, this.async_completion);
this.session.disconnect_async.end(async_result());
}
@ -55,7 +55,7 @@ class Integration.Imap.ClientSession : TestCase {
PASSWORD, "automated-integration-test", "password"
);
this.session.login_async.begin(
password_creds, null, async_complete_full
password_creds, null, this.async_completion
);
try {
this.session.login_async.end(async_result());
@ -78,7 +78,7 @@ class Integration.Imap.ClientSession : TestCase {
OAUTH2, "automated-integration-test", "password"
);
this.session.login_async.begin(
oauth2_creds, null, async_complete_full
oauth2_creds, null, this.async_completion
);
try {
this.session.login_async.end(async_result());
@ -92,13 +92,13 @@ class Integration.Imap.ClientSession : TestCase {
do_connect();
this.session.initiate_session_async.begin(
this.config.credentials, null, async_complete_full
this.config.credentials, null, this.async_completion
);
this.session.initiate_session_async.end(async_result());
}
private void do_connect() throws GLib.Error {
this.session.connect_async.begin(null, async_complete_full);
this.session.connect_async.begin(5, null, this.async_completion);
this.session.connect_async.end(async_result());
}

View file

@ -37,7 +37,7 @@ class Integration.Smtp.ClientSession : TestCase {
public override void tear_down() throws GLib.Error {
try {
this.session.logout_async.begin(false, null, async_complete_full);
this.session.logout_async.begin(false, null, this.async_completion);
this.session.logout_async.end(async_result());
} catch (GLib.Error err) {
// Oh well
@ -52,7 +52,7 @@ class Integration.Smtp.ClientSession : TestCase {
"deliberately-invalid-password"
);
this.session.login_async.begin(
password_creds, null, async_complete_full
password_creds, null, this.async_completion
);
try {
this.session.login_async.end(async_result());
@ -69,7 +69,7 @@ class Integration.Smtp.ClientSession : TestCase {
"deliberately-invalid-token"
);
this.session.login_async.begin(
oauth2_creds, null, async_complete_full
oauth2_creds, null, this.async_completion
);
try {
this.session.login_async.end(async_result());
@ -97,7 +97,7 @@ class Integration.Smtp.ClientSession : TestCase {
"Geary integration test",
this.config.credentials.user
),
async_complete_full
this.async_completion
);
Geary.RFC822.Message message = new_message.end(async_result());
@ -105,14 +105,14 @@ class Integration.Smtp.ClientSession : TestCase {
return_path,
message,
null,
async_complete_full
this.async_completion
);
this.session.send_email_async.end(async_result());
}
private void do_connect() throws GLib.Error {
this.session.login_async.begin(
this.config.credentials, null, async_complete_full
this.config.credentials, null, this.async_completion
);
this.session.login_async.end(async_result());
}

View file

@ -5,24 +5,24 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
class Components.PageStateTest : WebViewTestCase<WebView> {
class ClientPageStateTest : ClientWebViewTestCase<ClientWebView> {
private class TestWebView : Components.WebView {
private class TestClientWebView : ClientWebView {
public TestWebView(Application.Configuration config) {
public TestClientWebView(Application.Configuration config) {
base(config);
}
}
public PageStateTest() {
base("Components.PageStateTest");
public ClientPageStateTest() {
base("ClientPageStateTest");
add_test("content_loaded", content_loaded);
try {
WebView.load_resources(GLib.File.new_for_path("/tmp"));
ClientWebView.load_resources(GLib.File.new_for_path("/tmp"));
} catch (GLib.Error err) {
assert_not_reached();
}
@ -45,7 +45,7 @@ class Components.PageStateTest : WebViewTestCase<WebView> {
assert(content_loaded_triggered);
}
protected override WebView set_up_test_view() {
protected override ClientWebView set_up_test_view() {
WebKit.UserScript test_script;
test_script = new WebKit.UserScript(
"var geary = new PageState()",
@ -55,7 +55,7 @@ class Components.PageStateTest : WebViewTestCase<WebView> {
null
);
WebView view = new TestWebView(this.config);
ClientWebView view = new TestClientWebView(this.config);
view.get_user_content_manager().add_script(test_script);
return view;
}

View file

@ -5,7 +5,7 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
class Composer.PageStateTest : Components.WebViewTestCase<Composer.WebView> {
class Composer.PageStateTest : ClientWebViewTestCase<Composer.WebView> {
public const string COMPLETE_BODY_TEMPLATE =
"""<div id="geary-body" dir="auto">%s<div><br></div><div><br></div></div><div id="geary-signature" dir="auto"></div>""";

View file

@ -5,7 +5,7 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
class ConversationPageStateTest : Components.WebViewTestCase<ConversationWebView> {
class ConversationPageStateTest : ClientWebViewTestCase<ConversationWebView> {
public ConversationPageStateTest() {
base("ConversationPageStateTest");

View file

@ -3,6 +3,7 @@ subdir('data')
geary_test_lib_sources = [
'mock-object.vala',
'test-case.vala',
'test-server.vala',
]
geary_test_engine_sources = [
@ -41,6 +42,8 @@ geary_test_engine_sources = [
'engine/imap/message/imap-mailbox-specifier-test.vala',
'engine/imap/parameter/imap-list-parameter-test.vala',
'engine/imap/response/imap-namespace-response-test.vala',
'engine/imap/transport/imap-client-connection-test.vala',
'engine/imap/transport/imap-client-session-test.vala',
'engine/imap/transport/imap-deserializer-test.vala',
'engine/imap-db/imap-db-account-test.vala',
'engine/imap-db/imap-db-attachment-test.vala',
@ -82,16 +85,16 @@ geary_test_client_sources = [
'client/accounts/accounts-manager-test.vala',
'client/application/application-client-test.vala',
'client/application/application-configuration-test.vala',
'client/components/client-web-view-test.vala',
'client/components/client-web-view-test-case.vala',
'client/components/components-validator-test.vala',
'client/components/components-web-view-test-case.vala',
'client/components/components-web-view-test.vala',
'client/composer/composer-web-view-test.vala',
'client/util/util-avatar-test.vala',
'client/util/util-cache-test.vala',
'client/util/util-email-test.vala',
'client/util/util-js-test.vala',
'js/components-page-state-test.vala',
'js/client-page-state-test.vala',
'js/composer-page-state-test.vala',
'js/conversation-page-state-test.vala',

View file

@ -67,19 +67,62 @@ private class UintArgument : Object, Argument {
* expectations, such that the mock method should throw a specific
* error or return a specific value or object.
*/
public class ExpectedCall : Object {
public class ExpectedCall : GLib.Object {
/** Options for handling async calls. */
public enum AsyncCallOptions {
/** Check and return from the expected call immediately. */
CONTINUE,
/**
* Check and return from the expected call when idle.
*
* This will yield when the call is made, being resuming when
* idle.
*/
CONTINUE_AT_IDLE,
/**
* Check and return from the expected call when requested.
*
* This will yield when the call is made, resuming when {@link
* ExpectedCall.async_resume} is called.
*/
PAUSE;
}
/** The name of the expected call. */
public string name { get; private set; }
public Error? throw_error { get; private set; default = null; }
public Object? return_object { get; private set; default = null; }
public Variant? return_value { get; private set; default = null; }
/** Determines how async calls are handled. */
public AsyncCallOptions async_behaviour {
get; private set; default = CONTINUE;
}
/** The error to be thrown by the call, if any. */
public GLib.Error? throw_error { get; private set; default = null; }
/** An object to be returned by the call, if any. */
public GLib.Object? return_object { get; private set; default = null; }
/** A value to be returned by the call, if any. */
public GLib.Variant? return_value { get; private set; default = null; }
/** Determines if the call has been made or not. */
public bool was_called { get; private set; default = false; }
/** Determines if an async call has been resumed or not. */
public bool async_resumed { get; private set; default = false; }
// XXX Arrays can't be GObject properties :(
internal Object[]? expected_args = null;
private Object[]? called_args = null;
internal GLib.Object[]? expected_args = null;
private GLib.Object[]? called_args = null;
internal unowned GLib.SourceFunc? async_callback = null;
internal ExpectedCall(string name, Object[]? args) {
@ -87,21 +130,50 @@ public class ExpectedCall : Object {
this.expected_args = args;
}
/** Sets the behaviour for an async call. */
public ExpectedCall async_call(AsyncCallOptions behaviour) {
this.async_behaviour = behaviour;
return this;
}
/** Sets an object that the call should return. */
public ExpectedCall returns_object(Object value) {
this.return_object = value;
return this;
}
/** Sets a bool value that the call should return. */
public ExpectedCall returns_boolean(bool value) {
this.return_value = new GLib.Variant.boolean(value);
return this;
}
public ExpectedCall @throws(Error err) {
/** Sets an error that the cal should throw. */
public ExpectedCall @throws(GLib.Error err) {
this.throw_error = err;
return this;
}
/**
* Resumes an async call that has been paused.
*
* Throws an assertion error if the call has not yet been called
* or has not been paused.
*/
public void async_resume() throws GLib.Error {
assert_true(
this.async_callback != null,
"Async call not called, could not resume"
);
assert_false(
this.async_resumed,
"Async call already resumed"
);
this.async_resumed = true;
this.async_callback();
}
/** Determines if an argument was given in the specific position. */
public T called_arg<T>(int pos) throws GLib.Error {
assert_true(
this.called_args != null && this.called_args.length >= (pos + 1),
@ -149,7 +221,7 @@ public class ExpectedCall : Object {
* assert_expectations} to ensure that the actual calls made matched
* those expected.
*/
public interface MockObject {
public interface MockObject : GLib.Object {
public static Object box_arg<T>(T value) {
@ -184,39 +256,70 @@ public interface MockObject {
}
protected bool boolean_call(string name, Object[] args, bool default_return)
throws Error {
throws GLib.Error {
ExpectedCall? expected = call_made(name, args);
return check_boolean_call(expected, default_return);
}
bool return_value = default_return;
if (expected.return_value != null) {
return_value = expected.return_value.get_boolean();
protected async bool boolean_call_async(string name,
Object[] args,
bool default_return)
throws GLib.Error {
ExpectedCall? expected = call_made(name, args);
if (async_call_yield(expected, this.boolean_call_async.callback)) {
yield;
}
return return_value;
return check_boolean_call(expected, default_return);
}
protected R object_call<R>(string name, Object[] args, R default_return)
throws Error {
ExpectedCall? expected = call_made(name, args);
R? return_object = default_return;
if (expected.return_object != null) {
return_object = (R) expected.return_object;
}
return return_object;
}
protected R object_or_throw_call<R>(string name, Object[] args, GLib.Error default_error)
throws GLib.Error {
ExpectedCall? expected = call_made(name, args);
if (expected.return_object == null) {
throw default_error;
}
return expected.return_object;
return check_object_call(expected, default_return);
}
protected void void_call(string name, Object[] args) throws Error {
call_made(name, args);
protected async R object_call_async<R>(string name,
Object[] args,
R default_return)
throws GLib.Error {
ExpectedCall? expected = call_made(name, args);
if (async_call_yield(expected, this.object_call_async.callback)) {
yield;
}
return check_object_call(expected, default_return);
}
protected R object_or_throw_call<R>(string name,
Object[] args,
GLib.Error default_error)
throws GLib.Error {
ExpectedCall? expected = call_made(name, args);
return check_object_or_throw_call(expected, default_error);
}
protected async R object_or_throw_call_async<R>(string name,
Object[] args,
GLib.Error default_error)
throws GLib.Error {
ExpectedCall? expected = call_made(name, args);
if (async_call_yield(expected, this.object_or_throw_call_async.callback)) {
yield;
}
return check_object_or_throw_call(expected, default_error);
}
protected void void_call(string name, Object[] args) throws GLib.Error {
ExpectedCall? expected = call_made(name, args);
check_for_exception(expected);
}
protected async void void_call_async(string name, Object[] args)
throws GLib.Error {
ExpectedCall? expected = call_made(name, args);
if (async_call_yield(expected, this.void_call_async.callback)) {
yield;
}
check_for_exception(expected);
}
private ExpectedCall? call_made(string name, Object[] args) throws Error {
@ -229,11 +332,6 @@ public interface MockObject {
}
expected.called(args);
if (expected.throw_error != null) {
throw expected.throw_error;
}
return expected;
}
@ -280,4 +378,65 @@ public interface MockObject {
);
}
private bool async_call_yield(ExpectedCall expected,
GLib.SourceFunc @callback) {
var @yield = false;
if (expected.async_behaviour != CONTINUE) {
expected.async_callback = @callback;
if (expected.async_behaviour == CONTINUE_AT_IDLE) {
GLib.Idle.add(() => {
try {
expected.async_resume();
} catch (GLib.Error err) {
critical(
"Async call already resumed: %s", err.message
);
}
return GLib.Source.REMOVE;
});
}
@yield = true;
}
return @yield;
}
private inline bool check_boolean_call(ExpectedCall expected,
bool default_return)
throws GLib.Error {
check_for_exception(expected);
bool return_value = default_return;
if (expected.return_value != null) {
return_value = expected.return_value.get_boolean();
}
return return_value;
}
private inline R check_object_call<R>(ExpectedCall expected,
R default_return)
throws GLib.Error {
check_for_exception(expected);
R? return_object = default_return;
if (expected.return_object != null) {
return_object = (R) expected.return_object;
}
return return_object;
}
private inline R check_object_or_throw_call<R>(ExpectedCall expected,
GLib.Error default_error)
throws GLib.Error {
check_for_exception(expected);
if (expected.return_object == null) {
throw default_error;
}
return expected.return_object;
}
private inline void check_for_exception(ExpectedCall expected)
throws GLib.Error {
if (expected.throw_error != null) {
throw expected.throw_error;
}
}
}

View file

@ -96,6 +96,10 @@ public void assert_int64(int64 expected, int64 actual, string? context = null)
}
}
public void assert_double(double actual, double expected, double epsilon) {
assert(actual + epsilon >= expected && actual - epsilon <= expected);
}
public void assert_uint(uint expected, uint actual, string? context = null)
throws GLib.Error {
if (expected != actual) {
@ -196,7 +200,108 @@ public void delete_file(File parent) throws GLib.Error {
}
public abstract class TestCase : Object {
/**
* Allows non-async code to wait for async calls to be completed.
*
* To use instances of this class, call an async function or method
* using the `begin()` form, passing {@link async_complete} as
* completion argument (that is, the last argument):
*
* {{{
* var waiter = new AsyncResultWaiter();
* my_async_call.begin("foo", waiter.async_completion);
* }}}
*
* Then, when you want to ensure the call is complete, pass the result
* of calling {@link async_result} to its `end()` form:
*
* {{{
* my_async_call.end(waiter.async_result());
* }}}
*
* This will block until the async call has completed.
*
* Note that {@link TestCase} exposes the same interface, so it is
* usually easier to just call those when testing a single async call,
* or multiple, non-interleaved async calls.
*
* This class is implemented as a FIFO queue of {@link
* GLib.AsyncResult} instances, and thus can be used for waiting for
* multiple calls. Note however the ordering depends on the order in
* which the async calls being invoked are executed and are
* completed. Thus if testing multiple interleaved async calls, you
* should probably use an instance of this class per call.
*/
public class AsyncResultWaiter : GLib.Object {
/** The main loop that is executed when waiting for async results. */
public GLib.MainContext main_loop { get; construct set; }
private GLib.AsyncQueue<GLib.AsyncResult> results =
new GLib.AsyncQueue<GLib.AsyncResult>();
/**
* Constructs a new waiter.
*
* @param main_loop a main loop context to execute when waiting
* for an async result
*/
public AsyncResultWaiter(GLib.MainContext main_loop) {
Object(main_loop: main_loop);
}
/**
* The last argument of an async call to be tested.
*
* Records the given {@link GLib.AsyncResult}, adding it to the
* internal FIFO queue. This method should be called as the
* completion of an async call to be tested.
*
* To use it, pass as the last argument to the `begin()` form of
* the async call:
*
* {{{
* var waiter = new AsyncResultWaiter();
* my_async_call.begin("foo", waiter.async_completion);
* }}}
*/
public void async_completion(GLib.Object? object,
GLib.AsyncResult result) {
this.results.push(result);
// Notify the loop so that if async_result() has already been
// called, that method won't block.
this.main_loop.wakeup();
}
/**
* Waits for async calls to complete, returning the most recent one.
*
* This returns the first {@link GLib.AsyncResult} from the
* internal FIFO queue that has been provided by {@link
* async_completion}. If none are available, it will pump the main
* loop, blocking until one becomes available.
*
* To use it, pass its return value as the argument to the `end()`
* call:
*
* {{{
* my_async_call.end(waiter.async_result());
* }}}
*/
public GLib.AsyncResult async_result() {
GLib.AsyncResult? result = this.results.try_pop();
while (result == null) {
this.main_loop.iteration(true);
result = this.results.try_pop();
}
return result;
}
}
public abstract class TestCase : GLib.Object {
/** GLib.File URI for resources in test/data. */
@ -217,12 +322,13 @@ public abstract class TestCase : Object {
private GLib.TestSuite suite;
private Adaptor[] adaptors = new Adaptor[0];
private AsyncQueue<AsyncResult> async_results = new AsyncQueue<AsyncResult>();
private AsyncResultWaiter async_waiter;
public delegate void TestMethod() throws Error;
protected TestCase(string name) {
this.suite = new GLib.TestSuite(name);
this.async_waiter = new AsyncResultWaiter(this.main_loop);
}
public void add_test(string name, owned TestMethod test) {
@ -249,28 +355,23 @@ public abstract class TestCase : Object {
return this.suite;
}
protected void async_complete(AsyncResult result) {
this.async_results.push(result);
// notify the loop so that if async_result() has already been
// called, that method won't block
this.main_loop.wakeup();
}
protected void async_complete_full(GLib.Object? object,
AsyncResult result) {
this.async_results.push(result);
// notify the loop so that if async_result() has already been
// called, that method won't block
this.main_loop.wakeup();
/**
* Calls the same method on the test case's default async waiter.
*
* @see AsyncResultWaiter.async_completion
*/
protected void async_completion(GLib.Object? object,
AsyncResult result) {
this.async_waiter.async_completion(object, result);
}
/**
* Calls the same method on the test case's default async waiter.
*
* @see AsyncResultWaiter.async_result
*/
protected AsyncResult async_result() {
AsyncResult? result = null;
while (result == null) {
this.main_loop.iteration(true);
result = this.async_results.try_pop();
}
return result;
return this.async_waiter.async_result();
}
/**

View file

@ -39,6 +39,10 @@ int main(string[] args) {
Geary.RFC822.init();
Geary.HTML.init();
Geary.Logging.init();
if (GLib.Test.verbose()) {
GLib.Log.set_writer_func(Geary.Logging.default_log_writer);
Geary.Logging.log_to(GLib.stdout);
}
/*
* Hook up all tests into appropriate suites
@ -51,9 +55,9 @@ int main(string[] args) {
client.add_suite(new Accounts.ManagerTest().get_suite());
client.add_suite(new Application.ClientTest().get_suite());
client.add_suite(new Application.ConfigurationTest().get_suite());
client.add_suite(new Components.ValidatorTest().get_suite());
client.add_suite(new Components.WebViewTest().get_suite());
client.add_suite(new ClientWebViewTest().get_suite());
client.add_suite(new Composer.WebViewTest().get_suite());
client.add_suite(new Components.ValidatorTest().get_suite());
client.add_suite(new Util.Avatar.Test().get_suite());
client.add_suite(new Util.Cache.Test().get_suite());
client.add_suite(new Util.Email.Test().get_suite());
@ -61,7 +65,7 @@ int main(string[] args) {
TestSuite js = new TestSuite("js");
js.add_suite(new Components.PageStateTest().get_suite());
js.add_suite(new ClientPageStateTest().get_suite());
js.add_suite(new Composer.PageStateTest().get_suite());
js.add_suite(new ConversationPageStateTest().get_suite());

View file

@ -22,6 +22,10 @@ int main(string[] args) {
Geary.RFC822.init();
Geary.HTML.init();
Geary.Logging.init();
if (GLib.Test.verbose()) {
GLib.Log.set_writer_func(Geary.Logging.default_log_writer);
Geary.Logging.log_to(GLib.stdout);
}
/*
* Hook up all tests into appropriate suites
@ -46,20 +50,28 @@ int main(string[] args) {
engine.add_suite(new Geary.Db.DatabaseTest().get_suite());
engine.add_suite(new Geary.Db.VersionedDatabaseTest().get_suite());
engine.add_suite(new Geary.HTML.UtilTest().get_suite());
// Other IMAP tests rely on DataFormat working, so test that first
// Other IMAP tests rely on these working, so test them first
engine.add_suite(new Geary.Imap.DataFormatTest().get_suite());
engine.add_suite(new Geary.Imap.CreateCommandTest().get_suite());
engine.add_suite(new Geary.Imap.DeserializerTest().get_suite());
engine.add_suite(new Geary.Imap.FetchCommandTest().get_suite());
engine.add_suite(new Geary.Imap.ListParameterTest().get_suite());
engine.add_suite(new Geary.Imap.MailboxSpecifierTest().get_suite());
engine.add_suite(new Geary.Imap.NamespaceResponseTest().get_suite());
// Depends on IMAP commands working
engine.add_suite(new Geary.Imap.DeserializerTest().get_suite());
engine.add_suite(new Geary.Imap.ClientConnectionTest().get_suite());
engine.add_suite(new Geary.Imap.ClientSessionTest().get_suite());
engine.add_suite(new Geary.ImapDB.AccountTest().get_suite());
engine.add_suite(new Geary.ImapDB.AttachmentTest().get_suite());
engine.add_suite(new Geary.ImapDB.AttachmentIoTest().get_suite());
engine.add_suite(new Geary.ImapDB.DatabaseTest().get_suite());
engine.add_suite(new Geary.ImapDB.EmailIdentifierTest().get_suite());
engine.add_suite(new Geary.ImapDB.FolderTest().get_suite());
engine.add_suite(new Geary.ImapEngine.AccountProcessorTest().get_suite());
engine.add_suite(new Geary.ImapEngine.GenericAccountTest().get_suite());

222
test/test-server.vala Normal file
View file

@ -0,0 +1,222 @@
/*
* Copyright 2019 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
/**
* A simple mock server for testing network connections.
*
* To use it, unit tests should construct an instance as a fixture in
* set up, specify a test script by adding lines and then check the
* result, before stopping the server in tear down.
*/
public class TestServer : GLib.Object {
/** Possible actions a script may take. */
public enum Action {
/**
* The implicit first action.
*
* This does not need to be specified as a script action, it
* will always be taken when a client connects.
*/
CONNECTED,
/** Send a line to the client. */
SEND_LINE,
/** Receive a line from the client. */
RECEIVE_LINE,
/** Wait for the client to disconnect. */
WAIT_FOR_DISCONNECT,
/** Disconnect immediately. */
DISCONNECT;
}
/** A line of the server's script. */
public struct Line {
/** The action to take for this line. */
public Action action;
/**
* The value for the action.
*
* If sending, this string will be sent. If receiving, the
* expected line.
*/
public string value;
}
/** The result of executing a script line. */
public struct Result {
/** The expected action. */
public Line line;
/** Was the expected action successful. */
public bool succeeded;
/** The actual string sent by a client when not as expected. */
public string? actual;
/** In case of an error being thrown, the error itself. */
public GLib.Error? error;
}
private GLib.DataStreamNewlineType line_ending;
private uint16 port;
private GLib.ThreadedSocketService service =
new GLib.ThreadedSocketService(10);
private GLib.Cancellable running = new GLib.Cancellable();
private Gee.List<Line?> script = new Gee.ArrayList<Line?>();
private GLib.AsyncQueue<Result?> completion_queue =
new GLib.AsyncQueue<Result?>();
public TestServer(GLib.DataStreamNewlineType line_ending = CR_LF)
throws GLib.Error {
this.line_ending = line_ending;
this.port = this.service.add_any_inet_port(null);
this.service.run.connect((conn) => {
handle_connection(conn);
return true;
});
this.service.start();
}
public GLib.SocketConnectable get_client_address() {
return new GLib.NetworkAddress("localhost", this.port);
}
public void add_script_line(Action action, string value) {
this.script.add({ action, value });
}
public Result wait_for_script(GLib.MainContext loop) {
Result? result = null;
while (result == null) {
loop.iteration(false);
result = this.completion_queue.try_pop();
}
return result;
}
public void stop() {
this.service.stop();
this.running.cancel();
}
private void handle_connection(GLib.SocketConnection connection) {
debug("Connected");
var input = new GLib.DataInputStream(
connection.input_stream
);
input.set_newline_type(this.line_ending);
var output = new GLib.DataOutputStream(
connection.output_stream
);
Line connected_line = { CONNECTED, "" };
Result result = { connected_line, true, null, null };
foreach (var line in this.script) {
result.line = line;
switch (line.action) {
case SEND_LINE:
debug("Sending: %s", line.value);
try {
output.put_string(line.value);
switch (this.line_ending) {
case CR:
output.put_byte('\r');
break;
case LF:
output.put_byte('\n');
break;
default:
output.put_byte('\r');
output.put_byte('\n');
break;
}
} catch (GLib.Error err) {
result.succeeded = false;
result.error = err;
}
break;
case RECEIVE_LINE:
debug("Waiting for: %s", line.value);
try {
size_t len;
string? received = input.read_line(out len, this.running);
if (received == null || received != line.value) {
result.succeeded = false;
result.actual = received;
}
} catch (GLib.Error err) {
result.succeeded = false;
result.error = err;
}
break;
case WAIT_FOR_DISCONNECT:
debug("Waiting for disconnect");
var socket = connection.get_socket();
try {
uint8 buffer[4096];
while (socket.receive_with_blocking(buffer, true) > 0) { }
} catch (GLib.Error err) {
result.succeeded = false;
result.error = err;
}
break;
case DISCONNECT:
debug("Disconnecting");
try {
connection.close(this.running);
} catch (GLib.Error err) {
result.succeeded = false;
result.error = err;
}
break;
}
if (!result.succeeded) {
break;
}
}
if (result.succeeded) {
debug("Done");
} else if (result.error != null) {
warning("Error: %s", result.error.message);
} else if (result.line.action == RECEIVE_LINE) {
warning("Received unexpected line: %s", result.actual ?? "(null)");
} else {
warning("Failed for unknown reason");
}
if (connection.is_connected()) {
try {
connection.close(this.running);
} catch (GLib.Error err) {
warning(
"Error closing test server connection: %s", err.message
);
}
}
this.completion_queue.push(result);
}
}