mirror of
https://github.com/codership/wsrep-lib.git
synced 2025-07-27 09:01:50 +03:00
More unit tests for various error conditions on certification.
This commit is contained in:
@ -470,7 +470,7 @@ namespace wsrep
|
|||||||
* only for critical conditions which would sacrifice data
|
* only for critical conditions which would sacrifice data
|
||||||
* consistency.
|
* consistency.
|
||||||
*/
|
*/
|
||||||
virtual void abort() const = 0;
|
virtual void abort() = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
@ -485,7 +485,7 @@ namespace wsrep
|
|||||||
/*!
|
/*!
|
||||||
* Enter debug synchronization point.
|
* Enter debug synchronization point.
|
||||||
*/
|
*/
|
||||||
virtual void debug_sync(const char*) = 0;
|
virtual void debug_sync(wsrep::unique_lock<wsrep::mutex>&, const char*) = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
|
@ -38,6 +38,13 @@ namespace wsrep
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class log_warning : public log
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
log_warning()
|
||||||
|
: log("WARNING") { }
|
||||||
|
};
|
||||||
|
|
||||||
class log_debug : public log
|
class log_debug : public log
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -385,14 +385,14 @@ private:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
bool killed() const override { return false; }
|
bool killed() const override { return false; }
|
||||||
void abort() const override { ::abort(); }
|
void abort() override { ::abort(); }
|
||||||
public:
|
public:
|
||||||
void store_globals() override
|
void store_globals() override
|
||||||
{
|
{
|
||||||
wsrep::client_context::store_globals();
|
wsrep::client_context::store_globals();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
void debug_sync(const char*) override { }
|
void debug_sync(wsrep::unique_lock<wsrep::mutex>&, const char*) override { }
|
||||||
void debug_suicide(const char*) override { }
|
void debug_suicide(const char*) override { }
|
||||||
void on_error(enum wsrep::client_error) override { }
|
void on_error(enum wsrep::client_error) override { }
|
||||||
|
|
||||||
|
@ -31,6 +31,9 @@ namespace wsrep
|
|||||||
, bf_abort_during_wait_()
|
, bf_abort_during_wait_()
|
||||||
, error_during_prepare_data_()
|
, error_during_prepare_data_()
|
||||||
, killed_before_certify_()
|
, killed_before_certify_()
|
||||||
|
, sync_point_action_()
|
||||||
|
, replays_()
|
||||||
|
, aborts_()
|
||||||
{ }
|
{ }
|
||||||
~mock_client_context()
|
~mock_client_context()
|
||||||
{
|
{
|
||||||
@ -51,6 +54,7 @@ namespace wsrep
|
|||||||
tc.state(lock, wsrep::transaction_context::s_committing);
|
tc.state(lock, wsrep::transaction_context::s_committing);
|
||||||
tc.state(lock, wsrep::transaction_context::s_ordered_commit);
|
tc.state(lock, wsrep::transaction_context::s_ordered_commit);
|
||||||
tc.state(lock, wsrep::transaction_context::s_committed);
|
tc.state(lock, wsrep::transaction_context::s_committed);
|
||||||
|
++replays_;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void wait_for_replayers(wsrep::unique_lock<wsrep::mutex>& lock)
|
void wait_for_replayers(wsrep::unique_lock<wsrep::mutex>& lock)
|
||||||
@ -76,15 +80,26 @@ namespace wsrep
|
|||||||
|
|
||||||
}
|
}
|
||||||
bool killed() const WSREP_OVERRIDE { return killed_before_certify_; }
|
bool killed() const WSREP_OVERRIDE { return killed_before_certify_; }
|
||||||
void abort() const WSREP_OVERRIDE { }
|
void abort() WSREP_OVERRIDE { ++aborts_; }
|
||||||
void store_globals() WSREP_OVERRIDE { }
|
void store_globals() WSREP_OVERRIDE { }
|
||||||
void debug_sync(const char*) WSREP_OVERRIDE { }
|
void debug_sync(wsrep::unique_lock<wsrep::mutex>& lock,
|
||||||
|
const char* sync_point) WSREP_OVERRIDE
|
||||||
|
{
|
||||||
|
lock.unlock();
|
||||||
|
if (sync_point_action_ == sync_point)
|
||||||
|
{
|
||||||
|
wsrep_test::bf_abort_ordered(*this);
|
||||||
|
}
|
||||||
|
lock.lock();
|
||||||
|
}
|
||||||
void debug_suicide(const char*) WSREP_OVERRIDE
|
void debug_suicide(const char*) WSREP_OVERRIDE
|
||||||
{
|
{
|
||||||
::abort();
|
::abort();
|
||||||
}
|
}
|
||||||
void on_error(enum wsrep::client_error) { }
|
void on_error(enum wsrep::client_error) { }
|
||||||
|
|
||||||
|
size_t replays() const { return replays_; }
|
||||||
|
size_t aborts() const { return aborts_; }
|
||||||
//
|
//
|
||||||
private:
|
private:
|
||||||
wsrep::default_mutex mutex_;
|
wsrep::default_mutex mutex_;
|
||||||
@ -95,6 +110,10 @@ namespace wsrep
|
|||||||
bool bf_abort_during_wait_;
|
bool bf_abort_during_wait_;
|
||||||
bool error_during_prepare_data_;
|
bool error_during_prepare_data_;
|
||||||
bool killed_before_certify_;
|
bool killed_before_certify_;
|
||||||
|
std::string sync_point_action_;
|
||||||
|
private:
|
||||||
|
size_t replays_;
|
||||||
|
size_t aborts_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,10 @@ namespace wsrep
|
|||||||
wsrep::ws_meta& ws_meta)
|
wsrep::ws_meta& ws_meta)
|
||||||
{
|
{
|
||||||
assert(flags & wsrep::provider::flag::start_transaction);
|
assert(flags & wsrep::provider::flag::start_transaction);
|
||||||
|
if (next_error_)
|
||||||
|
{
|
||||||
|
return next_error_;
|
||||||
|
}
|
||||||
if ((flags & wsrep::provider::flag::commit) == 0)
|
if ((flags & wsrep::provider::flag::commit) == 0)
|
||||||
{
|
{
|
||||||
return wsrep::provider::error_provider_failed;
|
return wsrep::provider::error_provider_failed;
|
||||||
|
@ -11,10 +11,16 @@
|
|||||||
void wsrep_test::bf_abort_unordered(wsrep::client_context& cc)
|
void wsrep_test::bf_abort_unordered(wsrep::client_context& cc)
|
||||||
{
|
{
|
||||||
wsrep::unique_lock<wsrep::mutex> lock(cc.mutex());
|
wsrep::unique_lock<wsrep::mutex> lock(cc.mutex());
|
||||||
assert(cc.transaction().seqno().nil());
|
assert(cc.transaction().ordered() == false);
|
||||||
cc.bf_abort(lock, 1);
|
cc.bf_abort(lock, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wsrep_test::bf_abort_ordered(wsrep::client_context& cc)
|
||||||
|
{
|
||||||
|
wsrep::unique_lock<wsrep::mutex> lock(cc.mutex());
|
||||||
|
assert(cc.transaction().ordered());
|
||||||
|
cc.bf_abort(lock, 0);
|
||||||
|
}
|
||||||
// BF abort method to abort transactions via provider
|
// BF abort method to abort transactions via provider
|
||||||
void wsrep_test::bf_abort_provider(wsrep::mock_server_context& sc,
|
void wsrep_test::bf_abort_provider(wsrep::mock_server_context& sc,
|
||||||
const wsrep::transaction_context& tc,
|
const wsrep::transaction_context& tc,
|
||||||
|
@ -21,6 +21,9 @@ namespace wsrep_test
|
|||||||
// Simple BF abort method to BF abort unordered transasctions
|
// Simple BF abort method to BF abort unordered transasctions
|
||||||
void bf_abort_unordered(wsrep::client_context& cc);
|
void bf_abort_unordered(wsrep::client_context& cc);
|
||||||
|
|
||||||
|
// Simple BF abort method to BF abort unordered transasctions
|
||||||
|
void bf_abort_ordered(wsrep::client_context& cc);
|
||||||
|
|
||||||
// BF abort method to abort transactions via provider
|
// BF abort method to abort transactions via provider
|
||||||
void bf_abort_provider(wsrep::mock_server_context& sc,
|
void bf_abort_provider(wsrep::mock_server_context& sc,
|
||||||
const wsrep::transaction_context& tc,
|
const wsrep::transaction_context& tc,
|
||||||
|
@ -725,7 +725,7 @@ int wsrep::transaction_context::certify_commit(
|
|||||||
lock.lock();
|
lock.lock();
|
||||||
|
|
||||||
assert(state() == s_certifying || state() == s_must_abort);
|
assert(state() == s_certifying || state() == s_must_abort);
|
||||||
client_context_.debug_sync("wsrep_after_replication");
|
client_context_.debug_sync(lock, "wsrep_after_certification");
|
||||||
|
|
||||||
int ret(1);
|
int ret(1);
|
||||||
switch (cert_ret)
|
switch (cert_ret)
|
||||||
@ -761,8 +761,8 @@ int wsrep::transaction_context::certify_commit(
|
|||||||
state(lock, s_must_abort);
|
state(lock, s_must_abort);
|
||||||
// The execution should never reach this point if the
|
// The execution should never reach this point if the
|
||||||
// transaction has not generated any keys or data.
|
// transaction has not generated any keys or data.
|
||||||
|
wsrep::log_warning() << "Transaction was missing in provider";
|
||||||
client_context_.override_error(wsrep::e_error_during_commit);
|
client_context_.override_error(wsrep::e_error_during_commit);
|
||||||
assert(0);
|
|
||||||
break;
|
break;
|
||||||
case wsrep::provider::error_bf_abort:
|
case wsrep::provider::error_bf_abort:
|
||||||
// Transaction was replicated succesfully and it was either
|
// Transaction was replicated succesfully and it was either
|
||||||
@ -797,15 +797,20 @@ int wsrep::transaction_context::certify_commit(
|
|||||||
client_context_.override_error(wsrep::e_error_during_commit);
|
client_context_.override_error(wsrep::e_error_during_commit);
|
||||||
break;
|
break;
|
||||||
case wsrep::provider::error_fatal:
|
case wsrep::provider::error_fatal:
|
||||||
|
client_context_.override_error(wsrep::e_error_during_commit);
|
||||||
|
state(lock, s_must_abort);
|
||||||
client_context_.abort();
|
client_context_.abort();
|
||||||
break;
|
break;
|
||||||
case wsrep::provider::error_not_implemented:
|
case wsrep::provider::error_not_implemented:
|
||||||
case wsrep::provider::error_not_allowed:
|
case wsrep::provider::error_not_allowed:
|
||||||
client_context_.override_error(wsrep::e_error_during_commit);
|
client_context_.override_error(wsrep::e_error_during_commit);
|
||||||
state(lock, s_must_abort);
|
state(lock, s_must_abort);
|
||||||
assert(0);
|
wsrep::log_warning() << "Certification operation was not allowed: "
|
||||||
|
<< "id: " << id().get()
|
||||||
|
<< " flags: " << std::hex << flags() << std::dec;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
state(lock, s_must_abort);
|
||||||
client_context_.override_error(wsrep::e_error_during_commit);
|
client_context_.override_error(wsrep::e_error_during_commit);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -550,6 +550,334 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
|||||||
BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
|
BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test a 1PC transaction which gets "warning error" from certify call
|
||||||
|
//
|
||||||
|
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||||
|
transaction_context_1pc_warning_error_from_certify, T,
|
||||||
|
replicating_fixtures, T)
|
||||||
|
{
|
||||||
|
wsrep::mock_server_context& sc(T::sc);
|
||||||
|
wsrep::client_context& cc(T::cc);
|
||||||
|
const wsrep::transaction_context& tc(T::tc);
|
||||||
|
|
||||||
|
// Start a new transaction with ID 1
|
||||||
|
cc.start_transaction(1);
|
||||||
|
BOOST_REQUIRE(tc.active());
|
||||||
|
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::error_warning);
|
||||||
|
|
||||||
|
// Run before commit
|
||||||
|
BOOST_REQUIRE(cc.before_commit());
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::success);
|
||||||
|
|
||||||
|
// Rollback sequence
|
||||||
|
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborting);
|
||||||
|
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborted);
|
||||||
|
|
||||||
|
// Cleanup after statement
|
||||||
|
cc.after_statement();
|
||||||
|
BOOST_REQUIRE(tc.active() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(cc.current_error() == wsrep::e_error_during_commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test a 1PC transaction which gets transaction missing from certify call
|
||||||
|
//
|
||||||
|
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||||
|
transaction_context_1pc_transaction_missing_from_certify, T,
|
||||||
|
replicating_fixtures, T)
|
||||||
|
{
|
||||||
|
wsrep::mock_server_context& sc(T::sc);
|
||||||
|
wsrep::client_context& cc(T::cc);
|
||||||
|
const wsrep::transaction_context& tc(T::tc);
|
||||||
|
|
||||||
|
// Start a new transaction with ID 1
|
||||||
|
cc.start_transaction(1);
|
||||||
|
BOOST_REQUIRE(tc.active());
|
||||||
|
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::error_transaction_missing);
|
||||||
|
|
||||||
|
// Run before commit
|
||||||
|
BOOST_REQUIRE(cc.before_commit());
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::success);
|
||||||
|
|
||||||
|
// Rollback sequence
|
||||||
|
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborting);
|
||||||
|
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborted);
|
||||||
|
|
||||||
|
// Cleanup after statement
|
||||||
|
cc.after_statement();
|
||||||
|
BOOST_REQUIRE(tc.active() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(cc.current_error() == wsrep::e_error_during_commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test a 1PC transaction which gets size exceeded error from certify call
|
||||||
|
//
|
||||||
|
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||||
|
transaction_context_1pc_size_exceeded_from_certify, T,
|
||||||
|
replicating_fixtures, T)
|
||||||
|
{
|
||||||
|
wsrep::mock_server_context& sc(T::sc);
|
||||||
|
wsrep::client_context& cc(T::cc);
|
||||||
|
const wsrep::transaction_context& tc(T::tc);
|
||||||
|
|
||||||
|
// Start a new transaction with ID 1
|
||||||
|
cc.start_transaction(1);
|
||||||
|
BOOST_REQUIRE(tc.active());
|
||||||
|
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::error_size_exceeded);
|
||||||
|
|
||||||
|
// Run before commit
|
||||||
|
BOOST_REQUIRE(cc.before_commit());
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::success);
|
||||||
|
|
||||||
|
// Rollback sequence
|
||||||
|
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborting);
|
||||||
|
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborted);
|
||||||
|
|
||||||
|
// Cleanup after statement
|
||||||
|
cc.after_statement();
|
||||||
|
BOOST_REQUIRE(tc.active() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(cc.current_error() == wsrep::e_error_during_commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test a 1PC transaction which gets connection failed error from certify call
|
||||||
|
//
|
||||||
|
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||||
|
transaction_context_1pc_connection_failed_from_certify, T,
|
||||||
|
replicating_fixtures, T)
|
||||||
|
{
|
||||||
|
wsrep::mock_server_context& sc(T::sc);
|
||||||
|
wsrep::client_context& cc(T::cc);
|
||||||
|
const wsrep::transaction_context& tc(T::tc);
|
||||||
|
|
||||||
|
// Start a new transaction with ID 1
|
||||||
|
cc.start_transaction(1);
|
||||||
|
BOOST_REQUIRE(tc.active());
|
||||||
|
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::error_connection_failed);
|
||||||
|
|
||||||
|
// Run before commit
|
||||||
|
BOOST_REQUIRE(cc.before_commit());
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::success);
|
||||||
|
|
||||||
|
// Rollback sequence
|
||||||
|
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborting);
|
||||||
|
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborted);
|
||||||
|
|
||||||
|
// Cleanup after statement
|
||||||
|
cc.after_statement();
|
||||||
|
BOOST_REQUIRE(tc.active() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(cc.current_error() == wsrep::e_error_during_commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test a 1PC transaction which gets not allowed error from certify call
|
||||||
|
//
|
||||||
|
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||||
|
transaction_context_1pc_no_allowed_from_certify, T,
|
||||||
|
replicating_fixtures, T)
|
||||||
|
{
|
||||||
|
wsrep::mock_server_context& sc(T::sc);
|
||||||
|
wsrep::client_context& cc(T::cc);
|
||||||
|
const wsrep::transaction_context& tc(T::tc);
|
||||||
|
|
||||||
|
// Start a new transaction with ID 1
|
||||||
|
cc.start_transaction(1);
|
||||||
|
BOOST_REQUIRE(tc.active());
|
||||||
|
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::error_not_allowed);
|
||||||
|
|
||||||
|
// Run before commit
|
||||||
|
BOOST_REQUIRE(cc.before_commit());
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::success);
|
||||||
|
|
||||||
|
// Rollback sequence
|
||||||
|
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborting);
|
||||||
|
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborted);
|
||||||
|
|
||||||
|
// Cleanup after statement
|
||||||
|
cc.after_statement();
|
||||||
|
BOOST_REQUIRE(tc.active() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(cc.current_error() == wsrep::e_error_during_commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test a 1PC transaction which gets fatal error from certify call
|
||||||
|
//
|
||||||
|
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||||
|
transaction_context_1pc_fatal_from_certify, T,
|
||||||
|
replicating_fixtures, T)
|
||||||
|
{
|
||||||
|
wsrep::mock_server_context& sc(T::sc);
|
||||||
|
wsrep::mock_client_context& cc(T::cc);
|
||||||
|
const wsrep::transaction_context& tc(T::tc);
|
||||||
|
|
||||||
|
// Start a new transaction with ID 1
|
||||||
|
cc.start_transaction(1);
|
||||||
|
BOOST_REQUIRE(tc.active());
|
||||||
|
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::error_fatal);
|
||||||
|
|
||||||
|
// Run before commit
|
||||||
|
BOOST_REQUIRE(cc.before_commit());
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::success);
|
||||||
|
|
||||||
|
// Rollback sequence
|
||||||
|
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborting);
|
||||||
|
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborted);
|
||||||
|
|
||||||
|
// Cleanup after statement
|
||||||
|
cc.after_statement();
|
||||||
|
BOOST_REQUIRE(tc.active() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(cc.current_error() == wsrep::e_error_during_commit);
|
||||||
|
BOOST_REQUIRE(cc.aborts() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test a 1PC transaction which gets unknown from certify call
|
||||||
|
//
|
||||||
|
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||||
|
transaction_context_1pc_unknown_from_certify, T,
|
||||||
|
replicating_fixtures, T)
|
||||||
|
{
|
||||||
|
wsrep::mock_server_context& sc(T::sc);
|
||||||
|
wsrep::mock_client_context& cc(T::cc);
|
||||||
|
const wsrep::transaction_context& tc(T::tc);
|
||||||
|
|
||||||
|
// Start a new transaction with ID 1
|
||||||
|
cc.start_transaction(1);
|
||||||
|
BOOST_REQUIRE(tc.active());
|
||||||
|
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::error_unknown);
|
||||||
|
|
||||||
|
// Run before commit
|
||||||
|
BOOST_REQUIRE(cc.before_commit());
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
|
||||||
|
sc.provider().inject_error(wsrep::provider::success);
|
||||||
|
|
||||||
|
// Rollback sequence
|
||||||
|
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborting);
|
||||||
|
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborted);
|
||||||
|
|
||||||
|
// Cleanup after statement
|
||||||
|
cc.after_statement();
|
||||||
|
BOOST_REQUIRE(tc.active() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(cc.current_error() == wsrep::e_error_during_commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test a 1PC transaction which gets BF aborted before grabbing lock
|
||||||
|
// after certify call
|
||||||
|
//
|
||||||
|
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||||
|
transaction_context_1pc_bf_abort_after_certify_regain_lock, T,
|
||||||
|
replicating_fixtures, T)
|
||||||
|
{
|
||||||
|
// wsrep::mock_server_context& sc(T::sc);
|
||||||
|
wsrep::mock_client_context& cc(T::cc);
|
||||||
|
const wsrep::transaction_context& tc(T::tc);
|
||||||
|
|
||||||
|
// Start a new transaction with ID 1
|
||||||
|
cc.start_transaction(1);
|
||||||
|
BOOST_REQUIRE(tc.active());
|
||||||
|
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||||
|
|
||||||
|
cc.sync_point_action_ = "wsrep_after_certification";
|
||||||
|
// Run before commit
|
||||||
|
BOOST_REQUIRE(cc.before_commit());
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_replay);
|
||||||
|
BOOST_REQUIRE(tc.certified() == true);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == true);
|
||||||
|
|
||||||
|
// Rollback sequence
|
||||||
|
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_replay);
|
||||||
|
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||||
|
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_replay);
|
||||||
|
|
||||||
|
// Cleanup after statement
|
||||||
|
cc.after_statement();
|
||||||
|
BOOST_REQUIRE(cc.replays() == 1);
|
||||||
|
BOOST_REQUIRE(tc.active() == false);
|
||||||
|
BOOST_REQUIRE(tc.ordered() == false);
|
||||||
|
BOOST_REQUIRE(tc.certified() == false);
|
||||||
|
BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Test a 2PC transaction which gets BF aborted when trying to grab
|
// Test a 2PC transaction which gets BF aborted when trying to grab
|
||||||
// commit order.
|
// commit order.
|
||||||
|
Reference in New Issue
Block a user