Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/tests/gtest/TestCOMArray.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
// vim:cindent:ts=4:et:sw=4:
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "nsCOMArray.h"
8
#include "nsCOMPtr.h"
9
#include "nsISupports.h"
10
#include "gtest/gtest.h"
11
12
// {9e70a320-be02-11d1-8031-006008159b5a}
13
#define NS_IFOO_IID \
14
  {0x9e70a320, 0xbe02, 0x11d1,    \
15
    {0x80, 0x31, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a}}
16
17
class IFoo : public nsISupports {
18
public:
19
20
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
21
22
  NS_IMETHOD_(MozExternalRefCountType) RefCnt() = 0;
23
  NS_IMETHOD_(int32_t) ID() = 0;
24
};
25
26
NS_DEFINE_STATIC_IID_ACCESSOR(IFoo, NS_IFOO_IID)
27
28
class Foo final : public IFoo {
29
  ~Foo();
30
31
public:
32
33
  explicit Foo(int32_t aID);
34
35
  // nsISupports implementation
36
  NS_DECL_ISUPPORTS
37
38
  // IFoo implementation
39
0
  NS_IMETHOD_(MozExternalRefCountType) RefCnt() override { return mRefCnt; }
40
0
  NS_IMETHOD_(int32_t) ID() override { return mID; }
41
42
  static int32_t gCount;
43
44
  int32_t mID;
45
};
46
47
int32_t Foo::gCount = 0;
48
49
Foo::Foo(int32_t aID)
50
0
{
51
0
  mID = aID;
52
0
  ++gCount;
53
0
}
54
55
Foo::~Foo()
56
0
{
57
0
  --gCount;
58
0
}
59
60
NS_IMPL_ISUPPORTS(Foo, IFoo)
61
62
63
// {0e70a320-be02-11d1-8031-006008159b5a}
64
#define NS_IBAR_IID \
65
  {0x0e70a320, 0xbe02, 0x11d1,    \
66
    {0x80, 0x31, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a}}
67
68
class IBar : public nsISupports {
69
public:
70
71
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IBAR_IID)
72
};
73
74
NS_DEFINE_STATIC_IID_ACCESSOR(IBar, NS_IBAR_IID)
75
76
class Bar final : public IBar {
77
public:
78
79
  explicit Bar(nsCOMArray<IBar>& aArray);
80
81
  // nsISupports implementation
82
  NS_DECL_ISUPPORTS
83
84
  static int32_t sReleaseCalled;
85
86
private:
87
  ~Bar();
88
89
  nsCOMArray<IBar>& mArray;
90
};
91
92
int32_t Bar::sReleaseCalled = 0;
93
94
typedef nsCOMArray<IBar> Array2;
95
96
Bar::Bar(Array2& aArray)
97
  : mArray(aArray)
98
0
{
99
0
}
100
101
Bar::~Bar()
102
0
{
103
0
  EXPECT_FALSE(mArray.RemoveObject(this));
104
0
}
105
106
NS_IMPL_ADDREF(Bar)
107
NS_IMPL_QUERY_INTERFACE(Bar, IBar)
108
109
NS_IMETHODIMP_(MozExternalRefCountType)
110
Bar::Release(void)
111
0
{
112
0
  ++Bar::sReleaseCalled;
113
0
  EXPECT_GT(int(mRefCnt), 0);
114
0
  NS_ASSERT_OWNINGTHREAD(_class);
115
0
  --mRefCnt;
116
0
  NS_LOG_RELEASE(this, mRefCnt, "Bar");
117
0
  if (mRefCnt == 0) {
118
0
    mRefCnt = 1; /* stabilize */
119
0
    delete this;
120
0
    return 0;
121
0
  }
122
0
  return mRefCnt;
123
0
}
124
125
TEST(COMArray, Sizing)
126
0
{
127
0
  nsCOMArray<IFoo> arr;
128
0
129
0
  for (int32_t i = 0; i < 20; ++i) {
130
0
    nsCOMPtr<IFoo> foo = new Foo(i);
131
0
    arr.AppendObject(foo);
132
0
  }
133
0
134
0
  ASSERT_EQ(arr.Count(), int32_t(20));
135
0
  ASSERT_EQ(Foo::gCount, int32_t(20));
136
0
137
0
  arr.TruncateLength(10);
138
0
139
0
  ASSERT_EQ(arr.Count(), int32_t(10));
140
0
  ASSERT_EQ(Foo::gCount, int32_t(10));
141
0
142
0
  arr.SetCount(30);
143
0
144
0
  ASSERT_EQ(arr.Count(), int32_t(30));
145
0
  ASSERT_EQ(Foo::gCount, int32_t(10));
146
0
147
0
  for (int32_t i = 0; i < 10; ++i) {
148
0
  ASSERT_NE(arr[i], nullptr);
149
0
  }
150
0
151
0
  for (int32_t i = 10; i < 30; ++i) {
152
0
  ASSERT_EQ(arr[i], nullptr);
153
0
  }
154
0
}
155
156
TEST(COMArray, ObjectFunctions)
157
0
{
158
0
  int32_t base;
159
0
  {
160
0
    nsCOMArray<IBar> arr2;
161
0
162
0
    IBar *thirdObject = nullptr,
163
0
         *fourthObject = nullptr,
164
0
         *fifthObject = nullptr,
165
0
         *ninthObject = nullptr;
166
0
    for (int32_t i = 0; i < 20; ++i) {
167
0
      nsCOMPtr<IBar> bar = new Bar(arr2);
168
0
      switch (i) {
169
0
      case 2:
170
0
        thirdObject = bar; break;
171
0
      case 3:
172
0
        fourthObject = bar; break;
173
0
      case 4:
174
0
        fifthObject = bar; break;
175
0
      case 8:
176
0
        ninthObject = bar; break;
177
0
      }
178
0
      arr2.AppendObject(bar);
179
0
    }
180
0
181
0
    base = Bar::sReleaseCalled;
182
0
183
0
    arr2.SetCount(10);
184
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 10);
185
0
    ASSERT_EQ(arr2.Count(), int32_t(10));
186
0
187
0
    arr2.RemoveObjectAt(9);
188
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 11);
189
0
    ASSERT_EQ(arr2.Count(), int32_t(9));
