summaryrefslogtreecommitdiffstats
path: root/xpcom/tests/gtest/TestAutoOwningEventTarget.cpp
blob: 2bd34ecfeebf925c87e6a07896373be57e1d25e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:cindent:ts=4:et:sw=4:
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsCOMPtr.h"
#include "nsISupportsImpl.h"
#include "nsNetCID.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "gtest/gtest.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/TaskQueue.h"
#include "mozilla/gtest/MozAssertions.h"

namespace TestAutoOwningEventTarget {

using namespace mozilla;

#ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED

namespace {

static MozExternalRefCountType GetRefCount(nsISupports* aSupports) {
  aSupports->AddRef();
  return aSupports->Release();
}

void CheckAutoOwningEventTarget(
    nsISerialEventTarget* aSerialEventTarget,
    const nsAutoOwningEventTarget& aAutoOwningEventTarget,
    const bool aIsCurrent) {
  ASSERT_TRUE(aSerialEventTarget);

  ASSERT_EQ(aAutoOwningEventTarget.IsCurrentThread(), aIsCurrent);

  {
    const auto refCountBefore = GetRefCount(aSerialEventTarget);

    {
      nsAutoOwningEventTarget copyConstructedEventTarget(
          aAutoOwningEventTarget);
      ASSERT_EQ(copyConstructedEventTarget.IsCurrentThread(), aIsCurrent);
    }

    const auto refCountAfter = GetRefCount(aSerialEventTarget);

    ASSERT_GE(refCountAfter, refCountBefore);
    ASSERT_EQ(refCountAfter - refCountBefore, 0u);
  }

  {
    const auto refCountBefore = GetRefCount(aSerialEventTarget);

    {
      nsAutoOwningEventTarget copyAssignedEventTarget;
      ASSERT_TRUE(copyAssignedEventTarget.IsCurrentThread());

      copyAssignedEventTarget = aAutoOwningEventTarget;
      ASSERT_EQ(copyAssignedEventTarget.IsCurrentThread(), aIsCurrent);
    }

    const auto refCountAfter = GetRefCount(aSerialEventTarget);

    ASSERT_GE(refCountAfter, refCountBefore);
    ASSERT_EQ(refCountAfter - refCountBefore, 0u);
  }
}

}  // namespace

TEST(TestAutoOwningEventTarget, Simple)
{
  {
    nsAutoOwningEventTarget autoOwningEventTarget;

    ASSERT_NO_FATAL_FAILURE(CheckAutoOwningEventTarget(
        GetCurrentSerialEventTarget(), autoOwningEventTarget,
        /* aIsCurrent */ true));
  }
}

TEST(TestAutoOwningEventTarget, TaskQueue)
{
  nsresult rv;
  nsCOMPtr<nsIEventTarget> threadPool =
      do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
  ASSERT_NS_SUCCEEDED(rv);

  auto taskQueue = TaskQueue::Create(threadPool.forget(), "TestTaskQueue",
                                     /* aSupportsTailDispatch */ false);

  nsAutoOwningEventTarget autoOwningEventTarget;

  // XXX This call can't be wrapped with ASSERT_NS_SUCCEEDED directly because
  // base-toolchains builds fail with: error: duplicate label
  // 'gtest_label_testnofatal_111'
  rv = SyncRunnable::DispatchToThread(
      taskQueue,
      NS_NewRunnableFunction(
          "TestRunnable", [taskQueue, &autoOwningEventTarget] {
            {
              ASSERT_NO_FATAL_FAILURE(CheckAutoOwningEventTarget(
                  taskQueue, autoOwningEventTarget, /* aIsCurrent */ false));
            }

            {
              nsAutoOwningEventTarget autoOwningEventTarget;

              ASSERT_NO_FATAL_FAILURE(CheckAutoOwningEventTarget(
                  taskQueue, autoOwningEventTarget, /* aIsCurrent */ true));
            }
          }));
  ASSERT_NS_SUCCEEDED(rv);
}

#endif

}  // namespace TestAutoOwningEventTarget