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. 4 5#include <string> 6 7#include "base/logging.h" 8#include "content/browser/indexed_db/leveldb/leveldb_transaction.h" 9#include "content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h" 10#include "third_party/leveldatabase/src/include/leveldb/status.h" 11 12namespace { 13 14class FunctionTracer { 15 public: 16 FunctionTracer(const std::string& class_name, 17 const std::string& method_name, 18 int instance_num) 19 : class_name_(class_name), 20 method_name_(method_name), 21 instance_count_(instance_num), 22 current_call_num_(0) {} 23 24 void log_call() { 25 current_call_num_++; 26 VLOG(0) << class_name_ << '[' << instance_count_ << "]::" << method_name_ 27 << "()[" << current_call_num_ << ']'; 28 } 29 30 private: 31 std::string class_name_; 32 std::string method_name_; 33 int instance_count_; 34 int current_call_num_; 35}; 36 37} // namespace 38 39namespace content { 40 41class LevelDBTestTansaction : public LevelDBTransaction { 42 public: 43 LevelDBTestTansaction(LevelDBDatabase* db, 44 FailMethod fail_method, 45 int fail_on_call_num) 46 : LevelDBTransaction(db), 47 fail_method_(fail_method), 48 fail_on_call_num_(fail_on_call_num), 49 current_call_num_(0) { 50 DCHECK(fail_method != FAIL_METHOD_NOTHING); 51 DCHECK_GT(fail_on_call_num, 0); 52 } 53 54 virtual leveldb::Status Get(const base::StringPiece& key, 55 std::string* value, 56 bool* found) OVERRIDE { 57 if (fail_method_ != FAIL_METHOD_GET || 58 ++current_call_num_ != fail_on_call_num_) 59 return LevelDBTransaction::Get(key, value, found); 60 61 *found = false; 62 return leveldb::Status::Corruption("Corrupted for the test"); 63 } 64 65 virtual leveldb::Status Commit() OVERRIDE { 66 if (fail_method_ != FAIL_METHOD_COMMIT || 67 ++current_call_num_ != fail_on_call_num_) 68 return LevelDBTransaction::Commit(); 69 70 return leveldb::Status::Corruption("Corrupted for the test"); 71 } 72 73 private: 74 virtual ~LevelDBTestTansaction() {} 75 76 FailMethod fail_method_; 77 int fail_on_call_num_; 78 int current_call_num_; 79}; 80 81class LevelDBTraceTansaction : public LevelDBTransaction { 82 public: 83 LevelDBTraceTansaction(LevelDBDatabase* db, int tx_num) 84 : LevelDBTransaction(db), 85 commit_tracer_(s_class_name, "Commit", tx_num), 86 get_tracer_(s_class_name, "Get", tx_num) {} 87 88 virtual leveldb::Status Get(const base::StringPiece& key, 89 std::string* value, 90 bool* found) OVERRIDE { 91 get_tracer_.log_call(); 92 return LevelDBTransaction::Get(key, value, found); 93 } 94 95 virtual leveldb::Status Commit() OVERRIDE { 96 commit_tracer_.log_call(); 97 return LevelDBTransaction::Commit(); 98 } 99 100 private: 101 virtual ~LevelDBTraceTansaction() {} 102 103 const static std::string s_class_name; 104 105 FunctionTracer commit_tracer_; 106 FunctionTracer get_tracer_; 107}; 108 109const std::string LevelDBTraceTansaction::s_class_name = "LevelDBTransaction"; 110 111MockBrowserTestIndexedDBClassFactory::MockBrowserTestIndexedDBClassFactory() 112 : failure_class_(FAIL_CLASS_NOTHING), 113 failure_method_(FAIL_METHOD_NOTHING), 114 only_trace_calls_(false) { 115} 116 117MockBrowserTestIndexedDBClassFactory::~MockBrowserTestIndexedDBClassFactory() { 118} 119 120LevelDBTransaction* 121MockBrowserTestIndexedDBClassFactory::CreateLevelDBTransaction( 122 LevelDBDatabase* db) { 123 instance_count_[FAIL_CLASS_LEVELDB_TRANSACTION] = 124 instance_count_[FAIL_CLASS_LEVELDB_TRANSACTION] + 1; 125 if (only_trace_calls_) { 126 return new LevelDBTraceTansaction( 127 db, instance_count_[FAIL_CLASS_LEVELDB_TRANSACTION]); 128 } else { 129 if (failure_class_ == FAIL_CLASS_LEVELDB_TRANSACTION && 130 instance_count_[FAIL_CLASS_LEVELDB_TRANSACTION] == 131 fail_on_instance_num_[FAIL_CLASS_LEVELDB_TRANSACTION]) { 132 return new LevelDBTestTansaction( 133 db, 134 failure_method_, 135 fail_on_call_num_[FAIL_CLASS_LEVELDB_TRANSACTION]); 136 } else { 137 return IndexedDBClassFactory::CreateLevelDBTransaction(db); 138 } 139 } 140} 141 142void MockBrowserTestIndexedDBClassFactory::FailOperation( 143 FailClass failure_class, 144 FailMethod failure_method, 145 int fail_on_instance_num, 146 int fail_on_call_num) { 147 VLOG(0) << "FailOperation: class=" << failure_class 148 << ", method=" << failure_method 149 << ", instanceNum=" << fail_on_instance_num 150 << ", callNum=" << fail_on_call_num; 151 DCHECK(failure_class != FAIL_CLASS_NOTHING); 152 DCHECK(failure_method != FAIL_METHOD_NOTHING); 153 failure_class_ = failure_class; 154 failure_method_ = failure_method; 155 fail_on_instance_num_[failure_class_] = fail_on_instance_num; 156 fail_on_call_num_[failure_class_] = fail_on_call_num; 157 instance_count_.clear(); 158} 159 160void MockBrowserTestIndexedDBClassFactory::Reset() { 161 failure_class_ = FAIL_CLASS_NOTHING; 162 failure_method_ = FAIL_METHOD_NOTHING; 163 instance_count_.clear(); 164 fail_on_instance_num_.clear(); 165 fail_on_call_num_.clear(); 166} 167 168} // namespace content 169