3824 lines
93 KiB
C++

/*
Copyright (c) 2003, 2015, 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 <NDBT.hpp>
#include <NDBT_Test.hpp>
#include "NdbMgmd.hpp"
#include <mgmapi.h>
#include <mgmapi_debug.h>
#include "../../src/mgmapi/mgmapi_internal.h"
#include <InputStream.hpp>
#include <signaldata/EventReport.hpp>
#include <NdbRestarter.hpp>
#include <random.h>
/*
Tests that only need the mgmd(s) started
Start ndb_mgmd and set NDB_CONNECTSTRING pointing
to that/those ndb_mgmd(s), then run testMgm
*/
int runTestApiSession(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
Uint64 session_id= 0;
NdbMgmHandle h;
h= ndb_mgm_create_handle();
ndb_mgm_set_connectstring(h, mgmd.getConnectString());
ndb_mgm_connect(h,0,0,0);
#ifdef NDB_WIN
SOCKET s = ndb_mgm_get_fd(h);
#else
int s= ndb_mgm_get_fd(h);
#endif
session_id= ndb_mgm_get_session_id(h);
ndbout << "MGM Session id: " << session_id << endl;
send(s,"get",3,0);
ndb_mgm_disconnect(h);
ndb_mgm_destroy_handle(&h);
struct NdbMgmSession sess;
int slen= sizeof(struct NdbMgmSession);
h= ndb_mgm_create_handle();
ndb_mgm_set_connectstring(h, mgmd.getConnectString());
ndb_mgm_connect(h,0,0,0);
NdbSleep_SecSleep(1);
if(ndb_mgm_get_session(h,session_id,&sess,&slen))
{
ndbout << "Failed, session still exists" << endl;
ndb_mgm_disconnect(h);
ndb_mgm_destroy_handle(&h);
return NDBT_FAILED;
}
else
{
ndbout << "SUCCESS: session is gone" << endl;
ndb_mgm_disconnect(h);
ndb_mgm_destroy_handle(&h);
return NDBT_OK;
}
}
int runTestApiConnectTimeout(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
g_info << "Check connect works with timeout 3000" << endl;
if (!mgmd.set_timeout(3000))
return NDBT_FAILED;
if (!mgmd.connect(0, 0, 0))
{
g_err << "Connect failed with timeout 3000" << endl;
return NDBT_FAILED;
}
if (!mgmd.disconnect())
return NDBT_FAILED;
g_info << "Check connect to illegal host will timeout after 3000" << endl;
if (!mgmd.set_timeout(3000))
return NDBT_FAILED;
mgmd.setConnectString("1.1.1.1");
const Uint64 tstart= NdbTick_CurrentMillisecond();
if (mgmd.connect(0, 0, 0))
{
g_err << "Connect to illegal host suceeded" << endl;
return NDBT_FAILED;
}
const Uint64 msecs= NdbTick_CurrentMillisecond() - tstart;
ndbout << "Took about " << msecs <<" milliseconds"<<endl;
if(msecs > 6000)
{
g_err << "The connect to illegal host timedout after much longer "
<< "time than was expected, expected <= 6000, got " << msecs << endl;
return NDBT_FAILED;
}
return NDBT_OK;
}
int runTestApiTimeoutBasic(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
int result= NDBT_FAILED;
int cc= 0;
int mgmd_nodeid= 0;
ndb_mgm_reply reply;
NdbMgmHandle h;
h= ndb_mgm_create_handle();
ndb_mgm_set_connectstring(h, mgmd.getConnectString());
ndbout << "TEST timout check_connection" << endl;
int errs[] = { 1, 2, 3, -1};
for(int error_ins_no=0; errs[error_ins_no]!=-1; error_ins_no++)
{
int error_ins= errs[error_ins_no];
ndbout << "trying error " << error_ins << endl;
ndb_mgm_connect(h,0,0,0);
if(ndb_mgm_check_connection(h) < 0)
{
result= NDBT_FAILED;
goto done;
}
mgmd_nodeid= ndb_mgm_get_mgmd_nodeid(h);
if(mgmd_nodeid==0)
{
ndbout << "Failed to get mgmd node id to insert error" << endl;
result= NDBT_FAILED;
goto done;
}
reply.return_code= 0;
if(ndb_mgm_insert_error(h, mgmd_nodeid, error_ins, &reply)< 0)
{
ndbout << "failed to insert error " << endl;
result= NDBT_FAILED;
goto done;
}
ndb_mgm_set_timeout(h,2500);
cc= ndb_mgm_check_connection(h);
if(cc < 0)
result= NDBT_OK;
else
result= NDBT_FAILED;
if(ndb_mgm_is_connected(h))
{
ndbout << "FAILED: still connected" << endl;
result= NDBT_FAILED;
}
}
ndbout << "TEST get_mgmd_nodeid" << endl;
ndb_mgm_connect(h,0,0,0);
if(ndb_mgm_insert_error(h, mgmd_nodeid, 0, &reply)< 0)
{
ndbout << "failed to remove inserted error " << endl;
result= NDBT_FAILED;
goto done;
}
cc= ndb_mgm_get_mgmd_nodeid(h);
ndbout << "got node id: " << cc << endl;
if(cc==0)
{
ndbout << "FAILED: didn't get node id" << endl;
result= NDBT_FAILED;
}
else
result= NDBT_OK;
ndbout << "TEST end_session" << endl;
ndb_mgm_connect(h,0,0,0);
if(ndb_mgm_insert_error(h, mgmd_nodeid, 4, &reply)< 0)
{
ndbout << "FAILED: insert error 1" << endl;
result= NDBT_FAILED;
goto done;
}
cc= ndb_mgm_end_session(h);
if(cc==0)
{
ndbout << "FAILED: success in calling end_session" << endl;
result= NDBT_FAILED;
}
else if(ndb_mgm_get_latest_error(h)!=ETIMEDOUT)
{
ndbout << "FAILED: Incorrect error code (" << ndb_mgm_get_latest_error(h)
<< " != expected " << ETIMEDOUT << ") desc: "
<< ndb_mgm_get_latest_error_desc(h)
<< " line: " << ndb_mgm_get_latest_error_line(h)
<< " msg: " << ndb_mgm_get_latest_error_msg(h)
<< endl;
result= NDBT_FAILED;
}
else
result= NDBT_OK;
if(ndb_mgm_is_connected(h))
{
ndbout << "FAILED: is still connected after error" << endl;
result= NDBT_FAILED;
}
done:
ndb_mgm_disconnect(h);
ndb_mgm_destroy_handle(&h);
return result;
}
int runTestApiGetStatusTimeout(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
int result= NDBT_OK;
int mgmd_nodeid= 0;
NdbMgmHandle h;
h= ndb_mgm_create_handle();
ndb_mgm_set_connectstring(h, mgmd.getConnectString());
int errs[] = { 0, 5, 6, 7, 8, 9, -1 };
for(int error_ins_no=0; errs[error_ins_no]!=-1; error_ins_no++)
{
int error_ins= errs[error_ins_no];
ndb_mgm_connect(h,0,0,0);
if(ndb_mgm_check_connection(h) < 0)
{
result= NDBT_FAILED;
goto done;
}
mgmd_nodeid= ndb_mgm_get_mgmd_nodeid(h);
if(mgmd_nodeid==0)
{
ndbout << "Failed to get mgmd node id to insert error" << endl;
result= NDBT_FAILED;
goto done;
}
ndb_mgm_reply reply;
reply.return_code= 0;
if(ndb_mgm_insert_error(h, mgmd_nodeid, error_ins, &reply)< 0)
{
ndbout << "failed to insert error " << error_ins << endl;
result= NDBT_FAILED;
}
ndbout << "trying error: " << error_ins << endl;
ndb_mgm_set_timeout(h,2500);
struct ndb_mgm_cluster_state *cl= ndb_mgm_get_status(h);
if(cl!=NULL)
free(cl);
/*
* For whatever strange reason,
* get_status is okay with not having the last enter there.
* instead of "fixing" the api, let's have a special case
* so we don't break any behaviour
*/
if(error_ins!=0 && error_ins!=9 && cl!=NULL)
{
ndbout << "FAILED: got a ndb_mgm_cluster_state back" << endl;
result= NDBT_FAILED;
}
if(error_ins!=0 && error_ins!=9 && ndb_mgm_is_connected(h))
{
ndbout << "FAILED: is still connected after error" << endl;
result= NDBT_FAILED;
}
if(error_ins!=0 && error_ins!=9 && ndb_mgm_get_latest_error(h)!=ETIMEDOUT)
{
ndbout << "FAILED: Incorrect error code (" << ndb_mgm_get_latest_error(h)
<< " != expected " << ETIMEDOUT << ") desc: "
<< ndb_mgm_get_latest_error_desc(h)
<< " line: " << ndb_mgm_get_latest_error_line(h)
<< " msg: " << ndb_mgm_get_latest_error_msg(h)
<< endl;
result= NDBT_FAILED;
}
}
done:
ndb_mgm_disconnect(h);
ndb_mgm_destroy_handle(&h);
return result;
}
int runTestMgmApiGetConfigTimeout(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
int result= NDBT_OK;
int mgmd_nodeid= 0;
NdbMgmHandle h;
h= ndb_mgm_create_handle();
ndb_mgm_set_connectstring(h, mgmd.getConnectString());
int errs[] = { 0, 1, 2, 3, -1 };
for(int error_ins_no=0; errs[error_ins_no]!=-1; error_ins_no++)
{
int error_ins= errs[error_ins_no];
ndb_mgm_connect(h,0,0,0);
if(ndb_mgm_check_connection(h) < 0)
{
result= NDBT_FAILED;
goto done;
}
mgmd_nodeid= ndb_mgm_get_mgmd_nodeid(h);
if(mgmd_nodeid==0)
{
ndbout << "Failed to get mgmd node id to insert error" << endl;
result= NDBT_FAILED;
goto done;
}
ndb_mgm_reply reply;
reply.return_code= 0;
if(ndb_mgm_insert_error(h, mgmd_nodeid, error_ins, &reply)< 0)
{
ndbout << "failed to insert error " << error_ins << endl;
result= NDBT_FAILED;
}
ndbout << "trying error: " << error_ins << endl;
ndb_mgm_set_timeout(h,2500);
struct ndb_mgm_configuration *c= ndb_mgm_get_configuration(h,0);
if(c!=NULL)
free(c);
if(error_ins!=0 && c!=NULL)
{
ndbout << "FAILED: got a ndb_mgm_configuration back" << endl;
result= NDBT_FAILED;
}
if(error_ins!=0 && ndb_mgm_is_connected(h))
{
ndbout << "FAILED: is still connected after error" << endl;
result= NDBT_FAILED;
}
if(error_ins!=0 && ndb_mgm_get_latest_error(h)!=ETIMEDOUT)
{
ndbout << "FAILED: Incorrect error code (" << ndb_mgm_get_latest_error(h)
<< " != expected " << ETIMEDOUT << ") desc: "
<< ndb_mgm_get_latest_error_desc(h)
<< " line: " << ndb_mgm_get_latest_error_line(h)
<< " msg: " << ndb_mgm_get_latest_error_msg(h)
<< endl;
result= NDBT_FAILED;
}
}
done:
ndb_mgm_disconnect(h);
ndb_mgm_destroy_handle(&h);
return result;
}
int runTestMgmApiEventTimeout(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
int result= NDBT_OK;
int mgmd_nodeid= 0;
NdbMgmHandle h;
h= ndb_mgm_create_handle();
ndb_mgm_set_connectstring(h, mgmd.getConnectString());
int errs[] = { 10000, 0, -1 };
for(int error_ins_no=0; errs[error_ins_no]!=-1; error_ins_no++)
{
int error_ins= errs[error_ins_no];
ndb_mgm_connect(h,0,0,0);
if(ndb_mgm_check_connection(h) < 0)
{
result= NDBT_FAILED;
goto done;
}
mgmd_nodeid= ndb_mgm_get_mgmd_nodeid(h);
if(mgmd_nodeid==0)
{
ndbout << "Failed to get mgmd node id to insert error" << endl;
result= NDBT_FAILED;
goto done;
}
ndb_mgm_reply reply;
reply.return_code= 0;
if(ndb_mgm_insert_error(h, mgmd_nodeid, error_ins, &reply)< 0)
{
ndbout << "failed to insert error " << error_ins << endl;
result= NDBT_FAILED;
}
ndbout << "trying error: " << error_ins << endl;
ndb_mgm_set_timeout(h,2500);
int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP,
1, NDB_MGM_EVENT_CATEGORY_STARTUP,
0 };
NDB_SOCKET_TYPE my_fd;
#ifdef NDB_WIN
SOCKET fd= ndb_mgm_listen_event(h, filter);
my_fd.s= fd;
#else
int fd= ndb_mgm_listen_event(h, filter);
my_fd.fd= fd;
#endif
if(!my_socket_valid(my_fd))
{
ndbout << "FAILED: could not listen to event" << endl;
result= NDBT_FAILED;
}
union {
Uint32 theData[25];
EventReport repData;
};
EventReport *fake_event = &repData;
fake_event->setEventType(NDB_LE_NDBStopForced);
fake_event->setNodeId(42);
theData[2]= 0;
theData[3]= 0;
theData[4]= 0;
theData[5]= 0;
ndb_mgm_report_event(h, theData, 6);
char *tmp= 0;
char buf[512];
SocketInputStream in(my_fd,2000);
for(int i=0; i<20; i++)
{
if((tmp = in.gets(buf, sizeof(buf))))
{
// const char ping_token[]="<PING>";
// if(memcmp(ping_token,tmp,sizeof(ping_token)-1))
if(tmp && strlen(tmp))
ndbout << tmp;
}
else
{
if(in.timedout())
{
ndbout << "TIMED OUT READING EVENT at iteration " << i << endl;
break;
}
}
}
/*
* events go through a *DIFFERENT* socket than the NdbMgmHandle
* so we should still be connected (and be able to check_connection)
*
*/
if(ndb_mgm_check_connection(h) && !ndb_mgm_is_connected(h))
{
ndbout << "FAILED: is still connected after error" << endl;
result= NDBT_FAILED;
}
ndb_mgm_disconnect(h);
}
done:
ndb_mgm_disconnect(h);
ndb_mgm_destroy_handle(&h);
return result;
}
int runTestMgmApiStructEventTimeout(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
int result= NDBT_OK;
int mgmd_nodeid= 0;
NdbMgmHandle h;
h= ndb_mgm_create_handle();
ndb_mgm_set_connectstring(h, mgmd.getConnectString());
int errs[] = { 10000, 0, -1 };
for(int error_ins_no=0; errs[error_ins_no]!=-1; error_ins_no++)
{
int error_ins= errs[error_ins_no];
ndb_mgm_connect(h,0,0,0);
if(ndb_mgm_check_connection(h) < 0)
{
result= NDBT_FAILED;
goto done;
}
mgmd_nodeid= ndb_mgm_get_mgmd_nodeid(h);
if(mgmd_nodeid==0)
{
ndbout << "Failed to get mgmd node id to insert error" << endl;
result= NDBT_FAILED;
goto done;
}
ndb_mgm_reply reply;
reply.return_code= 0;
if(ndb_mgm_insert_error(h, mgmd_nodeid, error_ins, &reply)< 0)
{
ndbout << "failed to insert error " << error_ins << endl;
result= NDBT_FAILED;
}
ndbout << "trying error: " << error_ins << endl;
ndb_mgm_set_timeout(h,2500);
int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP,
1, NDB_MGM_EVENT_CATEGORY_STARTUP,
0 };
NdbLogEventHandle le_handle= ndb_mgm_create_logevent_handle(h, filter);
struct ndb_logevent le;
for(int i=0; i<20; i++)
{
if(error_ins==0 || (error_ins!=0 && i<5))
{
union {
Uint32 theData[25];
EventReport repData;
};
EventReport *fake_event = &repData;
fake_event->setEventType(NDB_LE_NDBStopForced);
fake_event->setNodeId(42);
theData[2]= 0;
theData[3]= 0;
theData[4]= 0;
theData[5]= 0;
ndb_mgm_report_event(h, theData, 6);
}
int r= ndb_logevent_get_next(le_handle, &le, 2500);
if(r>0)
{
ndbout << "Receieved event" << endl;
}
else if(r<0)
{
ndbout << "ERROR" << endl;
}
else // no event
{
ndbout << "TIMED OUT READING EVENT at iteration " << i << endl;
if(error_ins==0)
result= NDBT_FAILED;
else
result= NDBT_OK;
break;
}
}
/*
* events go through a *DIFFERENT* socket than the NdbMgmHandle
* so we should still be connected (and be able to check_connection)
*
*/
if(ndb_mgm_check_connection(h) && !ndb_mgm_is_connected(h))
{
ndbout << "FAILED: is still connected after error" << endl;
result= NDBT_FAILED;
}
ndb_mgm_disconnect(h);
}
done:
ndb_mgm_disconnect(h);
ndb_mgm_destroy_handle(&h);
return result;
}
int runSetConfig(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
int loops= ctx->getNumLoops();
for (int l= 0; l < loops; l++){
g_info << l << ": ";
struct ndb_mgm_configuration* conf=
ndb_mgm_get_configuration(mgmd.handle(), 0);
if (!conf)
{
g_err << "ndb_mgm_get_configuration failed, error: "
<< ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl;
return NDBT_FAILED;
}
int r= ndb_mgm_set_configuration(mgmd.handle(), conf);
free(conf);
if (r != 0)
{
g_err << "ndb_mgm_set_configuration failed, error: "
<< ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl;
return NDBT_FAILED;
}
}
return NDBT_OK;
}
int runSetConfigUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
{
int result= NDBT_OK;
while(!ctx->isTestStopped() &&
(result= runSetConfig(ctx, step)) == NDBT_OK)
;
return result;
}
int runGetConfig(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
int loops= ctx->getNumLoops();
for (int l= 0; l < loops; l++){
g_info << l << ": ";
struct ndb_mgm_configuration* conf=
ndb_mgm_get_configuration(mgmd.handle(), 0);
if (!conf)
return NDBT_FAILED;
free(conf);
}
return NDBT_OK;
}
int runGetConfigUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
{
int result= NDBT_OK;
while(!ctx->isTestStopped() &&
(result= runGetConfig(ctx, step)) == NDBT_OK)
;
return result;
}
// Find a random node of a given type.
static bool
get_nodeid_of_type(NdbMgmd& mgmd, ndb_mgm_node_type type, int *nodeId)
{
ndb_mgm_node_type
node_types[2] = { type,
NDB_MGM_NODE_TYPE_UNKNOWN };
ndb_mgm_cluster_state *cs = ndb_mgm_get_status2(mgmd.handle(), node_types);
if (cs == NULL)
{
g_err << "ndb_mgm_get_status2 failed, error: "
<< ndb_mgm_get_latest_error(mgmd.handle()) << " "
<< ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl;
return false;
}
int noOfNodes = cs->no_of_nodes;
int randomnode = myRandom48(noOfNodes);
ndb_mgm_node_state *ns = cs->node_states + randomnode;
require((Uint32)ns->node_type == (Uint32)type);
require(ns->node_id != 0);
*nodeId = ns->node_id;
g_info << "Got node id " << *nodeId << " of type " << type << endl;
free(cs);
return true;
}
// Ensure getting config from an illegal node fails.
// Return true in that case.
static bool
get_config_from_illegal_node(NdbMgmd& mgmd, int nodeId)
{
struct ndb_mgm_configuration* conf=
ndb_mgm_get_configuration_from_node(mgmd.handle(), nodeId);
// Get conf from an illegal node should fail.
if (ndb_mgm_get_latest_error(mgmd.handle()) != NDB_MGM_GET_CONFIG_FAILED)
{
g_err << "ndb_mgm_get_configuration from illegal node "
<< nodeId << " not failed, error: "
<< ndb_mgm_get_latest_error(mgmd.handle()) << " "
<< ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl;
return false;
}
if (conf)
{
// Should not get a conf from an illegal node.
g_err << "ndb_mgm_get_configuration from illegal node: "
<< nodeId << ", error: "
<< ndb_mgm_get_latest_error(mgmd.handle()) << " "
<< ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl;
free(conf);
return false;
}
return true;
}
// Check get_config from a non-existing node fails.
static bool
check_get_config_illegal_node(NdbMgmd& mgmd)
{
// Find a node that does not exist
Config conf;
if (!mgmd.get_config(conf))
return false;
int nodeId = 0;
for(Uint32 i= 1; i < MAX_NODES; i++){
ConfigIter iter(&conf, CFG_SECTION_NODE);
if (iter.find(CFG_NODE_ID, i) != 0){
nodeId = i;
break;
}
}
if (nodeId == 0)
return true; // All nodes probably defined
return get_config_from_illegal_node(mgmd, nodeId);
}
// Check get_config from a non-NDB/MGM node type fails
static bool
check_get_config_wrong_type(NdbMgmd& mgmd)
{
int myChoice = myRandom48(2);
ndb_mgm_node_type randomAllowedType = (myChoice) ?
NDB_MGM_NODE_TYPE_API :
NDB_MGM_NODE_TYPE_MGM;
int nodeId = 0;
if (get_nodeid_of_type(mgmd, randomAllowedType, &nodeId))
{
return get_config_from_illegal_node(mgmd, nodeId);
}
// No API/MGM nodes found.
return true;
}
/* Find management node or a random data node, and get config from it.
* Also ensure failure when getting config from
* an illegal node (a non-NDB/MGM type, nodeid not defined,
* or nodeid > MAX_NODES).
*/
int runGetConfigFromNode(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
if (!check_get_config_wrong_type(mgmd) ||
!check_get_config_illegal_node(mgmd) ||
!get_config_from_illegal_node(mgmd, MAX_NODES + 2))
{
return NDBT_FAILED;
}
int loops= ctx->getNumLoops();
for (int l= 0; l < loops; l++)
{
/* Get config from a node of type: * NDB_MGM_NODE_TYPE_NDB
*/
int nodeId = 0;
if (get_nodeid_of_type(mgmd, NDB_MGM_NODE_TYPE_NDB, &nodeId))
{
struct ndb_mgm_configuration* conf =
ndb_mgm_get_configuration_from_node(mgmd.handle(), nodeId);
if (!conf)
{
g_err << "ndb_mgm_get_configuration_from_node "
<< nodeId << " failed, error: "
<< ndb_mgm_get_latest_error(mgmd.handle()) << " "
<< ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl;
return NDBT_FAILED;
}
free(conf);
}
else
{
// ignore
}
}
return NDBT_OK;
}
int runGetConfigFromNodeUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
{
int result= NDBT_OK;
while(!ctx->isTestStopped() &&
(result= runGetConfigFromNode(ctx, step)) == NDBT_OK)
;
return result;
}
int runTestStatus(NDBT_Context* ctx, NDBT_Step* step)
{
ndb_mgm_node_type types[2] = {
NDB_MGM_NODE_TYPE_NDB,
NDB_MGM_NODE_TYPE_UNKNOWN
};
NdbMgmd mgmd;
struct ndb_mgm_cluster_state *state;
int iterations = ctx->getNumLoops();
if (!mgmd.connect())
return NDBT_FAILED;
int result= NDBT_OK;
while (iterations-- != 0 && result == NDBT_OK)
{
state = ndb_mgm_get_status(mgmd.handle());
if(state == NULL) {
ndbout_c("Could not get status!");
result= NDBT_FAILED;
continue;
}
free(state);
state = ndb_mgm_get_status2(mgmd.handle(), types);
if(state == NULL){
ndbout_c("Could not get status2!");
result= NDBT_FAILED;
continue;
}
free(state);
state = ndb_mgm_get_status2(mgmd.handle(), 0);
if(state == NULL){
ndbout_c("Could not get status2 second time!");
result= NDBT_FAILED;
continue;
}
free(state);
}
return result;
}
int runTestStatusUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
{
int result= NDBT_OK;
while(!ctx->isTestStopped() &&
(result= runTestStatus(ctx, step)) == NDBT_OK)
;
return result;
}
static bool
get_nodeid(NdbMgmd& mgmd,
const Properties& args,
Properties& reply)
{
// Fill in default values of other args
Properties call_args(args);
if (!call_args.contains("version"))
call_args.put("version", 1);
if (!call_args.contains("nodetype"))
call_args.put("nodetype", 1);
if (!call_args.contains("nodeid"))
call_args.put("nodeid", 1);
if (!call_args.contains("user"))
call_args.put("user", "mysqld");
if (!call_args.contains("password"))
call_args.put("password", "mysqld");
if (!call_args.contains("public key"))
call_args.put("public key", "a public key");
if (!call_args.contains("name"))
call_args.put("name", "testMgm");
if (!call_args.contains("log_event"))
call_args.put("log_event", 1);
if (!call_args.contains("timeout"))
call_args.put("timeout", 100);
if (!call_args.contains("endian"))
{
union { long l; char c[sizeof(long)]; } endian_check;
endian_check.l = 1;
call_args.put("endian", (endian_check.c[sizeof(long)-1])?"big":"little");
}
if (!mgmd.call("get nodeid", call_args,
"get nodeid reply", reply))
{
g_err << "get_nodeid: mgmd.call failed" << endl;
return false;
}
// reply.print();
return true;
}
static const char*
get_result(const Properties& reply)
{
const char* result;
if (!reply.get("result", &result)){
ndbout_c("result: no 'result' found in reply");
return NULL;
}
return result;
}
static bool result_contains(const Properties& reply,
const char* expected_result)
{
BaseString result(get_result(reply));
if (strstr(result.c_str(), expected_result) == NULL){
ndbout_c("result_contains: result string '%s' "
"didn't contain expected result '%s'",
result.c_str(), expected_result);
return false;
}
g_info << " result: " << result << endl;
return true;
}
static bool ok(const Properties& reply)
{
BaseString result(get_result(reply));
if (result == "Ok")
return true;
return false;
}
static bool failed(const Properties& reply)
{
BaseString result(get_result(reply));
if (result == "Failed")
return true;
return false;
}
static const char*
get_message(const Properties& reply)
{
const char* message;
if (!reply.get("message", &message)){
ndbout_c("message: no 'message' found in reply");
return NULL;
}
return message;
}
static bool message_contains(const Properties& reply,
const char* expected_message)
{
BaseString message(get_message(reply));
if (strstr(message.c_str(), expected_message) == NULL){
ndbout_c("message_contains: message string '%s' "
"didn't contain expected message '%s'",
message.c_str(), expected_message);
return false;
}
g_info << " message: " << message << endl;
return true;
}
static bool get_nodeid_result_contains(NdbMgmd& mgmd,
const Properties& args,
const char* expected_result)
{
Properties reply;
if (!get_nodeid(mgmd, args, reply))
return false;
return result_contains(reply, expected_result);
}
static bool
check_get_nodeid_invalid_endian1(NdbMgmd& mgmd)
{
union { long l; char c[sizeof(long)]; } endian_check;
endian_check.l = 1;
Properties args;
/* Set endian to opposite value */
args.put("endian", (endian_check.c[sizeof(long)-1])?"little":"big");
return get_nodeid_result_contains(mgmd, args,
"Node does not have the same endian");
}
static bool
check_get_nodeid_invalid_endian2(NdbMgmd& mgmd)
{
Properties args;
/* Set endian to weird value */
args.put("endian", "hepp");
return get_nodeid_result_contains(mgmd, args,
"Node does not have the same endian");
}
static bool
check_get_nodeid_invalid_nodetype1(NdbMgmd& mgmd)
{
Properties args;
args.put("nodetype", 37);
return get_nodeid_result_contains(mgmd, args,
"unknown nodetype 37");
}
static bool
check_get_nodeid_invalid_nodeid(NdbMgmd& mgmd)
{
for (int nodeId = MAX_NODES; nodeId < MAX_NODES+2; nodeId++){
g_info << "Testing invalid node " << nodeId << endl;;
Properties args;
args.put("nodeid", nodeId);
BaseString expected;
expected.assfmt("illegal nodeid %d", nodeId);
if (!get_nodeid_result_contains(mgmd, args, expected.c_str()))
return false;
}
return true;
}
static bool
check_get_nodeid_dynamic_nodeid(NdbMgmd& mgmd)
{
bool result = true;
Uint32 nodeId= 0; // Get dynamic node id
for (int nodeType = NDB_MGM_NODE_TYPE_MIN;
nodeType < NDB_MGM_NODE_TYPE_MAX; nodeType++){
while(true)
{
g_info << "Testing dynamic nodeid " << nodeId
<< ", nodeType: " << nodeType << endl;
Properties args;
args.put("nodeid", nodeId);
args.put("nodetype", nodeType);
Properties reply;
if (!get_nodeid(mgmd, args, reply))
return false;
/*
Continue to get dynamic id's until
an error "there is no more nodeid" occur
*/
if (!ok(reply)){
BaseString expected1;
expected1.assfmt("No free node id found for %s",
NdbMgmd::NodeType(nodeType).c_str());
BaseString expected2;
expected2.assfmt("Connection done from wrong host");
if (!(result_contains(reply, expected1.c_str()) ||
result_contains(reply, expected2.c_str())))
result= false; // Got wrong error message
break;
}
}
}
return result;
}
static bool
check_get_nodeid_nonode(NdbMgmd& mgmd)
{
// Find a node that does not exist
Config conf;
if (!mgmd.get_config(conf))
return false;
Uint32 nodeId = 0;
for(Uint32 i= 1; i < MAX_NODES; i++){
ConfigIter iter(&conf, CFG_SECTION_NODE);
if (iter.find(CFG_NODE_ID, i) != 0){
nodeId = i;
break;
}
}
if (nodeId == 0)
return true; // All nodes probably defined
g_info << "Testing nonexisting node " << nodeId << endl;;
Properties args;
args.put("nodeid", nodeId);
BaseString expected;
expected.assfmt("No node defined with id=%d", nodeId);
return get_nodeid_result_contains(mgmd, args, expected.c_str());
}
#if 0
static bool
check_get_nodeid_nodeid1(NdbMgmd& mgmd)
{
// Find a node that does exist
Config conf;
if (!mgmd.get_config(conf))
return false;
Uint32 nodeId = 0;
Uint32 nodeType = NDB_MGM_NODE_TYPE_UNKNOWN;
for(Uint32 i= 1; i < MAX_NODES; i++){
ConfigIter iter(&conf, CFG_SECTION_NODE);
if (iter.find(CFG_NODE_ID, i) == 0){
nodeId = i;
iter.get(CFG_TYPE_OF_SECTION, &nodeType);
break;
}
}
require(nodeId);
require(nodeType != (Uint32)NDB_MGM_NODE_TYPE_UNKNOWN);
Properties args, reply;
args.put("nodeid",nodeId);
args.put("nodetype",nodeType);
if (!get_nodeid(mgmd, args, reply))
{
g_err << "check_get_nodeid_nodeid1: failed for "
<< "nodeid: " << nodeId << ", nodetype: " << nodeType << endl;
return false;
}
reply.print();
return ok(reply);
}
#endif
static bool
check_get_nodeid_wrong_nodetype(NdbMgmd& mgmd)
{
// Find a node that does exist
Config conf;
if (!mgmd.get_config(conf))
return false;
Uint32 nodeId = 0;
Uint32 nodeType = NDB_MGM_NODE_TYPE_UNKNOWN;
for(Uint32 i= 1; i < MAX_NODES; i++){
ConfigIter iter(&conf, CFG_SECTION_NODE);
if (iter.find(CFG_NODE_ID, i) == 0){
nodeId = i;
iter.get(CFG_TYPE_OF_SECTION, &nodeType);
break;
}
}
require(nodeId);
require(nodeType != (Uint32)NDB_MGM_NODE_TYPE_UNKNOWN);
nodeType = (nodeType + 1) / NDB_MGM_NODE_TYPE_MAX;
require((int)nodeType >= (int)NDB_MGM_NODE_TYPE_MIN &&
(int)nodeType <= (int)NDB_MGM_NODE_TYPE_MAX);
Properties args, reply;
args.put("nodeid",nodeId);
args.put("nodeid",nodeType);
if (!get_nodeid(mgmd, args, reply))
{
g_err << "check_get_nodeid_nodeid1: failed for "
<< "nodeid: " << nodeId << ", nodetype: " << nodeType << endl;
return false;
}
BaseString expected;
expected.assfmt("Id %d configured as", nodeId);
return result_contains(reply, expected.c_str());
}
int runTestGetNodeId(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
int result= NDBT_FAILED;
if (
check_get_nodeid_invalid_endian1(mgmd) &&
check_get_nodeid_invalid_endian2(mgmd) &&
check_get_nodeid_invalid_nodetype1(mgmd) &&
check_get_nodeid_invalid_nodeid(mgmd) &&
check_get_nodeid_dynamic_nodeid(mgmd) &&
check_get_nodeid_nonode(mgmd) &&
// check_get_nodeid_nodeid1(mgmd) &&
check_get_nodeid_wrong_nodetype(mgmd) &&
true)
result= NDBT_OK;
if (!mgmd.end_session())
result= NDBT_FAILED;
return result;
}
int runTestGetNodeIdUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
{
int result= NDBT_OK;
while(!ctx->isTestStopped() &&
(result= runTestGetNodeId(ctx, step)) == NDBT_OK)
;
return result;
}
int runSleepAndStop(NDBT_Context* ctx, NDBT_Step* step)
{
int counter= 3*ctx->getNumLoops();
while(!ctx->isTestStopped() && counter--)
NdbSleep_SecSleep(1);;
ctx->stopTest();
return NDBT_OK;
}
static bool
check_connection(NdbMgmd& mgmd)
{
Properties args, reply;
mgmd.verbose(false); // Verbose off
bool result= mgmd.call("check connection", args,
"check connection reply", reply);
mgmd.verbose(); // Verbose on
return result;
}
static bool
check_transporter_connect(NdbMgmd& mgmd, const char * hello)
{
SocketOutputStream out(mgmd.socket());
// Call 'transporter connect'
if (out.println("transporter connect\n"))
{
g_err << "Send failed" << endl;
return false;
}
// Send the 'hello'
g_info << "Client hello: '" << hello << "'" << endl;
if (out.println("%s", hello))
{
g_err << "Send hello '" << hello << "' failed" << endl;
return false;
}
// Should not be possible to read a reply now, socket
// should have been closed
if (check_connection(mgmd)){
g_err << "not disconnected" << endl;
return false;
}
// disconnect and connect again
if (!mgmd.disconnect())
return false;
if (!mgmd.connect())
return false;
return true;
}
int runTestTransporterConnect(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
int result = NDBT_FAILED;
if (
// Junk hello strings
check_transporter_connect(mgmd, "hello") &&
check_transporter_connect(mgmd, "hello again") &&
// "Blow" the buffer
check_transporter_connect(mgmd, "string_longer_than_buf_1234567890") &&
// Out of range nodeid
check_transporter_connect(mgmd, "-1") &&
check_transporter_connect(mgmd, "-2 2") &&
check_transporter_connect(mgmd, "10000") &&
check_transporter_connect(mgmd, "99999 8") &&
// Valid nodeid, invalid transporter type
// Valid nodeid and transporter type, state != CONNECTING
// ^These are only possible to test by finding an existing
// NDB node that are not started and use its setting(s)
true)
result = NDBT_OK;
return result;
}
static bool
show_config(NdbMgmd& mgmd,
const Properties& args,
Properties& reply)
{
if (!mgmd.call("show config", args,
"show config reply", reply, NULL, false))
{
g_err << "show_config: mgmd.call failed" << endl;
return false;
}
// reply.print();
return true;
}
int runCheckConfig(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
// Connect to any mgmd and get the config
if (!mgmd.connect())
return NDBT_FAILED;
Properties args1;
Properties config1;
if (!show_config(mgmd, args1, config1))
return NDBT_FAILED;
// Get the binary config
Config conf;
if (!mgmd.get_config(conf))
return NDBT_FAILED;
// Extract list of connectstrings to each mgmd
BaseString connectstring;
conf.getConnectString(connectstring, ";");
Vector<BaseString> mgmds;
connectstring.split(mgmds, ";");
// Connect to each mgmd and check
// they all have the same config
for (unsigned i = 0; i < mgmds.size(); i++)
{
NdbMgmd mgmd2;
g_info << "Connecting to " << mgmds[i].c_str() << endl;
if (!mgmd2.connect(mgmds[i].c_str()))
return NDBT_FAILED;
Properties args2;
Properties config2;
if (!show_config(mgmd, args2, config2))
return NDBT_FAILED;
// Compare config1 and config2 line by line
Uint32 line = 1;
const char* value1;
const char* value2;
while (true)
{
if (config1.get("line", line, &value1))
{
// config1 had line, so should config2
if (config2.get("line", line, &value2))
{
// both configs had line, check they are equal
if (strcmp(value1, value2) != 0)
{
g_err << "the value on line " << line << "didn't match!" << endl;
g_err << "config1, value: " << value1 << endl;
g_err << "config2, value: " << value2 << endl;
return NDBT_FAILED;
}
// g_info << line << ": " << value1 << " = " << value2 << endl;
}
else
{
g_err << "config2 didn't have line " << line << "!" << endl;
return NDBT_FAILED;
}
}
else
{
// Make sure config2 does not have this line either and end loop
if (config2.get("line", line, &value2))
{
g_err << "config2 had line " << line << " not in config1!" << endl;
return NDBT_FAILED;
}
// End of loop
g_info << "There was " << line << " lines in config" << endl;
break;
}
line++;
}
if (line == 0)
{
g_err << "FAIL: config should have lines!" << endl;
return NDBT_FAILED;
}
// Compare the binary config
Config conf2;
if (!mgmd.get_config(conf2))
return NDBT_FAILED;
if (!conf.equal(&conf2))
{
g_err << "The binary config was different! host: " << mgmds[i] << endl;
return NDBT_FAILED;
}
}
return NDBT_OK;
}
static bool
reload_config(NdbMgmd& mgmd,
const Properties& args,
Properties& reply)
{
if (!mgmd.call("reload config", args,
"reload config reply", reply))
{
g_err << "reload config: mgmd.call failed" << endl;
return false;
}
//reply.print();
return true;
}
static bool reload_config_result_contains(NdbMgmd& mgmd,
const Properties& args,
const char* expected_result)
{
Properties reply;
if (!reload_config(mgmd, args, reply))
return false;
return result_contains(reply, expected_result);
}
static bool
check_reload_config_both_config_and_mycnf(NdbMgmd& mgmd)
{
Properties args;
// Send reload command with both config_filename and mycnf set
args.put("config_filename", "some filename");
args.put("mycnf", 1);
return reload_config_result_contains(mgmd, args,
"ERROR: Both mycnf and config_filename");
}
static bool
show_variables(NdbMgmd& mgmd, Properties& reply)
{
if (!mgmd.call("show variables", "",
"show variables reply", reply))
{
g_err << "show_variables: mgmd.call failed" << endl;
return false;
}
return true;
}
static bool
check_reload_config_invalid_config_filename(NdbMgmd& mgmd, bool mycnf)
{
BaseString expected("Could not load configuration from 'nonexisting_file");
if (mycnf)
{
// Differing error message if started from my.cnf
expected.assign("Can't switch to use config.ini 'nonexisting_file' "
"when node was started from my.cnf");
}
Properties args;
// Send reload command with an invalid config_filename
args.put("config_filename", "nonexisting_file");
return reload_config_result_contains(mgmd, args, expected.c_str());
}
int runTestReloadConfig(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
Properties variables;
if (!show_variables(mgmd, variables))
return NDBT_FAILED;
variables.print();
const char* mycnf_str;
if (!variables.get("mycnf", &mycnf_str))
abort();
bool uses_mycnf = (strcmp(mycnf_str, "yes") == 0);
int result= NDBT_FAILED;
if (
check_reload_config_both_config_and_mycnf(mgmd) &&
check_reload_config_invalid_config_filename(mgmd, uses_mycnf) &&
true)
result= NDBT_OK;
if (!mgmd.end_session())
result= NDBT_FAILED;
return result;
}
static bool
set_config(NdbMgmd& mgmd,
const Properties& args,
BaseString encoded_config,
Properties& reply)
{
// Fill in default values of other args
Properties call_args(args);
if (!call_args.contains("Content-Type"))
call_args.put("Content-Type", "ndbconfig/octet-stream");
if (!call_args.contains("Content-Transfer-Encoding"))
call_args.put("Content-Transfer-Encoding", "base64");
if (!call_args.contains("Content-Length"))
call_args.put("Content-Length",
encoded_config.length() ? encoded_config.length() - 1 : 1);
if (!mgmd.call("set config", call_args,
"set config reply", reply,
encoded_config.c_str()))
{
g_err << "set config: mgmd.call failed" << endl;
return false;
}
//reply.print();
return true;
}
static bool set_config_result_contains(NdbMgmd& mgmd,
const Properties& args,
const BaseString& encoded_config,
const char* expected_result)
{
Properties reply;
if (!set_config(mgmd, args, encoded_config, reply))
return false;
return result_contains(reply, expected_result);
}
static bool set_config_result_contains(NdbMgmd& mgmd,
const Config& conf,
const char* expected_result)
{
Properties reply;
Properties args;
BaseString encoded_config;
if (!conf.pack64(encoded_config))
return false;
if (!set_config(mgmd, args, encoded_config, reply))
return false;
return result_contains(reply, expected_result);
}
static bool
check_set_config_invalid_content_type(NdbMgmd& mgmd)
{
Properties args;
args.put("Content-Type", "illegal type");
return set_config_result_contains(mgmd, args, BaseString(""),
"Unhandled content type 'illegal type'");
}
static bool
check_set_config_invalid_content_encoding(NdbMgmd& mgmd)
{
Properties args;
args.put("Content-Transfer-Encoding", "illegal encoding");
return set_config_result_contains(mgmd, args, BaseString(""),
"Unhandled content encoding "
"'illegal encoding'");
}
static bool
check_set_config_too_large_content_length(NdbMgmd& mgmd)
{
Properties args;
args.put("Content-Length", 1024*1024 + 1);
return set_config_result_contains(mgmd, args, BaseString(""),
"Illegal config length size 1048577");
}
static bool
check_set_config_too_small_content_length(NdbMgmd& mgmd)
{
Properties args;
args.put("Content-Length", (Uint32)0);
return set_config_result_contains(mgmd, args, BaseString(""),
"Illegal config length size 0");
}
static bool
check_set_config_wrong_config_length(NdbMgmd& mgmd)
{
// Get the binary config
Config conf;
if (!mgmd.get_config(conf))
return false;
BaseString encoded_config;
if (!conf.pack64(encoded_config))
return false;
Properties args;
args.put("Content-Length", encoded_config.length() - 20);
bool res = set_config_result_contains(mgmd, args, encoded_config,
"Failed to unpack config");
if (res){
/*
There are now additional 20 bytes of junk that has been
sent to mgmd, reconnect to get rid of it
*/
if (!mgmd.disconnect())
return false;
if (!mgmd.connect())
return false;
}
return res;
}
static bool
check_set_config_any_node(NDBT_Context* ctx, NDBT_Step* step, NdbMgmd& mgmd)
{
// Get the binary config
Config conf;
if (!mgmd.get_config(conf))
return false;
// Extract list of connectstrings to each mgmd
BaseString connectstring;
conf.getConnectString(connectstring, ";");
Vector<BaseString> mgmds;
connectstring.split(mgmds, ";");
// Connect to each mgmd and check
// they all have the same config
for (unsigned i = 0; i < mgmds.size(); i++)
{
NdbMgmd mgmd2;
g_info << "Connecting to " << mgmds[i].c_str() << endl;
if (!mgmd2.connect(mgmds[i].c_str()))
return false;
// Get the binary config
Config conf2;
if (!mgmd2.get_config(conf2))
return false;
// Set the modified config
if (!mgmd2.set_config(conf2))
return false;
// Check that all mgmds now have the new config
if (runCheckConfig(ctx, step) != NDBT_OK)
return false;
}
return true;
}
static bool
check_set_config_fail_wrong_generation(NdbMgmd& mgmd)
{
// Get the binary config
Config conf;
if (!mgmd.get_config(conf))
return false;
// Change generation
if (!conf.setGeneration(conf.getGeneration() + 10))
return false;
// Set the modified config
return set_config_result_contains(mgmd, conf,
"Invalid generation in");
}
static bool
check_set_config_fail_wrong_name(NdbMgmd& mgmd)
{
// Get the binary config
Config conf;
if (!mgmd.get_config(conf))
return false;
// Change name
if (!conf.setName("NEWNAME"))
return false;
// Set the modified config
return set_config_result_contains(mgmd, conf,
"Invalid configuration name");
}
static bool
check_set_config_fail_wrong_primary(NdbMgmd& mgmd)
{
// Get the binary config
Config conf;
if (!mgmd.get_config(conf))
return false;
// Change primary and thus make this configuration invalid
if (!conf.setPrimaryMgmNode(conf.getPrimaryMgmNode()+10))
return false;
// Set the modified config
return set_config_result_contains(mgmd, conf,
"Not primary mgm node");
}
int runTestSetConfig(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
int result= NDBT_FAILED;
if (
check_set_config_invalid_content_type(mgmd) &&
check_set_config_invalid_content_encoding(mgmd) &&
check_set_config_too_large_content_length(mgmd) &&
check_set_config_too_small_content_length(mgmd) &&
check_set_config_wrong_config_length(mgmd) &&
check_set_config_any_node(ctx, step, mgmd) &&
check_set_config_fail_wrong_generation(mgmd) &&
check_set_config_fail_wrong_name(mgmd) &&
check_set_config_fail_wrong_primary(mgmd) &&
true)
result= NDBT_OK;
if (!mgmd.end_session())
result= NDBT_FAILED;
return result;
}
int runTestSetConfigParallel(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
int result = NDBT_OK;
int loops = ctx->getNumLoops();
int sucessful = 0;
int invalid_generation = 0, config_change_ongoing = 0;
/*
continue looping until "loops" number of successful
changes have been made from this thread
*/
while (sucessful < loops &&
!ctx->isTestStopped() &&
result == NDBT_OK)
{
// Get the binary config
Config conf;
if (!mgmd.get_config(conf))
return NDBT_FAILED;
/* Set the config and check for valid errors */
mgmd.verbose(false);
if (mgmd.set_config(conf))
{
/* Config change suceeded */
sucessful++;
}
else
{
/* Config change failed */
if (mgmd.last_error() != NDB_MGM_CONFIG_CHANGE_FAILED)
{
g_err << "Config change failed with unexpected error: "
<< mgmd.last_error() << endl;
result = NDBT_FAILED;
continue;
}
BaseString error(mgmd.last_error_message());
if (error == "Invalid generation in configuration")
invalid_generation++;
else
if (error == "Config change ongoing")
config_change_ongoing++;
else
{
g_err << "Config change failed with unexpected error: '"
<< error << "'" << endl;
result = NDBT_FAILED;
}
}
}
ndbout << "Thread " << step->getStepNo()
<< ", sucess: " << sucessful
<< ", ongoing: " << config_change_ongoing
<< ", invalid_generation: " << invalid_generation << endl;
return result;
}
int runTestSetConfigParallelUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
{
int result= NDBT_OK;
while(!ctx->isTestStopped() &&
(result= runTestSetConfigParallel(ctx, step)) == NDBT_OK)
;
return result;
}
static bool
get_connection_parameter(NdbMgmd& mgmd,
const Properties& args,
Properties& reply)
{
// Fill in default values of other args
Properties call_args(args);
if (!call_args.contains("node1"))
call_args.put("node1", 1);
if (!call_args.contains("node2"))
call_args.put("node2", 1);
if (!call_args.contains("param"))
call_args.put("param", CFG_CONNECTION_SERVER_PORT);
if (!mgmd.call("get connection parameter", call_args,
"get connection parameter reply", reply))
{
g_err << "get_connection_parameter: mgmd.call failed" << endl;
return false;
}
return true;
}
static bool
set_connection_parameter(NdbMgmd& mgmd,
const Properties& args,
Properties& reply)
{
// Fill in default values of other args
Properties call_args(args);
if (!call_args.contains("node1"))
call_args.put("node1", 1);
if (!call_args.contains("node2"))
call_args.put("node2", 1);
if (!call_args.contains("param"))
call_args.put("param", CFG_CONNECTION_SERVER_PORT);
if (!call_args.contains("value"))
call_args.put("value", 37);
if (!mgmd.call("set connection parameter", call_args,
"set connection parameter reply", reply))
{
g_err << "set_connection_parameter: mgmd.call failed" << endl;
return false;
}
return true;
}
static bool
check_connection_parameter_invalid_nodeid(NdbMgmd& mgmd)
{
for (int nodeId = MAX_NODES; nodeId < MAX_NODES+2; nodeId++){
g_info << "Testing invalid node " << nodeId << endl;;
Properties args;
args.put("node1", nodeId);
args.put("node2", nodeId);
Properties get_result;
if (!get_connection_parameter(mgmd, args, get_result))
return false;
if (!result_contains(get_result,
"Unable to find connection between nodes"))
return false;
Properties set_result;
if (!set_connection_parameter(mgmd, args, set_result))
return false;
if (!failed(set_result))
return false;
if (!message_contains(set_result,
"Unable to find connection between nodes"))
return false;
}
return true;
}
static bool
check_connection_parameter(NdbMgmd& mgmd)
{
// Find a NDB node with dynamic port
Config conf;
if (!mgmd.get_config(conf))
return false;
Uint32 nodeId1 = 0;
for(Uint32 i= 1; i < MAX_NODES; i++){
Uint32 nodeType;
ConfigIter iter(&conf, CFG_SECTION_NODE);
if (iter.find(CFG_NODE_ID, i) == 0 &&
iter.get(CFG_TYPE_OF_SECTION, &nodeType) == 0 &&
nodeType == NDB_MGM_NODE_TYPE_NDB){
nodeId1 = i;
break;
}
}
NodeId otherNodeId = 0;
BaseString original_value;
// Get current value of first connection between mgmd and other node
for (int nodeId = 1; nodeId < MAX_NODES; nodeId++){
g_info << "Checking if connection between " << nodeId1
<< " and " << nodeId << " exists" << endl;
Properties args;
args.put("node1", nodeId1);
args.put("node2", nodeId);
Properties result;
if (!get_connection_parameter(mgmd, args, result))
return false;
if (!ok(result))
continue;
result.print();
// Get the nodeid
otherNodeId = nodeId;
// Get original value
if (!result.get("value", original_value))
{
g_err << "Failed to get original value" << endl;
return false;
}
break; // Done with the loop
}
if (otherNodeId == 0)
{
g_err << "Could not find a suitable connection for test" << endl;
return false;
}
Properties get_args;
get_args.put("node1", nodeId1);
get_args.put("node2", otherNodeId);
{
g_info << "Set new value(37 by default)" << endl;
Properties set_args(get_args);
Properties set_result;
if (!set_connection_parameter(mgmd, set_args, set_result))
return false;
if (!ok(set_result))
return false;
}
{
g_info << "Check new value" << endl;
Properties get_result;
if (!get_connection_parameter(mgmd, get_args, get_result))
return false;
if (!ok(get_result))
return false;
BaseString new_value;
if (!get_result.get("value", new_value))
{
g_err << "Failed to get new value" << endl;
return false;
}
g_info << "new_value: " << new_value << endl;
if (new_value != "37")
{
g_err << "New value was not correct, expected 37, got "
<< new_value << endl;
return false;
}
}
{
g_info << "Restore old value" << endl;
Properties set_args(get_args);
if (!set_args.put("value", original_value.c_str()))
{
g_err << "Failed to put original_value" << endl;
return false;
}
Properties set_result;
if (!set_connection_parameter(mgmd, set_args, set_result))
return false;
if (!ok(set_result))
return false;
}
{
g_info << "Check restored value" << endl;
Properties get_result;
if (!get_connection_parameter(mgmd, get_args, get_result))
return false;
if (!ok(get_result))
return false;
BaseString restored_value;
if (!get_result.get("value", restored_value))
{
g_err << "Failed to get restored value" << endl;
return false;
}
if (restored_value != original_value)
{
g_err << "Restored value was not correct, expected "
<< original_value << ", got "
<< restored_value << endl;
return false;
}
g_info << "restored_value: " << restored_value << endl;
}
return true;
}
int runTestConnectionParameter(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
int result= NDBT_FAILED;
if (
check_connection_parameter(mgmd) &&
check_connection_parameter_invalid_nodeid(mgmd) &&
true)
result= NDBT_OK;
if (!mgmd.end_session())
result= NDBT_FAILED;
return result;
}
int runTestConnectionParameterUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
{
int result= NDBT_OK;
while(!ctx->isTestStopped() &&
(result= runTestConnectionParameter(ctx, step)) == NDBT_OK)
;
return result;
}
static bool
set_ports(NdbMgmd& mgmd,
const Properties& args, const char* bulk_arg,
Properties& reply)
{
if (!mgmd.call("set ports", args,
"set ports reply", reply, bulk_arg))
{
g_err << "set_ports: mgmd.call failed" << endl;
return false;
}
return true;
}
static bool
check_set_ports_invalid_nodeid(NdbMgmd& mgmd)
{
for (int nodeId = MAX_NODES; nodeId < MAX_NODES+2; nodeId++)
{
g_err << "Testing invalid node " << nodeId << endl;
Properties args;
args.put("node", nodeId);
args.put("num_ports", 2);
Properties set_result;
if (!set_ports(mgmd, args, "", set_result))
return false;
if (ok(set_result))
return false;
if (!result_contains(set_result, "Illegal value for argument node"))
return false;
}
return true;
}
static bool
check_set_ports_invalid_num_ports(NdbMgmd& mgmd)
{
g_err << "Testing invalid number of ports "<< endl;
Properties args;
args.put("node", 1);
args.put("num_ports", MAX_NODES + 37);
Properties set_result;
if (!set_ports(mgmd, args, "", set_result))
return false;
if (ok(set_result))
return false;
if (!result_contains(set_result, "Illegal value for argument num_ports"))
return false;
return true;
}
static bool
check_set_ports_invalid_mismatch_num_port_1(NdbMgmd& mgmd)
{
g_err << "Testing invalid num port 1"<< endl;
Properties args;
args.put("node", 1);
args.put("num_ports", 1);
// Intend to send 1 ^ but passes two below
Properties set_result;
if (!set_ports(mgmd, args, "1=-37\n2=-38\n", set_result))
return false;
if (ok(set_result))
return false;
set_result.print();
if (!result_contains(set_result, "expected empty line"))
return false;
return true;
}
static bool
check_set_ports_invalid_mismatch_num_port_2(NdbMgmd& mgmd)
{
g_err << "Testing invalid num port 2"<< endl;
Properties args;
args.put("node", 1);
args.put("num_ports", 2);
// Intend to send 2 ^ but pass only one line below
Properties set_result;
if (!set_ports(mgmd, args, "1=-37\n", set_result))
return false;
if (ok(set_result))
return false;
set_result.print();
if (!result_contains(set_result, "expected name=value pair"))
return false;
return true;
}
static bool
check_set_ports_invalid_port_list(NdbMgmd& mgmd)
{
g_err << "Testing invalid port list"<< endl;
Properties args;
args.put("node", 1);
// No connection from 1 -> 1 exist
args.put("num_ports", 1);
Properties set_result;
if (!set_ports(mgmd, args, "1=-37\n", set_result))
return false;
set_result.print();
if (ok(set_result))
return false;
if (!result_contains(set_result,
"Unable to find connection between nodes 1 -> 1"))
return false;
return true;
}
static bool check_mgmapi_err(NdbMgmd& mgmd,
int return_code,
int expected_error,
const char* expected_message)
{
if (return_code != -1)
{
ndbout_c("check_mgmapi_error: unexpected return code: %d", return_code);
return false;
}
if (mgmd.last_error() != expected_error)
{
ndbout_c("check_mgmapi_error: unexpected error code: %d "
"expected %d", mgmd.last_error(), expected_error);
return false;
}
if (strstr(mgmd.last_error_message(), expected_message) == NULL)
{
ndbout_c("check_mgmapi_error: last_error_message '%s' "
"didn't contain expected message '%s'",
mgmd.last_error_message(), expected_message);
return false;
}
return true;
}
static bool
check_set_ports_mgmapi(NdbMgmd& mgmd)
{
g_err << "Testing mgmapi"<< endl;
int ret;
int nodeid = 1;
unsigned num_ports = 1;
ndb_mgm_dynamic_port ports[MAX_NODES * 10];
compile_time_assert(MAX_NODES < NDB_ARRAY_SIZE(ports));
ports[0].nodeid = 1;
ports[0].port = -1;
{
ndbout_c("No handle");
NdbMgmd no_handle;
ret = ndb_mgm_set_dynamic_ports(no_handle.handle(), nodeid,
ports, num_ports);
if (ret != -1)
return false;
}
{
ndbout_c("Not connected");
NdbMgmd no_con;
no_con.verbose(false);
if (no_con.connect("no_such_host:12345", 0, 1))
{
// Connect should not suceed!
return false;
}
ret = ndb_mgm_set_dynamic_ports(no_con.handle(), nodeid,
ports, num_ports);
if (!check_mgmapi_err(no_con, ret, NDB_MGM_SERVER_NOT_CONNECTED, ""))
return false;
}
ndbout_c("Invalid number of ports");
num_ports = 0; // <<
ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid,
ports, num_ports);
if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR,
"Illegal number of dynamic ports"))
return false;
ndbout_c("Invalid nodeid");
nodeid = 0; // <<
num_ports = 1;
ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid,
ports, num_ports);
if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR,
"Illegal value for argument node: 0"))
return false;
ndbout_c("Invalid port in list");
nodeid = 1;
ports[0].nodeid = 1;
ports[0].port = 1; // <<
ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid,
ports, num_ports);
if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR,
"Illegal port specfied in ports array"))
return false;
ndbout_c("Invalid nodeid in list");
nodeid = 1;
ports[0].nodeid = 0; // <<
ports[0].port = -11;
ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid,
ports, num_ports);
if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR,
"Illegal nodeid specfied in ports array"))
return false;
ndbout_c("Max number of ports exceeded");
nodeid = 1;
num_ports = MAX_NODES; // <<
for (unsigned i = 0; i < num_ports; i++)
{
ports[i].nodeid = i+1;
ports[i].port = -37;
}
ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid,
ports, num_ports);
if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR,
"Illegal value for argument num_ports"))
return false;
ndbout_c("Many many ports");
nodeid = 1;
num_ports = NDB_ARRAY_SIZE(ports); // <<
for (unsigned i = 0; i < num_ports; i++)
{
ports[i].nodeid = i+1;
ports[i].port = -37;
}
ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid,
ports, num_ports);
if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR,
"Illegal value for argument num_ports"))
return false;
return true;
}
// Return name value pair of nodeid/ports which can be sent
// verbatim back to ndb_mgmd
static bool
get_all_ports(NdbMgmd& mgmd, Uint32 nodeId1, BaseString& values)
{
for (int nodeId = 1; nodeId < MAX_NODES; nodeId++)
{
Properties args;
args.put("node1", nodeId1);
args.put("node2", nodeId);
Properties result;
if (!get_connection_parameter(mgmd, args, result))
return false;
if (!ok(result))
continue;
// Get value
BaseString value;
if (!result.get("value", value))
{
g_err << "Failed to get value" << endl;
return false;
}
values.appfmt("%d=%s\n", nodeId, value.c_str());
}
return true;
}
static bool
check_set_ports(NdbMgmd& mgmd)
{
// Find a NDB node with dynamic port
Config conf;
if (!mgmd.get_config(conf))
return false;
Uint32 nodeId1 = 0;
for(Uint32 i= 1; i < MAX_NODES; i++){
Uint32 nodeType;
ConfigIter iter(&conf, CFG_SECTION_NODE);
if (iter.find(CFG_NODE_ID, i) == 0 &&
iter.get(CFG_TYPE_OF_SECTION, &nodeType) == 0 &&
nodeType == NDB_MGM_NODE_TYPE_NDB){
nodeId1 = i;
break;
}
}
g_err << "Using NDB node with id: " << nodeId1 << endl;
g_err << "Get original values of dynamic ports" << endl;
BaseString original_values;
if (!get_all_ports(mgmd, nodeId1, original_values))
{
g_err << "Failed to get all original values" << endl;
return false;
}
ndbout_c("original values: %s", original_values.c_str());
g_err << "Set new values for all dynamic ports" << endl;
BaseString new_values;
{
Vector<BaseString> port_pairs;
original_values.split(port_pairs, "\n");
// Remove last empty line
require(port_pairs[port_pairs.size()-1] == "");
port_pairs.erase(port_pairs.size()-1);
// Generate new portnumbers
for (unsigned i = 0; i < port_pairs.size(); i++)
{
int nodeid, port;
if (sscanf(port_pairs[i].c_str(), "%d=%d", &nodeid, &port) != 2)
{
g_err << "Failed to parse port_pairs[" << i << "]: '"
<< port_pairs[i] << "'" << endl;
return false;
}
const int new_port = -(int)(i + 37);
new_values.appfmt("%d=%d\n", nodeid, new_port);
}
Properties args;
args.put("node", nodeId1);
args.put("num_ports", port_pairs.size());
Properties set_result;
if (!set_ports(mgmd, args, new_values.c_str(), set_result))
return false;
if (!ok(set_result))
{
g_err << "Unexpected result received from set_ports" << endl;
set_result.print();
return false;
}
}
g_err << "Compare new values of dynamic ports" << endl;
{
BaseString current_values;
if (!get_all_ports(mgmd, nodeId1, current_values))
{
g_err << "Failed to get all current values" << endl;
return false;
}
ndbout_c("current values: %s", current_values.c_str());
if (current_values != new_values)
{
g_err << "Set values was not correct, expected "
<< new_values << ", got "
<< current_values << endl;
return false;
}
}
g_err << "Restore old values" << endl;
{
Vector<BaseString> port_pairs;
original_values.split(port_pairs, "\n");
// Remove last empty line
require(port_pairs[port_pairs.size()-1] == "");
port_pairs.erase(port_pairs.size()-1);
Properties args;
args.put("node", nodeId1);
args.put("num_ports", port_pairs.size());
Properties set_result;
if (!set_ports(mgmd, args, original_values.c_str(), set_result))
return false;
if (!ok(set_result))
{
g_err << "Unexpected result received from set_ports" << endl;
set_result.print();
return false;
}
}
g_err << "Check restored values" << endl;
{
BaseString current_values;
if (!get_all_ports(mgmd, nodeId1, current_values))
{
g_err << "Failed to get all current values" << endl;
return false;
}
ndbout_c("current values: %s", current_values.c_str());
if (current_values != original_values)
{
g_err << "Restored values was not correct, expected "
<< original_values << ", got "
<< current_values << endl;
return false;
}
}
return true;
}
int runTestSetPorts(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
int result= NDBT_FAILED;
if (
check_set_ports(mgmd) &&
check_set_ports_invalid_nodeid(mgmd) &&
check_set_ports_invalid_num_ports(mgmd) &&
check_set_ports_invalid_mismatch_num_port_1(mgmd) &&
check_set_ports_invalid_mismatch_num_port_2(mgmd) &&
check_set_ports_invalid_port_list(mgmd) &&
check_set_ports_mgmapi(mgmd) &&
true)
result= NDBT_OK;
if (!mgmd.end_session())
result= NDBT_FAILED;
return result;
}
#ifdef NOT_YET
static bool
check_restart_connected(NdbMgmd& mgmd)
{
if (!mgmd.restart())
return false;
return true;
}
int runTestRestartMgmd(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
int result= NDBT_FAILED;
if (
check_restart_connected(mgmd) &&
true)
result= NDBT_OK;
if (!mgmd.end_session())
result= NDBT_FAILED;
return result;
}
#endif
static bool
set_logfilter(NdbMgmd& mgmd,
enum ndb_mgm_event_severity severity,
int enable)
{
struct ndb_mgm_reply reply;
if (ndb_mgm_set_clusterlog_severity_filter(mgmd.handle(),
severity,
enable,
&reply
) == -1)
{
g_err << "set_logfilter: ndb_mgm_set_clusterlog_severity_filter failed"
<< endl;
return false;
}
return true;
}
static bool
get_logfilter(NdbMgmd& mgmd,
enum ndb_mgm_event_severity severity,
unsigned int* value)
{
struct ndb_mgm_severity severity_struct;
severity_struct.category = severity;
if (ndb_mgm_get_clusterlog_severity_filter(mgmd.handle(),
&severity_struct,
1) != 1)
{
g_err << "get_logfilter: ndb_mgm_get_clusterlog_severity_filter failed"
<< endl;
return false;
}
require(value);
*value = severity_struct.value;
return true;
}
int runTestSetLogFilter(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
for (int i = 0; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++)
{
g_info << "severity: " << i << endl;
ndb_mgm_event_severity severity = (ndb_mgm_event_severity)i;
// Get initial value of level
unsigned int initial_value;
if (!get_logfilter(mgmd, severity, &initial_value))
return NDBT_FAILED;
// Turn level off
if (!set_logfilter(mgmd, severity, 0))
return NDBT_FAILED;
// Check it's off
unsigned int curr_value;
if (!get_logfilter(mgmd, severity, &curr_value))
return NDBT_FAILED;
if (curr_value != 0)
{
g_err << "Failed to turn off severity: " << severity << endl;
return NDBT_FAILED;
}
// Turn level on
if (!set_logfilter(mgmd, severity, 1))
return NDBT_FAILED;
// Check it's on
if (!get_logfilter(mgmd, severity, &curr_value))
return NDBT_FAILED;
if (curr_value == 0)
{
g_err << "Filed to turn on severity: " << severity << endl;
return NDBT_FAILED;
}
// Toggle, ie. turn off
if (!set_logfilter(mgmd, severity, -1))
return NDBT_FAILED;
// Check it's off
if (!get_logfilter(mgmd, severity, &curr_value))
return NDBT_FAILED;
if (curr_value != 0)
{
g_err << "Failed to toggle severity : " << severity << endl;
return NDBT_FAILED;
}
// Set back initial value
if (!set_logfilter(mgmd, severity, initial_value))
return NDBT_FAILED;
}
return NDBT_OK;
}
int runTestBug40922(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
int filter[] = {
15, NDB_MGM_EVENT_CATEGORY_BACKUP,
1, NDB_MGM_EVENT_CATEGORY_STARTUP,
0
};
NdbLogEventHandle le_handle =
ndb_mgm_create_logevent_handle(mgmd.handle(), filter);
if (!le_handle)
return NDBT_FAILED;
g_info << "Calling ndb_log_event_get_next" << endl;
struct ndb_logevent le_event;
int r = ndb_logevent_get_next(le_handle,
&le_event,
2000);
g_info << "ndb_log_event_get_next returned " << r << endl;
int result = NDBT_FAILED;
if (r == 0)
{
// Got timeout
g_info << "ndb_logevent_get_next returned timeout" << endl;
result = NDBT_OK;
}
else
{
if(r>0)
g_err << "ERROR: Receieved unexpected event: "
<< le_event.type << endl;
if(r<0)
g_err << "ERROR: ndb_logevent_get_next returned error: "
<< r << endl;
}
ndb_mgm_destroy_logevent_handle(&le_handle);
return result;
}
int runTestBug45497(NDBT_Context* ctx, NDBT_Step* step)
{
int result = NDBT_OK;
int loops = ctx->getNumLoops();
Vector<NdbMgmd*> mgmds;
while(true)
{
NdbMgmd* mgmd = new NdbMgmd();
// Set quite short timeout
if (!mgmd->set_timeout(1000))
{
result = NDBT_FAILED;
break;
}
if (mgmd->connect())
{
mgmds.push_back(mgmd);
g_info << "connections: " << mgmds.size() << endl;
continue;
}
g_err << "Failed to make another connection, connections: "
<< mgmds.size() << endl;
// Disconnect some connections
int to_disconnect = 10;
while(mgmds.size() && to_disconnect--)
{
g_info << "disconnnect, connections: " << mgmds.size() << endl;
NdbMgmd* mgmd = mgmds[0];
mgmds.erase(0);
delete mgmd;
}
if (loops-- == 0)
break;
}
while(mgmds.size())
{
NdbMgmd* mgmd = mgmds[0];
mgmds.erase(0);
delete mgmd;
}
return result;
}
bool isCategoryValid(struct ndb_logevent* le)
{
switch (le->category)
{
case NDB_MGM_EVENT_CATEGORY_BACKUP:
case NDB_MGM_EVENT_CATEGORY_STARTUP:
case NDB_MGM_EVENT_CATEGORY_NODE_RESTART:
case NDB_MGM_EVENT_CATEGORY_CONNECTION:
case NDB_MGM_EVENT_CATEGORY_STATISTIC:
case NDB_MGM_EVENT_CATEGORY_CHECKPOINT:
return true;
default:
return false;
}
}
int runTestBug16723708(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
int loops = ctx->getNumLoops();
int result = NDBT_FAILED;
if (!mgmd.connect())
return NDBT_FAILED;
int filter[] = {
15, NDB_MGM_EVENT_CATEGORY_BACKUP,
15, NDB_MGM_EVENT_CATEGORY_STARTUP,
15, NDB_MGM_EVENT_CATEGORY_NODE_RESTART,
15, NDB_MGM_EVENT_CATEGORY_CONNECTION,
15, NDB_MGM_EVENT_CATEGORY_STATISTIC,
15, NDB_MGM_EVENT_CATEGORY_CHECKPOINT,
0
};
NdbLogEventHandle le_handle =
ndb_mgm_create_logevent_handle(mgmd.handle(), filter);
if (!le_handle)
return NDBT_FAILED;
NdbLogEventHandle le_handle2 =
ndb_mgm_create_logevent_handle(mgmd.handle(), filter);
if (!le_handle2)
return NDBT_FAILED;
for(int l=0; l<loops; l++)
{
g_info << "Calling ndb_log_event_get_next" << endl;
struct ndb_logevent le_event;
int r = ndb_logevent_get_next(le_handle,
&le_event,
2000);
g_info << "ndb_log_event_get_next returned " << r << endl;
struct ndb_logevent le_event2;
int r2 = ndb_logevent_get_next2(le_handle2,
&le_event2,
2000);
g_info << "ndb_log_event_get_next2 returned " << r2 << endl;
result = NDBT_OK;
if ((r == 0) || (r2 == 0))
{
// Got timeout
g_info << "ndb_logevent_get_next[2] returned timeout" << endl;
}
else
{
if(r>0)
{
g_info << "next() ndb_logevent type : " << le_event.type
<< " category : " << le_event.category
<< " " << ndb_mgm_get_event_category_string(le_event.category)
<< endl;
if (isCategoryValid(&le_event))
{
g_err << "ERROR: ndb_logevent_get_next() returned valid category! "
<< le_event.category << endl;
result = NDBT_FAILED;
}
}
else
{
g_err << "ERROR: ndb_logevent_get_next returned error: "
<< r << endl;
}
if(r2>0)
{
g_info << "next2() ndb_logevent type : " << le_event2.type
<< " category : " << le_event2.category
<< " " << ndb_mgm_get_event_category_string(le_event2.category)
<< endl;
if (!isCategoryValid(&le_event2))
{
g_err << "ERROR: ndb_logevent_get_next2() returned invalid category! "
<< le_event2.category << endl;
result = NDBT_FAILED;
}
}
else
{
g_err << "ERROR: ndb_logevent_get_next2 returned error: "
<< r << endl;
result = NDBT_FAILED;
}
}
if(result == NDBT_FAILED)
break;
}
ndb_mgm_destroy_logevent_handle(&le_handle2);
ndb_mgm_destroy_logevent_handle(&le_handle);
return result;
}
static int
runTestGetVersion(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
char verStr[64];
int major, minor, build;
if (ndb_mgm_get_version(mgmd.handle(),
&major, &minor, &build,
sizeof(verStr), verStr) != 1)
{
g_err << "ndb_mgm_get_version failed,"
<< "error: " << ndb_mgm_get_latest_error_msg(mgmd.handle())
<< "desc: " << ndb_mgm_get_latest_error_desc(mgmd.handle()) << endl;
return NDBT_FAILED;
}
g_info << "Using major: " << major
<< " minor: " << minor
<< " build: " << build
<< " string: " << verStr << endl;
int l = 0;
int loops = ctx->getNumLoops();
while(l < loops)
{
char verStr2[64];
int major2, minor2, build2;
if (ndb_mgm_get_version(mgmd.handle(),
&major2, &minor2, &build2,
sizeof(verStr2), verStr2) != 1)
{
g_err << "ndb_mgm_get_version failed,"
<< "error: " << ndb_mgm_get_latest_error_msg(mgmd.handle())
<< "desc: " << ndb_mgm_get_latest_error_desc(mgmd.handle()) << endl;
return NDBT_FAILED;
}
if (major != major2)
{
g_err << "Got different major: " << major2
<< " excpected: " << major << endl;
return NDBT_FAILED;
}
if (minor != minor2)
{
g_err << "Got different minor: " << minor2
<< " excpected: " << minor << endl;
return NDBT_FAILED;
}
if (build != build2)
{
g_err << "Got different build: " << build2
<< " excpected: " << build << endl;
return NDBT_FAILED;
}
if (strcmp(verStr, verStr2) != 0)
{
g_err << "Got different verStr: " << verStr2
<< " excpected: " << verStr << endl;
return NDBT_FAILED;
}
l++;
}
return NDBT_OK;
}
static int
runTestGetVersionUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
{
int result= NDBT_OK;
while(!ctx->isTestStopped() &&
(result= runTestGetVersion(ctx, step)) == NDBT_OK)
;
return result;
}
int runTestDumpEvents(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
// Test with unsupported logevent_type
{
const Ndb_logevent_type unsupported = NDB_LE_NDBStopForced;
g_info << "ndb_mgm_dump_events(" << unsupported << ")" << endl;
const struct ndb_mgm_events* events =
ndb_mgm_dump_events(mgmd.handle(), unsupported, 0, 0);
if (events != NULL)
{
g_err << "ndb_mgm_dump_events returned events "
<< "for unsupported Ndb_logevent_type" << endl;
return NDBT_FAILED;
}
if (ndb_mgm_get_latest_error(mgmd.handle()) != NDB_MGM_USAGE_ERROR ||
strcmp("ndb_logevent_type 59 not supported",
ndb_mgm_get_latest_error_desc(mgmd.handle())))
{
g_err << "Unexpected error for unsupported logevent type, "
<< ndb_mgm_get_latest_error(mgmd.handle())
<< ", desc: " << ndb_mgm_get_latest_error_desc(mgmd.handle())
<< endl;
return NDBT_FAILED;
}
}
// Test with nodes >= MAX_NDB_NODES
for (int i = MAX_NDB_NODES; i < MAX_NDB_NODES + 3; i++)
{
g_info << "ndb_mgm_dump_events(NDB_LE_MemoryUsage, 1, "
<< i << ")" << endl;
const struct ndb_mgm_events* events =
ndb_mgm_dump_events(mgmd.handle(), NDB_LE_MemoryUsage, 1, &i);
if (events != NULL)
{
g_err << "ndb_mgm_dump_events returned events "
<< "for too large nodeid" << endl;
return NDBT_FAILED;
}
int invalid_nodeid;
if (ndb_mgm_get_latest_error(mgmd.handle()) != NDB_MGM_USAGE_ERROR ||
sscanf(ndb_mgm_get_latest_error_desc(mgmd.handle()),
"invalid nodes: '%d'", &invalid_nodeid) != 1 ||
invalid_nodeid != i)
{
g_err << "Unexpected error for too large nodeid, "
<< ndb_mgm_get_latest_error(mgmd.handle())
<< ", desc: " << ndb_mgm_get_latest_error_desc(mgmd.handle())
<< endl;
return NDBT_FAILED;
}
}
int l = 0;
int loops = ctx->getNumLoops();
while (l<loops)
{
const Ndb_logevent_type supported[] =
{
NDB_LE_MemoryUsage,
NDB_LE_BackupStatus,
(Ndb_logevent_type)0
};
// Test with supported logevent_type
for (int i = 0; supported[i]; i++)
{
g_info << "ndb_mgm_dump_events(" << supported[i] << ")" << endl;
struct ndb_mgm_events* events =
ndb_mgm_dump_events(mgmd.handle(), supported[i], 0, 0);
if (events == NULL)
{
g_err << "ndb_mgm_dump_events failed, type: " << supported[i]
<< ", error: " << ndb_mgm_get_latest_error(mgmd.handle())
<< ", msg: " << ndb_mgm_get_latest_error_msg(mgmd.handle())
<< endl;
return NDBT_FAILED;
}
if (events->no_of_events < 0)
{
g_err << "ndb_mgm_dump_events returned a negative number of events: "
<< events->no_of_events << endl;
free(events);
return NDBT_FAILED;
}
g_info << "Got " << events->no_of_events << " events" << endl;
free(events);
}
l++;
}
return NDBT_OK;
}
int runTestStatusAfterStop(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
ndb_mgm_node_type
node_types[2] = { NDB_MGM_NODE_TYPE_NDB,
NDB_MGM_NODE_TYPE_UNKNOWN };
// Test: get status, stop node, get status again
printf("Getting status\n");
ndb_mgm_cluster_state *cs = ndb_mgm_get_status2(mgmd.handle(), node_types);
if (cs == NULL)
{
printf("%s (%d)\n", ndb_mgm_get_latest_error_msg(mgmd.handle()),
ndb_mgm_get_latest_error(mgmd.handle()));
return NDBT_FAILED;
}
int nodeId = 0;
for(int i=0; i < cs->no_of_nodes; i++ )
{
ndb_mgm_node_state *ns = cs->node_states + i;
printf("Node ID: %d status:%d\n", ns->node_id, ns->node_status);
if (nodeId == 0 && ns->node_type == NDB_MGM_NODE_TYPE_NDB)
nodeId = ns->node_id;
}
free(cs);
cs = NULL;
printf("Stopping data node\n");
// We only stop 1 data node, in this case NodeId=2
int nodes[1] = { nodeId };
int stopped = ndb_mgm_restart2(mgmd.handle(), NDB_ARRAY_SIZE(nodes), nodes,
0, 0, 1);
if (stopped < 0)
{
printf("ndb_mgm_stop failed, '%s' (%d)\n",
ndb_mgm_get_latest_error_msg(mgmd.handle()),
ndb_mgm_get_latest_error(mgmd.handle()));
return NDBT_FAILED;
}
printf("Stopped %d data node(s)\n", stopped);
printf("Getting status\n");
cs = ndb_mgm_get_status2(mgmd.handle(), node_types);
if (cs == NULL)
{
printf("%s (%d)\n", ndb_mgm_get_latest_error_msg(mgmd.handle()),
ndb_mgm_get_latest_error(mgmd.handle()));
return NDBT_FAILED;
}
for(int i=0; i < cs->no_of_nodes; i++ )
{
ndb_mgm_node_state *ns = cs->node_states + i;
printf("Node ID: %d status:%d\n", ns->node_id, ns->node_status);
}
free(cs);
NdbRestarter res;
res.startAll();
res.waitClusterStarted();
return NDBT_OK;
}
int
sort_ng(const void * _e0, const void * _e1)
{
const struct ndb_mgm_node_state * e0 = (const struct ndb_mgm_node_state*)_e0;
const struct ndb_mgm_node_state * e1 = (const struct ndb_mgm_node_state*)_e1;
if (e0->node_group != e1->node_group)
return e0->node_group - e1->node_group;
return e0->node_id - e1->node_id;
}
int
runBug12928429(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
{
return NDBT_FAILED;
}
ndb_mgm_node_type node_types[2] =
{ NDB_MGM_NODE_TYPE_NDB, NDB_MGM_NODE_TYPE_UNKNOWN };
ndb_mgm_cluster_state * cs = ndb_mgm_get_status2(mgmd.handle(), node_types);
if (cs == NULL)
{
printf("%s (%d)\n", ndb_mgm_get_latest_error_msg(mgmd.handle()),
ndb_mgm_get_latest_error(mgmd.handle()));
return NDBT_FAILED;
}
/**
* sort according to node-group
*/
qsort(cs->node_states, cs->no_of_nodes,
sizeof(cs->node_states[0]), sort_ng);
int ng = cs->node_states[0].node_group;
int replicas = 1;
for (int i = 1; i < cs->no_of_nodes; i++)
{
if (cs->node_states[i].node_status != NDB_MGM_NODE_STATUS_STARTED)
{
ndbout_c("node %u is not started!!!", cs->node_states[i].node_id);
free(cs);
return NDBT_OK;
}
if (cs->node_states[i].node_group == ng)
{
replicas++;
}
else
{
break;
}
}
if (replicas == 1)
{
free(cs);
return NDBT_OK;
}
int nodes[MAX_NODES];
int cnt = 0;
for (int i = 0; i < cs->no_of_nodes; i += replicas)
{
printf("%u ", cs->node_states[i].node_id);
nodes[cnt++] = cs->node_states[i].node_id;
}
printf("\n");
int initial = 0;
int nostart = 1;
int abort = 0;
int force = 1;
int disconnnect = 0;
/**
* restart half of the node...should be only restart half of the nodes
*/
int res = ndb_mgm_restart4(mgmd.handle(), cnt, nodes,
initial, nostart, abort, force, &disconnnect);
if (res == -1)
{
ndbout_c("%u res: %u ndb_mgm_get_latest_error: %u line: %u msg: %s",
__LINE__,
res,
ndb_mgm_get_latest_error(mgmd.handle()),
ndb_mgm_get_latest_error_line(mgmd.handle()),
ndb_mgm_get_latest_error_msg(mgmd.handle()));
return NDBT_FAILED;
}
{
ndb_mgm_cluster_state * cs2 = ndb_mgm_get_status2(mgmd.handle(),node_types);
if (cs2 == NULL)
{
printf("%s (%d)\n", ndb_mgm_get_latest_error_msg(mgmd.handle()),
ndb_mgm_get_latest_error(mgmd.handle()));
return NDBT_FAILED;
}
for (int i = 0; i < cs2->no_of_nodes; i++)
{
int node_id = cs2->node_states[i].node_id;
int expect = NDB_MGM_NODE_STATUS_STARTED;
for (int c = 0; c < cnt; c++)
{
if (node_id == nodes[c])
{
expect = NDB_MGM_NODE_STATUS_NOT_STARTED;
break;
}
}
if (cs2->node_states[i].node_status != expect)
{
ndbout_c("%u node %u expect: %u found: %u",
__LINE__,
cs2->node_states[i].node_id,
expect,
cs2->node_states[i].node_status);
return NDBT_FAILED;
}
}
free(cs2);
}
NdbRestarter restarter;
restarter.startAll();
restarter.waitClusterStarted();
/**
* restart half of the node...and all nodes in one node group
* should restart cluster
*/
cnt = 0;
for (int i = 0; i < replicas; i++)
{
printf("%u ", cs->node_states[i].node_id);
nodes[cnt++] = cs->node_states[i].node_id;
}
for (int i = replicas; i < cs->no_of_nodes; i += replicas)
{
printf("%u ", cs->node_states[i].node_id);
nodes[cnt++] = cs->node_states[i].node_id;
}
printf("\n");
res = ndb_mgm_restart4(mgmd.handle(), cnt, nodes,
initial, nostart, abort, force, &disconnnect);
if (res == -1)
{
ndbout_c("%u res: %u ndb_mgm_get_latest_error: %u line: %u msg: %s",
__LINE__,
res,
ndb_mgm_get_latest_error(mgmd.handle()),
ndb_mgm_get_latest_error_line(mgmd.handle()),
ndb_mgm_get_latest_error_msg(mgmd.handle()));
return NDBT_FAILED;
}
{
ndb_mgm_cluster_state * cs2 = ndb_mgm_get_status2(mgmd.handle(),node_types);
if (cs2 == NULL)
{
printf("%s (%d)\n", ndb_mgm_get_latest_error_msg(mgmd.handle()),
ndb_mgm_get_latest_error(mgmd.handle()));
return NDBT_FAILED;
}
for (int i = 0; i < cs2->no_of_nodes; i++)
{
int expect = NDB_MGM_NODE_STATUS_NOT_STARTED;
if (cs2->node_states[i].node_status != expect)
{
ndbout_c("%u node %u expect: %u found: %u",
__LINE__,
cs2->node_states[i].node_id,
expect,
cs2->node_states[i].node_status);
return NDBT_FAILED;
}
}
free(cs2);
}
restarter.startAll();
restarter.waitClusterStarted();
free(cs);
return NDBT_OK;
}
int runTestNdbApiConfig(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
if (!mgmd.connect())
return NDBT_FAILED;
struct test_parameter
{
Uint32 key;
Uint32 NdbApiConfig::*ptr;
Uint32 values[2];
} parameters[] =
{
{ CFG_MAX_SCAN_BATCH_SIZE, &NdbApiConfig::m_scan_batch_size, { 10, 1000 } },
{ CFG_BATCH_BYTE_SIZE, &NdbApiConfig::m_batch_byte_size, { 10, 1000 } },
{ CFG_BATCH_SIZE, &NdbApiConfig::m_batch_size, { 10, 1000 } },
// Skip test of m_waitfor_timeout since it is not configurable in API-section
{ CFG_DEFAULT_OPERATION_REDO_PROBLEM_ACTION, &NdbApiConfig::m_default_queue_option,
{ OPERATION_REDO_PROBLEM_ACTION_ABORT, OPERATION_REDO_PROBLEM_ACTION_QUEUE } },
{ CFG_DEFAULT_HASHMAP_SIZE, &NdbApiConfig::m_default_hashmap_size, { 240, 3840 } },
};
// Catch if new members are added to NdbApiConfig,
// if so add tests and adjust expected size
NDB_STATIC_ASSERT(sizeof(NdbApiConfig) == 6 * sizeof(Uint32));
Config savedconf;
if (!mgmd.get_config(savedconf))
return NDBT_FAILED;
for (size_t i = 0; i < NDB_ARRAY_SIZE(parameters[0].values) ; i ++)
{
/**
* Setup configuration
*/
// Get the binary config
Config conf;
if (!mgmd.get_config(conf))
return NDBT_FAILED;
ConfigValues::Iterator iter(conf.m_configValues->m_config);
for (Uint32 nodeid = 1; nodeid < MAX_NODES; nodeid ++)
{
Uint32 type;
if (!iter.openSection(CFG_SECTION_NODE, nodeid))
continue;
if (iter.get(CFG_TYPE_OF_SECTION, &type) &&
type == NDB_MGM_NODE_TYPE_API)
{
for (size_t param = 0; param < NDB_ARRAY_SIZE(parameters) ; param ++)
{
iter.set(parameters[param].key, parameters[param].values[i]);
}
}
iter.closeSection();
}
// Set the modified config
if (!mgmd.set_config(conf))
return NDBT_FAILED;
/**
* Connect api
*/
Ndb_cluster_connection con(mgmd.getConnectString());
const int retries = 12;
const int retry_delay = 5;
const int verbose = 1;
if (con.connect(retries, retry_delay, verbose) != 0)
{
g_err << "Ndb_cluster_connection.connect failed" << endl;
return NDBT_FAILED;
}
/**
* Check api configuration
*/
NDBT_Context conctx(con);
int failures = 0;
for (size_t param = 0; param < NDB_ARRAY_SIZE(parameters) ; param ++)
{
Uint32 expected = parameters[param].values[i];
Uint32 got = conctx.getConfig().*parameters[param].ptr;
if (got != expected)
{
int j;
for(j = 0; j < ConfigInfo::m_NoOfParams ; j ++)
{
if (ConfigInfo::m_ParamInfo[j]._paramId == parameters[param].key)
break;
}
g_err << "Parameter ";
if (j < ConfigInfo::m_NoOfParams)
g_err << ConfigInfo::m_ParamInfo[j]._fname << " (" << parameters[param].key << ")";
else
g_err << "Unknown (" << parameters[param].key << ")";
g_err << ": Expected " << expected << " got " << got << endl;
failures++;
}
if (failures > 0)
return NDBT_FAILED;
}
}
// Restore conf after upgrading config generation
Config conf;
if (!mgmd.get_config(conf))
return NDBT_FAILED;
savedconf.setGeneration(conf.getGeneration());
if (!mgmd.set_config(savedconf))
{
g_err << "Failed to restore config." << endl;
return NDBT_FAILED;
}
return NDBT_OK;
}
static
int runTestCreateLogEvent(NDBT_Context* ctx, NDBT_Step* step)
{
NdbMgmd mgmd;
int loops = ctx->getNumLoops();
if (!mgmd.connect())
return NDBT_FAILED;
int filter[] = {
15, NDB_MGM_EVENT_CATEGORY_BACKUP,
0
};
for(int l=0; l<loops; l++)
{
g_info << "Creating log event handle " << l << endl;
NdbLogEventHandle le_handle =
ndb_mgm_create_logevent_handle(mgmd.handle(), filter);
if (!le_handle)
return NDBT_FAILED;
ndb_mgm_destroy_logevent_handle(&le_handle);
}
return NDBT_OK;
}
NDBT_TESTSUITE(testMgm);
DRIVER(DummyDriver); /* turn off use of NdbApi */
TESTCASE("ApiSessionFailure",
"Test failures in MGMAPI session"){
INITIALIZER(runTestApiSession);
}
TESTCASE("ApiConnectTimeout",
"Connect timeout tests for MGMAPI"){
INITIALIZER(runTestApiConnectTimeout);
}
TESTCASE("ApiTimeoutBasic",
"Basic timeout tests for MGMAPI"){
INITIALIZER(runTestApiTimeoutBasic);
}
TESTCASE("ApiGetStatusTimeout",
"Test timeout for MGMAPI getStatus"){
INITIALIZER(runTestApiGetStatusTimeout);
}
TESTCASE("ApiGetConfigTimeout",
"Test timeouts for mgmapi get_configuration"){
INITIALIZER(runTestMgmApiGetConfigTimeout);
}
TESTCASE("ApiMgmEventTimeout",
"Test timeouts for mgmapi get_configuration"){
INITIALIZER(runTestMgmApiEventTimeout);
}
TESTCASE("ApiMgmStructEventTimeout",
"Test timeouts for mgmapi get_configuration"){
INITIALIZER(runTestMgmApiStructEventTimeout);
}
TESTCASE("SetConfig",
"Tests the ndb_mgm_set_configuration function"){
INITIALIZER(runSetConfig);
}
TESTCASE("CheckConfig",
"Connect to each ndb_mgmd and check they have the same configuration"){
INITIALIZER(runCheckConfig);
}
TESTCASE("TestReloadConfig",
"Test of 'reload config'"){
INITIALIZER(runTestReloadConfig);
}
TESTCASE("TestSetConfig",
"Test of 'set config'"){
INITIALIZER(runTestSetConfig);
}
TESTCASE("TestSetConfigParallel",
"Test of 'set config' from 5 threads"){
STEPS(runTestSetConfigParallel, 5);
}
TESTCASE("GetConfig", "Run ndb_mgm_get_configuration in parallel"){
STEPS(runGetConfig, 64);
}
TESTCASE("TestStatus",
"Test status and status2"){
INITIALIZER(runTestStatus);
}
TESTCASE("TestStatusMultiple",
"Test status and status2 with 64 threads"){
/**
* For this and other tests we are limited in how much TCP backlog
* the MGM server socket has. It is currently set to a maximum of
* 64, so if we need to test more than 64 threads in parallel we
* need to introduce some sort of wait state to ensure that we
* don't get all threads sending TCP connect at the same time.
*/
STEPS(runTestStatus, 64);
}
TESTCASE("TestGetNodeId",
"Test 'get nodeid'"){
INITIALIZER(runTestGetNodeId);
}
TESTCASE("TestGetVersion",
"Test 'get version' and 'ndb_mgm_get_version'"){
STEPS(runTestGetVersion, 20);
}
TESTCASE("TestTransporterConnect",
"Test 'transporter connect'"){
INITIALIZER(runTestTransporterConnect);
}
TESTCASE("TestConnectionParameter",
"Test 'get/set connection parameter'"){
INITIALIZER(runTestConnectionParameter);
}
TESTCASE("TestSetLogFilter",
"Test 'set logfilter' and 'get info clusterlog'"){
INITIALIZER(runTestSetLogFilter);
}
#ifdef NOT_YET
TESTCASE("TestRestartMgmd",
"Test restart of ndb_mgmd(s)"){
INITIALIZER(runTestRestartMgmd);
}
#endif
TESTCASE("Bug40922",
"Make sure that ndb_logevent_get_next returns when "
"called with a timeout"){
INITIALIZER(runTestBug40922);
}
TESTCASE("Bug16723708",
"Check that ndb_logevent_get_next returns events "
"which have valid category values"){
INITIALIZER(runTestBug16723708);
}
TESTCASE("Stress",
"Run everything while changing config"){
STEP(runTestGetNodeIdUntilStopped);
STEP(runSetConfigUntilStopped);
STEPS(runGetConfigUntilStopped, 10);
STEPS(runGetConfigFromNodeUntilStopped, 10);
STEPS(runTestStatusUntilStopped, 10);
STEPS(runTestGetVersionUntilStopped, 5);
STEP(runSleepAndStop);
}
TESTCASE("Stress2",
"Run everything while changing config in parallel"){
STEP(runTestGetNodeIdUntilStopped);
STEPS(runTestSetConfigParallelUntilStopped, 5);
STEPS(runGetConfigUntilStopped, 10);
STEPS(runGetConfigFromNodeUntilStopped, 10);
STEPS(runTestStatusUntilStopped, 10);
STEPS(runTestGetVersionUntilStopped, 5);
STEP(runSleepAndStop);
}
X_TESTCASE("Bug45497",
"Connect to ndb_mgmd until it can't handle more connections"){
STEP(runTestBug45497);
}
TESTCASE("TestGetVersion",
"Test 'get version' and 'ndb_mgm_get_version'"){
STEPS(runTestGetVersion, 20);
}
TESTCASE("TestDumpEvents",
"Test 'dump events'"){
STEPS(runTestDumpEvents, 1);
}
TESTCASE("TestStatusAfterStop",
"Test get status after stop "){
STEPS(runTestStatusAfterStop, 1);
}
TESTCASE("Bug12928429", "")
{
STEP(runBug12928429);
}
TESTCASE("TestNdbApiConfig", "")
{
STEP(runTestNdbApiConfig);
}
TESTCASE("TestSetPorts",
"Test 'set ports'"){
INITIALIZER(runTestSetPorts);
}
TESTCASE("TestCreateLogEvent", "Test ndb_mgm_create_log_event_handle"){
STEPS(runTestCreateLogEvent, 5);
}
NDBT_TESTSUITE_END(testMgm);
int main(int argc, const char** argv){
ndb_init();
NDBT_TESTSUITE_INSTANCE(testMgm);
testMgm.setCreateTable(false);
testMgm.setRunAllTables(true);
return testMgm.execute(argc, argv);
}
template class Vector<NdbMgmd*>;