MCPcopy Create free account
hub / github.com/aethersdr/AetherSDR / section5

Function section5

tests/rigctld_test.cpp:743–1068  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

741// ═════════════════════════════════════════════════════════════════════════════
742
743void section5(RigctlClient& c, Runner& r, qint64 origFreq)
744{
745 r.section(QStringLiteral("Section 5 — Split VFO"));
746 const qint64 splitTxFreq = origFreq + 1000;
747
748 // ── DAX-assign settle guard ──────────────────────────────────────────────
749 // Closing a TX slice we created on demand frees its SliceModel. If a deferred
750 // DAX-channel-assign timer is still pending — it's armed on sliceAdded when a
751 // DAX/TCI audio client is active, e.g. after WSJT-X has been used on this radio
752 // — it fires on the freed slice and crashes ASDR. A real client never creates
753 // and removes a split slice this fast; only this test does. So settle before
754 // every on-demand split teardown to let that timer fire on the LIVE slice
755 // first. (The underlying DAX-timer UAF is a separate, app-side issue.)
756 constexpr int kDaxSettleMs = 700;
757 const QString kSplitOff = QStringLiteral("\\set_split_vfo 0 VFOA");
758 auto disableSplitSettled = [&]() {
759 QThread::msleep(kDaxSettleMs);
760 return c.send(kSplitOff);
761 };
762
763 // Poll get_split_vfo until Split == want (or timeout); return the final value.
764 // Replaces the do/while poll loop that was hand-rolled at every split check.
765 auto waitForSplit = [&](QLatin1String want, int timeoutMs) -> QString {
766 QString s;
767 QElapsedTimer t; t.start();
768 do {
769 s = c.field(c.send(QStringLiteral("\\get_split_vfo")), QStringLiteral("Split"));
770 if (s == want || t.elapsed() >= timeoutMs) break;
771 QThread::msleep(150);
772 } while (true);
773 return s;
774 };
775 // Settle-disable split and confirm it reached the off state — the "known-off
776 // baseline" precondition several subtests need.
777 auto resetSplitOff = [&]() {
778 disableSplitSettled();
779 return waitForSplit(QLatin1String("0"), 2000) == QLatin1String("0");
780 };
781
782 // 5.1 baseline split state
783 QStringList lines = c.send(QStringLiteral("\\get_split_vfo"));
784 const QString splitVal = c.field(lines, QStringLiteral("Split"));
785 const QString txVfo = c.field(lines, QStringLiteral("TX VFO"));
786 r.check(QStringLiteral("5.1 get_split_vfo returns Split (0/1) and TX VFO fields"),
787 c.ok(lines)
788 && (splitVal == QLatin1String("0") || splitVal == QLatin1String("1"))
789 && (txVfo == QLatin1String("VFOA") || txVfo == QLatin1String("VFOB")),
790 QStringLiteral("Split=%1 TX VFO=%2").arg(splitVal, txVfo));
791
792 // 5.2 enable split
793 lines = c.send(QStringLiteral("\\set_split_vfo 1 VFOB"));
794 r.check(QStringLiteral("5.2 set_split_vfo 1 VFOB returns RPRT 0"), c.ok(lines));
795
796 // 5.3 poll until split is confirmed active (creating a new slice takes variable time)
797 const QString splitOn = waitForSplit(QLatin1String("1"), 5000);
798 r.check(QStringLiteral("5.3 get_split_vfo reports Split: 1 [needs 2 slices in GUI]"),
799 splitOn == QLatin1String("1"),
800 QStringLiteral("Split=%1 — open a second slice in AetherSDR if this fails")

Callers 1

mainFunction · 0.70

Calls 9

isIntFunction · 0.85
containsMethod · 0.80
sectionMethod · 0.45
sendMethod · 0.45
startMethod · 0.45
fieldMethod · 0.45
checkMethod · 0.45
okMethod · 0.45
skipMethod · 0.45

Tested by

no test coverage detected