Exemplo n.º 1
0
// static bool mutatorTest3and4(int testno, const char *testname)
test_results_t test_thread_3_Mutator::executeTest() {
  test3_threadCreateCounter = 0;
  callback_tids.clear();

  unsigned int timeout = 0; // in ms
  int err = 0;

  BPatchAsyncThreadEventCallback createcb = threadCreateCB;
  if (!bpatch->registerThreadEventCallback(BPatch_threadCreateEvent, createcb))
  {
    FAIL_MES(TESTNAME, TESTDESC);
    logerror("%s[%d]:  failed to register thread callback\n",
           __FILE__, __LINE__);
    appThread->getProcess()->terminateExecution();
    return FAILED;
  }

#if 0
  //  unset mutateeIde to trigger thread (10) spawn.
  int zero = 0;
  // FIXME Check the return value of setVar()
  setVar("mutateeIdle", (void *) &zero, TESTNO, TESTDESC);
  dprintf("%s[%d]:  continue execution for test %d\n", __FILE__, __LINE__, TESTNO);
  appThread->continueExecution();
#endif

  //  wait until we have received the desired number of events
  //  (or timeout happens)

  BPatch_Vector<BPatch_thread *> threads;
  BPatch_process *appProc = appThread->getProcess();
  assert(appProc);
  appProc->getThreads(threads);
  int active_threads = 11; // FIXME Magic number
  threads.clear();
  while (((test3_threadCreateCounter < TEST3_THREADS)
         || (active_threads > 1))
         && (timeout < TIMEOUT)) {
    dprintf("%s[%d]: waiting for completion for test %d, num active threads = %d\n",
            __FILE__, __LINE__, TESTNO, active_threads);
    sleep_ms(SLEEP_INTERVAL/*ms*/);
    timeout += SLEEP_INTERVAL;
    if (appProc->isTerminated()) {
       dprintf("%s[%d]:  BAD NEWS:  somehow the process died\n", __FILE__, __LINE__);
       err = 1;
       break;
    }
    bpatch->pollForStatusChange();
    if (appProc->isStopped()) {
        appProc->continueExecution();
    }
    appProc->getThreads(threads);
    active_threads = threads.size();
    threads.clear();
  }

  if (timeout >= TIMEOUT) {
    FAIL_MES(TESTNAME, TESTDESC);
    logerror("%s[%d]:  test timed out. got %d/10 events\n", __FILE__, __LINE__, test3_threadCreateCounter);
    logerror("test3_createCounter is %d, expected %d; active threads %d, expected %d\n",
            test3_threadCreateCounter, TEST3_THREADS, active_threads, 1);
    err = 1;
  }

  dprintf("%s[%d]: ending test %d, num active threads = %d\n",
            __FILE__, __LINE__, TESTNO, active_threads);
  dprintf("%s[%d]:  stop execution for test %d\n", __FILE__, __LINE__, TESTNO);
  appProc->stopExecution();

  //   read all tids from the mutatee and verify that we got them all
  unsigned long mutatee_tids[TEST3_THREADS];
  const char *threads_varname = "test4_threads";
  getVar(threads_varname, (void *) mutatee_tids,
         (sizeof(unsigned long) * TEST3_THREADS),
         TESTNO, TESTDESC);

  if (debugPrint()) {
    dprintf("%s[%d]:  read following tids for test%d from mutatee\n", __FILE__, __LINE__, TESTNO);

    for (unsigned int i = 0; i < TEST3_THREADS; ++i) {
       dprintf("\t%lu\n", mutatee_tids[i]);
    }
  }

  for (unsigned int i = 0; i < TEST3_THREADS; ++i) {
     bool found = false;
     for (unsigned int j = 0; j < callback_tids.size(); ++j) {
       if (callback_tids[j] == mutatee_tids[i]) {
         found = true;
         break;
       }
     }

    if (!found) {
      FAIL_MES(TESTNAME, TESTDESC);
      logerror("%s[%d]:  could not find record for tid %lu: have these:\n",
             __FILE__, __LINE__, mutatee_tids[i]);
       for (unsigned int j = 0; j < callback_tids.size(); ++j) {
          logerror("%lu\n", callback_tids[j]);
       }
      err = true;
      break;
    }
  }

  dprintf("%s[%d]: removing thread callback\n", __FILE__, __LINE__);
  if (!bpatch->removeThreadEventCallback(BPatch_threadCreateEvent, createcb)) {
    FAIL_MES(TESTNAME, TESTDESC);
    logerror("%s[%d]:  failed to remove thread callback\n",
           __FILE__, __LINE__);
    err = true;
  }

  if (!err)  {
    PASS_MES(TESTNAME, TESTDESC);
    appProc->terminateExecution();
    return PASSED;
  }
  appProc->terminateExecution();
  return FAILED;
}
Exemplo n.º 2
0
// static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage)
test_results_t test_callback_2_Mutator::executeTest() 
{
	//  a simple single threaded user messagin scenario where we want to send
	//  async messages at function entry/exit and call points.

	// load libtest12.so -- currently only used by subtest 5, but make it generally
	// available
	const char *libname = "./libTest12.so";    
	test7err = false;
	test7done = false;
	callback_counter = 0;
	elog.resize(0);

#if defined(arch_x86_64_test)
	if (appProc->getAddressWidth() == 4)
		libname = "./libTest12_m32.so";
#endif

	dprintf("%s[%d]:  loading test library: %s\n", __FILE__, __LINE__, libname);

	if (!appProc->loadLibrary(libname))
	{
		logerror("%s[%d]:  failed to load library %s, cannot proceed\n", 
				__FILE__, __LINE__, libname);
                appProc->terminateExecution();
		return FAILED;
	}

	dprintf("%s[%d]:  loaded test library: %s\n", __FILE__, __LINE__, libname);
	BPatchUserEventCallback cb = test7cb;

	if (!bpatch->registerUserEventCallback(cb)) 
	{
		FAIL_MES(TESTNAME, TESTDESC);
		logerror("%s[%d]: could not register callback\n", __FILE__, __LINE__);
                appProc->terminateExecution();
		return FAILED;
	}

	//  instrument entry and exit of call7_1, as well as call points inside call7_1

	const char *call1name = "test_callback_2_call1";

	BPatch_function *call7_1 = findFunction(call1name, appImage,TESTNO, TESTNAME);

	BPatch_point *entry = findPoint(call7_1, BPatch_entry,TESTNO, TESTNAME);

	if (NULL == entry) 
	{
		logerror("%s[%d]: Unable to find entry point to function %s\n", 
				__FILE__, __LINE__, call1name);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}

	BPatch_point *exit = findPoint(call7_1, BPatch_exit,TESTNO, TESTNAME);

	if (NULL == entry) 
	{
		logerror("%s[%d]:  Unable to find exit point to function %s\n", 
				__FILE__, __LINE__, call1name);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}

	BPatch_point *callsite = findPoint(call7_1, BPatch_subroutine,TESTNO, TESTNAME);

	if (NULL == callsite) 
	{
		logerror("%s[%d]:  Unable to find subroutine call point in function %s\n",
				__FILE__, __LINE__, call1name);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}

	//  These are our asynchronous message functions (in libTest12) that we
	//  attach to the "interesting" points

	BPatch_function *reportEntry = findFunction("reportEntry", appImage,TESTNO, TESTNAME);
	BPatch_function *reportExit = findFunction("reportExit", appImage,TESTNO, TESTNAME);
	BPatch_function *reportCallsite = findFunction("reportCallsite", appImage,TESTNO, TESTNAME);

	if (!reportEntry)
	{
		logerror("%s[%d]:  reportEntry = NULL\n", FILE__, __LINE__);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}
	if (!reportExit)
	{
		logerror("%s[%d]:  reportExit = NULL\n", FILE__, __LINE__);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}
	if (!reportCallsite)
	{
		logerror("%s[%d]:  reportCallsite = NULL\n", FILE__, __LINE__);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}

	//  Do the instrumentation
	BPatchSnippetHandle *entryHandle = at(entry, reportEntry, TESTNO, TESTNAME);
	BPatchSnippetHandle *exitHandle = at(exit, reportExit, TESTNO, TESTNAME);
	BPatchSnippetHandle *callsiteHandle = at(callsite, reportCallsite, TESTNO, TESTNAME);

	//  "at" may set test7err
	if ((test7err)
			||  (NULL == entryHandle) 
			|| (NULL == exitHandle) 
			|| (NULL == callsiteHandle) )
	{
		logerror("%s[%d]:  instrumentation failed, test7err = %d\n", FILE__, __LINE__, test7err);
		logerror("%s[%d]:  entryHandle = %p\n", FILE__, __LINE__, entryHandle);
		logerror("%s[%d]:  exitHandle = %p\n", FILE__, __LINE__, exitHandle);
		logerror("%s[%d]:  callsiteHandle = %p\n", FILE__, __LINE__, callsiteHandle);
		bpatch->removeUserEventCallback(test7cb);
		return FAILED;
	}
	if (debugPrint()) 
	{
		int one = 1;
		const char *varName = "libraryDebug";
		if (setVar(varName, (void *) &one, TESTNO, TESTNAME)) 
		{
			logerror("%s[%d]:  Error setting variable '%s' in mutatee\n", 
					FILE__, __LINE__, varName);
			bpatch->removeUserEventCallback(test7cb);
                        appProc->terminateExecution();
			return FAILED;
		}
	}

	dprintf("%s[%d]:  did instrumentation, continuing process...: %s\n", 
			__FILE__, __LINE__, libname);
	//  unset mutateeIdle to trigger mutatee to issue messages.

	int timeout = 0;

        appProc->continueExecution();

	dprintf("%s[%d]:  continued process...: %s\n", 
			__FILE__, __LINE__, libname);
	//  wait until we have received the desired number of events
	//  (or timeout happens)

	while(!test7err && !test7done && (timeout < TIMEOUT)) 
	{
		sleep_ms(SLEEP_INTERVAL/*ms*/);
		timeout += SLEEP_INTERVAL;
		bpatch->pollForStatusChange();

                if (appProc->isTerminated())
		{
			BPatch_exitType et = appProc->terminationStatus();
			if (et == ExitedNormally)
			{
				int ecode = appProc->getExitCode();
				logerror("%s[%d]:  normal exit with code %d\n",
						__FILE__, __LINE__, ecode);
			}
			if (et == ExitedViaSignal)
			{
				int ecode = appProc->getExitSignal();
				logerror("%s[%d]:  caught signal %d\n",
						__FILE__, __LINE__, ecode);
			}
			log_res();
			bpatch->removeUserEventCallback(test7cb);
			return FAILED;
		}
	}

	dprintf("%s[%d]:  after wait loop:  test7err = %s, test7done = %s, timeout = %d\n", 
			__FILE__, __LINE__, test7err ? "true" : "false", test7done ? "true" : "false", timeout);

	if (timeout >= TIMEOUT) 
	{
		FAIL_MES(TESTNAME, TESTDESC);
		logerror("%s[%d]:  test timed out: %d ms\n",
				__FILE__, __LINE__, TIMEOUT);
		test7err = true;
	}

	if (!appProc->stopExecution())
	{
		logerror("%s[%d]:  stopExecution failed\n",
				__FILE__, __LINE__);

	}

	dprintf("%s[%d]:  stopped process...\n", 
			__FILE__, __LINE__ );

	if (!bpatch->removeUserEventCallback(test7cb)) 
	{
		FAIL_MES(TESTNAME, TESTDESC);
		logerror("%s[%d]:  failed to remove callback\n",
				__FILE__, __LINE__);
		appProc->terminateExecution();
		log_res();
		return FAILED;
	}

	dprintf("%s[%d]:  removed callback...\n", 
			__FILE__, __LINE__ );
	if (!appProc->terminateExecution())
	{
		//  don't care
		//fprintf(stderr, "%s[%d]:  terminateExecution failed\n", FILE__, __LINE__);
		//return FAILED;
	}

#if 0
	int one = 1;

	if (setVar("test_callback_2_idle", (void *) &one, TESTNO, TESTNAME)) 
	{
		logerror("Error setting variable 'test_callback_2_idle' in mutatee\n");
		test7err = true;
		appProc->terminateExecution();
	}
#endif

#if 0
	// And let it run out
	if (!appThread->isTerminated()) 
	{
		appProc->continueExecution();
	}

	while (!appThread->isTerminated()) 
	{
		// Workaround for pgCC_high mutatee issue
		bpatch->waitForStatusChange();
	}
#endif

	if (!test7err) 
	{
		PASS_MES(TESTNAME, TESTDESC);
		return PASSED;
	}

	log_res();
	FAIL_MES(TESTNAME, TESTDESC);
	return FAILED;
}