Bug 547190 - AsInt64 (and other AsXXX cpp helpers) ignores GetInt64 failures. r=sdwilsh
authorMarco Bonardo <mbonardo@mozilla.com>
Tue, 22 Jun 2010 02:01:33 +0200
changeset 49032 ce14f575aff99391467a7e4f5b2ec4455b67a8fd
parent 49031 7f54a4f3efe8e01d50dab0cdd16dca0b70bc0d4e
child 49033 92a9a7c997f1d20eaab889d794e26ae825a128e0
push idunknown
push userunknown
push dateunknown
reviewerssdwilsh
bugs547190
milestone2.0b4pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 547190 - AsInt64 (and other AsXXX cpp helpers) ignores GetInt64 failures. r=sdwilsh
storage/public/mozIStorageStatement.idl
storage/public/mozIStorageValueArray.idl
storage/test/Makefile.in
storage/test/storage_test_harness.h
storage/test/test_AsXXX_helpers.cpp
storage/test/test_true_async.cpp
--- a/storage/public/mozIStorageStatement.idl
+++ b/storage/public/mozIStorageStatement.idl
@@ -259,51 +259,68 @@ interface mozIStorageStatement : mozISto
   /**
    * Getters for native code that return their values as
    * the return type, for convenience and sanity.
    *
    * Not virtual; no vtable bloat.
    */
 
   inline PRInt32 AsInt32(PRUint32 idx) {
-    PRInt32 v;
-    GetInt32(idx, &v);
+    PRInt32 v = 0;
+    nsresult rv = GetInt32(idx, &v);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return v;
   }
 
   inline PRInt64 AsInt64(PRUint32 idx) {
-    PRInt64 v;
-    GetInt64(idx, &v);
+    PRInt64 v = 0;
+    nsresult rv = GetInt64(idx, &v);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return v;
   }
 
   inline double AsDouble(PRUint32 idx) {
-    double v;
-    GetDouble(idx, &v);
+    double v = 0.0;
+    nsresult rv = GetDouble(idx, &v);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return v;
   }
 
   inline const char* AsSharedUTF8String(PRUint32 idx, PRUint32 *len) {
     const char *str = nsnull;
-    GetSharedUTF8String(idx, len, &str);
+    *len = 0;
+    nsresult rv = GetSharedUTF8String(idx, len, &str);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return str;
   }
 
   inline const PRUnichar* AsSharedWString(PRUint32 idx, PRUint32 *len) {
     const PRUnichar *str = nsnull;
-    GetSharedString(idx, len, &str);
+    *len = 0;
+    nsresult rv = GetSharedString(idx, len, &str);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return str;
   }
 
   inline const PRUint8* AsSharedBlob(PRUint32 idx, PRUint32 *len) {
     const PRUint8 *blob = nsnull;
-    GetSharedBlob(idx, len, &blob);
+    *len = 0;
+    nsresult rv = GetSharedBlob(idx, len, &blob);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return blob;
   }
 
   inline PRBool IsNull(PRUint32 idx) {
     PRBool b = PR_FALSE;
-    GetIsNull(idx, &b);
+    nsresult rv = GetIsNull(idx, &b);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv),
+                      "Getting value failed, wrong column index?");
     return b;
   }
 
 %}
 };
