Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/image/test/gtest/TestCopyOnWrite.cpp
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#include "gtest/gtest.h"
6
7
#include "CopyOnWrite.h"
8
9
using namespace mozilla;
10
using namespace mozilla::image;
11
12
struct ValueStats
13
{
14
  int32_t mCopies = 0;
15
  int32_t mFrees = 0;
16
  int32_t mCalls = 0;
17
  int32_t mConstCalls = 0;
18
  int32_t mSerial = 0;
19
};
20
21
struct Value
22
{
23
  NS_INLINE_DECL_REFCOUNTING(Value)
24
25
  explicit Value(ValueStats& aStats)
26
    : mStats(aStats)
27
    , mSerial(mStats.mSerial++)
28
0
  { }
29
30
  Value(const Value& aOther)
31
    : mStats(aOther.mStats)
32
    , mSerial(mStats.mSerial++)
33
0
  {
34
0
    mStats.mCopies++;
35
0
  }
36
37
0
  void Go() { mStats.mCalls++; }
38
0
  void Go() const { mStats.mConstCalls++; }
39
40
0
  int32_t Serial() const { return mSerial; }
41
42
protected:
43
0
  ~Value() { mStats.mFrees++; }
44
45
private:
46
  ValueStats& mStats;
47
  int32_t mSerial;
48
};
49
50
TEST(ImageCopyOnWrite, Read)
51
0
{
52
0
  ValueStats stats;
53
0
54
0
  {
55
0
    CopyOnWrite<Value> cow(new Value(stats));
56
0
57
0
    EXPECT_EQ(0, stats.mCopies);
58
0
    EXPECT_EQ(0, stats.mFrees);
59
0
    EXPECT_TRUE(cow.CanRead());
60
0
61
0
    cow.Read([&](const Value* aValue) {
62
0
      EXPECT_EQ(0, stats.mCopies);
63
0
      EXPECT_EQ(0, stats.mFrees);
64
0
      EXPECT_EQ(0, aValue->Serial());
65
0
      EXPECT_TRUE(cow.CanRead());
66
0
      EXPECT_TRUE(cow.CanWrite());
67
0
68
0
      aValue->Go();
69
0
70
0
      EXPECT_EQ(0, stats.mCalls);
71
0
      EXPECT_EQ(1, stats.mConstCalls);
72
0
    });
73
0
74
0
    EXPECT_EQ(0, stats.mCopies);
75
0
    EXPECT_EQ(0, stats.mFrees);
76
0
    EXPECT_EQ(0, stats.mCalls);
77
0
    EXPECT_EQ(1, stats.mConstCalls);
78
0
  }
79
0
80
0
  EXPECT_EQ(0, stats.mCopies);
81
0
  EXPECT_EQ(1, stats.mFrees);
82
0
}
83
84
TEST(ImageCopyOnWrite, RecursiveRead)
85
0
{
86
0
  ValueStats stats;
87
0
88
0
  {
89
0
    CopyOnWrite<Value> cow(new Value(stats));
90
0
91
0
    EXPECT_EQ(0, stats.mCopies);
92
0
    EXPECT_EQ(0, stats.mFrees);
93
0
    EXPECT_TRUE(cow.CanRead());
94
0
95
0
    cow.Read([&](const Value* aValue) {
96
0
      EXPECT_EQ(0, stats.mCopies);
97
0
      EXPECT_EQ(0, stats.mFrees);
98
0
      EXPECT_EQ(0, aValue->Serial());
99
0
      EXPECT_TRUE(cow.CanRead());
100
0
      EXPECT_TRUE(cow.CanWrite());
101
0
102
0
      // Make sure that Read() inside a Read() succeeds.
103
0
      cow.Read([&](const Value* aValue) {
104
0
        EXPECT_EQ(0, stats.mCopies);
105
0
        EXPECT_EQ(0, stats.mFrees);
106
0
        EXPECT_EQ(0, aValue->Serial());
107
0
        EXPECT_TRUE(cow.CanRead());
108
0
        EXPECT_TRUE(cow.CanWrite());
109
0
110
0
        aValue->Go();
111
0
112
0
        EXPECT_EQ(0, stats.mCalls);
113
0
        EXPECT_EQ(1, stats.mConstCalls);
114
0
      }, []() {
115
0
        // This gets called if we can't read. We shouldn't get here.
116
0
        EXPECT_TRUE(false);
117
0
      });
118
0
    });
119
0
120
0
    EXPECT_EQ(0, stats.mCopies);
121
0
    EXPECT_EQ(0, stats.mFrees);
122
0
    EXPECT_EQ(0, stats.mCalls);
123
0
    EXPECT_EQ(1, stats.mConstCalls);
124
0
  }
125
0
126
0
  EXPECT_EQ(0, stats.mCopies);
127
0
  EXPECT_EQ(1, stats.mFrees);
128
0
}
129
130
TEST(ImageCopyOnWrite, Write)
131
0
{
132
0
  ValueStats stats;
133
0
134
0
  {
135
0
    CopyOnWrite<Value> cow(new Value(stats));
136
0
137
0
    EXPECT_EQ(0, stats.mCopies);
138
0
    EXPECT_EQ(0, stats.mFrees);
139
0
    EXPECT_TRUE(cow.CanRead());
140
0
    EXPECT_TRUE(cow.CanWrite());
141
0
142
0
    cow.Write([&](Value* aValue) {
143
0
      EXPECT_EQ(0, stats.mCopies);
144
0
      EXPECT_EQ(0, stats.mFrees);
145
0
      EXPECT_EQ(0, aValue->Serial());
146
0
      EXPECT_TRUE(!cow.CanRead());
147
0
      EXPECT_TRUE(!cow.CanWrite());
148
0
149
0
      aValue->Go();
150
0
151
0
      EXPECT_EQ(1, stats.mCalls);
152
0
      EXPECT_EQ(0, stats.mConstCalls);
153
0
    });
154
0
155
0
    EXPECT_EQ(0, stats.mCopies);
156
0
    EXPECT_EQ(0, stats.mFrees);
157
0
    EXPECT_EQ(1, stats.mCalls);
158
0
    EXPECT_EQ(0, stats.mConstCalls);
159
0
  }
160
0
161
0
  EXPECT_EQ(0, stats.mCopies);
162
0
  EXPECT_EQ(1, stats.mFrees);
163
0
}
164
165
TEST(ImageCopyOnWrite, WriteRecursive)
166
0
{
167
0
  ValueStats stats;
168
0
169
0
  {
170
0
    CopyOnWrite<Value> cow(new Value(stats));
171
0
172
0
    EXPECT_EQ(0, stats.mCopies);
173
0
    EXPECT_EQ(0, stats.mFrees);
174
0
    EXPECT_TRUE(cow.CanRead());
175
0
    EXPECT_TRUE(cow.CanWrite());
176
0
177
0
    cow.Read([&](const Value* aValue) {
178
0
      EXPECT_EQ(0, stats.mCopies);
179
0
      EXPECT_EQ(0, stats.mFrees);
180
0
      EXPECT_EQ(0, aValue->Serial());
181
0
      EXPECT_TRUE(cow.CanRead());
182
0
      EXPECT_TRUE(cow.CanWrite());
183
0
184
0
      // Make sure Write() inside a Read() succeeds.
185
0
      cow.Write([&](Value* aValue) {
186
0
        EXPECT_EQ(1, stats.mCopies);
187
0
        EXPECT_EQ(0, stats.mFrees);
188
0
        EXPECT_EQ(1, aValue->Serial());
189
0
        EXPECT_TRUE(!cow.CanRead());
190
0
        EXPECT_TRUE(!cow.CanWrite());
191
0
192
0
        aValue->Go();
193
0
194
0
        EXPECT_EQ(1, stats.mCalls);
195
0
        EXPECT_EQ(0, stats.mConstCalls);
196
0
197
0
        // Make sure Read() inside a Write() fails.
198
0
        cow.Read([](const Value* aValue) {
199
0
          // This gets called if we can read. We shouldn't get here.
200
0
          EXPECT_TRUE(false);
201
0
        }, []() {
202
0
          // This gets called if we can't read. We *should* get here.
203
0
          EXPECT_TRUE(true);
204
0
        });
205
0
206
0
        // Make sure Write() inside a Write() fails.
207
0
        cow.Write([](Value* aValue) {
208
0
          // This gets called if we can write. We shouldn't get here.
209
0
          EXPECT_TRUE(false);
210
0
        }, []() {
211
0
          // This gets called if we can't write. We *should* get here.
212
0
          EXPECT_TRUE(true);
213
0
        });
214
0
      }, []() {
215
0
        // This gets called if we can't write. We shouldn't get here.
216
0
        EXPECT_TRUE(false);
217
0
      });
218
0
219
0
      aValue->Go();
220
0
221
0
      EXPECT_EQ(1, stats.mCopies);
222
0
      EXPECT_EQ(0, stats.mFrees);
223
0
      EXPECT_EQ(1, stats.mCalls);
224
0
      EXPECT_EQ(1, stats.mConstCalls);
225
0
    });
226
0
227
0
    EXPECT_EQ(1, stats.mCopies);
228
0
    EXPECT_EQ(1, stats.mFrees);
229
0
    EXPECT_EQ(1, stats.mCalls);
230
0
    EXPECT_EQ(1, stats.mConstCalls);
231
0
  }
232
0
233
0
  EXPECT_EQ(1, stats.mCopies);
234
0
  EXPECT_EQ(2, stats.mFrees);
235
0
}