190
0
191
0
    arr2.RemoveObject(ninthObject);
192
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 12);
193
0
    ASSERT_EQ(arr2.Count(), int32_t(8));
194
0
195
0
    arr2.RemoveObjectsAt(2, 3);
196
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 15);
197
0
    ASSERT_EQ(arr2.Count(), int32_t(5));
198
0
    for (int32_t j = 0; j < arr2.Count(); ++j) {
199
0
      ASSERT_NE(arr2.ObjectAt(j), thirdObject);
200
0
      ASSERT_NE(arr2.ObjectAt(j), fourthObject);
201
0
      ASSERT_NE(arr2.ObjectAt(j), fifthObject);
202
0
    }
203
0
204
0
    arr2.RemoveObjectsAt(4, 1);
205
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 16);
206
0
    ASSERT_EQ(arr2.Count(), int32_t(4));
207
0
208
0
    arr2.Clear();
209
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 20);
210
0
  }
211
0
}
212
213
TEST(COMArray, ElementFunctions)
214
0
{
215
0
  int32_t base;
216
0
  {
217
0
    nsCOMArray<IBar> arr2;
218
0
219
0
    IBar *thirdElement = nullptr,
220
0
         *fourthElement = nullptr,
221
0
         *fifthElement = nullptr,
222
0
         *ninthElement = nullptr;
223
0
    for (int32_t i = 0; i < 20; ++i) {
224
0
      nsCOMPtr<IBar> bar = new Bar(arr2);
225
0
      switch (i) {
226
0
      case 2:
227
0
        thirdElement = bar; break;
228
0
      case 3:
229
0
        fourthElement = bar; break;
230
0
      case 4:
231
0
        fifthElement = bar; break;
232
0
      case 8:
233
0
        ninthElement = bar; break;
234
0
      }
235
0
      arr2.AppendElement(bar);
236
0
    }
237
0
238
0
    base = Bar::sReleaseCalled;
239
0
240
0
    arr2.TruncateLength(10);
241
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 10);
242
0
    ASSERT_EQ(arr2.Length(), uint32_t(10));
243
0
244
0
    arr2.RemoveElementAt(9);
245
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 11);
246
0
    ASSERT_EQ(arr2.Length(), uint32_t(9));
247
0
248
0
    arr2.RemoveElement(ninthElement);
249
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 12);
250
0
    ASSERT_EQ(arr2.Length(), uint32_t(8));
251
0
252
0
    arr2.RemoveElementsAt(2, 3);
253
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 15);
254
0
    ASSERT_EQ(arr2.Length(), uint32_t(5));
255
0
    for (uint32_t j = 0; j < arr2.Length(); ++j) {
256
0
      ASSERT_NE(arr2.ElementAt(j), thirdElement);
257
0
      ASSERT_NE(arr2.ElementAt(j), fourthElement);
258
0
      ASSERT_NE(arr2.ElementAt(j), fifthElement);
259
0
    }
260
0
261
0
    arr2.RemoveElementsAt(4, 1);
262
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 16);
263
0
    ASSERT_EQ(arr2.Length(), uint32_t(4));
264
0
265
0
    arr2.Clear();
266
0
    ASSERT_EQ(Bar::sReleaseCalled, base + 20);
267
0
  }
268
0
}
269
270
TEST(COMArray, Destructor)
271
0
{
272
0
  int32_t base;
273
0
  Bar::sReleaseCalled = 0;
274
0
275
0
  {
276
0
    nsCOMArray<IBar> arr2;
277
0
278
0
    for (int32_t i = 0; i < 20; ++i) {
279
0
      nsCOMPtr<IBar> bar  = new Bar(arr2);
280
0
      arr2.AppendObject(bar);
281
0
    }
282
0
283
0
    base = Bar::sReleaseCalled;
284
0
285
0
    // Let arr2 be destroyed
286
0
  }
287
0
  ASSERT_EQ(Bar::sReleaseCalled, base + 20);
288
0
}