284 lines
10 KiB
C++
284 lines
10 KiB
C++
/*
|
|
* -------------------------------------------------------------------------
|
|
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
|
*
|
|
* openGauss is licensed under Mulan PSL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
* You may obtain a copy of Mulan PSL v2 at:
|
|
*
|
|
* http://license.coscl.org.cn/MulanPSL2
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PSL v2 for more details.
|
|
* -------------------------------------------------------------------------
|
|
*
|
|
* knl_uheaptest.cpp
|
|
* Implementation for uheap test framework.
|
|
*
|
|
* IDENTIFICATION
|
|
* src/gausskernel/cbb/utils/debug/knl_uheaptest.cpp
|
|
*
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "knl/knl_variable.h"
|
|
#include "utils/builtins.h"
|
|
#include "access/ustore/knl_whitebox_test.h"
|
|
#include "port.h"
|
|
|
|
const uint32 BUFSIZE = 1024;
|
|
|
|
bool VerifyBeforeTest (const char* newval)
|
|
{
|
|
if (g_instance.whitebox_test_param_instance &&
|
|
strcmp(newval, g_instance.whitebox_test_param_instance->test_file_name) == 0) {
|
|
elog(LOG, "AssignUstoreUnitTest: g_instance.whitebox_test_param_instance is already initialized");
|
|
return false;
|
|
}
|
|
if (!g_instance.whitebox_test_param_instance) {
|
|
g_instance.whitebox_test_param_instance =
|
|
(WhiteboxTestParam *)palloc(sizeof(WhiteboxTestParam) * (MAX_UNIT_TEST));
|
|
}
|
|
g_instance.whitebox_test_param_instance->elevel = WARNING;
|
|
int rc = sprintf_s(g_instance.whitebox_test_param_instance->test_file_name, MAX_NAME_STR_LEN, "%s", newval);
|
|
securec_check_ss_c(rc, "\0", "\0");
|
|
if (strcmp(newval, "") == 0) {
|
|
g_instance.whitebox_test_param_instance->num_testcase = 0;
|
|
elog(LOG, "AssignUstoreUnitTest: ustore_unit_test is empty");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void AssignUStoreUnitTest(const char* newval, const void* extra)
|
|
{
|
|
FILE *fp;
|
|
char buffer[BUFSIZE];
|
|
int i = 0;
|
|
bool ret = false;
|
|
|
|
ret = VerifyBeforeTest(newval);
|
|
if (!ret) {
|
|
return;
|
|
}
|
|
|
|
fp = fopen(newval, PG_BINARY_RW);
|
|
if (!fp) {
|
|
g_instance.whitebox_test_param_instance->num_testcase = 0;
|
|
elog(LOG, "AssignUstoreUnitTest: ustore_unit_test does not exist");
|
|
return;
|
|
}
|
|
|
|
while (fgets(buffer, BUFSIZE, fp) != NULL) {
|
|
char* ptoken = NULL;
|
|
char* psave = NULL;
|
|
char* ptype = NULL;
|
|
char* pvalue = NULL;
|
|
const char* pcomma = ",";
|
|
const char* pequal = "=";
|
|
|
|
// skip comment
|
|
if (!buffer || buffer[0] == '#') {
|
|
continue;
|
|
}
|
|
elog(LOG, "ustore_unit_test: %s", buffer);
|
|
|
|
// expand array of test param
|
|
g_instance.whitebox_test_param_instance->num_testcase = i + 1;
|
|
|
|
// test stub name
|
|
ptoken = strtok_r(buffer, pcomma, &psave);
|
|
int rc = sprintf_s(g_instance.whitebox_test_param_instance[i].test_stub_name, MAX_NAME_STR_LEN, "%s", ptoken);
|
|
securec_check_ss_c(rc, "\0", "\0");
|
|
// test stub type
|
|
ptoken = strtok_r(NULL, pcomma, &psave);
|
|
if (strcmp(ptoken, "PRINT") == 0) {
|
|
g_instance.whitebox_test_param_instance[i].type = WHITEBOX_PRINT;
|
|
} else if (strcmp(ptoken, "SLEEP") == 0) {
|
|
g_instance.whitebox_test_param_instance[i].type = WHITEBOX_SLEEP;
|
|
} else if (strcmp(ptoken, "SUSPEND") == 0) {
|
|
g_instance.whitebox_test_param_instance[i].type = WHITEBOX_SUSPEND;
|
|
} else if (strcmp(ptoken, "ENABLE") == 0) {
|
|
g_instance.whitebox_test_param_instance[i].type = WHITEBOX_ENABLE;
|
|
} else if (strcmp(ptoken, "DISABLE") == 0) {
|
|
g_instance.whitebox_test_param_instance[i].type = WHITEBOX_DISABLE;
|
|
} else if (strcmp(ptoken, "ERROR") == 0) {
|
|
g_instance.whitebox_test_param_instance[i].type = WHITEBOX_ERROR;
|
|
}
|
|
|
|
// test stub attributes
|
|
ptoken = strtok_r(NULL, pcomma, &psave);
|
|
while (ptoken) {
|
|
ptype = TrimStr(strtok_r(ptoken, pequal, &pvalue));
|
|
if (!ptype || !pvalue) {
|
|
break;
|
|
}
|
|
if (strcmp(ptype, "TIMEOUT") == 0) {
|
|
g_instance.whitebox_test_param_instance[i].attributes.timeout = pg_strtoint32(pvalue);
|
|
} else if (strcmp(ptype, "ENABLED") == 0) {
|
|
g_instance.whitebox_test_param_instance[i].attributes.enabled = (bool) pg_strtoint32(pvalue);
|
|
} else if (strcmp(ptype, "SKIP_ITERATION") == 0) {
|
|
g_instance.whitebox_test_param_instance[i].attributes.skip_iteration = pg_strtoint32(pvalue);
|
|
} else if (strcmp(ptype, "TARGET_TEST_STUB") == 0) {
|
|
rc = sprintf_s(g_instance.whitebox_test_param_instance[i].attributes.target_test_stub, MAX_NAME_STR_LEN,
|
|
"%s", TrimStr(pvalue));
|
|
securec_check_ss_c(rc, "\0", "\0");
|
|
}
|
|
ptoken = strtok_r(NULL, pcomma, &psave);
|
|
}
|
|
g_instance.whitebox_test_param_instance[i].attributes.hit_count = 0;
|
|
i++;
|
|
}
|
|
fclose(fp);
|
|
}
|
|
|
|
/**
|
|
* @Description: check whether the test stub can be activated.
|
|
* @in name - the white-box single-point fault fire tag, is a string defined in GUC
|
|
* @in function - callback function
|
|
* @return - true if one or more breakpoints have been activated; false otherwise
|
|
*/
|
|
bool WhiteboxTestStubActivator(const char* name, whitebox_stub_callback function)
|
|
{
|
|
bool result = false;
|
|
if (g_instance.whitebox_test_param_instance == NULL) {
|
|
return false;
|
|
}
|
|
|
|
if (t_thrd.proc_cxt.proc_exit_inprogress) {
|
|
return false;
|
|
}
|
|
|
|
if (g_instance.whitebox_test_param_instance->num_testcase > MAX_UNIT_TEST) {
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < g_instance.whitebox_test_param_instance->num_testcase; i++) {
|
|
if (pg_strcasecmp(name, g_instance.whitebox_test_param_instance[i].test_stub_name) == 0) {
|
|
result = result || (*function)(g_instance.whitebox_test_param_instance[i]);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @Description: default uheap-error emit callback function.
|
|
* @in - a reference to test parameters
|
|
* @return - true if one or more breakpoints have been activated; false otherwise
|
|
*/
|
|
bool WhiteboxDefaultErrorEmit(WhiteboxTestParam& uheapTestParamInstance)
|
|
{
|
|
bool result = false;
|
|
if (g_instance.whitebox_test_param_instance->elevel == PANIC) {
|
|
exit(0);
|
|
}
|
|
|
|
switch (uheapTestParamInstance.type) {
|
|
case WHITEBOX_PRINT:
|
|
result = WhiteboxTestPrint(uheapTestParamInstance.test_stub_name);
|
|
break;
|
|
case WHITEBOX_SLEEP:
|
|
result = WhiteboxTestSleep(
|
|
uheapTestParamInstance.test_stub_name,
|
|
uheapTestParamInstance.attributes.timeout,
|
|
uheapTestParamInstance.attributes.skip_iteration,
|
|
uheapTestParamInstance.attributes.hit_count);
|
|
break;
|
|
case WHITEBOX_SUSPEND:
|
|
result = WhiteboxTestSuspend(
|
|
uheapTestParamInstance.test_stub_name,
|
|
uheapTestParamInstance.attributes.timeout,
|
|
uheapTestParamInstance.attributes.enabled);
|
|
break;
|
|
case WHITEBOX_ENABLE:
|
|
result = WhiteboxTestSetEnable(
|
|
uheapTestParamInstance.attributes.target_test_stub, true);
|
|
break;
|
|
case WHITEBOX_DISABLE:
|
|
result = WhiteboxTestSetEnable(
|
|
uheapTestParamInstance.attributes.target_test_stub, false);
|
|
break;
|
|
case WHITEBOX_ERROR:
|
|
result = WhiteboxTestSetError(
|
|
uheapTestParamInstance.test_stub_name,
|
|
uheapTestParamInstance.attributes.enabled);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return false; // make it always false for now, to mute the message printing at each breakpoint
|
|
}
|
|
|
|
bool WhiteboxTestPrint(const char* functionName)
|
|
{
|
|
ereport(NOTICE, (errmsg("Hitting breakpoint %s", functionName)));
|
|
return true;
|
|
}
|
|
|
|
bool WhiteboxTestSetError(const char* functionName, const bool& enabled)
|
|
{
|
|
if (enabled) {
|
|
ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("Hitting breakpoint %s", functionName)));
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool WhiteboxTestSleep(const char* functionName, int timeout, int skipIteration, int& hitCount)
|
|
{
|
|
hitCount++;
|
|
if (hitCount > skipIteration) {
|
|
hitCount = 0;
|
|
elog(g_instance.whitebox_test_param_instance->elevel,
|
|
"Suspending at breakpoint %s timeout=%d", functionName, timeout);
|
|
pg_usleep(timeout);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool WhiteboxTestSuspend(const char* functionName, int timeout, const bool& enabled)
|
|
{
|
|
int elapseTime = 0;
|
|
int elapseInterval = 1000; // 1/1000 second
|
|
if (enabled) {
|
|
elog(g_instance.whitebox_test_param_instance->elevel, "Suspending at breakpoint %s timeout=%d",
|
|
functionName, timeout);
|
|
while (elapseTime < timeout) {
|
|
// check for interrupts
|
|
if (!enabled) {
|
|
break;
|
|
}
|
|
elapseTime += elapseInterval;
|
|
pg_usleep(elapseInterval);
|
|
}
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool WhiteboxTestSetEnable(const char* functionName, bool enabled)
|
|
{
|
|
for (int i = 0; i < g_instance.whitebox_test_param_instance->num_testcase; i++) {
|
|
if (pg_strcasecmp(functionName, g_instance.whitebox_test_param_instance[i].test_stub_name) == 0) {
|
|
g_instance.whitebox_test_param_instance[i].attributes.enabled = enabled;
|
|
if (enabled) {
|
|
elog(g_instance.whitebox_test_param_instance->elevel, "Enabling breakpoint %s type=%d", functionName,
|
|
g_instance.whitebox_test_param_instance[i].type);
|
|
} else {
|
|
elog(g_instance.whitebox_test_param_instance->elevel, "Disabling breakpoint %s type=%d", functionName,
|
|
g_instance.whitebox_test_param_instance[i].type);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|