Test stream audio toggles and viewer scoped radio suppression
This commit is contained in:
1 parent
2a572af2bb
commit
559d66ae20
2 files changed
+88
-4
No files matched your search
@@ -9,6 +9,7 @@
|
||||
#include "../src/stream/stream.h"
|
||||
#include "../src/stream/stream_member.h"
|
||||
#include "../src/stream/stream_priv.h"
|
||||
#include "../src/radio/radio.h"
|
||||
#include "../src/chat/chat_core.h"
|
||||
#include "../src/chat/merkle_tree.h"
|
||||
#include "../src/routing_layer/topo_node_sqlite.h"
|
||||
@@ -1011,7 +1012,7 @@ static void test_profile_atomicity(void) {
|
||||
uint64_t before_version, after_version;
|
||||
profile(0, GROUP1, before, before_signature, &before_version); root_hash(0, GROUP1, before_hash);
|
||||
memset(huge, 'p', MS_USERINFO_MAX); huge[MS_USERINFO_MAX] = 0;
|
||||
struct chat_profile_option options[] = {{"stream_source", "0000000000000001:8:2:1189"}, {"stream_subscriptions", huge}};
|
||||
struct chat_profile_option options[] = {{"stream_source", "0000000000000001:8:2:1189:0"}, {"stream_subscriptions", huge}};
|
||||
CHECK(chat_core_set_my_profile_options(nodes[0], "710001", options, 2) < 0);
|
||||
profile(0, GROUP1, after, after_signature, &after_version); root_hash(0, GROUP1, after_hash);
|
||||
CHECK(!strcmp(before, after) && before_version == after_version && !memcmp(before_signature, after_signature, 64));
|
||||
@@ -1385,21 +1386,22 @@ static void test_supernode_relay(void) {
|
||||
/* Канонический список исключает неоднозначные IDs, дубли и обрезание значений. */
|
||||
static void test_member_format(void) {
|
||||
struct stream_member_state state = {.source = {.group_id = GROUP1, .source_node_id = 1, .source_epoch = 2,
|
||||
.n = 8, .r = 2, .block_size = STREAM_RS_DEFAULT_SIZE}, .published = 1, .count = 2,
|
||||
.n = 8, .r = 2, .block_size = STREAM_RS_DEFAULT_SIZE}, .published = 1, .audio_enabled = 1, .count = 2,
|
||||
.subscriptions = {{1, 2}, {UINT64_MAX, UINT64_MAX, 1}}};
|
||||
char source[MS_USERINFO_MAX + 1], subscriptions[MS_USERINFO_MAX + 1], json[2 * MS_USERINFO_MAX + 64];
|
||||
CHECK(stream_member_format(&state, source, subscriptions) == STREAM_OK);
|
||||
snprintf(json, sizeof(json), "{\"stream_source\":\"%s\",\"stream_subscriptions\":\"%s\"}", source, subscriptions);
|
||||
struct stream_member_state parsed;
|
||||
CHECK(stream_member_parse(GROUP1, 1, json, &parsed) == STREAM_OK);
|
||||
CHECK(parsed.published && parsed.source.source_epoch == 2 && parsed.count == 2);
|
||||
CHECK(parsed.published && parsed.audio_enabled && parsed.source.source_epoch == 2 && parsed.count == 2);
|
||||
CHECK(parsed.subscriptions[1].source_node_id == UINT64_MAX && parsed.subscriptions[1].source_epoch == UINT64_MAX);
|
||||
CHECK(!parsed.subscriptions[0].relay_only && parsed.subscriptions[1].relay_only);
|
||||
const char *bad[] = {
|
||||
"{\"stream_subscriptions\":\"1:2\"}",
|
||||
"{\"stream_subscriptions\":\"0000000000000001:0000000000000002,\"}",
|
||||
"{\"stream_subscriptions\":\"0000000000000001:0000000000000002,0000000000000001:0000000000000002\"}",
|
||||
"{\"stream_source\":\"0000000000000002:256:2:1189\"}",
|
||||
"{\"stream_source\":\"0000000000000002:256:2:1189:1\"}",
|
||||
"{\"stream_source\":\"0000000000000002:8:2:1189:2\",\"stream_subscriptions\":\"0000000000000001:0000000000000002\"}",
|
||||
"{\"stream_source\":\"0000000000000002:8:2:1189\"}",
|
||||
"{\"stream_source\":\"\",\"stream_source\":\"\"}"
|
||||
};
|
||||
@@ -1408,6 +1410,62 @@ static void test_member_format(void) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] member format: full 64-bit IDs, canonical lists, duplicate/overflow rejection");
|
||||
}
|
||||
|
||||
static void wait_source_audio(uint64_t epoch, int enabled) {
|
||||
uint64_t deadline = get_time_tb() + 100000;
|
||||
for (;;) {
|
||||
struct stream_member_state state;
|
||||
if (stream_member_load(nodes[1], GROUP1, nodes[0]->node_id, &state, NULL) == STREAM_OK
|
||||
&& state.published && state.source.source_epoch == epoch && state.audio_enabled == enabled) return;
|
||||
CHECK(get_time_tb() < deadline); test_clock_poll(ua, 100);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_viewer_radio_mute(void) {
|
||||
struct STREAM_HANDLE *publisher = NULL, *raw = NULL, *relay = NULL, *first = NULL, *second = NULL;
|
||||
struct stream_info info;
|
||||
uint64_t source = nodes[0]->node_id;
|
||||
CHECK(stream_publish_open(nodes[0], GROUP1, NULL, &publisher) == STREAM_OK);
|
||||
CHECK(stream_publish_set_audio_enabled(publisher, 1) == STREAM_OK);
|
||||
CHECK(stream_get_info(publisher, &info) == STREAM_OK);
|
||||
uint64_t epoch = info.descriptor.source_epoch;
|
||||
wait_source_audio(epoch, 1);
|
||||
CHECK(!radio_member_silenced(nodes[1], GROUP1, source));
|
||||
CHECK(stream_relay_open(nodes[1], &info.descriptor, &relay) == STREAM_OK);
|
||||
CHECK(stream_subscribe_open(nodes[1], GROUP1, source, &raw) == STREAM_OK);
|
||||
CHECK(!radio_member_silenced(nodes[1], GROUP1, source));
|
||||
CHECK(stream_media_open(nodes[1], GROUP1, source, epoch, STREAM_MEDIA_TRACK_VIDEO, &first) == STREAM_OK);
|
||||
CHECK(stream_media_open(nodes[1], GROUP1, source, epoch, STREAM_MEDIA_TRACK_VIDEO | STREAM_MEDIA_TRACK_AUDIO, &second) == STREAM_OK);
|
||||
CHECK(radio_member_silenced(nodes[1], GROUP1, source) && !radio_member_muted(nodes[1], GROUP1, source));
|
||||
CHECK(!radio_member_silenced(nodes[1], GROUP2, source));
|
||||
CHECK(!radio_member_silenced(nodes[1], GROUP1, nodes[2]->node_id));
|
||||
stream_close(first); first = NULL;
|
||||
CHECK(radio_member_silenced(nodes[1], GROUP1, source));
|
||||
CHECK(radio_set_member_muted(nodes[1], GROUP1, source, 1) == 0);
|
||||
CHECK(stream_publish_set_audio_enabled(publisher, 0) == STREAM_OK); wait_source_audio(epoch, 0);
|
||||
CHECK(!stream_radio_muted(nodes[1], GROUP1, source) && radio_member_silenced(nodes[1], GROUP1, source));
|
||||
CHECK(radio_set_member_muted(nodes[1], GROUP1, source, 0) == 0);
|
||||
CHECK(!radio_member_silenced(nodes[1], GROUP1, source));
|
||||
CHECK(stream_publish_set_audio_enabled(publisher, 1) == STREAM_OK); wait_source_audio(epoch, 1);
|
||||
CHECK(radio_member_silenced(nodes[1], GROUP1, source));
|
||||
stream_close(second); second = NULL;
|
||||
CHECK(!radio_member_silenced(nodes[1], GROUP1, source));
|
||||
CHECK(stream_media_open(nodes[1], GROUP1, source, epoch, STREAM_MEDIA_TRACK_VIDEO, &first) == STREAM_OK);
|
||||
CHECK(radio_member_silenced(nodes[1], GROUP1, source));
|
||||
stream_close(publisher); publisher = NULL;
|
||||
CHECK(stream_publish_open(nodes[0], GROUP1, NULL, &publisher) == STREAM_OK);
|
||||
CHECK(stream_publish_set_audio_enabled(publisher, 1) == STREAM_OK);
|
||||
CHECK(stream_get_info(publisher, &info) == STREAM_OK && info.descriptor.source_epoch != epoch);
|
||||
wait_source_audio(info.descriptor.source_epoch, 1);
|
||||
CHECK(!stream_handle_active(first) && !radio_member_silenced(nodes[1], GROUP1, source));
|
||||
stream_close(first); stream_close(raw); stream_close(relay); first = NULL;
|
||||
CHECK(stream_media_open(nodes[1], GROUP1, source, info.descriptor.source_epoch, STREAM_MEDIA_TRACK_VIDEO, &first) == STREAM_OK);
|
||||
CHECK(radio_member_silenced(nodes[1], GROUP1, source));
|
||||
stream_cancel_group(nodes[1], GROUP1);
|
||||
CHECK(!radio_member_silenced(nodes[1], GROUP1, source));
|
||||
stream_close(first); stream_close(publisher);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] viewer radio mute: source audio, manual mute, group isolation, owners, relay, epoch, close");
|
||||
}
|
||||
|
||||
/* Пауза player не останавливает live ingest/selector; FIN сохраняет источник до дочитывания локального owner. */
|
||||
static void test_delayed_media_reader(void) {
|
||||
struct STREAM_HANDLE *publisher = NULL, *remote = NULL, *preview = NULL;
|
||||
@@ -1766,6 +1824,7 @@ int main(int argc, char **argv) {
|
||||
for (unsigned i = 0; i < 4; i++) stream_set_event_callback(nodes[i], NULL, NULL);
|
||||
test_partial_bootstrap_and_end();
|
||||
test_delayed_media_reader();
|
||||
test_viewer_radio_mute();
|
||||
for (unsigned i = 0; i < 3; i++) topo_group_peer_close(connections[i]);
|
||||
for (unsigned i = 0; i < 4; i++) utun_instance_destroy(nodes[i]);
|
||||
uasync_destroy(ua, 1); test_clock_finish();
|
||||
|
||||
Reference in new issue
Block a user