--- a/storage/public/mozIStorageValueArray.idl
+++ b/storage/public/mozIStorageValueArray.idl
@@ -105,52 +105,69 @@ interface mozIStorageValueArray : nsISup
   /**
    * Getters for native code that return their values as
    * the return type, for convenience and sanity.
    *
    * Not virtual; no vtable bloat.
    */
 
   inline PRInt32 AsInt32(PRUint32 idx) {
-    PRInt32 v;
-    GetInt32(idx, &v);
+    PRInt32 v = 0;
+    nsresult rv = GetInt32(idx, &v);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return v;
   }
 
   inline PRInt64 AsInt64(PRUint32 idx) {
-    PRInt64 v;
-    GetInt64(idx, &v);
+    PRInt64 v = 0;
+    nsresult rv = GetInt64(idx, &v);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return v;
   }
 
   inline double AsDouble(PRUint32 idx) {
-    double v;
-    GetDouble(idx, &v);
+    double v = 0.0;
+    nsresult rv = GetDouble(idx, &v);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return v;
   }
 
   inline const char* AsSharedUTF8String(PRUint32 idx, PRUint32 *len) {
     const char *str = nsnull;
-    GetSharedUTF8String(idx, len, &str);
+    *len = 0;
+    nsresult rv = GetSharedUTF8String(idx, len, &str);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return str;
   }
 
   inline const PRUnichar* AsSharedWString(PRUint32 idx, PRUint32 *len) {
     const PRUnichar *str = nsnull;
-    GetSharedString(idx, len, &str);
+    *len = 0;
+    nsresult rv = GetSharedString(idx, len, &str);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return str;
   }
 
   inline const PRUint8* AsSharedBlob(PRUint32 idx, PRUint32 *len) {
     const PRUint8 *blob = nsnull;
-    GetSharedBlob(idx, len, &blob);
+    *len = 0;
+    nsresult rv = GetSharedBlob(idx, len, &blob);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) || IsNull(idx),
+                      "Getting value failed, wrong column index?");
     return blob;
   }
 
   inline PRBool IsNull(PRUint32 idx) {
     PRBool b = PR_FALSE;
-    GetIsNull(idx, &b);
+    nsresult rv = GetIsNull(idx, &b);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv),
+                      "Getting value failed, wrong column index?");
     return b;
   }
 
 %}
 
 };
--- a/storage/test/Makefile.in
+++ b/storage/test/Makefile.in
@@ -51,16 +51,17 @@ XPCSHELL_TESTS = unit
 CPP_UNIT_TESTS = \
   test_transaction_helper.cpp \
   test_statement_scoper.cpp \
   test_mutex.cpp \
   test_binding_params.cpp \
   test_true_async.cpp \
   test_unlock_notify.cpp \
   test_service_init_background_thread.cpp \
+  test_AsXXX_helpers.cpp \
   $(NULL)
 
 ifdef MOZ_DEBUG
 # FIXME bug 523392: test_deadlock_detector doesn't like Windows
 # FIXME bug 523378: also fails on OS X
 ifneq (,$(filter-out WINNT WINCE Darwin,$(OS_ARCH)))
 CPP_UNIT_TESTS += \
   test_deadlock_detector.cpp \
--- a/storage/test/storage_test_harness.h
+++ b/storage/test/storage_test_harness.h
@@ -38,16 +38,24 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "TestHarness.h"
 #include "nsMemory.h"
 #include "nsThreadUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "mozIStorageService.h"
 #include "mozIStorageConnection.h"
+#include "mozIStorageStatementCallback.h"
+#include "mozIStorageCompletionCallback.h"
+#include "mozIStorageBindingParamsArray.h"
+#include "mozIStorageBindingParams.h"
+#include "mozIStorageAsyncStatement.h"
+#include "mozIStorageStatement.h"
+#include "mozIStoragePendingStatement.h"
+#include "nsThreadUtils.h"
 
 static int gTotalTests = 0;
 static int gPassedTests = 0;
 
 #define do_check_true(aCondition) \
   PR_BEGIN_MACRO \
     gTotalTests++; \
     if (aCondition) { \
@@ -104,8 +112,78 @@ getDatabase()
   do_check_success(rv);
 
   nsCOMPtr<mozIStorageService> ss = getService();
   nsCOMPtr<mozIStorageConnection> conn;
   rv = ss->OpenDatabase(dbFile, getter_AddRefs(conn));
   do_check_success(rv);
   return conn.forget();
 }
