Browse Source

Fix Windows stream test and compact Android call diagnostics

master
evgeny 4 days ago
parent
commit
b88d76a8ab
  1. 46
      tests/test_stream_core.c
  2. 46
      tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/CallScreen.kt
  3. 4
      tools/chatgui-android/app/src/main/res/values-ru/strings.xml
  4. 4
      tools/chatgui-android/app/src/main/res/values/strings.xml

46
tests/test_stream_core.c

@ -507,36 +507,36 @@ static void test_source_timer(void) {
/* Близкий сосед, цена дополнительных hops и проблем сравниваются в одних единицах, неизвестный RTT не становится нулём. */ /* Близкий сосед, цена дополнительных hops и проблем сравниваются в одних единицах, неизвестный RTT не становится нулём. */
static void test_supplier_score(void) { static void test_supplier_score(void) {
struct stream_receive_info near = {.rtt_ms = 10, .path_rtt_ms = 80, .rtt_valid = 1, .path_rtt_valid = 1, .path = {.count = 3}}; struct stream_receive_info near_peer = {.rtt_ms = 10, .path_rtt_ms = 80, .rtt_valid = 1, .path_rtt_valid = 1, .path = {.count = 3}};
struct stream_receive_info far = {.rtt_ms = 45, .path_rtt_ms = 40, .rtt_valid = 1, .path_rtt_valid = 1, .path = {.count = 2}}; struct stream_receive_info far_peer = {.rtt_ms = 45, .path_rtt_ms = 40, .rtt_valid = 1, .path_rtt_valid = 1, .path = {.count = 2}};
struct stream_metric_snapshot clean = {.blocks = 100}, late = {.blocks = 100, .late_blocks = 2}; struct stream_metric_snapshot clean = {.blocks = 100}, late = {.blocks = 100, .late_blocks = 2};
CHECK(stream_supplier_score(&near, &clean, 1) == 109 && stream_supplier_score(&far, &clean, 1) == 136); CHECK(stream_supplier_score(&near_peer, &clean, 1) == 109 && stream_supplier_score(&far_peer, &clean, 1) == 136);
/* Обычная сумма RTT предпочла бы far (85 < 90); удвоенный RTT соседа предпочитает near. */ /* Обычная сумма RTT предпочла бы far_peer (85 < 90); удвоенный RTT соседа предпочитает near_peer. */
CHECK(stream_supplier_score(&near, &clean, 1) < stream_supplier_score(&far, &clean, 1)); CHECK(stream_supplier_score(&near_peer, &clean, 1) < stream_supplier_score(&far_peer, &clean, 1));
CHECK(stream_supplier_score(&near, &late, 1) == 129); CHECK(stream_supplier_score(&near_peer, &late, 1) == 129);
CHECK(stream_supplier_score(&near, &late, 1) < stream_supplier_score(&far, &clean, 1)); CHECK(stream_supplier_score(&near_peer, &late, 1) < stream_supplier_score(&far_peer, &clean, 1));
late.late_blocks = 3; late.late_blocks = 3;
CHECK(stream_supplier_score(&near, &late, 1) > stream_supplier_score(&far, &clean, 1)); CHECK(stream_supplier_score(&near_peer, &late, 1) > stream_supplier_score(&far_peer, &clean, 1));
far = near; far.rtt_ms = 9; far.path.count = 4; far_peer = near_peer; far_peer.rtt_ms = 9; far_peer.path.count = 4;
CHECK(stream_supplier_score(&far, &clean, 1) == 110); CHECK(stream_supplier_score(&far_peer, &clean, 1) == 110);
CHECK(stream_supplier_score(&near, &clean, 1) < stream_supplier_score(&far, &clean, 1)); CHECK(stream_supplier_score(&near_peer, &clean, 1) < stream_supplier_score(&far_peer, &clean, 1));
late = (struct stream_metric_snapshot){.blocks = 4, .late_blocks = 1, .stops = 7}; late = (struct stream_metric_snapshot){.blocks = 4, .late_blocks = 1, .stops = 7};
CHECK(stream_supplier_score(&near, &late, 1) == 369); CHECK(stream_supplier_score(&near_peer, &late, 1) == 369);
late.lag_ms = STREAM_LATE_MS; late.lag_ms = STREAM_LATE_MS;
CHECK(stream_supplier_score(&near, &late, 1) == 369); CHECK(stream_supplier_score(&near_peer, &late, 1) == 369);
late.lag_ms++; late.lag_ms++;
CHECK(stream_supplier_score(&near, &late, 1) == 1109); CHECK(stream_supplier_score(&near_peer, &late, 1) == 1109);
late.lag_ms = 0; late.stopped = 1; late.lag_ms = 0; late.stopped = 1;
CHECK(stream_supplier_score(&near, &late, 1) == 1109); CHECK(stream_supplier_score(&near_peer, &late, 1) == 1109);
late.stopped = 0; late.late_blocks = late.blocks; late.stopped = 0; late.late_blocks = late.blocks;
CHECK(stream_supplier_score(&near, &late, 1) == 1109); /* История остановок не превышает лимит штрафа. */ CHECK(stream_supplier_score(&near_peer, &late, 1) == 1109); /* История остановок не превышает лимит штрафа. */
CHECK(stream_supplier_score(&near, &late, 0) == 109); CHECK(stream_supplier_score(&near_peer, &late, 0) == 109);
near.rtt_valid = 0; near_peer.rtt_valid = 0;
CHECK(stream_supplier_score(&near, &clean, 1) == UINT64_MAX); CHECK(stream_supplier_score(&near_peer, &clean, 1) == UINT64_MAX);
near.rtt_valid = 1; near.path_rtt_valid = 0; near_peer.rtt_valid = 1; near_peer.path_rtt_valid = 0;
CHECK(stream_supplier_score(&near, &clean, 1) == UINT64_MAX); CHECK(stream_supplier_score(&near_peer, &clean, 1) == UINT64_MAX);
near.path_rtt_valid = 1; near.rtt_ms = near.path_rtt_ms = UINT32_MAX; near_peer.path_rtt_valid = 1; near_peer.rtt_ms = near_peer.path_rtt_ms = UINT32_MAX;
CHECK(stream_supplier_score(&near, &late, 1) == 3 * (uint64_t)UINT32_MAX + 1009); CHECK(stream_supplier_score(&near_peer, &late, 1) == 3 * (uint64_t)UINT32_MAX + 1009);
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] supplier score: nearby peer, hop cost, problem tradeoffs, 1000ms cap, unknown and wide RTT"); DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] supplier score: nearby peer, hop cost, problem tradeoffs, 1000ms cap, unknown and wide RTT");
} }

