1
0
mirror of https://github.com/codership/wsrep-lib.git synced 2025-08-06 15:02:41 +03:00

Moved 2PC tests into separate compliation unit.

This commit is contained in:
Teemu Ollakka
2018-06-13 12:22:03 +03:00
parent 9ff5d61111
commit 37c56cb5ec
6 changed files with 415 additions and 335 deletions

View File

@@ -239,8 +239,15 @@ int wsrep::transaction_context::before_commit()
} }
else if (state() != s_committing) else if (state() != s_committing)
{ {
assert(state() == s_must_abort); assert(state() == s_must_abort);
if (certified())
{
state(lock, s_must_replay);
}
else
{
client_context_.override_error(wsrep::e_deadlock_error); client_context_.override_error(wsrep::e_deadlock_error);
}
} }
else else
{ {
@@ -768,10 +775,10 @@ int wsrep::transaction_context::certify_commit(
{ {
case wsrep::provider::success: case wsrep::provider::success:
assert(ordered()); assert(ordered());
certified_ = true;
switch (state()) switch (state())
{ {
case s_certifying: case s_certifying:
certified_ = true;
state(lock, s_committing); state(lock, s_committing);
ret = 0; ret = 0;
break; break;
@@ -786,7 +793,6 @@ int wsrep::transaction_context::certify_commit(
assert(0); assert(0);
break; break;
} }
certified_ = true;
break; break;
case wsrep::provider::error_warning: case wsrep::provider::error_warning:
assert(ordered() == false); assert(ordered() == false);

View File

@@ -8,6 +8,7 @@ add_executable(wsrep-lib_test
id_test.cpp id_test.cpp
server_context_test.cpp server_context_test.cpp
transaction_context_test.cpp transaction_context_test.cpp
transaction_context_test_2pc.cpp
wsrep-lib_test.cpp wsrep-lib_test.cpp
) )
target_link_libraries(wsrep-lib_test wsrep-lib) target_link_libraries(wsrep-lib_test wsrep-lib)

View File

@@ -0,0 +1,123 @@
//
// Copyright (C) 2018 Codership Oy <info@codership.com>
//
#ifndef WSREP_TEST_CLIENT_CONTEXT_FIXTURE_HPP
#define WSREP_TEST_CLIENT_CONTEXT_FIXTURE_HPP
#include "fake_server_context.hpp"
#include "fake_client_context.hpp"
#include <boost/test/unit_test.hpp>
namespace
{
struct replicating_client_fixture_sync_rm
{
replicating_client_fixture_sync_rm()
: sc("s1", "s1", wsrep::server_context::rm_sync)
, cc(sc, wsrep::client_id(1),
wsrep::client_context::m_replicating)
, tc(cc.transaction())
{
BOOST_REQUIRE(cc.before_command() == 0);
BOOST_REQUIRE(cc.before_statement() == 0);
// Verify initial state
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
}
wsrep::fake_server_context sc;
wsrep::fake_client_context cc;
const wsrep::transaction_context& tc;
};
struct replicating_client_fixture_async_rm
{
replicating_client_fixture_async_rm()
: sc("s1", "s1", wsrep::server_context::rm_async)
, cc(sc, wsrep::client_id(1),
wsrep::client_context::m_replicating)
, tc(cc.transaction())
{
BOOST_REQUIRE(cc.before_command() == 0);
BOOST_REQUIRE(cc.before_statement() == 0);
// Verify initial state
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
}
wsrep::fake_server_context sc;
wsrep::fake_client_context cc;
const wsrep::transaction_context& tc;
};
struct replicating_client_fixture_autocommit
{
replicating_client_fixture_autocommit()
: sc("s1", "s1", wsrep::server_context::rm_sync)
, cc(sc, wsrep::client_id(1),
wsrep::client_context::m_replicating, true)
, tc(cc.transaction())
{
BOOST_REQUIRE(cc.before_command() == 0);
BOOST_REQUIRE(cc.before_statement() == 0);
// Verify initial state
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
}
wsrep::fake_server_context sc;
wsrep::fake_client_context cc;
const wsrep::transaction_context& tc;
};
struct applying_client_fixture
{
applying_client_fixture()
: sc("s1", "s1",
wsrep::server_context::rm_async)
, cc(sc,
wsrep::client_id(1),
wsrep::client_context::m_applier)
, tc(cc.transaction())
{
BOOST_REQUIRE(cc.before_command() == 0);
BOOST_REQUIRE(cc.before_statement() == 0);
wsrep::ws_handle ws_handle(1, (void*)1);
wsrep::ws_meta ws_meta(wsrep::gtid(wsrep::id("1"), wsrep::seqno(1)),
wsrep::stid(sc.id(), 1, cc.id()),
wsrep::seqno(0),
wsrep::provider::flag::start_transaction |
wsrep::provider::flag::commit);
BOOST_REQUIRE(cc.start_transaction(ws_handle, ws_meta) == 0);
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(cc.start_transaction() == 0);
BOOST_REQUIRE(tc.active() == true);
BOOST_REQUIRE(tc.certified() == true);
BOOST_REQUIRE(tc.ordered() == true);
}
wsrep::fake_server_context sc;
wsrep::fake_client_context cc;
const wsrep::transaction_context& tc;
};
struct streaming_client_fixture_row
{
streaming_client_fixture_row()
: sc("s1", "s1", wsrep::server_context::rm_sync)
, cc(sc, wsrep::client_id(1),
wsrep::client_context::m_replicating)
, tc(cc.transaction())
{
BOOST_REQUIRE(cc.before_command() == 0);
BOOST_REQUIRE(cc.before_statement() == 0);
// Verify initial state
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
cc.enable_streaming(wsrep::transaction_context::streaming_context::row, 1);
}
wsrep::fake_server_context sc;
wsrep::fake_client_context cc;
const wsrep::transaction_context& tc;
};
}
#endif // WSREP_TEST_CLIENT_CONTEXT_FIXTURE_HPP

View File

@@ -31,6 +31,7 @@ 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_enabled_()
, sync_point_action_() , sync_point_action_()
, replays_() , replays_()
, aborts_() , aborts_()
@@ -105,9 +106,14 @@ namespace wsrep
const char* sync_point) WSREP_OVERRIDE const char* sync_point) WSREP_OVERRIDE
{ {
lock.unlock(); lock.unlock();
if (sync_point_action_ == sync_point) if (sync_point_enabled_ == sync_point)
{ {
wsrep_test::bf_abort_ordered(*this); switch (sync_point_action_)
{
case spa_bf_abort:
wsrep_test::bf_abort_ordered(*this);
break;
}
} }
lock.lock(); lock.lock();
} }
@@ -129,7 +135,11 @@ 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_; std::string sync_point_enabled_;
enum sync_point_action
{
spa_bf_abort
} sync_point_action_;
private: private:
size_t replays_; size_t replays_;
size_t aborts_; size_t aborts_;

View File

@@ -5,123 +5,13 @@
#include "wsrep/transaction_context.hpp" #include "wsrep/transaction_context.hpp"
#include "wsrep/provider.hpp" #include "wsrep/provider.hpp"
#include "fake_client_context.hpp"
#include "fake_server_context.hpp"
#include "test_utils.hpp" #include "test_utils.hpp"
#include "client_context_fixture.hpp"
#include <boost/test/unit_test.hpp>
#include <boost/mpl/vector.hpp> #include <boost/mpl/vector.hpp>
namespace namespace
{ {
struct replicating_client_fixture_sync_rm
{
replicating_client_fixture_sync_rm()
: sc("s1", "s1", wsrep::server_context::rm_sync)
, cc(sc, wsrep::client_id(1),
wsrep::client_context::m_replicating)
, tc(cc.transaction())
{
BOOST_REQUIRE(cc.before_command() == 0);
BOOST_REQUIRE(cc.before_statement() == 0);
// Verify initial state
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
}
wsrep::fake_server_context sc;
wsrep::fake_client_context cc;
const wsrep::transaction_context& tc;
};
struct replicating_client_fixture_async_rm
{
replicating_client_fixture_async_rm()
: sc("s1", "s1", wsrep::server_context::rm_async)
, cc(sc, wsrep::client_id(1),
wsrep::client_context::m_replicating)
, tc(cc.transaction())
{
BOOST_REQUIRE(cc.before_command() == 0);
BOOST_REQUIRE(cc.before_statement() == 0);
// Verify initial state
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
}
wsrep::fake_server_context sc;
wsrep::fake_client_context cc;
const wsrep::transaction_context& tc;
};
struct replicating_client_fixture_autocommit
{
replicating_client_fixture_autocommit()
: sc("s1", "s1", wsrep::server_context::rm_sync)
, cc(sc, wsrep::client_id(1),
wsrep::client_context::m_replicating, true)
, tc(cc.transaction())
{
BOOST_REQUIRE(cc.before_command() == 0);
BOOST_REQUIRE(cc.before_statement() == 0);
// Verify initial state
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
}
wsrep::fake_server_context sc;
wsrep::fake_client_context cc;
const wsrep::transaction_context& tc;
};
struct applying_client_fixture
{
applying_client_fixture()
: sc("s1", "s1",
wsrep::server_context::rm_async)
, cc(sc,
wsrep::client_id(1),
wsrep::client_context::m_applier)
, tc(cc.transaction())
{
BOOST_REQUIRE(cc.before_command() == 0);
BOOST_REQUIRE(cc.before_statement() == 0);
wsrep::ws_handle ws_handle(1, (void*)1);
wsrep::ws_meta ws_meta(wsrep::gtid(wsrep::id("1"), wsrep::seqno(1)),
wsrep::stid(sc.id(), 1, cc.id()),
wsrep::seqno(0),
wsrep::provider::flag::start_transaction |
wsrep::provider::flag::commit);
BOOST_REQUIRE(cc.start_transaction(ws_handle, ws_meta) == 0);
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(cc.start_transaction() == 0);
BOOST_REQUIRE(tc.active() == true);
BOOST_REQUIRE(tc.certified() == true);
BOOST_REQUIRE(tc.ordered() == true);
}
wsrep::fake_server_context sc;
wsrep::fake_client_context cc;
const wsrep::transaction_context& tc;
};
struct streaming_client_fixture_row
{
streaming_client_fixture_row()
: sc("s1", "s1", wsrep::server_context::rm_sync)
, cc(sc, wsrep::client_id(1),
wsrep::client_context::m_replicating)
, tc(cc.transaction())
{
BOOST_REQUIRE(cc.before_command() == 0);
BOOST_REQUIRE(cc.before_statement() == 0);
// Verify initial state
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
cc.enable_streaming(wsrep::transaction_context::streaming_context::row, 1);
}
wsrep::fake_server_context sc;
wsrep::fake_client_context cc;
const wsrep::transaction_context& tc;
};
typedef typedef
boost::mpl::vector<replicating_client_fixture_sync_rm, boost::mpl::vector<replicating_client_fixture_sync_rm,
replicating_client_fixture_async_rm> replicating_client_fixture_async_rm>
@@ -188,47 +78,6 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(transaction_context_1pc, T,
BOOST_REQUIRE(cc.current_error() == wsrep::e_success); BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
} }
//
// Test a succesful 2PC transaction lifecycle
//
BOOST_FIXTURE_TEST_CASE_TEMPLATE(transaction_context_2pc, T,
replicating_fixtures, T)
{
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);
// Run before prepare
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_preparing);
// Run after prepare
BOOST_REQUIRE(cc.after_prepare() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committing);
// Run before commit
BOOST_REQUIRE(cc.before_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committing);
// Run ordered commit
BOOST_REQUIRE(cc.ordered_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_ordered_commit);
// Run after commit
BOOST_REQUIRE(cc.after_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committed);
// 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_success);
}
// //
// Test a voluntary rollback // Test a voluntary rollback
@@ -299,85 +148,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
BOOST_REQUIRE(cc.current_error()); BOOST_REQUIRE(cc.current_error());
} }
//
// Test a 2PC transaction which gets BF aborted before before_prepare
//
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
transaction_context_2pc_bf_before_before_prepare, T,
replicating_fixtures, T)
{
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);
wsrep_test::bf_abort_unordered(cc);
// Run before commit
BOOST_REQUIRE(cc.before_prepare());
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
BOOST_REQUIRE(tc.certified() == false);
BOOST_REQUIRE(tc.ordered() == false);
// 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());
}
//
// Test a 2PC transaction which gets BF aborted before before_prepare
//
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
transaction_context_2pc_bf_before_after_prepare, T,
replicating_fixtures, T)
{
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);
// Run before prepare
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_preparing);
wsrep_test::bf_abort_unordered(cc);
// Run before commit
BOOST_REQUIRE(cc.after_prepare());
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
BOOST_REQUIRE(tc.certified() == false);
BOOST_REQUIRE(tc.ordered() == false);
// 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());
}
// //
// Test a 1PC transaction which gets BF aborted during before_commit via // Test a 1PC transaction which gets BF aborted during before_commit via
@@ -885,7 +656,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1)); BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing); BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
cc.sync_point_action_ = "wsrep_after_certification"; cc.sync_point_enabled_ = "wsrep_after_certification";
// Run before commit // Run before commit
BOOST_REQUIRE(cc.before_commit()); BOOST_REQUIRE(cc.before_commit());
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_replay); BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_replay);
@@ -907,49 +678,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
BOOST_REQUIRE(cc.current_error() == wsrep::e_success); BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
} }
//
// Test a 2PC transaction which gets BF aborted when trying to grab
// commit order.
//
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
transaction_context_2pc_bf_during_commit_order_enter, T,
replicating_fixtures, T)
{
wsrep::fake_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);
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(cc.after_prepare() == 0);
sc.provider().commit_order_enter_status_ = wsrep::provider::error_bf_abort;
// 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);
sc.provider().commit_order_enter_status_ = wsrep::provider::success;
// 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(tc.active() == false);
BOOST_REQUIRE(tc.ordered() == false);
BOOST_REQUIRE(tc.certified() == false);
BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
}
// //
// Test a transaction which gets BF aborted before before_statement. // Test a transaction which gets BF aborted before before_statement.
@@ -1152,24 +881,6 @@ BOOST_FIXTURE_TEST_CASE(transaction_context_1pc_applying,
BOOST_REQUIRE(cc.current_error() == wsrep::e_success); BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
} }
BOOST_FIXTURE_TEST_CASE(transaction_context_2pc_applying,
applying_client_fixture)
{
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_preparing);
BOOST_REQUIRE(cc.after_prepare() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committing);
BOOST_REQUIRE(cc.before_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committing);
BOOST_REQUIRE(cc.ordered_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_ordered_commit);
BOOST_REQUIRE(cc.after_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committed);
cc.after_statement();
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committed);
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
}
BOOST_FIXTURE_TEST_CASE(transaction_context_applying_rollback, BOOST_FIXTURE_TEST_CASE(transaction_context_applying_rollback,
applying_client_fixture) applying_client_fixture)
@@ -1184,7 +895,6 @@ BOOST_FIXTURE_TEST_CASE(transaction_context_applying_rollback,
BOOST_REQUIRE(cc.current_error() == wsrep::e_success); BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// STREAMING REPLICATION // // STREAMING REPLICATION //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -1204,23 +914,6 @@ BOOST_FIXTURE_TEST_CASE(transaction_context_streaming_1pc_commit,
BOOST_REQUIRE(sc.provider().commit_fragments() == 1); BOOST_REQUIRE(sc.provider().commit_fragments() == 1);
} }
BOOST_FIXTURE_TEST_CASE(transaction_context_streaming_2pc_commit,
streaming_client_fixture_row)
{
BOOST_REQUIRE(cc.start_transaction(1) == 0);
BOOST_REQUIRE(cc.after_row() == 0);
BOOST_REQUIRE(tc.streaming_context_.fragments_certified() == 1);
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(cc.after_prepare() == 0);
BOOST_REQUIRE(cc.before_commit() == 0);
BOOST_REQUIRE(cc.ordered_commit() == 0);
BOOST_REQUIRE(cc.after_commit() == 0);
BOOST_REQUIRE(cc.after_statement() == wsrep::client_context::asr_success);
BOOST_REQUIRE(sc.provider().fragments() == 2);
BOOST_REQUIRE(sc.provider().start_fragments() == 1);
BOOST_REQUIRE(sc.provider().commit_fragments() == 1);
}
BOOST_FIXTURE_TEST_CASE(transaction_context_streaming_1pc_commit_two_statements, BOOST_FIXTURE_TEST_CASE(transaction_context_streaming_1pc_commit_two_statements,
@@ -1243,26 +936,6 @@ BOOST_FIXTURE_TEST_CASE(transaction_context_streaming_1pc_commit_two_statements,
} }
BOOST_FIXTURE_TEST_CASE(transaction_context_streaming_2pc_commit_two_statements,
streaming_client_fixture_row)
{
BOOST_REQUIRE(cc.start_transaction(1) == 0);
BOOST_REQUIRE(cc.after_row() == 0);
BOOST_REQUIRE(tc.streaming_context_.fragments_certified() == 1);
BOOST_REQUIRE(cc.after_statement() == wsrep::client_context::asr_success);
BOOST_REQUIRE(cc.before_statement() == 0);
BOOST_REQUIRE(cc.after_row() == 0);
BOOST_REQUIRE(tc.streaming_context_.fragments_certified() == 2);
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(cc.after_prepare() == 0);
BOOST_REQUIRE(cc.before_commit() == 0);
BOOST_REQUIRE(cc.ordered_commit() == 0);
BOOST_REQUIRE(cc.after_commit() == 0);
BOOST_REQUIRE(cc.after_statement() == wsrep::client_context::asr_success);
BOOST_REQUIRE(sc.provider().fragments() == 3);
BOOST_REQUIRE(sc.provider().start_fragments() == 1);
BOOST_REQUIRE(sc.provider().commit_fragments() == 1);
}
BOOST_FIXTURE_TEST_CASE(transaction_context_streaming_rollback, BOOST_FIXTURE_TEST_CASE(transaction_context_streaming_rollback,
streaming_client_fixture_row) streaming_client_fixture_row)

View File

@@ -0,0 +1,267 @@
//
// Copyright (C) 2018 Codership Oy <info@codership.com>
//
#include "client_context_fixture.hpp"
//
// Test a succesful 2PC transaction lifecycle
//
BOOST_FIXTURE_TEST_CASE(transaction_context_2pc,
replicating_client_fixture_sync_rm)
{
// 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);
// Run before prepare
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_preparing);
// Run after prepare
BOOST_REQUIRE(cc.after_prepare() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committing);
// Run before commit
BOOST_REQUIRE(cc.before_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committing);
// Run ordered commit
BOOST_REQUIRE(cc.ordered_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_ordered_commit);
// Run after commit
BOOST_REQUIRE(cc.after_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committed);
// 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_success);
}
//
// Test a 2PC transaction which gets BF aborted before before_prepare
//
BOOST_FIXTURE_TEST_CASE(
transaction_context_2pc_bf_before_before_prepare,
replicating_client_fixture_sync_rm)
{
// 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);
wsrep_test::bf_abort_unordered(cc);
// Run before commit
BOOST_REQUIRE(cc.before_prepare());
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
BOOST_REQUIRE(tc.certified() == false);
BOOST_REQUIRE(tc.ordered() == false);
// 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());
}
//
// Test a 2PC transaction which gets BF aborted before before_prepare
//
BOOST_FIXTURE_TEST_CASE(
transaction_context_2pc_bf_before_after_prepare,
replicating_client_fixture_sync_rm)
{
// 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);
// Run before prepare
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_preparing);
wsrep_test::bf_abort_unordered(cc);
// Run before commit
BOOST_REQUIRE(cc.after_prepare());
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
BOOST_REQUIRE(tc.certified() == false);
BOOST_REQUIRE(tc.ordered() == false);
// 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());
}
//
// Test a 2PC transaction which gets BF aborted between after_prepare()
// and before_commit()
//
BOOST_FIXTURE_TEST_CASE(
transaction_context_2pc_bf_before_before_commit,
replicating_client_fixture_sync_rm)
{
// 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);
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(cc.after_prepare() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committing);
wsrep_test::bf_abort_ordered(cc);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_abort);
// 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(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
// commit order.
//
BOOST_FIXTURE_TEST_CASE(
transaction_context_2pc_bf_during_commit_order_enter,
replicating_client_fixture_sync_rm)
{
// 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);
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(cc.after_prepare() == 0);
sc.provider().commit_order_enter_status_ = wsrep::provider::error_bf_abort;
// 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);
sc.provider().commit_order_enter_status_ = wsrep::provider::success;
// 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(tc.active() == false);
BOOST_REQUIRE(tc.ordered() == false);
BOOST_REQUIRE(tc.certified() == false);
BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
}
///////////////////////////////////////////////////////////////////////////////
// STREAMING REPLICATION //
///////////////////////////////////////////////////////////////////////////////
BOOST_FIXTURE_TEST_CASE(transaction_context_streaming_2pc_commit,
streaming_client_fixture_row)
{
BOOST_REQUIRE(cc.start_transaction(1) == 0);
BOOST_REQUIRE(cc.after_row() == 0);
BOOST_REQUIRE(tc.streaming_context_.fragments_certified() == 1);
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(cc.after_prepare() == 0);
BOOST_REQUIRE(cc.before_commit() == 0);
BOOST_REQUIRE(cc.ordered_commit() == 0);
BOOST_REQUIRE(cc.after_commit() == 0);
BOOST_REQUIRE(cc.after_statement() == wsrep::client_context::asr_success);
BOOST_REQUIRE(sc.provider().fragments() == 2);
BOOST_REQUIRE(sc.provider().start_fragments() == 1);
BOOST_REQUIRE(sc.provider().commit_fragments() == 1);
}
BOOST_FIXTURE_TEST_CASE(transaction_context_streaming_2pc_commit_two_statements,
streaming_client_fixture_row)
{
BOOST_REQUIRE(cc.start_transaction(1) == 0);
BOOST_REQUIRE(cc.after_row() == 0);
BOOST_REQUIRE(tc.streaming_context_.fragments_certified() == 1);
BOOST_REQUIRE(cc.after_statement() == wsrep::client_context::asr_success);
BOOST_REQUIRE(cc.before_statement() == 0);
BOOST_REQUIRE(cc.after_row() == 0);
BOOST_REQUIRE(tc.streaming_context_.fragments_certified() == 2);
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(cc.after_prepare() == 0);
BOOST_REQUIRE(cc.before_commit() == 0);
BOOST_REQUIRE(cc.ordered_commit() == 0);
BOOST_REQUIRE(cc.after_commit() == 0);
BOOST_REQUIRE(cc.after_statement() == wsrep::client_context::asr_success);
BOOST_REQUIRE(sc.provider().fragments() == 3);
BOOST_REQUIRE(sc.provider().start_fragments() == 1);
BOOST_REQUIRE(sc.provider().commit_fragments() == 1);
}
///////////////////////////////////////////////////////////////////////////////
// APPLYING //
///////////////////////////////////////////////////////////////////////////////
BOOST_FIXTURE_TEST_CASE(transaction_context_2pc_applying,
applying_client_fixture)
{
BOOST_REQUIRE(cc.before_prepare() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_preparing);
BOOST_REQUIRE(cc.after_prepare() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committing);
BOOST_REQUIRE(cc.before_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committing);
BOOST_REQUIRE(cc.ordered_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_ordered_commit);
BOOST_REQUIRE(cc.after_commit() == 0);
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committed);
cc.after_statement();
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_committed);
BOOST_REQUIRE(tc.active() == false);
BOOST_REQUIRE(cc.current_error() == wsrep::e_success);
}