489 lines
13 KiB
C++
489 lines
13 KiB
C++
/* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
#include "expect.h"
|
|
#include "xpl_error.h"
|
|
#include "ngs_common/protocol_protobuf.h"
|
|
|
|
|
|
static const int EXPECT_NO_ERROR = 1;
|
|
|
|
namespace xpl
|
|
{
|
|
namespace test
|
|
{
|
|
static ngs::Error_code success;
|
|
|
|
static ngs::Error_code simulate_instruction(Expectation_stack &xs, int8_t mid, ngs::Error_code fail)
|
|
{
|
|
ngs::Error_code err = xs.pre_client_stmt(mid);
|
|
if (!err)
|
|
{
|
|
// execution would come here
|
|
err = fail;
|
|
xs.post_client_stmt(mid, fail);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static ngs::Error_code simulate_close(Expectation_stack &xs)
|
|
{
|
|
ngs::Error_code err = xs.pre_client_stmt(Mysqlx::ClientMessages::EXPECT_CLOSE);
|
|
if (!err)
|
|
{
|
|
err = xs.close();
|
|
xs.post_client_stmt(Mysqlx::ClientMessages::EXPECT_CLOSE, err);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static ngs::Error_code simulate_open(Expectation_stack &xs, const Mysqlx::Expect::Open &open)
|
|
{
|
|
ngs::Error_code err = xs.pre_client_stmt(Mysqlx::ClientMessages::EXPECT_OPEN);
|
|
if (!err)
|
|
{
|
|
err = xs.open(open);
|
|
xs.post_client_stmt(Mysqlx::ClientMessages::EXPECT_OPEN, err);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static Mysqlx::Expect::Open Inherit()
|
|
{
|
|
Mysqlx::Expect::Open open;
|
|
open.set_op(Mysqlx::Expect::Open::EXPECT_CTX_COPY_PREV);
|
|
return open;
|
|
}
|
|
|
|
static Mysqlx::Expect::Open Noerror()
|
|
{
|
|
Mysqlx::Expect::Open open;
|
|
|
|
open.set_op(Mysqlx::Expect::Open::EXPECT_CTX_EMPTY);
|
|
Mysqlx::Expect::Open::Condition *cond = open.mutable_cond()->Add();
|
|
cond->set_condition_key(EXPECT_NO_ERROR);
|
|
cond->set_op(Mysqlx::Expect::Open::Condition::EXPECT_OP_SET);
|
|
return open;
|
|
}
|
|
|
|
static Mysqlx::Expect::Open Plain()
|
|
{
|
|
Mysqlx::Expect::Open open;
|
|
|
|
open.set_op(Mysqlx::Expect::Open::EXPECT_CTX_EMPTY);
|
|
return open;
|
|
}
|
|
|
|
static Mysqlx::Expect::Open Inherit_and_clear_noerror()
|
|
{
|
|
Mysqlx::Expect::Open open = Inherit();
|
|
|
|
Mysqlx::Expect::Open::Condition *cond = open.mutable_cond()->Add();
|
|
cond->set_condition_key(EXPECT_NO_ERROR);
|
|
cond->set_op(Mysqlx::Expect::Open::Condition::EXPECT_OP_UNSET);
|
|
|
|
return open;
|
|
}
|
|
|
|
static Mysqlx::Expect::Open Inherit_and_add_noerror()
|
|
{
|
|
Mysqlx::Expect::Open open = Inherit();
|
|
|
|
Mysqlx::Expect::Open::Condition *cond = open.mutable_cond()->Add();
|
|
cond->set_condition_key(EXPECT_NO_ERROR);
|
|
cond->set_op(Mysqlx::Expect::Open::Condition::EXPECT_OP_SET);
|
|
|
|
return open;
|
|
}
|
|
|
|
|
|
#define EXPECT_ok_cmd() ASSERT_EQ(success, simulate_instruction(xs, 1, ngs::Error_code()))
|
|
#define EXPECT_error_cmd() ASSERT_EQ(ngs::Error_code(1234, "whatever"), simulate_instruction(xs, 2, ngs::Error_code(1234, "whatever")))
|
|
#define EXPECT_fail(exp) ASSERT_EQ(ngs::Error_code(ER_X_EXPECT_FAILED, "Expectation failed: " exp), simulate_instruction(xs, 3, ngs::Error_code()))
|
|
|
|
#define EXPECT_open_ok(msg) ASSERT_EQ(success, simulate_open(xs, msg))
|
|
#define EXPECT_open_fail(msg, exp) ASSERT_EQ(ngs::Error_code(ER_X_EXPECT_FAILED, "Expectation failed: " exp), simulate_open(xs, msg))
|
|
|
|
#define EXPECT_close_ok() ASSERT_EQ(success, simulate_close(xs))
|
|
#define EXPECT_close_fail(exp) ASSERT_EQ(ngs::Error_code(ER_X_EXPECT_FAILED, "Expectation failed: " exp), simulate_close(xs))
|
|
|
|
|
|
TEST(expect, plain)
|
|
{
|
|
Expectation_stack xs;
|
|
|
|
// open expect block
|
|
EXPECT_open_ok(Plain());
|
|
|
|
// ok command 1
|
|
EXPECT_ok_cmd();
|
|
EXPECT_ok_cmd();
|
|
// error command 2
|
|
EXPECT_error_cmd();
|
|
|
|
// subsequent cmds succeed normally
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
|
|
// now close the block
|
|
EXPECT_close_ok();
|
|
|
|
EXPECT_ok_cmd();
|
|
|
|
// close too much should fail
|
|
EXPECT_EQ(ngs::Error_code(ER_X_EXPECT_NOT_OPEN, "Expect block currently not open"), xs.close());
|
|
}
|
|
|
|
|
|
TEST(expect, noerror)
|
|
{
|
|
Expectation_stack xs;
|
|
|
|
// open expect block
|
|
EXPECT_open_ok(Noerror());
|
|
|
|
// ok command 1
|
|
EXPECT_ok_cmd();
|
|
// error command 2
|
|
EXPECT_error_cmd();
|
|
// now everything fails
|
|
EXPECT_fail("no_error");
|
|
EXPECT_fail("no_error");
|
|
|
|
// now close the block
|
|
EXPECT_close_fail("no_error");
|
|
|
|
// now commands should succeed again
|
|
EXPECT_ok_cmd();
|
|
}
|
|
|
|
|
|
TEST(expect, noerror_in_noerror)
|
|
{
|
|
Expectation_stack xs;
|
|
|
|
// fail in the inner block
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
}
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
|
|
EXPECT_ok_cmd();
|
|
EXPECT_EQ(ngs::Error_code(ER_X_EXPECT_NOT_OPEN, "Expect block currently not open"), xs.close());
|
|
|
|
// fail in the outer block
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
{
|
|
EXPECT_open_fail(Noerror(), "no_error");
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
}
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
|
|
EXPECT_ok_cmd();
|
|
EXPECT_EQ(ngs::Error_code(ER_X_EXPECT_NOT_OPEN, "Expect block currently not open"), xs.close());
|
|
|
|
// fail in inner block again
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Inherit());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
}
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
|
|
EXPECT_ok_cmd();
|
|
}
|
|
|
|
|
|
TEST(expect, plain_in_noerror)
|
|
{
|
|
Expectation_stack xs;
|
|
|
|
// fail in the inner block
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Plain());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_ok_cmd();
|
|
EXPECT_close_ok();
|
|
}
|
|
EXPECT_close_ok();
|
|
|
|
EXPECT_ok_cmd();
|
|
EXPECT_EQ(ngs::Error_code(ER_X_EXPECT_NOT_OPEN, "Expect block currently not open"), xs.close());
|
|
|
|
// fail in the outer block
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
{
|
|
EXPECT_open_fail(Plain(), "no_error");
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
}
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
|
|
EXPECT_ok_cmd();
|
|
EXPECT_EQ(ngs::Error_code(ER_X_EXPECT_NOT_OPEN, "Expect block currently not open"), xs.close());
|
|
|
|
// fail in inner block again
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Inherit());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
}
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Inherit_and_add_noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
}
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Inherit_and_clear_noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_ok_cmd();
|
|
EXPECT_close_ok();
|
|
}
|
|
EXPECT_close_ok();
|
|
|
|
EXPECT_ok_cmd();
|
|
}
|
|
|
|
|
|
TEST(expect, noerror_in_plain)
|
|
{
|
|
Expectation_stack xs;
|
|
|
|
// fail in the inner block
|
|
EXPECT_open_ok(Plain());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
}
|
|
EXPECT_ok_cmd();
|
|
EXPECT_close_ok();
|
|
|
|
EXPECT_ok_cmd();
|
|
EXPECT_EQ(ngs::Error_code(ER_X_EXPECT_NOT_OPEN, "Expect block currently not open"), xs.close());
|
|
|
|
// fail in the outer block
|
|
EXPECT_open_ok(Plain());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
{
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_close_ok();
|
|
}
|
|
EXPECT_ok_cmd();
|
|
EXPECT_close_ok();
|
|
|
|
EXPECT_ok_cmd();
|
|
EXPECT_EQ(ngs::Error_code(ER_X_EXPECT_NOT_OPEN, "Expect block currently not open"), xs.close());
|
|
|
|
// fail in inner block again
|
|
EXPECT_open_ok(Plain());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Inherit());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_ok_cmd();
|
|
EXPECT_close_ok();
|
|
}
|
|
EXPECT_close_ok();
|
|
|
|
EXPECT_open_ok(Plain());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Inherit_and_add_noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
}
|
|
EXPECT_ok_cmd();
|
|
EXPECT_close_ok();
|
|
|
|
EXPECT_ok_cmd();
|
|
}
|
|
|
|
|
|
TEST(expect, nested_inheriting)
|
|
{
|
|
Expectation_stack xs;
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Inherit_and_add_noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
}
|
|
EXPECT_close_fail("no_error");
|
|
|
|
EXPECT_open_ok(Noerror());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Inherit_and_clear_noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_ok_cmd();
|
|
EXPECT_close_ok();
|
|
}
|
|
EXPECT_close_ok();
|
|
|
|
EXPECT_open_ok(Plain());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Inherit_and_add_noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_fail("no_error");
|
|
EXPECT_close_fail("no_error");
|
|
}
|
|
EXPECT_close_ok();
|
|
|
|
EXPECT_open_ok(Plain());
|
|
EXPECT_ok_cmd();
|
|
{
|
|
EXPECT_open_ok(Inherit_and_clear_noerror());
|
|
EXPECT_ok_cmd();
|
|
EXPECT_error_cmd();
|
|
EXPECT_ok_cmd();
|
|
EXPECT_close_ok();
|
|
}
|
|
EXPECT_close_ok();
|
|
}
|
|
|
|
TEST(expect, invalid)
|
|
{
|
|
{
|
|
Expectation exp;
|
|
EXPECT_EQ(ngs::Error_code(ER_X_EXPECT_BAD_CONDITION, "Unknown condition key"), exp.set(1234, "1"));
|
|
}
|
|
|
|
{
|
|
Expectation exp;
|
|
EXPECT_EQ(ngs::Error_code(), exp.set(1, ""));
|
|
EXPECT_EQ(true, exp.fail_on_error());
|
|
|
|
EXPECT_EQ(ngs::Error_code(), exp.set(1, "1"));
|
|
EXPECT_EQ(true, exp.fail_on_error());
|
|
|
|
EXPECT_EQ(ngs::Error_code(), exp.set(1, "0"));
|
|
EXPECT_FALSE(exp.fail_on_error());
|
|
|
|
EXPECT_EQ(ngs::Error_code(ER_X_EXPECT_BAD_CONDITION_VALUE, "Invalid value 'bla' for expectation no_error"), exp.set(1, "bla"));
|
|
EXPECT_FALSE(exp.fail_on_error());
|
|
}
|
|
}
|
|
|
|
|
|
class Expect_surprise : public xpl::Expect_condition
|
|
{
|
|
public:
|
|
Expect_surprise(bool v) : m_value(v) {}
|
|
|
|
virtual Expect_condition *copy()
|
|
{
|
|
Expect_surprise *exp = new Expect_surprise(m_value);
|
|
return exp;
|
|
}
|
|
|
|
virtual ngs::Error_code check()
|
|
{
|
|
if (m_value)
|
|
return ngs::Error_code(1, "surprise");
|
|
return ngs::Error_code();
|
|
}
|
|
|
|
void set(bool flag)
|
|
{
|
|
m_value = flag;
|
|
}
|
|
|
|
private:
|
|
bool m_value;
|
|
};
|
|
|
|
|
|
TEST(expect, condition)
|
|
{
|
|
Expectation expect;
|
|
|
|
Expect_surprise *surp;
|
|
ASSERT_EQ(ngs::Error_code(), expect.check());
|
|
expect.add_condition(surp = new Expect_surprise(false));
|
|
surp->set_key(1234);
|
|
ASSERT_EQ(ngs::Error_code(), expect.check());
|
|
surp->set(true);
|
|
ASSERT_EQ(ngs::Error_code(1, "surprise"), expect.check());
|
|
{
|
|
Expectation copy(expect);
|
|
|
|
ASSERT_EQ(ngs::Error_code(1, "surprise"), expect.check());
|
|
ASSERT_EQ(ngs::Error_code(1, "surprise"), copy.check());
|
|
expect.unset(1234);
|
|
ASSERT_EQ(ngs::Error_code(), expect.check());
|
|
ASSERT_EQ(ngs::Error_code(1, "surprise"), copy.check());
|
|
}
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace xpl
|
|
|