/*
 * Checks if the returned string segments are within memory limit for ascii characters.
 */
void
test__find_memory_limited_substring__ascii_chars_within_memory_limit(void **state)
{
	int subStringByteLength = -1;
	int subStringCharLength = -1;
	int cumulativeLengthConsidered = 0;

	char *strStart = 0xabcdefab;

	int totalByteLength = 25;

	while (cumulativeLengthConsidered < totalByteLength - MEMORY_LIMIT)
	{
		will_return(pg_database_encoding_max_length, 1);
		find_memory_limited_substring(strStart, totalByteLength - cumulativeLengthConsidered, MEMORY_LIMIT, &subStringByteLength, &subStringCharLength);
		cumulativeLengthConsidered += subStringByteLength;
		assert_true(subStringByteLength == MEMORY_LIMIT);
		assert_true(subStringByteLength == subStringCharLength);
	}

#ifdef USE_ASSERT_CHECKING
	expect_any(ExceptionalCondition,conditionName);
	expect_any(ExceptionalCondition,errorType);
	expect_any(ExceptionalCondition,fileName);
	expect_any(ExceptionalCondition,lineNumber);
	will_be_called_with_sideeffect(ExceptionalCondition,&_ExceptionalCondition,NULL);

	/* Test if the left-over string that fits in memory cause assertion failure */
	PG_TRY();
	{
		find_memory_limited_substring(strStart, totalByteLength - cumulativeLengthConsidered, MEMORY_LIMIT, &subStringByteLength, &subStringCharLength);
		assert_true(false);
	}
	PG_CATCH();
	{
	}
	PG_END_TRY();

	expect_any(ExceptionalCondition,conditionName);
	expect_any(ExceptionalCondition,errorType);
	expect_any(ExceptionalCondition,fileName);
	expect_any(ExceptionalCondition,lineNumber);
	will_be_called_with_sideeffect(ExceptionalCondition,&_ExceptionalCondition,NULL);

	/* Test if null strings cause assertion failure */
	PG_TRY();
	{
		find_memory_limited_substring(NULL, totalByteLength, MEMORY_LIMIT, &subStringByteLength, &subStringCharLength);
	}
	PG_CATCH();
	{
		return;
	}
	PG_END_TRY();
	assert_true(false);
#endif
}
/*
 * Checks if null input string causes assertion failure.
 */
void
test__find_memory_limited_substring__null_string(void **state)
{
	int subStringByteLength = -1;
	int subStringCharLength = -1;
	int totalByteLength = MEMORY_LIMIT + 1;
	char *strStart = NULL;

#ifdef USE_ASSERT_CHECKING
	expect_any(ExceptionalCondition,conditionName);
	expect_any(ExceptionalCondition,errorType);
	expect_any(ExceptionalCondition,fileName);
	expect_any(ExceptionalCondition,lineNumber);
	will_be_called_with_sideeffect(ExceptionalCondition,&_ExceptionalCondition,NULL);

 	/* Test if null strings cause assertion failure */
	PG_TRY();
	{
		find_memory_limited_substring(strStart, totalByteLength, MEMORY_LIMIT, &subStringByteLength, &subStringCharLength);
		assert_true(false);
	}
	PG_CATCH();
	{
	}
	PG_END_TRY();
#endif
}
Beispiel #3
0
/*
 * A shared method to test proper deactivation during IdleTracker_Shutdown()
 * or a direct call to IdleTracker_DeactivateProcess() during regular
 * deactivation of an active process when a proper cleanup was done, throwing
 * and elog(ERROR,...) and therefore the call would never return to the calling
 * function
 */
