Geary.App.ConversationMonitor: Fix more races when starting/stopping

Ensure that if stopping the conversation monitor while it is waiting
for the folder to open that the folder isn't closed, and if an error
is thrown when opening the folder that it gets thrown by
::start_monitoring anyway.

Hopefully fixes #741
This commit is contained in:
Michael Gratton 2020-04-10 14:55:18 +10:00 committed by Michael James Gratton
parent a385ce8fc2
commit 991c9ef5d7
2 changed files with 84 additions and 12 deletions

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);
@ -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);