Debug and fixing of unit tests (#1023)
* Add tooling to enable debugging of hung tests.
* Force rebuild.
* Revert "Force rebuild."
This reverts commit 6f13e7382b.
* Add five minute timeout for unit tests.
* Fix max time calculation and increase to 10mins.
* Increase timeout to 20 minutes.
* We were actually calculating the counter wrong.
* Use atomics for UT related globals.
* Force build for more testing.
* Revert README change.
* Add retry logic for hdiutil due to known bugs.
* Encode EOO as a single unit.
* Revert GitHub debugging.
* Add PR #1023 to changelog.
ms-hamlib-465
parent
955985f66e
commit
6dbb3b7f8f
|
|
@ -849,6 +849,7 @@ LDPC | Low Density Parity Check Codes - a family of powerful FEC codes
|
|||
* macOS: Fix spurious error on startup when changing locales. (PR #1010)
|
||||
* Prevent lockup/crash when testing Hamlib in PTT Config window. (PR #1016)
|
||||
* Linux: fix rendering bug for mic/speaker slider when transitioning from TX to RX. (PR #1021)
|
||||
* Various unit test fixes to reduce failure rate in CI environment. (PR #1023)
|
||||
2. Enhancements:
|
||||
* Add Mic/Speaker volume control to main window. (PR #980)
|
||||
* Move less used Spectrum plot configuration to free up space on main window. (PR #996)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
#! /bin/bash
|
||||
# Simple Utility Script for allowing debug of hardened macOS apps.
|
||||
# This is useful mostly for plug-in developer that would like keep developing without turning SIP off.
|
||||
# Credit for idea goes to (McMartin): https://forum.juce.com/t/apple-gatekeeper-notarised-distributables/29952/57?u=ttg
|
||||
# Update 2022-03-10: Based on Fabian's feedback, add capability to inject DYLD for sanitizers.
|
||||
#
|
||||
# Please note:
|
||||
# - Modern Logic (on M1s) uses `AUHostingService` which resides within the system thus not patchable and REQUIRES to turn-off SIP.
|
||||
# - Some hosts uses separate plug-in scanning or sandboxing.
|
||||
# if that's the case, it's required to patch those (if needed) and attach debugger to them instead.
|
||||
#
|
||||
# If you see `operation not permitted`, make sure the calling process has Full Disk Access.
|
||||
# For example Terminal.app is showing and has Full Disk Access under System Preferences -> Privacy & Security
|
||||
#
|
||||
app_path=$1
|
||||
|
||||
if [ -z "$app_path" ];
|
||||
then
|
||||
echo "You need to specify app to re-codesign!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# This uses local codesign. so it'll be valid ONLY on the machine you've re-signed with.
|
||||
entitlements_plist=/tmp/debug_entitlements.plist
|
||||
echo "Grabbing entitlements from app..."
|
||||
codesign -d --entitlements - "$app_path" --xml >> $entitlements_plist || { exit 1; }
|
||||
echo "Patch entitlements (if missing)..."
|
||||
/usr/libexec/PlistBuddy -c "Add :com.apple.security.cs.disable-library-validation bool true" $entitlements_plist
|
||||
/usr/libexec/PlistBuddy -c "Add :com.apple.security.cs.allow-unsigned-executable-memory bool true" $entitlements_plist
|
||||
/usr/libexec/PlistBuddy -c "Add :com.apple.security.get-task-allow bool true" $entitlements_plist
|
||||
# allow custom dyld for sanitizers...
|
||||
/usr/libexec/PlistBuddy -c "Add :com.apple.security.cs.allow-dyld-environment-variables bool true" $entitlements_plist
|
||||
echo "Re-applying entitlements (if missing)..."
|
||||
codesign --force --options runtime --sign - --entitlements $entitlements_plist "$app_path" || { echo "codesign failed!"; }
|
||||
echo "Removing temporary plist..."
|
||||
rm $entitlements_plist
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
#!/bin/sh
|
||||
|
||||
SOURCE_FOLDER=$1
|
||||
|
||||
# Note: retry logic from https://github.com/darktable-org/darktable/pull/16394/files
|
||||
|
||||
# When building on github runner, 'hdiutil create' occasionally fails (resource busy)
|
||||
# so we make several retries
|
||||
try_count=0
|
||||
hdiutil_success=0
|
||||
|
||||
while [ $hdiutil_success -ne 1 -a $try_count -lt 8 ]; do
|
||||
# Create temporary rw image
|
||||
if hdiutil create -srcfolder $SOURCE_FOLDER/ -volname FreeDV -format UDZO -fs HFS+ ./FreeDV.dmg
|
||||
then
|
||||
hdiutil_success=1
|
||||
break
|
||||
fi
|
||||
try_count=$(( $try_count + 1 ))
|
||||
echo "'hdiutil create' failed (attempt ${try_count}). Retrying..."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [ $hdiutil_success -ne 1 -a -n "${GITHUB_RUN_ID}" ]; then
|
||||
# Still no success after 8 attempts.
|
||||
# If we are on github runner, kill the Xprotect service and make one
|
||||
# final attempt.
|
||||
# see https://github.com/actions/runner-images/issues/7522
|
||||
echo "Killing XProtect..."
|
||||
sudo pkill -9 XProtect >/dev/null || true;
|
||||
sleep 3
|
||||
|
||||
if hdiutil create -srcfolder $SOURCE_FOLDER/ -volname FreeDV -format UDZO -fs HFS+ ./FreeDV.dmg
|
||||
then
|
||||
hdiutil_success=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $hdiutil_success -ne 1 ]; then
|
||||
echo "FATAL: 'hdiutil create' FAILED!"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -168,14 +168,14 @@ if(APPLE)
|
|||
COMMAND xcrun stapler staple ./FreeDV.app
|
||||
COMMAND mkdir dist_tmp
|
||||
COMMAND cp -a FreeDV.app dist_tmp
|
||||
COMMAND hdiutil create -srcfolder dist_tmp/ -volname FreeDV -format UDZO -fs HFS+ ./FreeDV.dmg
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/cmake/macos_build_dmg.sh dist_tmp/
|
||||
COMMAND rm -rf dist_tmp
|
||||
DEPENDS FreeDV)
|
||||
else(MACOS_CODESIGN_KEYCHAIN_PROFILE)
|
||||
add_custom_target(release
|
||||
COMMAND mkdir dist_tmp
|
||||
COMMAND cp -a FreeDV.app dist_tmp
|
||||
COMMAND hdiutil create -srcfolder dist_tmp/ -volname FreeDV -format UDZO -fs HFS+ ./FreeDV.dmg
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/cmake/macos_build_dmg.sh dist_tmp/
|
||||
COMMAND rm -rf dist_tmp
|
||||
DEPENDS FreeDV)
|
||||
endif (MACOS_CODESIGN_KEYCHAIN_PROFILE)
|
||||
|
|
|
|||
23
src/main.cpp
23
src/main.cpp
|
|
@ -150,7 +150,7 @@ int g_AEstatus2[4];
|
|||
// playing and recording from sound files
|
||||
|
||||
extern SNDFILE *g_sfPlayFile;
|
||||
extern bool g_playFileToMicIn;
|
||||
extern std::atomic<bool> g_playFileToMicIn;
|
||||
extern bool g_loopPlayFileToMicIn;
|
||||
extern int g_playFileToMicInEventId;
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ extern unsigned int g_recFromRadioSamples;
|
|||
extern int g_recFileFromRadioEventId;
|
||||
|
||||
extern SNDFILE *g_sfPlayFileFromRadio;
|
||||
extern bool g_playFileFromRadio;
|
||||
extern std::atomic<bool> g_playFileFromRadio;
|
||||
extern int g_sfFs;
|
||||
extern int g_sfTxFs;
|
||||
extern bool g_loopPlayFileFromRadio;
|
||||
|
|
@ -335,6 +335,7 @@ void MainApp::UnitTest_()
|
|||
std::this_thread::sleep_for(20ms);
|
||||
}
|
||||
|
||||
constexpr int MAX_TIME_AS_COUNTER = 12000; // 20 minutes
|
||||
if (testName == "tx")
|
||||
{
|
||||
log_info("Transmitting %d times", utTxAttempts);
|
||||
|
|
@ -361,9 +362,10 @@ void MainApp::UnitTest_()
|
|||
g_sfPlayFile = sf_open((const char*)utTxFile.ToUTF8(), SFM_READ, &sfInfo);
|
||||
g_sfTxFs = sfInfo.samplerate;
|
||||
g_loopPlayFileToMicIn = false;
|
||||
g_playFileToMicIn = true;
|
||||
g_playFileToMicIn.store(true, std::memory_order_release);
|
||||
|
||||
while (g_playFileToMicIn)
|
||||
int counter = 0;
|
||||
while (g_playFileToMicIn.load(std::memory_order_acquire) && (counter++) < MAX_TIME_AS_COUNTER)
|
||||
{
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
|
|
@ -403,10 +405,11 @@ void MainApp::UnitTest_()
|
|||
g_sfPlayFileFromRadio = sf_open((const char*)utRxFile.ToUTF8(), SFM_READ, &sfInfo);
|
||||
g_sfFs = sfInfo.samplerate;
|
||||
g_loopPlayFileFromRadio = false;
|
||||
g_playFileFromRadio = true;
|
||||
g_playFileFromRadio.store(true, std::memory_order_release);
|
||||
|
||||
auto sync = 0;
|
||||
while (g_playFileFromRadio)
|
||||
int counter = 0;
|
||||
while (g_playFileFromRadio.load(std::memory_order_acquire) && (counter++) < MAX_TIME_AS_COUNTER)
|
||||
{
|
||||
std::this_thread::sleep_for(100ms);
|
||||
auto newSync = freedvInterface.getSync();
|
||||
|
|
@ -1151,14 +1154,14 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent, wxID_ANY, _("FreeDV ")
|
|||
#endif //_USE_ONIDLE
|
||||
|
||||
g_sfPlayFile = NULL;
|
||||
g_playFileToMicIn = false;
|
||||
g_playFileToMicIn.store(false, std::memory_order_release);
|
||||
g_loopPlayFileToMicIn = false;
|
||||
|
||||
g_sfRecFile = NULL;
|
||||
g_recFileFromRadio = false;
|
||||
|
||||
g_sfPlayFileFromRadio = NULL;
|
||||
g_playFileFromRadio = false;
|
||||
g_playFileFromRadio.store(false, std::memory_order_release);
|
||||
g_loopPlayFileFromRadio = false;
|
||||
|
||||
g_sfRecFileFromModulator = NULL;
|
||||
|
|
@ -1799,7 +1802,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
|
|||
pendingSnr,
|
||||
freqLongLong);
|
||||
|
||||
if (!g_playFileFromRadio)
|
||||
if (!g_playFileFromRadio.load(std::memory_order_acquire))
|
||||
{
|
||||
for (auto& obj : wxGetApp().m_reporters)
|
||||
{
|
||||
|
|
@ -1828,7 +1831,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
|
|||
if (freq > 0 && wxGetApp().m_reportCounter == 0)
|
||||
{
|
||||
wxGetApp().m_reportCounter = 0;
|
||||
if (!g_playFileFromRadio)
|
||||
if (!g_playFileFromRadio.load(std::memory_order_acquire))
|
||||
{
|
||||
wxGetApp().m_sharedReporterObject->addReceiveRecord(
|
||||
"",
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ short* RADETransmitStep::execute(short* inputSamples, int numInputSamples, int*
|
|||
if (numInputSamples == 0)
|
||||
{
|
||||
// Special case logic for EOO
|
||||
*numOutputSamples = std::min(outputSampleFifo_.numUsed(), (FRAME_DURATION_MS * getOutputSampleRate()) / MS_TO_SEC);
|
||||
*numOutputSamples = outputSampleFifo_.numUsed();
|
||||
if (*numOutputSamples > 0)
|
||||
{
|
||||
outputSampleFifo_.read(outputSamples_.get(), *numOutputSamples);
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ extern std::atomic<bool> g_half_duplex;
|
|||
extern std::atomic<int> g_tx;
|
||||
extern int g_dump_fifo_state;
|
||||
extern bool endingTx;
|
||||
extern bool g_playFileToMicIn;
|
||||
extern std::atomic<bool> g_playFileToMicIn;
|
||||
extern int g_sfTxFs;
|
||||
extern bool g_loopPlayFileToMicIn;
|
||||
extern float g_TxFreqOffsetHz;
|
||||
|
|
@ -88,7 +88,7 @@ extern bool g_queueResync;
|
|||
extern int g_resyncs;
|
||||
extern bool g_recFileFromRadio;
|
||||
extern unsigned int g_recFromRadioSamples;
|
||||
extern bool g_playFileFromRadio;
|
||||
extern std::atomic<bool> g_playFileFromRadio;
|
||||
extern int g_sfFs;
|
||||
extern bool g_loopPlayFileFromRadio;
|
||||
extern int g_SquelchActive;
|
||||
|
|
@ -166,7 +166,7 @@ void TxRxThread::initializePipeline_()
|
|||
auto playMicIn = new PlaybackStep(
|
||||
inputSampleRate_,
|
||||
[]() { return g_sfTxFs; },
|
||||
[]() { return g_playFileToMicIn ? g_sfPlayFile : nullptr; },
|
||||
[]() { return g_playFileToMicIn.load(std::memory_order_acquire) ? g_sfPlayFile : nullptr; },
|
||||
[]() {
|
||||
if (g_loopPlayFileToMicIn)
|
||||
sf_seek(g_sfPlayFile, 0, SEEK_SET);
|
||||
|
|
@ -179,7 +179,7 @@ void TxRxThread::initializePipeline_()
|
|||
eitherOrPlayMicIn->appendPipelineStep(playMicIn);
|
||||
|
||||
auto eitherOrPlayStep = new EitherOrStep(
|
||||
[]() { return g_playFileToMicIn && (g_sfPlayFile != NULL); },
|
||||
[]() { return g_playFileToMicIn.load(std::memory_order_acquire) && (g_sfPlayFile != NULL); },
|
||||
eitherOrPlayMicIn,
|
||||
eitherOrBypassPlay);
|
||||
pipeline_->appendPipelineStep(eitherOrPlayStep);
|
||||
|
|
@ -325,7 +325,7 @@ void TxRxThread::initializePipeline_()
|
|||
|
||||
auto eitherOrPlayRadioStep = new EitherOrStep(
|
||||
[]() {
|
||||
auto result = g_playFileFromRadio && (g_sfPlayFileFromRadio != NULL);
|
||||
auto result = g_playFileFromRadio.load(std::memory_order_acquire) && (g_sfPlayFileFromRadio != NULL);
|
||||
return result;
|
||||
},
|
||||
eitherOrPlayRadio,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
extern wxMutex g_mutexProtectingCallbackData;
|
||||
SNDFILE *g_sfPlayFile;
|
||||
bool g_playFileToMicIn;
|
||||
std::atomic<bool> g_playFileToMicIn;
|
||||
bool g_loopPlayFileToMicIn;
|
||||
int g_playFileToMicInEventId;
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ SNDFILE *g_sfRecMicFile;
|
|||
bool g_recFileFromMic;
|
||||
|
||||
SNDFILE *g_sfPlayFileFromRadio;
|
||||
bool g_playFileFromRadio;
|
||||
std::atomic<bool> g_playFileFromRadio;
|
||||
int g_sfFs;
|
||||
int g_sfTxFs;
|
||||
bool g_loopPlayFileFromRadio;
|
||||
|
|
@ -57,9 +57,9 @@ static wxWindow* createMyExtraPlayFilePanel(wxWindow *parent)
|
|||
void MainFrame::StopPlayFileToMicIn(void)
|
||||
{
|
||||
g_mutexProtectingCallbackData.Lock();
|
||||
if (g_playFileToMicIn)
|
||||
if (g_playFileToMicIn.load(std::memory_order_acquire))
|
||||
{
|
||||
g_playFileToMicIn = false;
|
||||
g_playFileToMicIn.store(false, std::memory_order_release);
|
||||
sf_close(g_sfPlayFile);
|
||||
g_sfPlayFile = nullptr;
|
||||
SetStatusText(wxT(""));
|
||||
|
|
@ -71,7 +71,7 @@ void MainFrame::StopPlayFileToMicIn(void)
|
|||
void MainFrame::StopPlaybackFileFromRadio()
|
||||
{
|
||||
g_mutexProtectingCallbackData.Lock();
|
||||
g_playFileFromRadio = false;
|
||||
g_playFileFromRadio.store(false, std::memory_order_release);
|
||||
sf_close(g_sfPlayFileFromRadio);
|
||||
g_sfPlayFileFromRadio = nullptr;
|
||||
SetStatusText(wxT(""));
|
||||
|
|
@ -88,8 +88,8 @@ void MainFrame::OnPlayFileFromRadio(wxCommandEvent& event)
|
|||
{
|
||||
wxUnusedVar(event);
|
||||
|
||||
log_debug("OnPlayFileFromRadio:: %d", (int)g_playFileFromRadio);
|
||||
if (g_playFileFromRadio)
|
||||
log_debug("OnPlayFileFromRadio:: %d", (int)g_playFileFromRadio.load(std::memory_order_acquire));
|
||||
if (g_playFileFromRadio.load(std::memory_order_acquire))
|
||||
{
|
||||
log_debug("OnPlayFileFromRadio:: Stop");
|
||||
StopPlaybackFileFromRadio();
|
||||
|
|
@ -161,7 +161,7 @@ void MainFrame::OnPlayFileFromRadio(wxCommandEvent& event)
|
|||
SetStatusText(statusText, 0);
|
||||
log_debug("OnPlayFileFromRadio:: Playing File Fs = %d", (int)sfInfo.samplerate);
|
||||
m_menuItemPlayFileFromRadio->SetItemLabel(wxString(_("Stop Play File - From Radio...")));
|
||||
g_playFileFromRadio = true;
|
||||
g_playFileFromRadio.store(true, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ void MainFrame::OnSetMonitorVKAudioVol( wxCommandEvent& event )
|
|||
}
|
||||
|
||||
extern SNDFILE *g_sfPlayFile;
|
||||
extern bool g_playFileToMicIn;
|
||||
extern std::atomic<bool> g_playFileToMicIn;
|
||||
extern bool g_loopPlayFileToMicIn;
|
||||
extern FreeDVInterface freedvInterface;
|
||||
extern int g_sfTxFs;
|
||||
|
|
@ -239,7 +239,7 @@ int MainFrame::VoiceKeyerStartTx(void)
|
|||
|
||||
SetStatusText(wxT("Voice Keyer: Playing file ") + wxString::FromUTF8(vkFileName_.c_str()) + wxT(" to mic input") , 0);
|
||||
g_loopPlayFileToMicIn = false;
|
||||
g_playFileToMicIn = true;
|
||||
g_playFileToMicIn.store(true, std::memory_order_release);
|
||||
|
||||
m_btnTogPTT->SetValue(true); togglePTT();
|
||||
next_state = VK_TX;
|
||||
|
|
|
|||
Loading…
Reference in New Issue