static void
CheckForDeactivationWithProperCleanup(void (*testFunc)(void))
{
	static EventVersion fakeCurrentVersion = 10;
	CurrentVersion = &fakeCurrentVersion;

	InitFakeSessionState(1 /* activeProcessCount */, CLEANUP_COUNTDOWN_BEFORE_RUNAWAY /* cleanupCountdown */,
			RunawayStatus_NotRunaway /* runawayStatus */, 1 /* pinCount */, 0 /* vmem */);

	EventVersion oldVersion = *CurrentVersion;
	/* Ensure we have a pending runaway event */
	EventVersion fakeLatestRunawayVersion = *CurrentVersion - 1;
	latestRunawayVersion = &fakeLatestRunawayVersion;

	activationVersion = 0;
	deactivationVersion = 0;

	assert_true(*CurrentVersion != activationVersion);
	assert_true(*CurrentVersion != deactivationVersion);

	/*
	 * Set to true as we want to verify that it gets set to false
	 * once the testFunc() call returns
	 */
	isProcessActive = true;

	assert_true(MySessionState->activeProcessCount == 1);

	/*
	 * Deactivation must call RunawayCleaner_StartCleanup before finishing deactivation
	 * to check for cleanup requirement for any pending runaway event. The mocked method
	 * is throwing an exception here, which would block execution of code following the call
	 * site
	 */
	will_be_called_with_sideeffect(RunawayCleaner_StartCleanup, &_ExceptionalCondition, NULL);

	PG_TRY();
	{
		testFunc();
		assert_false("Expected an exception");
	}
	PG_CATCH();
	{

	}
	PG_END_TRY();

	assert_true(activationVersion == 0);
	assert_true(deactivationVersion == *CurrentVersion);
	assert_true(isProcessActive == false);
	assert_true(MySessionState->activeProcessCount == 0);
}
/*
 * SUT: rest_request
 * call_rest throws an error while not in HA mode
 */
void
test__rest_request__callRestThrowsNoHA(void **state)
{
	GPHDUri *hadoop_uri = (GPHDUri*)  palloc0(sizeof(GPHDUri));
	hadoop_uri->host = pstrdup("host1");
	hadoop_uri->port = pstrdup("port1");
	ClientContext* client_context =  (ClientContext*)  palloc0(sizeof(ClientContext));
	char *restMsg = "empty message";

	expect_any(call_rest, hadoop_uri);
	expect_any(call_rest, client_context);
	expect_any(call_rest, rest_msg);
	will_be_called_with_sideeffect(call_rest, &FirstException, NULL);

	/* test */
	PG_TRY();
	{
		rest_request(hadoop_uri, client_context, restMsg);
	}
	PG_CATCH();
	{
		pfree(hadoop_uri->host);
		pfree(hadoop_uri->port);
		pfree(hadoop_uri);
		pfree(client_context);

		CurrentMemoryContext = 1;
		ErrorData *edata = CopyErrorData();

		/*Validate the type of expected error */
		assert_string_equal(edata->message, "first exception");
		return;
	}
	PG_END_TRY();

	assert_true(false);
}
/*
 * SUT: rest_request
 * call_rest throws an error while in HA mode
 * and the failover method finds an active IP so the second
 * call to call_rest does  no throw an exception
 */
void
test__rest_request__callRestThrowsHAFirstTime(void **state)
{
	GPHDUri *hadoop_uri = (GPHDUri*)  palloc0(sizeof(GPHDUri));
	hadoop_uri->host = pstrdup("host1");
	hadoop_uri->port = pstrdup("port1");
	NNHAConf *ha_nodes = (NNHAConf*)  palloc0(sizeof(NNHAConf));
    hadoop_uri->ha_nodes = ha_nodes;
	ha_nodes->nodes = (char *[]){"host1", "host2"};
	ha_nodes->restports = (char *[]){"port1", "port2"};
	ha_nodes->numn = 2;

	ClientContext* client_context =  (ClientContext*)  palloc0(sizeof(ClientContext));
	char *restMsg = "empty message";

	expect_any(call_rest, hadoop_uri);
	expect_any(call_rest, client_context);
	expect_any(call_rest, rest_msg);
	will_be_called_with_sideeffect(call_rest, &FirstException, NULL);

	/* the second call from ha_failover */
	expect_any(call_rest, hadoop_uri);
	expect_any(call_rest, client_context);
	expect_any(call_rest, rest_msg);
	will_be_called(call_rest);


	/* test */
	rest_request(hadoop_uri, client_context, restMsg);

	pfree(hadoop_uri);
	pfree(client_context);
}

