chore: remove skeleton build mode and stub #ifdef scaffolding
Some checks failed
Build Linux Binaries / linux/amd64 (push) Has been cancelled
Build Linux Binaries / linux/arm64 (push) Has been cancelled

Drop the M0 no-deps skeleton preset and all VOICECAT_HAS_NET/AUDIO/OPUS/NS
guards that it required. Every subsystem is fully implemented; the stub
#else paths were dead code that added noise to every header and source file.

- CMakePresets.json: remove skeleton configure/build/test entries
- CMakeLists.txt (root/core/tests): remove VOICECAT_USE_VCPKG_DEPS option
  and guards; all targets now build unconditionally
- 17 C++ source files: unwrap HAS_* guards, delete stub #else blocks
- apm_processor.cpp: delete ApmPassthrough no-op class; create() always
  returns RnnoiseProcessor
- 18 test files: remove HAS_* guards and stub int main() skip bodies
- docs/building.md: remove skeleton from preset table and prose

VOICECAT_HAS_LOOPBACK (Windows WASAPI loopback platform gate) unchanged.
29/29 ctest green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 11:32:22 +01:00
parent 9a20953c08
commit 2c8178fa02
55 changed files with 25 additions and 675 deletions

View File

@@ -6,7 +6,6 @@ target_link_libraries(test_smoke PRIVATE voicecat::voicecat)
target_compile_features(test_smoke PRIVATE cxx_std_20)
add_test(NAME smoke COMMAND test_smoke)
# frame_codec has no third-party deps; runs under both skeleton and dev.
# Needs core/src on the include path to reach internal headers (protocol/, session/, etc.).
add_executable(test_frame_codec test_frame_codec.cpp)
target_link_libraries(test_frame_codec PRIVATE voicecat::voicecat)
@@ -14,8 +13,7 @@ target_compile_features(test_frame_codec PRIVATE cxx_std_20)
target_include_directories(test_frame_codec PRIVATE ${CMAKE_SOURCE_DIR}/core/src)
add_test(NAME frame_codec COMMAND test_frame_codec)
if(VOICECAT_USE_VCPKG_DEPS)
set(VC_TEST_INTERNAL_INCLUDES
set(VC_TEST_INTERNAL_INCLUDES
${CMAKE_SOURCE_DIR}/core/src
${CMAKE_SOURCE_DIR}/server/src
${CMAKE_BINARY_DIR}/core/generated) # protobuf-generated headers
@@ -247,4 +245,3 @@ if(VOICECAT_USE_VCPKG_DEPS)
target_include_directories(test_recv_noise_reduction PRIVATE ${VC_TEST_INTERNAL_INCLUDES})
add_test(NAME recv_noise_reduction COMMAND test_recv_noise_reduction)
set_tests_properties(recv_noise_reduction PROPERTIES TIMEOUT 90)
endif()

View File

@@ -14,8 +14,6 @@
*/
#include <cstdio>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <cmath>
@@ -309,12 +307,3 @@ int main() {
std::printf("channel_samplerate: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("channel_samplerate: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -21,8 +21,6 @@
*/
#include <cstdio>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -333,12 +331,3 @@ int main() {
std::printf("channel_user_list_abi: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("channel_user_list_abi: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -9,8 +9,6 @@
*/
#include <cstdio>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -210,12 +208,3 @@ int main() {
std::printf("disconnect_left: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("disconnect_left: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -9,8 +9,6 @@
*/
#include <cstdio>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -268,12 +266,3 @@ int main() {
std::printf("dred_toggle: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("dred_toggle: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -15,8 +15,6 @@
*/
#include <cstdio>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -445,12 +443,3 @@ int main() {
std::printf("external_pcm: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("external_pcm: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -17,8 +17,6 @@
*/
#include <cstdio>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <cmath>
@@ -318,12 +316,3 @@ int main() {
std::printf("frame_ms_reframe: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("frame_ms_reframe: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -10,8 +10,6 @@
#include <cstdio>
#include <cstring>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -255,12 +253,3 @@ int main() {
std::printf("m1_integration: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("m1_integration: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -14,8 +14,6 @@
#include <cstdio>
#include <cstring>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -53,9 +51,7 @@
#include "server.h"
#include "db.h"
#ifdef VOICECAT_HAS_OPUS
#include "codec/opus_codec.h"
#endif
using namespace voicecat;
using namespace voicecat::net;
@@ -441,7 +437,6 @@ int main() {
constexpr int kFramesToSend = 50;
constexpr int kFrameSamples = 960; // 20 ms @48 kHz
#ifdef VOICECAT_HAS_OPUS
voicecat::codec::OpusEncoder enc;
{
voicecat::codec::OpusParams p;
@@ -450,24 +445,17 @@ int main() {
p.fec = true;
CHECK(enc.init(p));
}
#endif
std::vector<uint8_t> aead_buf(4096); // scratch
for (int i = 0; i < kFramesToSend; ++i) {
auto pcm = make_sine_frame(i, kFrameSamples);
#ifdef VOICECAT_HAS_OPUS
uint8_t opus_buf[1000];
int opus_len = enc.encode(pcm.data(), kFrameSamples, opus_buf, sizeof(opus_buf));
if (opus_len <= 0) continue;
const uint8_t* payload = opus_buf;
size_t payload_len = static_cast<size_t>(opus_len);
#else
// Fallback: use raw PCM as synthetic payload
const uint8_t* payload = reinterpret_cast<const uint8_t*>(pcm.data());
size_t payload_len = pcm.size() * sizeof(int16_t);
#endif
// Build the voice frame header (AAD).
VoiceFrame hdr;
@@ -494,9 +482,7 @@ int main() {
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
#ifdef VOICECAT_HAS_OPUS
enc.destroy();
#endif
// ── B collects received frames (2s window after last send) ────────────────
int recv_count = 0, decrypt_ok = 0;
@@ -541,12 +527,3 @@ int main() {
std::printf("m2_voice: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("m2_voice: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -20,8 +20,6 @@
*/
#include <cstdio>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <cmath>
@@ -387,12 +385,3 @@ int main() {
std::printf("m3_multistream: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("m3_multistream: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -13,8 +13,6 @@
#include <cstdio>
#include <cstring>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -265,12 +263,3 @@ int main() {
std::printf("m5_admin_accounts: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("m5_admin_accounts: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -12,8 +12,6 @@
#include <cstdio>
#include <cstring>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -308,12 +306,3 @@ int main() {
std::printf("m5_channel_crud: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("m5_channel_crud: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -10,8 +10,6 @@
#include <cstdio>
#include <cstring>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -320,12 +318,3 @@ int main() {
std::printf("m5_kick_ban_move_mute: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("m5_kick_ban_move_mute: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -12,8 +12,6 @@
#include <cstdio>
#include <cstring>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -255,12 +253,3 @@ int main() {
std::printf("m5_permissions: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("m5_permissions: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -20,14 +20,6 @@ static int g_failures = 0;
++g_failures; \
}} while (0)
#ifndef VOICECAT_HAS_OPUS
int main() {
std::printf("opus_codec: VOICECAT_HAS_OPUS not defined — skipped\n");
return 0;
}
#else
static constexpr int kSampleRate = 48000;
static constexpr int kFrameMs = 20;
@@ -145,5 +137,3 @@ int main() {
std::printf("opus_codec: %d test(s) FAILED\n", g_failures);
return 1;
}
#endif // VOICECAT_HAS_OPUS

View File

@@ -13,8 +13,6 @@
*/
#include <cstdio>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -195,12 +193,3 @@ int main() {
std::printf("reaper_timeout: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("reaper_timeout: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -1,9 +1,8 @@
/*
* test_smoke — verifies the core links and the C ABI behaves as specified for M0.
* test_smoke — verifies the core links and the C ABI behaves as specified.
*
* This is intentionally a behavior test, not a "does it compile" check: it asserts the
* documented contract (version present, handle lifecycle, invalid-arg guards, and that
* unimplemented calls report VC_ERR_NOT_IMPLEMENTED rather than crashing).
* documented contract (version present, handle lifecycle, invalid-arg guards).
*/
#include <cstdio>
#include <cstring>
@@ -25,8 +24,6 @@ int main() {
CHECK(vc_version_string() != nullptr);
CHECK(std::strlen(vc_version_string()) > 0);
CHECK(std::strcmp(vc_result_string(VC_OK), "ok") == 0);
CHECK(std::strcmp(vc_result_string(VC_ERR_NOT_IMPLEMENTED), "not implemented") == 0);
// Null-config create is rejected; valid create yields a handle.
vc_callbacks cb{};
CHECK(vc_client_create(nullptr, cb) == nullptr);
@@ -43,34 +40,26 @@ int main() {
CHECK(vc_connect(c, nullptr, 1) == VC_ERR_INVALID_ARG);
CHECK(vc_send_text(c, VC_TEXT_CHANNEL, 0, nullptr) == VC_ERR_INVALID_ARG);
// Under skeleton preset: NOT_IMPLEMENTED. Under dev: VC_OK (async connect).
vc_result rc_connect = vc_connect(c, "127.0.0.1", 8384);
CHECK(rc_connect == VC_ERR_NOT_IMPLEMENTED || rc_connect == VC_OK);
CHECK(rc_connect == VC_OK);
// Auth before connected (or on a stub) → NOT_CONNECTED or NOT_IMPLEMENTED.
// Auth before connected → NOT_CONNECTED.
{
vc_config cfg2 = cfg;
vc_client* c2 = vc_client_create(&cfg2, cb);
vc_result rc_auth = vc_authenticate_guest(c2, "nick");
CHECK(rc_auth == VC_ERR_NOT_IMPLEMENTED || rc_auth == VC_ERR_NOT_CONNECTED);
CHECK(rc_auth == VC_ERR_NOT_CONNECTED);
vc_client_destroy(c2);
}
// join_channel before connected → NOT_CONNECTED or NOT_IMPLEMENTED.
// join_channel before connected → NOT_CONNECTED.
vc_result rc_join = vc_join_channel(c, 1, nullptr);
CHECK(rc_join == VC_ERR_NOT_IMPLEMENTED || rc_join == VC_ERR_NOT_CONNECTED);
CHECK(rc_join == VC_ERR_NOT_CONNECTED);
vc_device_list dl{};
vc_result rc_devices = vc_list_devices(c, VC_DEVICE_INPUT, &dl);
#ifdef VOICECAT_HAS_AUDIO
// Real device enumeration is wired up once miniaudio is linked in (post-M3 follow-up).
// Never assert count > 0 here — a headless CI build agent may legitimately report zero
// audio devices; only that the call itself succeeded.
// Never assert count > 0 — a headless CI agent may report zero audio devices.
CHECK(rc_devices == VC_OK);
#else
CHECK(rc_devices == VC_ERR_NOT_IMPLEMENTED);
CHECK(dl.count == 0);
#endif
vc_free_device_list(&dl);
vc_client_destroy(c);

View File

@@ -19,8 +19,6 @@
*/
#include <cstdio>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -374,12 +372,3 @@ int main() {
std::printf("tofu_flow: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("tofu_flow: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -18,8 +18,6 @@
*/
#include <cstdio>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <cmath>
@@ -35,12 +33,8 @@
#include "server.h"
#include "db.h"
#ifdef VOICECAT_HAS_AUDIO
#include "audio/audio_engine.h"
#endif
#ifdef VOICECAT_HAS_OPUS
#include "codec/opus_codec.h"
#endif
// ── Event tracking (same shape as test_m3_multistream.cpp) ──────────────────────
@@ -159,7 +153,6 @@ static void test_device_enumeration() {
for (vc_device_kind kind : {VC_DEVICE_INPUT, VC_DEVICE_OUTPUT}) {
vc_device_list dl{};
vc_result r = vc_list_devices(c, kind, &dl);
#ifdef VOICECAT_HAS_AUDIO
CHECK(r == VC_OK);
// Headless CI build agents may legitimately report zero devices — never assert
// count > 0, only that the call itself succeeded and the list is well-formed.
@@ -167,9 +160,6 @@ static void test_device_enumeration() {
CHECK(dl.items[i].id != nullptr);
CHECK(dl.items[i].name != nullptr);
}
#else
CHECK(r == VC_ERR_NOT_IMPLEMENTED);
#endif
vc_free_device_list(&dl);
vc_free_device_list(&dl); // idempotent — must not crash on a second call
}
@@ -179,7 +169,6 @@ static void test_device_enumeration() {
}
// ── 4. Stereo playback mixer (white-box, no audio hardware needed) ──────────────
#if defined(VOICECAT_HAS_AUDIO) && defined(VOICECAT_HAS_OPUS)
static void test_stereo_mix() {
voicecat::audio::AudioEngine engine;
voicecat::audio::AudioParams p;
@@ -245,7 +234,7 @@ static void test_stereo_mix() {
// and mixes — asserting L != R across the frame. A mono-downmixed-then-upmixed bitstream would
// have L == R. Mirrors test_stereo_mix but routes the encode side through the loopback
// accumulator path that the fix touches (feed_loopback_for_test → on_loopback's accumulator).
#if defined(VOICECAT_HAS_LOOPBACK) && defined(VOICECAT_HAS_OPUS)
#if defined(VOICECAT_HAS_LOOPBACK)
static void test_loopback_stereo_capture() {
voicecat::audio::AudioEngine engine;
voicecat::audio::AudioParams p;
@@ -382,14 +371,12 @@ static void test_playout_resync() {
engine.stop();
std::printf("test_playout_resync: ok (energy=%lld)\n", static_cast<long long>(energy));
}
#endif // VOICECAT_HAS_AUDIO && VOICECAT_HAS_OPUS
// ── 5. Capture-frame accumulation (white-box, no audio hardware needed) ──────────
// Regression for the capture-side analogue of the playback ring fix: miniaudio's capture
// callback fires at the hardware period (commonly 480 samples on WASAPI shared mode), while
// opus_encode() requires exactly frame_samples_ (960). Sub-frame chunks must be accumulated;
// the callback must receive exactly 960-sample frames regardless of input chunk size.
#ifdef VOICECAT_HAS_AUDIO
static void test_capture_frame_accumulation() {
voicecat::audio::AudioEngine engine;
voicecat::audio::AudioParams p;
@@ -436,7 +423,6 @@ static void test_capture_frame_accumulation() {
engine.stop();
std::printf("test_capture_frame_accumulation: ok (callbacks=%d)\n", call_count.load());
}
#endif // VOICECAT_HAS_AUDIO
// ── 2/3. VAD + PTT gate, through the real ABI against a real server ─────────────
static void test_vad_and_ptt_gate() {
@@ -601,7 +587,6 @@ static void test_vad_and_ptt_gate() {
// downmix). Mirrors test_loopback_stereo_capture but routes through the mic capture
// accumulator (feed_capture_for_test with channels=2) instead of the loopback path.
// This is the headless CI test for the iOS stereo built-in mic feature (Part D).
#if defined(VOICECAT_HAS_AUDIO) && defined(VOICECAT_HAS_OPUS)
static void test_stereo_mic_capture() {
voicecat::audio::AudioEngine engine;
voicecat::audio::AudioParams p;
@@ -674,7 +659,6 @@ static void test_stereo_mic_capture() {
std::printf("test_stereo_mic_capture: ok (total_diff=%lld, seen_channels=%d)\n",
static_cast<long long>(total_diff), seen_channels);
}
#endif
// ── 6. Stereo mic capture on a MONO channel (downmix safety) ──────────────────
// A stereo mic (vc_set_capture_channels=2) can be enabled while on a mono channel. The mic
@@ -683,7 +667,6 @@ static void test_stereo_mic_capture() {
// opus_encode makes it read 2× the samples it should (wrong pitch / garbage). This mirrors that
// fold and proves the result is a valid mono bitstream that decodes to the expected averaged
// signal, rather than half-length junk.
#if defined(VOICECAT_HAS_AUDIO) && defined(VOICECAT_HAS_OPUS)
static void test_stereo_mic_mono_channel() {
voicecat::codec::OpusParams mono_params;
mono_params.stereo = false; // mono channel — encoder is mono
@@ -727,11 +710,9 @@ static void test_stereo_mic_mono_channel() {
std::printf("test_stereo_mic_mono_channel: ok (opus_len=%d, energy=%lld)\n",
opus_len, static_cast<long long>(energy));
}
#endif
int main() {
test_device_enumeration();
#if defined(VOICECAT_HAS_AUDIO) && defined(VOICECAT_HAS_OPUS)
test_stereo_mix();
#if defined(VOICECAT_HAS_LOOPBACK)
test_loopback_stereo_capture();
@@ -739,10 +720,7 @@ int main() {
test_stereo_mic_capture();
test_stereo_mic_mono_channel();
test_playout_resync();
#endif
#ifdef VOICECAT_HAS_AUDIO
test_capture_frame_accumulation();
#endif
test_vad_and_ptt_gate();
if (g_failures == 0) {
@@ -752,12 +730,3 @@ int main() {
std::printf("vad_ptt_devices: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("vad_ptt_devices: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET

View File

@@ -9,8 +9,6 @@
*/
#include <cstdio>
#ifdef VOICECAT_HAS_NET
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -253,12 +251,3 @@ int main() {
std::printf("voice_client_abi: %d failure(s)\n", g_failures);
return 1;
}
#else // !VOICECAT_HAS_NET
int main() {
std::printf("voice_client_abi: SKIP (VOICECAT_HAS_NET not defined)\n");
return 0;
}
#endif // VOICECAT_HAS_NET