wxthread unit test synchronization.

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
rafae11
Experienced Solver
Experienced Solver
Posts: 85
Joined: Sat Jun 02, 2012 8:41 am

wxthread unit test synchronization.

Post by rafae11 » Wed Jul 04, 2018 11:07 am

I am trying to rewrite the unit test below so that it waits for the thread to finish and carry on the next test without a specified sleep time.
I was told to make the thread joinable, and remove the sleep.

I am currently struggling to synchronize the thread with the test suite. the program always crashes on CloseConnection(std::string("closing comports\n"));
because the thread is trying to post an event while the test has already moved on.

I was also advised to put a mutex, or a semaphore.
Would the mutex be a member of the test fixture or the thread?

Code: Select all

TEST_F(UserInterfaceTest, DownloadConfigurationVersion9)
{
	downloadconfigurationresponse = Response::GetDownloadConfigurationVersion9Response();

	downloadconfigurationcommand = commands.DownloadConfiguration(9);

	EXPECT_CALL(*m_View, SetNoteBookSelection(Display::SurveyPanel));
	EXPECT_CALL(*m_View, SaveFilePathDialog()).WillOnce(Return(wxID_OK));

	std::string val("C:\\Temp\\version9.bin");
	EXPECT_CALL(*m_View, GetSavePath()).WillOnce(Return(val));

	EXPECT_CALL(*m_Param, SetFunction(download_config));
	EXPECT_CALL(*m_Param, SetPathName(_));
	EXPECT_CALL(*m_Param, SetSurveyTimes(_));
	EXPECT_CALL(*m_Param, SetSurveyDelay(_));

	EXPECT_CALL(*m_Param, GetFunction()).WillOnce(Return(download_config));
	EXPECT_CALL(*m_Param, GetPathName()).WillOnce(Return(val));
	EXPECT_CALL(*m_Param, GetSurveyTimes()).WillOnce(Return(1));
	EXPECT_CALL(*m_Param, GetSurveyDelay()).WillOnce(Return(20));

	EXPECT_CALL(*m_View, CheckInstance(_, _));
	EXPECT_CALL(*m_View, GetSerialPortInstance()).WillRepeatedly(ReturnRef(serialport));
	EXPECT_CALL(*m_View, GetSerialPortAddress()).WillOnce(Return(port));

	EXPECT_CALL(*m_View, CustomEventDisplayData(_)).Times(AtLeast(1));

	EXPECT_CALL(serialport, Read(_))
		.WillOnce(DoAll(SetArgReferee<0>(downloadconfigurationresponse), Return(0)));

	EXPECT_CALL(masserialport, Write(_))
		.WillOnce(DoAll(SetArgReferee<0>(downloadconfigurationcommand), Return(0)));

	EXPECT_EQ(wxTHREAD_NO_ERROR, m_Controller->DownloadConfiguration());
	
	Sleep(1000);
	
}

Code: Select all

	CCThread(Iwxframeview* Parent,
				  Iserial& Serial,
			IAdditionalParameters* AdditionalParameters)
		: wxThread(wxTHREAD_JOINABLE),
		  m_Serial(Serial),
		  m_AdditionalParameters(AdditionalParameters)

	{
		m_Parent = Parent;											// associated frame.
		m_Function = m_AdditionalParameters->GetFunction();			// function to be called		
		m_PathName = m_AdditionalParameters->GetPathName();			//pathname to download file.
		m_SurveyTime = m_AdditionalParameters->GetSurveyTimes();		// number of times to take survey
		m_SurveyDelay = m_AdditionalParameters->GetSurveyDelay();	// delay in seconds
	}
How do i make the test wait for this code to finish executing.

Code: Select all

wxThread::ExitCode CCThread::Entry()
{
	if (m_Function == download_config)
	{

		DownloadConfig(m_PathName);

		// program always crashes here without the Sleep.
		CloseConnection(std::string("closing comports\n"));

		return 0;
	}
}
I think i got it working now. Is this the correct approach?
I created a semaphore at the controller class which creates the thread.
I call semaphore.wait() in the unit test and call semaphore.post inside the thread.

Code: Select all

public:
	CCThread(Iwxframeview* Parent,
		Iserial& Serial,
		IAdditionalParameters* AdditionalParameters,
		wxSemaphore* Semaphore)

		: wxThread(wxTHREAD_JOINABLE),
		  m_Serial(Serial),
		  m_AdditionalParameters(AdditionalParameters),
		  m_Semaphore(Semaphore)

	{
		m_Parent = Parent;											// associated frame.
		m_Function = m_AdditionalParameters->GetFunction();			// function to be called		
		m_PathName = m_AdditionalParameters->GetPathName();			//pathname to download file.
		m_SurveyTime = m_AdditionalParameters->GetSurveyTimes();		// number of times to take survey
		m_SurveyDelay = m_AdditionalParameters->GetSurveyDelay();	// delay in seconds
	}

Code: Select all

wxThread::ExitCode CCThread::Entry()
{
	if (m_Function == download_config)
	{

		DownloadConfig(m_PathName);

		CloseConnection(std::string("closing comports\n"));

		m_Semaphore->Post();

		return 0;
	}
}

Code: Select all

TEST_F(UserInterfaceTest, DownloadConfiguration)
{
       EXPECT_EQ(wxTHREAD_NO_ERROR, m_Controller->DownloadConfiguration());
	m_Controller->GetSemaphore()->Wait();
}

Post Reply