/*
 * SUT: rest_request
 * call_rest throws an error while in HA mode
 * and the failover method finds an an active IP so the second
 * call to call_rest is issued on the second IP. This call also throws
 * an exception - but this time the exception is not caught.
 */
void
test__rest_request__callRestThrowsHASecondTime(void **state)
{
	GPHDUri *hadoop_uri = (GPHDUri*)  palloc0(sizeof(GPHDUri));
	hadoop_uri->host = pstrdup("host1");
	hadoop_uri->port = pstrdup("port1");
	NNHAConf *ha_nodes = (NNHAConf*)  palloc0(sizeof(NNHAConf));
    hadoop_uri->ha_nodes = ha_nodes;
	ha_nodes->nodes = (char *[]){"host1", "host2"};
	ha_nodes->restports = (char *[]){"port1", "port2"};
	ha_nodes->numn = 2;

	ClientContext* client_context =  (ClientContext*)  palloc0(sizeof(ClientContext));
	char *restMsg = "empty message";

	expect_any(call_rest, hadoop_uri);
	expect_any(call_rest, client_context);
	expect_any(call_rest, rest_msg);
	will_be_called_with_sideeffect(call_rest, &FirstException, NULL);

	/* the second call from ha_failover */
	expect_any(call_rest, hadoop_uri);
	expect_any(call_rest, client_context);
	expect_any(call_rest, rest_msg);
	will_be_called_with_sideeffect(call_rest, &SecondException, NULL);


	/* test */
	PG_TRY();
	{
		rest_request(hadoop_uri, client_context, restMsg);
	}
	PG_CATCH();
	{
		pfree(hadoop_uri->host);
		pfree(hadoop_uri->port);
		pfree(hadoop_uri);
		pfree(client_context);

		CurrentMemoryContext = 1;
		ErrorData *edata = CopyErrorData();

		/*Validate the type of expected error */
		assert_string_equal(edata->message, "second exception");
		/* the first exception was caught by rest_request() */
		return;
	}
	PG_END_TRY();

	assert_true(false);
}

/*
 * SUT: rest_request
 * the first time call_rest is called we succeed, since the first IP is valid
 * No exceptions are thrown
 */
void
test__rest_request__callRestHASuccessFromTheFirstCall(void **state)
{
	GPHDUri *hadoop_uri = (GPHDUri*)  palloc0(sizeof(GPHDUri));
	hadoop_uri->host = pstrdup("host1");
	hadoop_uri->port = pstrdup("port1");
	NNHAConf *ha_nodes = (NNHAConf*)  palloc0(sizeof(NNHAConf));
    hadoop_uri->ha_nodes = ha_nodes;
	ha_nodes->nodes = (char *[]){"host1", "host2"};
	ha_nodes->restports = (char *[]){"port1", "port2"};
	ha_nodes->numn = 2;

	ClientContext* client_context =  (ClientContext*)  palloc0(sizeof(ClientContext));
	char *restMsg = "empty message";

	expect_any(call_rest, hadoop_uri);
	expect_any(call_rest, client_context);
	expect_any(call_rest, rest_msg);
	will_be_called(call_rest);

	/* test */
	rest_request(hadoop_uri, client_context, restMsg);

	pfree(hadoop_uri->host);
	pfree(hadoop_uri->port);
	pfree(hadoop_uri);
	pfree(client_context);
}

void
test__normalize_size(void **state)
{
	float4 result = normalize_size(10000000, "B");
	assert_int_equal(result, 10000000);

	result = normalize_size(10000000, "KB");
	assert_int_equal(result, 10240000000);

	result = normalize_size(500, "MB");
	assert_int_equal(result, 524288000);

	result = normalize_size(10, "GB");
	assert_int_equal(result, 10737418240);

	result = normalize_size(10000, "TB");
	assert_int_equal(result, 10995116277760000);
}

