1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/logging.h"
8 #include "content/browser/indexed_db/leveldb/leveldb_iterator_impl.h"
9 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
10 #include "content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h"
11 #include "third_party/leveldatabase/src/include/leveldb/status.h"
15 class FunctionTracer
{
17 FunctionTracer(const std::string
& class_name
,
18 const std::string
& method_name
,
20 : class_name_(class_name
),
21 method_name_(method_name
),
22 instance_count_(instance_num
),
23 current_call_num_(0) {}
27 VLOG(0) << class_name_
<< '[' << instance_count_
<< "]::" << method_name_
28 << "()[" << current_call_num_
<< ']';
32 std::string class_name_
;
33 std::string method_name_
;
35 int current_call_num_
;
42 class LevelDBTestTansaction
: public LevelDBTransaction
{
44 LevelDBTestTansaction(LevelDBDatabase
* db
,
45 FailMethod fail_method
,
47 : LevelDBTransaction(db
),
48 fail_method_(fail_method
),
49 fail_on_call_num_(fail_on_call_num
),
50 current_call_num_(0) {
51 DCHECK(fail_method
!= FAIL_METHOD_NOTHING
);
52 DCHECK_GT(fail_on_call_num
, 0);
55 leveldb::Status
Get(const base::StringPiece
& key
,
57 bool* found
) override
{
58 if (fail_method_
!= FAIL_METHOD_GET
||
59 ++current_call_num_
!= fail_on_call_num_
)
60 return LevelDBTransaction::Get(key
, value
, found
);
63 return leveldb::Status::Corruption("Corrupted for the test");
66 leveldb::Status
Commit() override
{
67 if (fail_method_
!= FAIL_METHOD_COMMIT
||
68 ++current_call_num_
!= fail_on_call_num_
)
69 return LevelDBTransaction::Commit();
71 return leveldb::Status::Corruption("Corrupted for the test");
75 ~LevelDBTestTansaction() override
{}
77 FailMethod fail_method_
;
78 int fail_on_call_num_
;
79 int current_call_num_
;
82 class LevelDBTraceTansaction
: public LevelDBTransaction
{
84 LevelDBTraceTansaction(LevelDBDatabase
* db
, int tx_num
)
85 : LevelDBTransaction(db
),
86 commit_tracer_(s_class_name
, "Commit", tx_num
),
87 get_tracer_(s_class_name
, "Get", tx_num
) {}
89 leveldb::Status
Get(const base::StringPiece
& key
,
91 bool* found
) override
{
92 get_tracer_
.log_call();
93 return LevelDBTransaction::Get(key
, value
, found
);
96 leveldb::Status
Commit() override
{
97 commit_tracer_
.log_call();
98 return LevelDBTransaction::Commit();
102 static const std::string s_class_name
;
104 ~LevelDBTraceTansaction() override
{}
106 FunctionTracer commit_tracer_
;
107 FunctionTracer get_tracer_
;
110 const std::string
LevelDBTraceTansaction::s_class_name
= "LevelDBTransaction";
112 class LevelDBTraceIteratorImpl
: public LevelDBIteratorImpl
{
114 LevelDBTraceIteratorImpl(scoped_ptr
<leveldb::Iterator
> iterator
, int inst_num
)
115 : LevelDBIteratorImpl(iterator
.Pass()),
116 is_valid_tracer_(s_class_name
, "IsValid", inst_num
),
117 seek_to_last_tracer_(s_class_name
, "SeekToLast", inst_num
),
118 seek_tracer_(s_class_name
, "Seek", inst_num
),
119 next_tracer_(s_class_name
, "Next", inst_num
),
120 prev_tracer_(s_class_name
, "Prev", inst_num
),
121 key_tracer_(s_class_name
, "Key", inst_num
),
122 value_tracer_(s_class_name
, "Value", inst_num
) {}
123 ~LevelDBTraceIteratorImpl() override
{}
126 static const std::string s_class_name
;
128 bool IsValid() const override
{
129 is_valid_tracer_
.log_call();
130 return LevelDBIteratorImpl::IsValid();
132 leveldb::Status
SeekToLast() override
{
133 seek_to_last_tracer_
.log_call();
134 return LevelDBIteratorImpl::SeekToLast();
136 leveldb::Status
Seek(const base::StringPiece
& target
) override
{
137 seek_tracer_
.log_call();
138 return LevelDBIteratorImpl::Seek(target
);
140 leveldb::Status
Next() override
{
141 next_tracer_
.log_call();
142 return LevelDBIteratorImpl::Next();
144 leveldb::Status
Prev() override
{
145 prev_tracer_
.log_call();
146 return LevelDBIteratorImpl::Prev();
148 base::StringPiece
Key() const override
{
149 key_tracer_
.log_call();
150 return LevelDBIteratorImpl::Key();
152 base::StringPiece
Value() const override
{
153 value_tracer_
.log_call();
154 return LevelDBIteratorImpl::Value();
157 mutable FunctionTracer is_valid_tracer_
;
158 mutable FunctionTracer seek_to_last_tracer_
;
159 mutable FunctionTracer seek_tracer_
;
160 mutable FunctionTracer next_tracer_
;
161 mutable FunctionTracer prev_tracer_
;
162 mutable FunctionTracer key_tracer_
;
163 mutable FunctionTracer value_tracer_
;
166 const std::string
LevelDBTraceIteratorImpl::s_class_name
= "LevelDBIterator";
168 class LevelDBTestIteratorImpl
: public content::LevelDBIteratorImpl
{
170 LevelDBTestIteratorImpl(scoped_ptr
<leveldb::Iterator
> iterator
,
171 FailMethod fail_method
,
172 int fail_on_call_num
)
173 : LevelDBIteratorImpl(iterator
.Pass()),
174 fail_method_(fail_method
),
175 fail_on_call_num_(fail_on_call_num
),
176 current_call_num_(0) {}
177 ~LevelDBTestIteratorImpl() override
{}
180 leveldb::Status
Seek(const base::StringPiece
& target
) override
{
181 if (fail_method_
!= FAIL_METHOD_SEEK
||
182 ++current_call_num_
!= fail_on_call_num_
)
183 return LevelDBIteratorImpl::Seek(target
);
184 return leveldb::Status::Corruption("Corrupted for test");
187 FailMethod fail_method_
;
188 int fail_on_call_num_
;
189 int current_call_num_
;
192 MockBrowserTestIndexedDBClassFactory::MockBrowserTestIndexedDBClassFactory()
193 : failure_class_(FAIL_CLASS_NOTHING
),
194 failure_method_(FAIL_METHOD_NOTHING
),
195 only_trace_calls_(false) {
198 MockBrowserTestIndexedDBClassFactory::~MockBrowserTestIndexedDBClassFactory() {
202 MockBrowserTestIndexedDBClassFactory::CreateLevelDBTransaction(
203 LevelDBDatabase
* db
) {
204 instance_count_
[FAIL_CLASS_LEVELDB_TRANSACTION
] =
205 instance_count_
[FAIL_CLASS_LEVELDB_TRANSACTION
] + 1;
206 if (only_trace_calls_
) {
207 return new LevelDBTraceTansaction(
208 db
, instance_count_
[FAIL_CLASS_LEVELDB_TRANSACTION
]);
210 if (failure_class_
== FAIL_CLASS_LEVELDB_TRANSACTION
&&
211 instance_count_
[FAIL_CLASS_LEVELDB_TRANSACTION
] ==
212 fail_on_instance_num_
[FAIL_CLASS_LEVELDB_TRANSACTION
]) {
213 return new LevelDBTestTansaction(
216 fail_on_call_num_
[FAIL_CLASS_LEVELDB_TRANSACTION
]);
218 return IndexedDBClassFactory::CreateLevelDBTransaction(db
);
223 LevelDBIteratorImpl
* MockBrowserTestIndexedDBClassFactory::CreateIteratorImpl(
224 scoped_ptr
<leveldb::Iterator
> iterator
) {
225 instance_count_
[FAIL_CLASS_LEVELDB_ITERATOR
] =
226 instance_count_
[FAIL_CLASS_LEVELDB_ITERATOR
] + 1;
227 if (only_trace_calls_
) {
228 return new LevelDBTraceIteratorImpl(
229 iterator
.Pass(), instance_count_
[FAIL_CLASS_LEVELDB_ITERATOR
]);
231 if (failure_class_
== FAIL_CLASS_LEVELDB_ITERATOR
&&
232 instance_count_
[FAIL_CLASS_LEVELDB_ITERATOR
] ==
233 fail_on_instance_num_
[FAIL_CLASS_LEVELDB_ITERATOR
]) {
234 return new LevelDBTestIteratorImpl(
237 fail_on_call_num_
[FAIL_CLASS_LEVELDB_ITERATOR
]);
239 return new LevelDBIteratorImpl(iterator
.Pass());
244 void MockBrowserTestIndexedDBClassFactory::FailOperation(
245 FailClass failure_class
,
246 FailMethod failure_method
,
247 int fail_on_instance_num
,
248 int fail_on_call_num
) {
249 VLOG(0) << "FailOperation: class=" << failure_class
250 << ", method=" << failure_method
251 << ", instanceNum=" << fail_on_instance_num
252 << ", callNum=" << fail_on_call_num
;
253 DCHECK(failure_class
!= FAIL_CLASS_NOTHING
);
254 DCHECK(failure_method
!= FAIL_METHOD_NOTHING
);
255 failure_class_
= failure_class
;
256 failure_method_
= failure_method
;
257 fail_on_instance_num_
[failure_class_
] = fail_on_instance_num
;
258 fail_on_call_num_
[failure_class_
] = fail_on_call_num
;
259 instance_count_
.clear();
262 void MockBrowserTestIndexedDBClassFactory::Reset() {
263 failure_class_
= FAIL_CLASS_NOTHING
;
264 failure_method_
= FAIL_METHOD_NOTHING
;
265 instance_count_
.clear();
266 fail_on_instance_num_
.clear();
267 fail_on_call_num_
.clear();
270 } // namespace content