diff options
author | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-18 22:18:10 +0000 |
---|---|---|
committer | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-18 22:18:10 +0000 |
commit | 4350e321e41d0faa025ac516aad6365bc8e9a83f (patch) | |
tree | 23d66544bf4dc0f62a20820f66ad2264b2323eee /sql/test | |
parent | 90392f8e3110e58c0367c4d87caa7f33709bff6c (diff) | |
download | chromium_src-4350e321e41d0faa025ac516aad6365bc8e9a83f.zip chromium_src-4350e321e41d0faa025ac516aad6365bc8e9a83f.tar.gz chromium_src-4350e321e41d0faa025ac516aad6365bc8e9a83f.tar.bz2 |
[sql] Framework for allowing tests to handle errors.
sql/ throws FATAL whenever it sees inappropriate calls, which makes
production code to handle errors hard to test. ScopedErrorIgnorer
provides a way for tests to signal that specific errors are expected
and will be handled.
As a first pass, code up some additional tests for some Raze() edge
cases, and modify things to pass those tests.
BUG=159490
Review URL: https://chromiumcodereview.appspot.com/16664005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207096 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sql/test')
-rw-r--r-- | sql/test/scoped_error_ignorer.cc | 60 | ||||
-rw-r--r-- | sql/test/scoped_error_ignorer.h | 64 |
2 files changed, 124 insertions, 0 deletions
diff --git a/sql/test/scoped_error_ignorer.cc b/sql/test/scoped_error_ignorer.cc new file mode 100644 index 0000000..c585229 --- /dev/null +++ b/sql/test/scoped_error_ignorer.cc @@ -0,0 +1,60 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sql/test/scoped_error_ignorer.h" + +#include "base/bind.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace sql { + +ScopedErrorIgnorer::ScopedErrorIgnorer() + : checked_(false) { + callback_ = + base::Bind(&ScopedErrorIgnorer::ShouldIgnore, base::Unretained(this)); + Connection::SetErrorIgnorer(&callback_); +} + +ScopedErrorIgnorer::~ScopedErrorIgnorer() { + EXPECT_TRUE(checked_) << " Test must call CheckIgnoredErrors()"; + Connection::ResetErrorIgnorer(); +} + +void ScopedErrorIgnorer::IgnoreError(int err) { + EXPECT_EQ(0u, ignore_errors_.count(err)) + << " Error " << err << " is already ignored"; + ignore_errors_.insert(err); +} + +bool ScopedErrorIgnorer::CheckIgnoredErrors() { + checked_ = true; + return errors_ignored_ == ignore_errors_; +} + +bool ScopedErrorIgnorer::ShouldIgnore(int err) { + // Look for extended code. + if (ignore_errors_.count(err) > 0) { + // Record that the error was seen and ignore it. + errors_ignored_.insert(err); + return true; + } + + // Trim extended codes and check again. + int base_err = err & 0xff; + if (ignore_errors_.count(base_err) > 0) { + // Record that the error was seen and ignore it. + errors_ignored_.insert(base_err); + return true; + } + + // Unexpected error. + ADD_FAILURE() << " Unexpected SQLite error " << err; + + // TODO(shess): If it never makes sense to pass through an error + // under the test harness, then perhaps the ignore callback + // signature should be changed. + return true; +} + +} // namespace sql diff --git a/sql/test/scoped_error_ignorer.h b/sql/test/scoped_error_ignorer.h new file mode 100644 index 0000000..e777179 --- /dev/null +++ b/sql/test/scoped_error_ignorer.h @@ -0,0 +1,64 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SQL_TEST_SCOPED_ERROR_IGNORER_H_ +#define SQL_TEST_SCOPED_ERROR_IGNORER_H_ + +#include <set> + +#include "base/basictypes.h" +#include "sql/connection.h" + +namespace sql { + +// sql::Connection and sql::Statement treat most SQLite errors as +// fatal in debug mode. The intention is to catch inappropriate uses +// of SQL before the code is shipped to production. This makes it +// challenging to write tests for things like recovery from +// corruption. This scoper can be used to ignore selected errors +// during a test. Errors are ignored globally (on all connections). +// +// Since errors can be very context-dependent, the class is pedantic - +// specific errors must be ignored, and every error ignored must be +// seen. +// +// NOTE(shess): There are still fatal error cases this does not +// address. If your test is handling database errors and you're +// hitting a case not handled, contact me. +class ScopedErrorIgnorer { + public: + ScopedErrorIgnorer(); + ~ScopedErrorIgnorer(); + + // Add an error to ignore. Extended error codes can be ignored + // specifically, or the base code can ignore an entire group + // (SQLITE_IOERR_* versus SQLITE_IOERR). + void IgnoreError(int err); + + // Allow containing test to check if the errors were encountered. + // Failure to call results in ADD_FAILURE() in destructor. + bool CheckIgnoredErrors(); + + // Record an error and check if it should be ignored. + bool ShouldIgnore(int err); + + private: + // Storage for callback passed to Connection::SetErrorIgnorer(). + Connection::ErrorIgnorerCallback callback_; + + // Record whether CheckIgnoredErrors() has been called. + bool checked_; + + // Errors to ignore. + std::set<int> ignore_errors_; + + // Errors which have been ignored. + std::set<int> errors_ignored_; + + DISALLOW_COPY_AND_ASSIGN(ScopedErrorIgnorer); +}; + +} // namespace sql + +#endif // SQL_TEST_SCOPED_ERROR_IGNORER_H_ |