int 
main(int argc, char *argv[]) 
{
	cmockery_parse_arguments(argc, argv);

	const UnitTest tests[] = {
		    unit_test(test__rest_request__callRestThrowsNoHA),
		    unit_test(test__rest_request__callRestThrowsHAFirstTime),
		    unit_test(test__rest_request__callRestThrowsHASecondTime),
		    unit_test(test__rest_request__callRestHASuccessFromTheFirstCall),
			unit_test(test__normalize_size)
	};
	return run_tests(tests);
}
Beispiel #6
0
/* Checks CdbCheckDispatchResult is called when queryDesc
 * is not null (when shouldDispatch is true).
 * This test falls in PG_CATCH when SetupInterconnect
 * does not allocate queryDesc->estate->interconnect_context.
 * The test is successful if the */
void 
test__ExecSetParamPlan__Check_Dispatch_Results(void **state) 
{

	/*Set plan to explain.*/
	SubPlanState *plan = makeNode(SubPlanState);
	plan->xprstate.expr = makeNode(SubPlanState);
	plan->planstate = makeNode(SubPlanState);
	plan->planstate->instrument = (Instrumentation *)palloc(sizeof(Instrumentation));
	plan->planstate->plan = makeNode(SubPlanState);
	
	EState *estate = CreateExecutorState();

	/*Assign mocked estate to plan.*/
	((PlanState *)(plan->planstate))->state= estate;

	/*Re-use estate mocked object. Needed as input parameter for
	tested function */
	ExprContext *econtext = GetPerTupleExprContext(estate);

	/*Set QueryDescriptor input parameter for tested function */
	PlannedStmt   *plannedstmt = (PlannedStmt *)palloc(sizeof(PlannedStmt));
	QueryDesc *queryDesc = (QueryDesc *)palloc(sizeof(QueryDesc));
	queryDesc->plannedstmt = plannedstmt;
	queryDesc->estate = (EState *)palloc(sizeof(EState));
	queryDesc->estate->es_sliceTable = (SliceTable *) palloc(sizeof(SliceTable));
	
	/*QueryDescriptor generated when shouldDispatch is true.*/
	QueryDesc *internalQueryDesc = (QueryDesc *)palloc(sizeof(QueryDesc));
	internalQueryDesc->estate = (EState *)palloc(sizeof(EState));
	/* Added to force assertion on queryDesc->estate->interconnect_context;
	to fail */
	internalQueryDesc->estate->interconnect_context=NULL;
	internalQueryDesc->estate->es_sliceTable = (SliceTable *) palloc(sizeof(SliceTable));

	expect_any(CreateQueryDesc,plannedstmt);
	expect_any(CreateQueryDesc,sourceText);
	expect_any(CreateQueryDesc,snapshot);
	expect_any(CreateQueryDesc,crosscheck_snapshot);
	expect_any(CreateQueryDesc,dest);
	expect_any(CreateQueryDesc,params);
	expect_any(CreateQueryDesc,doInstrument);
	will_return(CreateQueryDesc,internalQueryDesc);
	
	Gp_role = GP_ROLE_DISPATCH;
	plan->planstate->plan->dispatch=DISPATCH_PARALLEL;

	will_be_called(isCurrentDtxTwoPhase);

	expect_any(cdbdisp_dispatchPlan,queryDesc);
	expect_any(cdbdisp_dispatchPlan,planRequiresTxn);
	expect_any(cdbdisp_dispatchPlan,cancelOnError);
	expect_any(cdbdisp_dispatchPlan,ds);
	will_be_called(cdbdisp_dispatchPlan);

	expect_any(SetupInterconnect,estate);
	/* Force SetupInterconnect to fail */
	will_be_called_with_sideeffect(SetupInterconnect,&_RETHROW,NULL);


	expect_any(cdbexplain_localExecStats,planstate);
	expect_any(cdbexplain_localExecStats,showstatctx);
	will_be_called(cdbexplain_localExecStats);

	expect_any(CdbCheckDispatchResult,ds);
	expect_any(CdbCheckDispatchResult,waitMode);
	will_be_called(CdbCheckDispatchResult);

	expect_any(cdbexplain_recvExecStats,planstate);
	expect_any(cdbexplain_recvExecStats,dispatchResults);
	expect_any(cdbexplain_recvExecStats,sliceIndex);
	expect_any(cdbexplain_recvExecStats,showstatctx);
	will_be_called(cdbexplain_recvExecStats);

	will_be_called(TeardownSequenceServer);

	expect_any(TeardownInterconnect,transportStates);
	expect_any(TeardownInterconnect,mlStates);
	expect_any(TeardownInterconnect,forceEOS);
	will_be_called(TeardownInterconnect);

	/* Catch PG_RE_THROW(); after cleaning with CdbCheckDispatchResult */
	PG_TRY();
		ExecSetParamPlan(plan,econtext,queryDesc);
	PG_CATCH();
		assert_true(true);
	PG_END_TRY();
}
/*
 * Checks if the returned string segments are within memory limit for multi-bytes chars.
 */