46
tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/CallScreen.kt

@ -43,6 +43,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.PlatformTextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -240,28 +241,29 @@ fun CallScreen(
fontSize = 16.sp fontSize = 16.sp
) )
Spacer(Modifier.height(8.dp)) Spacer(Modifier.height(8.dp))
Text(stringResource(R.string.connection_label, st?.connectionType?.label ?: stringResource(R.string.connection_none)), ProvideTextStyle(MaterialTheme.typography.bodySmall.copy(
color = Color(0xFFAEBCC8), fontSize = 13.sp) color = Color(0xFFAEBCC8), fontSize = 12.sp, lineHeight = 14.sp,
val bgpPath = st?.bgpPath ?: "" textAlign = TextAlign.Center, platformStyle = PlatformTextStyle(includeFontPadding = false)
if (bgpPath.isNotEmpty()) { )) {
Spacer(Modifier.height(8.dp)) Column(Modifier.fillMaxWidth().padding(horizontal = 16.dp),
Text( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(2.dp)) {
bgpPath, LaunchedEffect(Unit) {
color = Color(0xFFAEBCC8), LogManager.addLog("DEBUG", "call", "compact call diagnostics shown: font=12sp lineHeight=14sp gap=2dp")
fontSize = 13.sp }
) Text(stringResource(R.string.connection_label, st?.connectionType?.label ?: stringResource(R.string.connection_none)),
} modifier = Modifier.fillMaxWidth())
if (phase == CallPhase.ACTIVE) st?.stats?.let { stats -> val bgpPath = st?.bgpPath ?: ""
Spacer(Modifier.height(8.dp)) if (bgpPath.isNotEmpty()) Text(bgpPath, modifier = Modifier.fillMaxWidth())
Text(stringResource(R.string.call_stats, stats.bufferMs, stats.reserveMs, if (phase == CallPhase.ACTIVE) st?.stats?.let { stats ->
stats.minMs, stats.maxMs, "%.2f".format(stats.tempoX100 / 100.0), stats.rttMs, stats.dropped, stats.underruns), Text(stringResource(R.string.call_stats, stats.bufferMs, stats.reserveMs,
modifier = Modifier.padding(horizontal = 16.dp), color = Color(0xFFAEBCC8), stats.minMs, stats.maxMs, "%.2f".format(stats.tempoX100 / 100.0), stats.rttMs, stats.dropped, stats.underruns),
fontSize = 12.sp, textAlign = TextAlign.Center) modifier = Modifier.fillMaxWidth())
Text(stringResource(R.string.call_output_stats, Text(stringResource(R.string.call_output_stats,
stats.output.queueMs.takeIf { it >= 0 }?.toString() ?: "—", stats.output.queueMs.takeIf { it >= 0 }?.toString() ?: "—",
stats.output.outputMs.takeIf { it >= 0 }?.toString() ?: "—"), stats.output.outputMs.takeIf { it >= 0 }?.toString() ?: "—"),
modifier = Modifier.padding(horizontal = 16.dp), color = Color(0xFFAEBCC8), modifier = Modifier.fillMaxWidth())
fontSize = 12.sp, textAlign = TextAlign.Center) }
}
} }
Spacer(Modifier.height(40.dp)) Spacer(Modifier.height(40.dp))
} }

