1// Copyright (c) 2011 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 "net/disk_cache/disk_cache_test_util.h"
6
7#include "base/files/file.h"
8#include "base/files/file_path.h"
9#include "base/logging.h"
10#include "base/path_service.h"
11#include "base/thread_task_runner_handle.h"
12#include "net/base/net_errors.h"
13#include "net/disk_cache/blockfile/backend_impl.h"
14#include "net/disk_cache/blockfile/file.h"
15#include "net/disk_cache/cache_util.h"
16
17using base::Time;
18using base::TimeDelta;
19
20std::string GenerateKey(bool same_length) {
21  char key[200];
22  CacheTestFillBuffer(key, sizeof(key), same_length);
23
24  key[199] = '\0';
25  return std::string(key);
26}
27
28void CacheTestFillBuffer(char* buffer, size_t len, bool no_nulls) {
29  static bool called = false;
30  if (!called) {
31    called = true;
32    int seed = static_cast<int>(Time::Now().ToInternalValue());
33    srand(seed);
34  }
35
36  for (size_t i = 0; i < len; i++) {
37    buffer[i] = static_cast<char>(rand());
38    if (!buffer[i] && no_nulls)
39      buffer[i] = 'g';
40  }
41  if (len && !buffer[0])
42    buffer[0] = 'g';
43}
44
45bool CreateCacheTestFile(const base::FilePath& name) {
46  int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ |
47              base::File::FLAG_WRITE;
48
49  base::File file(name, flags);
50  if (!file.IsValid())
51    return false;
52
53  file.SetLength(4 * 1024 * 1024);
54  return true;
55}
56
57bool DeleteCache(const base::FilePath& path) {
58  disk_cache::DeleteCache(path, false);
59  return true;
60}
61
62bool CheckCacheIntegrity(const base::FilePath& path, bool new_eviction,
63                         uint32 mask) {
64  scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(
65      path, mask, base::ThreadTaskRunnerHandle::Get(), NULL));
66  if (!cache.get())
67    return false;
68  if (new_eviction)
69    cache->SetNewEviction();
70  cache->SetFlags(disk_cache::kNoRandom);
71  if (cache->SyncInit() != net::OK)
72    return false;
73  return cache->SelfCheck() >= 0;
74}
75
76// -----------------------------------------------------------------------
77
78MessageLoopHelper::MessageLoopHelper()
79    : num_callbacks_(0),
80      num_iterations_(0),
81      last_(0),
82      completed_(false),
83      callback_reused_error_(false),
84      callbacks_called_(0) {
85}
86
87MessageLoopHelper::~MessageLoopHelper() {
88}
89
90bool MessageLoopHelper::WaitUntilCacheIoFinished(int num_callbacks) {
91  if (num_callbacks == callbacks_called_)
92    return true;
93
94  ExpectCallbacks(num_callbacks);
95  // Create a recurrent timer of 50 mS.
96  if (!timer_.IsRunning())
97    timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(50), this,
98                 &MessageLoopHelper::TimerExpired);
99  base::MessageLoop::current()->Run();
100  return completed_;
101}
102
103// Quits the message loop when all callbacks are called or we've been waiting
104// too long for them (2 secs without a callback).
105void MessageLoopHelper::TimerExpired() {
106  CHECK_LE(callbacks_called_, num_callbacks_);
107  if (callbacks_called_ == num_callbacks_) {
108    completed_ = true;
109    base::MessageLoop::current()->Quit();
110  } else {
111    // Not finished yet. See if we have to abort.
112    if (last_ == callbacks_called_)
113      num_iterations_++;
114    else
115      last_ = callbacks_called_;
116    if (40 == num_iterations_)
117      base::MessageLoop::current()->Quit();
118  }
119}
120
121// -----------------------------------------------------------------------
122
123CallbackTest::CallbackTest(MessageLoopHelper* helper,
124                           bool reuse)
125    : helper_(helper),
126      reuse_(reuse ? 0 : 1) {
127}
128
129CallbackTest::~CallbackTest() {
130}
131
132// On the actual callback, increase the number of tests received and check for
133// errors (an unexpected test received)
134void CallbackTest::Run(int result) {
135  last_result_ = result;
136
137  if (reuse_) {
138    DCHECK_EQ(1, reuse_);
139    if (2 == reuse_)
140      helper_->set_callback_reused_error(true);
141    reuse_++;
142  }
143
144  helper_->CallbackWasCalled();
145}
146