From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- .../test_async_callbacks_with_spun_event_loops.cpp | 174 +++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 storage/test/test_async_callbacks_with_spun_event_loops.cpp (limited to 'storage/test/test_async_callbacks_with_spun_event_loops.cpp') diff --git a/storage/test/test_async_callbacks_with_spun_event_loops.cpp b/storage/test/test_async_callbacks_with_spun_event_loops.cpp new file mode 100644 index 000000000..75687c7f3 --- /dev/null +++ b/storage/test/test_async_callbacks_with_spun_event_loops.cpp @@ -0,0 +1,174 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +#include "storage_test_harness.h" +#include "prthread.h" +#include "nsIEventTarget.h" +#include "nsIInterfaceRequestorUtils.h" +#include "mozilla/Attributes.h" + +#include "sqlite3.h" + +//////////////////////////////////////////////////////////////////////////////// +//// Async Helpers + +/** + * Spins the events loop for current thread until aCondition is true. + */ +void +spin_events_loop_until_true(const bool* const aCondition) +{ + nsCOMPtr thread(::do_GetCurrentThread()); + nsresult rv = NS_OK; + bool processed = true; + while (!(*aCondition) && NS_SUCCEEDED(rv)) { + rv = thread->ProcessNextEvent(true, &processed); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//// mozIStorageStatementCallback implementation + +class UnownedCallback final : public mozIStorageStatementCallback +{ +public: + NS_DECL_ISUPPORTS + + // Whether the object has been destroyed. + static bool sAlive; + // Whether the first result was received. + static bool sResult; + // Whether an error was received. + static bool sError; + + explicit UnownedCallback(mozIStorageConnection* aDBConn) + : mDBConn(aDBConn) + , mCompleted(false) + { + sAlive = true; + sResult = false; + sError = false; + } + +private: + ~UnownedCallback() + { + sAlive = false; + blocking_async_close(mDBConn); + } + +public: + NS_IMETHOD HandleResult(mozIStorageResultSet* aResultSet) override + { + sResult = true; + spin_events_loop_until_true(&mCompleted); + if (!sAlive) { + NS_RUNTIMEABORT("The statement callback was destroyed prematurely."); + } + return NS_OK; + } + + NS_IMETHOD HandleError(mozIStorageError* aError) override + { + sError = true; + spin_events_loop_until_true(&mCompleted); + if (!sAlive) { + NS_RUNTIMEABORT("The statement callback was destroyed prematurely."); + } + return NS_OK; + } + + NS_IMETHOD HandleCompletion(uint16_t aReason) override + { + mCompleted = true; + return NS_OK; + } + +protected: + nsCOMPtr mDBConn; + bool mCompleted; +}; + +NS_IMPL_ISUPPORTS(UnownedCallback, mozIStorageStatementCallback) + +bool UnownedCallback::sAlive = false; +bool UnownedCallback::sResult = false; +bool UnownedCallback::sError = false; + +//////////////////////////////////////////////////////////////////////////////// +//// Tests + +void +test_SpinEventsLoopInHandleResult() +{ + nsCOMPtr db(getMemoryDatabase()); + + // Create a test table and populate it. + nsCOMPtr stmt; + db->CreateStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(stmt)); + stmt->Execute(); + stmt->Finalize(); + + db->CreateStatement(NS_LITERAL_CSTRING( + "INSERT INTO test (id) VALUES (?)" + ), getter_AddRefs(stmt)); + for (int32_t i = 0; i < 30; ++i) { + stmt->BindInt32ByIndex(0, i); + stmt->Execute(); + stmt->Reset(); + } + stmt->Finalize(); + + db->CreateStatement(NS_LITERAL_CSTRING( + "SELECT * FROM test" + ), getter_AddRefs(stmt)); + nsCOMPtr ps; + do_check_success(stmt->ExecuteAsync(new UnownedCallback(db), + getter_AddRefs(ps))); + stmt->Finalize(); + + spin_events_loop_until_true(&UnownedCallback::sResult); +} + +void +test_SpinEventsLoopInHandleError() +{ + nsCOMPtr db(getMemoryDatabase()); + + // Create a test table and populate it. + nsCOMPtr stmt; + db->CreateStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(stmt)); + stmt->Execute(); + stmt->Finalize(); + + db->CreateStatement(NS_LITERAL_CSTRING( + "INSERT INTO test (id) VALUES (1)" + ), getter_AddRefs(stmt)); + stmt->Execute(); + stmt->Finalize(); + + // This will cause a constraint error. + db->CreateStatement(NS_LITERAL_CSTRING( + "INSERT INTO test (id) VALUES (1)" + ), getter_AddRefs(stmt)); + nsCOMPtr ps; + do_check_success(stmt->ExecuteAsync(new UnownedCallback(db), + getter_AddRefs(ps))); + stmt->Finalize(); + + spin_events_loop_until_true(&UnownedCallback::sError); +} + +void (*gTests[])(void) = { + test_SpinEventsLoopInHandleResult, + test_SpinEventsLoopInHandleError, +}; + +const char *file = __FILE__; +#define TEST_NAME "test async callbacks with spun event loops" +#define TEST_FILE file +#include "storage_test_harness_tail.h" -- cgit v1.2.3