+
+
+class AsyncStatementSpinner : public mozIStorageStatementCallback
+                            , public mozIStorageCompletionCallback
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_MOZISTORAGESTATEMENTCALLBACK
+  NS_DECL_MOZISTORAGECOMPLETIONCALLBACK
+
+  AsyncStatementSpinner();
+
+  void SpinUntilCompleted();
+
+  PRUint16 completionReason;
+
+protected:
+  ~AsyncStatementSpinner() {}
+  volatile bool mCompleted;
+};
+
+NS_IMPL_ISUPPORTS2(AsyncStatementSpinner,
+                   mozIStorageStatementCallback,
+                   mozIStorageCompletionCallback)
+
+AsyncStatementSpinner::AsyncStatementSpinner()
+: completionReason(0)
+, mCompleted(false)
+{
+}
+
+NS_IMETHODIMP
+AsyncStatementSpinner::HandleResult(mozIStorageResultSet *aResultSet)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AsyncStatementSpinner::HandleError(mozIStorageError *aError)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AsyncStatementSpinner::HandleCompletion(PRUint16 aReason)
+{
+  completionReason = aReason;
+  mCompleted = true;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AsyncStatementSpinner::Complete()
+{
+  mCompleted = true;
+  return NS_OK;
+}
+
+void AsyncStatementSpinner::SpinUntilCompleted()
+{
+  nsCOMPtr<nsIThread> thread(::do_GetCurrentThread());
+  nsresult rv = NS_OK;
+  PRBool processed = PR_TRUE;
+  while (!mCompleted && NS_SUCCEEDED(rv)) {
+    rv = thread->ProcessNextEvent(true, &processed);
+  }
+}
+
+#define NS_DECL_ASYNCSTATEMENTSPINNER \
+  NS_IMETHOD HandleResult(mozIStorageResultSet *aResultSet);
new file mode 100644
--- /dev/null
+++ b/storage/test/test_AsXXX_helpers.cpp
@@ -0,0 +1,123 @@
+/*
+ *Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+#include "storage_test_harness.h"
+#include "mozIStorageRow.h"
+#include "mozIStorageResultSet.h"
+
+/**
+ * This file tests AsXXX (AsInt32, AsInt64, ...) helpers.
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+//// Event Loop Spinning
+
+class Spinner : public AsyncStatementSpinner
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_ASYNCSTATEMENTSPINNER
+  Spinner() {}
+};
+
+NS_IMPL_ISUPPORTS_INHERITED0(Spinner,
+                             AsyncStatementSpinner)
+
+NS_IMETHODIMP
+Spinner::HandleResult(mozIStorageResultSet *aResultSet)
+{
+  nsCOMPtr<mozIStorageRow> row;
+  do_check_true(NS_SUCCEEDED(aResultSet->GetNextRow(getter_AddRefs(row))) && row);
+
+  do_check_eq(row->AsInt32(0), 0);
+  do_check_eq(row->AsInt64(0), 0);
+  do_check_eq(row->AsDouble(0), 0.0);
+
+  PRUint32 len = 100;
+  do_check_eq(row->AsSharedUTF8String(0, &len), nsnull);
+  do_check_eq(len, 0);
+  len = 100;
+  do_check_eq(row->AsSharedWString(0, &len), nsnull);
+  do_check_eq(len, 0);
+  len = 100;
+  do_check_eq(row->AsSharedBlob(0, &len), nsnull);
+  do_check_eq(len, 0);
+
+  do_check_eq(row->IsNull(0), PR_TRUE);
+  return NS_OK;
+}
+
+void
+test_NULLFallback()
+{
+  nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
+
+  nsCOMPtr<mozIStorageStatement> stmt;
+  (void)db->CreateStatement(NS_LITERAL_CSTRING(
+    "SELECT NULL"
+  ), getter_AddRefs(stmt));
+
+  nsCOMPtr<mozIStorageValueArray> valueArray = do_QueryInterface(stmt);
+  do_check_true(valueArray);
+
+  PRBool hasMore;
+  do_check_true(NS_SUCCEEDED(stmt->ExecuteStep(&hasMore)) && hasMore);
+
+  do_check_eq(stmt->AsInt32(0), 0);
+  do_check_eq(stmt->AsInt64(0), 0);
+  do_check_eq(stmt->AsDouble(0), 0.0);
+  PRUint32 len = 100;
+  do_check_eq(stmt->AsSharedUTF8String(0, &len), nsnull);
+  do_check_eq(len, 0);
+  len = 100;
+  do_check_eq(stmt->AsSharedWString(0, &len), nsnull);
+  do_check_eq(len, 0);
+  len = 100;
+  do_check_eq(stmt->AsSharedBlob(0, &len), nsnull);
+  do_check_eq(len, 0);
+  do_check_eq(stmt->IsNull(0), PR_TRUE);
+
+  do_check_eq(valueArray->AsInt32(0), 0);
+  do_check_eq(valueArray->AsInt64(0), 0);
+  do_check_eq(valueArray->AsDouble(0), 0.0);
+  len = 100;
+  do_check_eq(valueArray->AsSharedUTF8String(0, &len), nsnull);
+  do_check_eq(len, 0);
+  len = 100;
+  do_check_eq(valueArray->AsSharedWString(0, &len), nsnull);
+  do_check_eq(len, 0);
+  len = 100;
+  do_check_eq(valueArray->AsSharedBlob(0, &len), nsnull);
+  do_check_eq(len, 0);
+  do_check_eq(valueArray->IsNull(0), PR_TRUE);
+}
+
+void
+test_asyncNULLFallback()
+{
+  nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
+
+  nsCOMPtr<mozIStorageStatement> stmt;
+  (void)db->CreateStatement(NS_LITERAL_CSTRING(
+    "SELECT NULL"
+  ), getter_AddRefs(stmt));
+
+  nsRefPtr<Spinner> asyncSpin(new Spinner());
+  nsCOMPtr<mozIStoragePendingStatement> pendingStmt;
+  do_check_true(NS_SUCCEEDED(stmt->ExecuteAsync(asyncSpin, getter_AddRefs(pendingStmt))));
+  do_check_true(pendingStmt);
+  asyncSpin->SpinUntilCompleted();
+
+}
+
+void (*gTests[])(void) = {
+  test_NULLFallback
+, test_asyncNULLFallback
+};
+
+const char *file = __FILE__;
+#define TEST_NAME "AsXXX helpers"
+#define TEST_FILE file
+#include "storage_test_harness_tail.h"
--- a/storage/test/test_true_async.cpp
+++ b/storage/test/test_true_async.cpp
@@ -33,32 +33,22 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "storage_test_harness.h"
 #include "prthread.h"
-#include "nsIThread.h"
-#include "nsThreadUtils.h"
 #include "nsIEventTarget.h"
 
 #include "sqlite3.h"
 
 #include "mozilla/Monitor.h"
 
-#include "mozIStorageStatementCallback.h"
-#include "mozIStorageCompletionCallback.h"
-#include "mozIStorageBindingParamsArray.h"
-#include "mozIStorageBindingParams.h"
-#include "mozIStorageAsyncStatement.h"
-#include "mozIStorageStatement.h"
-#include "mozIStoragePendingStatement.h"
-
 using mozilla::Monitor;
 using mozilla::MonitorAutoEnter;
 
 /**
  * Verify that mozIStorageAsyncStatement's life-cycle never triggers a mutex on
  * the caller (generally main) thread.  We do this by decorating the sqlite
  * mutex logic with our own code that checks what thread it is being invoked on
  * and sets a flag if it is invoked on the main thread.  We are able to easily
@@ -131,85 +121,16 @@ void hook_sqlite_mutex()
 void watch_for_mutex_use_on_this_thread()
 {
   watched_thread = ::PR_GetCurrentThread();
   mutex_used_on_watched_thread = false;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
-//// Event Loop Spinning
-
-class AsyncStatementSpinner : public mozIStorageStatementCallback,
-                              public mozIStorageCompletionCallback
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_MOZISTORAGESTATEMENTCALLBACK
-  NS_DECL_MOZISTORAGECOMPLETIONCALLBACK
-
-  AsyncStatementSpinner();
-
-  void SpinUntilCompleted();
-
-  PRUint16 completionReason;
-
-private:
-  ~AsyncStatementSpinner() {}
-  volatile bool mCompleted;
-};
-
-NS_IMPL_ISUPPORTS2(AsyncStatementSpinner,
-                   mozIStorageStatementCallback,
-                   mozIStorageCompletionCallback)
-
-AsyncStatementSpinner::AsyncStatementSpinner()
-: completionReason(0)
-, mCompleted(false)
-{
-}
-
-NS_IMETHODIMP
-AsyncStatementSpinner::HandleResult(mozIStorageResultSet *aResultSet)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-AsyncStatementSpinner::HandleError(mozIStorageError *aError)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-AsyncStatementSpinner::HandleCompletion(PRUint16 aReason)
-{
-  completionReason = aReason;
-  mCompleted = true;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-AsyncStatementSpinner::Complete()
-{
-  mCompleted = true;
-  return NS_OK;
-}
-
-void AsyncStatementSpinner::SpinUntilCompleted()
-{
-  nsCOMPtr<nsIThread> thread(::do_GetCurrentThread());
-  nsresult rv = NS_OK;
-  PRBool processed = PR_TRUE;
-  while (!mCompleted && NS_SUCCEEDED(rv)) {
-    rv = thread->ProcessNextEvent(true, &processed);
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
 //// Thread Wedgers
 
 /**
  * A runnable that blocks until code on another thread invokes its unwedge
  * method.  By dispatching this to a thread you can ensure that no subsequent
  * runnables dispatched to the thread will execute until you invoke unwedge.
  *
  * The wedger is self-dispatching, just construct it with its target.