void
test__find_memory_limited_substring__mb_chars_within_memory_limit(void **state)
{
	int subStringByteLength = -1;
	int subStringCharLength = -1;
	int cumulativeLengthConsidered = 0;

	/* Lengths of the multi-byte characters at different positions */
	int stringByteLengths[] = {3, 3, 3 /* seg1 */, 2, 2, 1, 2 /* seg2 */, 2, 1, 1, 1, 2, /* seg3 */ 5, 4 /* seg4 */, 4};

	/* Total length in terms of number of characters */
	int stringCharLength = sizeof(stringByteLengths) / sizeof(int);

	/* Total byte lengths of all the characters */
	int totalByteLength = 0;
	for (int charIndex = 0; charIndex < stringCharLength; charIndex++)
	{
		totalByteLength += stringByteLengths[charIndex];
	}

	int segmentByteLength = 0; /* Number of bytes in current segment */
	int segmentCharLength = 0; /* Number of characters in current segment */

	/* Length of the char that spilled over from one partition to another */
	int carryoverLength = 0;

	/* Fictitious multi-byte string to segment */
	char *strStart = 0xabcdefab;

	for (int charIndex = 0; charIndex < stringCharLength; charIndex++)
	{
		if (carryoverLength > 0)
		{
			expect_any(pg_mblen, mbstr);
			will_return(pg_mblen, carryoverLength);
			carryoverLength = 0;
		}

		expect_any(pg_mblen, mbstr);
		will_return(pg_mblen, stringByteLengths[charIndex]);
		segmentByteLength += stringByteLengths[charIndex];
		segmentCharLength++;

		if (segmentByteLength > MEMORY_LIMIT)
		{

			will_return(pg_database_encoding_max_length, 6);
			find_memory_limited_substring(strStart, totalByteLength - cumulativeLengthConsidered, MEMORY_LIMIT, &subStringByteLength, &subStringCharLength);
			assert_true(subStringByteLength == (segmentByteLength - stringByteLengths[charIndex]));
			assert_true(subStringCharLength == (segmentCharLength - 1));
			assert_true(subStringByteLength <= MEMORY_LIMIT);
			assert_true(subStringCharLength <= MEMORY_LIMIT);

			cumulativeLengthConsidered += subStringByteLength;

			segmentByteLength = stringByteLengths[charIndex];
			segmentCharLength = 1;
			carryoverLength = stringByteLengths[charIndex];
		}
	}

	/* Now purge any unused pg_mblen call because of the suffix that does not exceed MEMORY_LIMIT */
	for (int partitionCharIndex = 0; partitionCharIndex < segmentCharLength; partitionCharIndex++)
	{
		pg_mblen("a");
	}

#ifdef USE_ASSERT_CHECKING
	expect_any(ExceptionalCondition,conditionName);
	expect_any(ExceptionalCondition,errorType);
	expect_any(ExceptionalCondition,fileName);
	expect_any(ExceptionalCondition,lineNumber);
	will_be_called_with_sideeffect(ExceptionalCondition,&_ExceptionalCondition,NULL);

	/* Test if the left-over string that fits in memory cause assertion failure */
	PG_TRY();
	{
		find_memory_limited_substring(strStart, totalByteLength - cumulativeLengthConsidered, MEMORY_LIMIT, &subStringByteLength, &subStringCharLength);
	}
	PG_CATCH();
	{
		return;
	}
	PG_END_TRY();

	assert_true(false);
#endif
}
Beispiel #8
0
/* Tests whether SharedChunkHeadersMemoryAccount ignores the overhead of null Account header */
void
test__AllocFreeInfo__SharedChunkHeadersMemoryAccountIgnoresNullHeader(void **state)
{
	/* This has two parts:
	 * 1. Check the assertion that nullAccountHeader creation requires
	 * SharedChunkHeadersMemoryAccount to be NULL
	 *
	 * 2. Reset the context that hosts the nullAccountHeader, and make sure
	 * that SharedChunkHeadersMemoryAccount balance does not get changed
	 */

	MemoryContext *newContext = AllocSetContextCreate(ErrorContext,
			   "TestContext",
			   ALLOCSET_DEFAULT_MINSIZE,
			   ALLOCSET_DEFAULT_INITSIZE,
			   ALLOCSET_DEFAULT_MAXSIZE);

	AllocSet newSet = (AllocSet)newContext;
	assert_true(newSet->sharedHeaderList == NULL);
	assert_true(newSet->nullAccountHeader == NULL);

	MemoryAccount *oldActive = ActiveMemoryAccount;
	MemoryAccount *oldShared = SharedChunkHeadersMemoryAccount;

	/* Turning off memory monitoring */
	ActiveMemoryAccount = NULL;

	#ifdef USE_ASSERT_CHECKING
	    expect_any(ExceptionalCondition,conditionName);
	    expect_any(ExceptionalCondition,errorType);
	    expect_any(ExceptionalCondition,fileName);
	    expect_any(ExceptionalCondition,lineNumber);

	    will_be_called_with_sideeffect(ExceptionalCondition, &_ExceptionalCondition, NULL);

	    /* Test if within memory-limit strings cause assertion failure */
		PG_TRY();
		{
			/*
			 * ActiveMemoryAccount is NULL, but SharedChunkHeadersMemoryAccount is
			 * *not* null. This should trigger an assertion
			 */
			void *testAlloc = MemoryContextAlloc(newContext, NEW_ALLOC_SIZE);

			assert_true(false);
		}
		PG_CATCH();
		{
		}
		PG_END_TRY();
	#endif

	/*
	 * Now make SharedChunkHeadersMemoryAccount NULL to avoid assert failure
	 * and allow creation of a nullAccountHeader
	 */
	SharedChunkHeadersMemoryAccount = NULL;

	/* Allocate from the new context which should trigger a nullAccountHeader creation*/
	void *testAlloc = MemoryContextAlloc(newContext, NEW_ALLOC_SIZE);

	StandardChunkHeader *header = (StandardChunkHeader *)
		((char *) testAlloc - STANDARDCHUNKHEADERSIZE);

	/*
	 * Assert if we are using nullAccountHeader, as we have simulated absence
	 * of memory monitoring
	 */
	assert_true(header->sharedHeader != NULL && header->sharedHeader == newSet->nullAccountHeader);

	/*
	 * Restore the SharedChunkHeadersMemoryAccount so that we can turn on
	 * sharedHeader balance releasing if a sharedHeader is deleted (except
	 * nullAccountHeader of course)
	 */
	SharedChunkHeadersMemoryAccount = oldShared;
	/* Activate the memory accounting */
	ActiveMemoryAccount = oldActive;

	uint64 sharedBalance = SharedChunkHeadersMemoryAccount->allocated - SharedChunkHeadersMemoryAccount->freed;

	pfree(testAlloc);

	/*
	 * As testAlloc is holding a pointer to nullAccountHeader, releasing that allocation
	 * should not change SharedChunkHeadersMemoryAccount balance
	 */
	assert_true(sharedBalance == SharedChunkHeadersMemoryAccount->allocated - SharedChunkHeadersMemoryAccount->freed);

	MemoryContextDelete(newContext);
}