xpcom/tests/TestThreadUtils.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/tests/TestThreadUtils.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,174 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 +* License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 +* file, You can obtain one at http:mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "TestHarness.h"
     1.9 +#include "nsThreadUtils.h"
    1.10 +
    1.11 +enum {
    1.12 +  TEST_CALL_VOID_ARG_VOID_RETURN,
    1.13 +  TEST_CALL_VOID_ARG_NONVOID_RETURN,
    1.14 +  TEST_CALL_NONVOID_ARG_VOID_RETURN,
    1.15 +  TEST_CALL_NONVOID_ARG_NONVOID_RETURN,
    1.16 +  TEST_CALL_NONVOID_ARG_VOID_RETURN_EXPLICIT,
    1.17 +  TEST_CALL_NONVOID_ARG_NONVOID_RETURN_EXPLICIT,
    1.18 +#ifdef HAVE_STDCALL
    1.19 +  TEST_STDCALL_VOID_ARG_VOID_RETURN,
    1.20 +  TEST_STDCALL_VOID_ARG_NONVOID_RETURN,
    1.21 +  TEST_STDCALL_NONVOID_ARG_VOID_RETURN,
    1.22 +  TEST_STDCALL_NONVOID_ARG_NONVOID_RETURN,
    1.23 +  TEST_STDCALL_NONVOID_ARG_NONVOID_RETURN_EXPLICIT,
    1.24 +#endif
    1.25 +  TEST_CALL_NEWTHREAD_SUICIDAL,
    1.26 +  MAX_TESTS
    1.27 +};
    1.28 +
    1.29 +bool gRunnableExecuted[MAX_TESTS];
    1.30 +
    1.31 +class nsFoo : public nsISupports {
    1.32 +  NS_DECL_ISUPPORTS
    1.33 +  nsresult DoFoo(bool* aBool) {
    1.34 +    *aBool = true;
    1.35 +    return NS_OK;
    1.36 +  }
    1.37 +  virtual ~nsFoo() {}
    1.38 +};
    1.39 +
    1.40 +NS_IMPL_ISUPPORTS0(nsFoo)
    1.41 +
    1.42 +class TestSuicide : public nsRunnable {
    1.43 +  NS_IMETHOD Run() {
    1.44 +    // Runs first time on thread "Suicide", then dies on MainThread
    1.45 +    if (!NS_IsMainThread()) {
    1.46 +      mThread = do_GetCurrentThread();
    1.47 +      NS_DispatchToMainThread(this);
    1.48 +      return NS_OK;
    1.49 +    }
    1.50 +    MOZ_ASSERT(mThread);
    1.51 +    mThread->Shutdown();
    1.52 +    gRunnableExecuted[TEST_CALL_NEWTHREAD_SUICIDAL] = true;
    1.53 +    return NS_OK;
    1.54 +  }
    1.55 +
    1.56 +private:
    1.57 +  nsCOMPtr<nsIThread> mThread;
    1.58 +};
    1.59 +
    1.60 +class nsBar : public nsISupports {
    1.61 +  NS_DECL_ISUPPORTS
    1.62 +  virtual ~nsBar() {}
    1.63 +  void DoBar1(void) {
    1.64 +    gRunnableExecuted[TEST_CALL_VOID_ARG_VOID_RETURN] = true;
    1.65 +  }
    1.66 +  nsresult DoBar2(void) {
    1.67 +    gRunnableExecuted[TEST_CALL_VOID_ARG_NONVOID_RETURN] = true;
    1.68 +    return NS_OK;
    1.69 +  }
    1.70 +  void DoBar3(nsFoo* aFoo) {
    1.71 +    aFoo->DoFoo(&gRunnableExecuted[TEST_CALL_NONVOID_ARG_VOID_RETURN]);
    1.72 +  }
    1.73 +  nsresult DoBar4(nsFoo* aFoo) {
    1.74 +    return aFoo->DoFoo(&gRunnableExecuted[TEST_CALL_NONVOID_ARG_NONVOID_RETURN]);
    1.75 +  }
    1.76 +  void DoBar5(nsFoo* aFoo) {
    1.77 +    if (aFoo)
    1.78 +      gRunnableExecuted[TEST_CALL_NONVOID_ARG_VOID_RETURN_EXPLICIT] = true;
    1.79 +  }
    1.80 +  nsresult DoBar6(char* aFoo) {
    1.81 +    if (strlen(aFoo))
    1.82 +      gRunnableExecuted[TEST_CALL_NONVOID_ARG_NONVOID_RETURN_EXPLICIT] = true;
    1.83 +    return NS_OK;
    1.84 +  }
    1.85 +#ifdef HAVE_STDCALL
    1.86 +  void __stdcall DoBar1std(void) {
    1.87 +    gRunnableExecuted[TEST_STDCALL_VOID_ARG_VOID_RETURN] = true;
    1.88 +  }
    1.89 +  nsresult __stdcall DoBar2std(void) {
    1.90 +    gRunnableExecuted[TEST_STDCALL_VOID_ARG_NONVOID_RETURN] = true;
    1.91 +    return NS_OK;
    1.92 +  }
    1.93 +  void __stdcall DoBar3std(nsFoo* aFoo) {
    1.94 +    aFoo->DoFoo(&gRunnableExecuted[TEST_STDCALL_NONVOID_ARG_VOID_RETURN]);
    1.95 +  }
    1.96 +  nsresult __stdcall DoBar4std(nsFoo* aFoo) {
    1.97 +    return aFoo->DoFoo(&gRunnableExecuted[TEST_STDCALL_NONVOID_ARG_NONVOID_RETURN]);
    1.98 +  }
    1.99 +  void __stdcall DoBar5std(nsFoo* aFoo) {
   1.100 +    if (aFoo)
   1.101 +      gRunnableExecuted[TEST_STDCALL_NONVOID_ARG_VOID_RETURN_EXPLICIT] = true;
   1.102 +  }
   1.103 +  nsresult __stdcall DoBar6std(char* aFoo) {
   1.104 +    if (strlen(aFoo))
   1.105 +      gRunnableExecuted[TEST_CALL_NONVOID_ARG_VOID_RETURN_EXPLICIT] = true;
   1.106 +    return NS_OK;
   1.107 +  }
   1.108 +#endif
   1.109 +};
   1.110 +
   1.111 +NS_IMPL_ISUPPORTS0(nsBar)
   1.112 +
   1.113 +int main(int argc, char** argv)
   1.114 +{
   1.115 +  ScopedXPCOM xpcom("ThreadUtils");
   1.116 +  NS_ENSURE_FALSE(xpcom.failed(), 1);
   1.117 +
   1.118 +  memset(gRunnableExecuted, false, MAX_TESTS * sizeof(bool));
   1.119 +  // Scope the smart ptrs so that the runnables need to hold on to whatever they need
   1.120 +  {
   1.121 +    nsRefPtr<nsFoo> foo = new nsFoo();
   1.122 +    nsRefPtr<nsBar> bar = new nsBar();
   1.123 +
   1.124 +    // This pointer will be freed at the end of the block
   1.125 +    // Do not dereference this pointer in the runnable method!
   1.126 +    nsFoo * rawFoo = new nsFoo();
   1.127 +
   1.128 +    // Read only string. Dereferencing in runnable method to check this works.
   1.129 +    char* message = (char*)"Test message";
   1.130 +
   1.131 +    NS_DispatchToMainThread(NS_NewRunnableMethod(bar, &nsBar::DoBar1));
   1.132 +    NS_DispatchToMainThread(NS_NewRunnableMethod(bar, &nsBar::DoBar2));
   1.133 +    NS_DispatchToMainThread(NS_NewRunnableMethodWithArg< nsRefPtr<nsFoo> >
   1.134 +      (bar, &nsBar::DoBar3, foo));
   1.135 +    NS_DispatchToMainThread(NS_NewRunnableMethodWithArg< nsRefPtr<nsFoo> >
   1.136 +      (bar, &nsBar::DoBar4, foo));
   1.137 +    NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<nsFoo*>(bar, &nsBar::DoBar5, rawFoo));
   1.138 +    NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<char*>(bar, &nsBar::DoBar6, message));
   1.139 +#ifdef HAVE_STDCALL
   1.140 +    NS_DispatchToMainThread(NS_NewRunnableMethod(bar, &nsBar::DoBar1std));
   1.141 +    NS_DispatchToMainThread(NS_NewRunnableMethod(bar, &nsBar::DoBar2std));
   1.142 +    NS_DispatchToMainThread(NS_NewRunnableMethodWithArg< nsRefPtr<nsFoo> >
   1.143 +      (bar, &nsBar::DoBar3std, foo));
   1.144 +    NS_DispatchToMainThread(NS_NewRunnableMethodWithArg< nsRefPtr<nsFoo> >
   1.145 +      (bar, &nsBar::DoBar4std, foo));
   1.146 +    NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<nsFoo*>(bar, &nsBar::DoBar5std, rawFoo));
   1.147 +    NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<char*>(bar, &nsBar::DoBar6std, message));
   1.148 +#endif
   1.149 +
   1.150 +    delete rawFoo;
   1.151 +  }
   1.152 +
   1.153 +  // Spin the event loop
   1.154 +  NS_ProcessPendingEvents(nullptr);
   1.155 +
   1.156 +  // Now test a suicidal event in NS_New(Named)Thread
   1.157 +  nsCOMPtr<nsIThread> thread;
   1.158 +  NS_NewNamedThread("SuicideThread", getter_AddRefs(thread), new TestSuicide());
   1.159 +  MOZ_ASSERT(thread);
   1.160 +
   1.161 +  while (!gRunnableExecuted[TEST_CALL_NEWTHREAD_SUICIDAL]) {
   1.162 +    NS_ProcessPendingEvents(nullptr);
   1.163 +  }
   1.164 +
   1.165 +  int result = 0;
   1.166 +
   1.167 +  for (uint32_t i = 0; i < MAX_TESTS; i++) {
   1.168 +    if (gRunnableExecuted[i]) {
   1.169 +      passed("Test %d passed",i);
   1.170 +    } else {
   1.171 +      fail("Error in test %d", i);
   1.172 +      result = 1;
   1.173 +    }
   1.174 +  }
   1.175 +
   1.176 +  return result;
   1.177 +}

mercurial