Keep main loop running until FilesystemCopierAction under test has stopped.
This CL fixes FilesystemCopierActionTest.RunAsRootTerminateEarlyTest
such that it does not prematurely terminate the glib main loop before
FilesystemCopierAction::AsyncReadReadyCallback is invoked upon the
cancellation of the action.
BUG=chromium-os:34448
TEST=Run unit tests repeatedly with glib 2.30 and 2.32.
Change-Id: I26c15811ee41d16df731c4acbe24ed48c8739dde
Reviewed-on: https://gerrit.chromium.org/gerrit/34976
Commit-Ready: Ben Chan <benchan@chromium.org>
Tested-by: Ben Chan <benchan@chromium.org>
Reviewed-by: Gilad Arnold <garnold@chromium.org>
diff --git a/filesystem_copier_action.cc b/filesystem_copier_action.cc
index c9be962..1561f93 100644
--- a/filesystem_copier_action.cc
+++ b/filesystem_copier_action.cc
@@ -128,6 +128,10 @@
}
}
+bool FilesystemCopierAction::IsCleanupPending() const {
+ return (src_stream_ != NULL);
+}
+
void FilesystemCopierAction::Cleanup(ActionExitCode code) {
for (int i = 0; i < 2; i++) {
g_object_unref(canceller_[i]);
diff --git a/filesystem_copier_action.h b/filesystem_copier_action.h
index 9bd9b20..366ae40 100644
--- a/filesystem_copier_action.h
+++ b/filesystem_copier_action.h
@@ -46,6 +46,12 @@
void PerformAction();
void TerminateProcessing();
+ // Used for testing. Return true if Cleanup() has not yet been called due
+ // to a callback upon the completion or cancellation of the copier action.
+ // A test should wait until IsCleanupPending() returns false before
+ // terminating the glib main loop.
+ bool IsCleanupPending() const;
+
// Used for testing, so we can copy from somewhere other than root
void set_copy_source(const std::string& path) { copy_source_ = path; }
diff --git a/filesystem_copier_action_unittest.cc b/filesystem_copier_action_unittest.cc
index 25e9484..f7bb618 100644
--- a/filesystem_copier_action_unittest.cc
+++ b/filesystem_copier_action_unittest.cc
@@ -43,10 +43,18 @@
class FilesystemCopierActionTestDelegate : public ActionProcessorDelegate {
public:
- FilesystemCopierActionTestDelegate() : ran_(false), code_(kActionCodeError) {}
+ FilesystemCopierActionTestDelegate(GMainLoop* loop,
+ FilesystemCopierAction* action)
+ : loop_(loop), action_(action), ran_(false), code_(kActionCodeError) {}
void ExitMainLoop() {
- while (g_main_context_pending(NULL)) {
- g_main_context_iteration(NULL, false);
+ GMainContext* context = g_main_loop_get_context(loop_);
+ // We cannot use g_main_context_pending() alone to determine if it is safe
+ // to quit the main loop here becasuse g_main_context_pending() may return
+ // FALSE when g_input_stream_read_async() in FilesystemCopierAction has
+ // been cancelled but the callback has not yet been invoked.
+ while (g_main_context_pending(context) || action_->IsCleanupPending()) {
+ g_main_context_iteration(context, false);
+ g_usleep(100);
}
g_main_loop_quit(loop_);
}
@@ -64,13 +72,11 @@
code_ = code;
}
}
- void set_loop(GMainLoop* loop) {
- loop_ = loop;
- }
- bool ran() { return ran_; }
- ActionExitCode code() { return code_; }
+ bool ran() const { return ran_; }
+ ActionExitCode code() const { return code_; }
private:
GMainLoop* loop_;
+ FilesystemCopierAction* action_;
bool ran_;
ActionExitCode code_;
};
@@ -188,9 +194,6 @@
}
ActionProcessor processor;
- FilesystemCopierActionTestDelegate delegate;
- delegate.set_loop(loop);
- processor.set_delegate(&delegate);
ObjectFeederAction<InstallPlan> feeder_action;
FilesystemCopierAction copier_action(use_kernel_partition,
@@ -200,6 +203,8 @@
BondActions(&feeder_action, &copier_action);
BondActions(&copier_action, &collector_action);
+ FilesystemCopierActionTestDelegate delegate(loop, &copier_action);
+ processor.set_delegate(&delegate);
processor.EnqueueAction(&feeder_action);
processor.EnqueueAction(&copier_action);
processor.EnqueueAction(&collector_action);