4
tools/chatgui-android/app/src/main/res/values-ru/strings.xml

@ -373,8 +373,8 @@
<string name="address_unknown">"неизвестный (%1$d)"</string> <string name="address_unknown">"неизвестный (%1$d)"</string>
<string name="file_save_failed">"Не удалось сохранить файл"</string> <string name="file_save_failed">"Не удалось сохранить файл"</string>
<string name="transfer_key_confirm">"Передать приватный ключ канала участнику «%1$s»?\n\nКлюч передаётся зашифрованным и подписанным. Получатель станет совладельцем и сможет управлять участниками."</string> <string name="transfer_key_confirm">"Передать приватный ключ канала участнику «%1$s»?\n\nКлюч передаётся зашифрованным и подписанным. Получатель станет совладельцем и сможет управлять участниками."</string>
<string name="call_stats">"Буфер: %1$s мс · Запас: %2$s мс\nЗа 10 с: минимум %3$s · максимум %4$s мс\nСкорость: %5$s× · RTT: %6$s мс\nПотери буфера: %7$s · Недостачи: %8$s"</string> <string name="call_stats">"Буфер %1$s · запас %2$s мс\nМин–макс за 10 с: %3$s–%4$s мс\nТемп %5$s× · RTT %6$s мс\nСбросы %7$s · недостачи %8$s"</string>
<string name="call_output_stats">"Аудиовыход: %2$s мс (включая очередь приложения: %1$s мс)"</string> <string name="call_output_stats">"Выход %2$s мс · из них очередь %1$s мс"</string>
<plurals name="bgp_nodes"> <plurals name="bgp_nodes">
<item quantity="one">BGP: %1$d узел</item> <item quantity="one">BGP: %1$d узел</item>
<item quantity="few">BGP: %1$d узла</item> <item quantity="few">BGP: %1$d узла</item>

4
tools/chatgui-android/app/src/main/res/values/strings.xml

@ -374,8 +374,8 @@
<string name="address_unknown">"unknown (%1$d)"</string> <string name="address_unknown">"unknown (%1$d)"</string>
<string name="file_save_failed">"Could not save file"</string> <string name="file_save_failed">"Could not save file"</string>
<string name="transfer_key_confirm">"Send the channel private key to “%1$s”?\n\nThe key is transferred encrypted and signed. The recipient will become a co-owner and will be able to manage members."</string> <string name="transfer_key_confirm">"Send the channel private key to “%1$s”?\n\nThe key is transferred encrypted and signed. The recipient will become a co-owner and will be able to manage members."</string>
<string name="call_stats">"Buffer: %1$s ms · Reserve: %2$s ms\nOver 10 s: min %3$s · max %4$s ms\nSpeed: %5$s× · RTT: %6$s ms\nBuffer drops: %7$s · Underruns: %8$s"</string> <string name="call_stats">"Buffer %1$s · reserve %2$s ms\nMin–max over 10 s: %3$s–%4$s ms\nTempo %5$s× · RTT %6$s ms\nDrops %7$s · underruns %8$s"</string>
<string name="call_output_stats">"Audio output: %2$s ms (includes app queue: %1$s ms)"</string> <string name="call_output_stats">"Output %2$s ms · includes queue %1$s ms"</string>
<plurals name="bgp_nodes"> <plurals name="bgp_nodes">
<item quantity="one">BGP: %1$d node</item> <item quantity="one">BGP: %1$d node</item>
<item quantity="other">BGP: %1$d nodes</item> <item quantity="other">BGP: %1$d nodes</item>

Loading…
Cancel
Save