From 2c407540a0a3eff3846cf36eb86bd3cc516ce774 Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 7 Oct 2026 19:33:53 +0200 Subject: [PATCH] Test Android radio talk lifecycle and translate speaker status --- .../app/src/main/res/values-ru/strings.xml | 3 ++ .../app/src/main/res/values/strings.xml | 3 ++ .../com/utun/chat/data/RadioTalkStateTest.kt | 52 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 tools/chatgui-android/app/src/test/java/com/utun/chat/data/RadioTalkStateTest.kt diff --git a/tools/chatgui-android/app/src/main/res/values-ru/strings.xml b/tools/chatgui-android/app/src/main/res/values-ru/strings.xml index fbdb5589..b18aa2d8 100644 --- a/tools/chatgui-android/app/src/main/res/values-ru/strings.xml +++ b/tools/chatgui-android/app/src/main/res/values-ru/strings.xml @@ -48,6 +48,9 @@ Не слушать этого участника в рации Слушать этого участника в рации Не удалось изменить настройку прослушивания рации + Рация: молчит + Рация: говорит + Рация: заглушён "Рация: PTT / автоматическая передача по голосу" "Плавающая кнопка остановлена" "Текущий звонок" diff --git a/tools/chatgui-android/app/src/main/res/values/strings.xml b/tools/chatgui-android/app/src/main/res/values/strings.xml index 319394a6..bb3552d7 100644 --- a/tools/chatgui-android/app/src/main/res/values/strings.xml +++ b/tools/chatgui-android/app/src/main/res/values/strings.xml @@ -48,6 +48,9 @@ Mute this member in radio Listen to this member in radio Cannot change radio listening setting + Radio: silent + Radio: speaking + Radio: muted "Radio: PTT / automatic voice transmission" "Floating button stopped" "Ongoing call" diff --git a/tools/chatgui-android/app/src/test/java/com/utun/chat/data/RadioTalkStateTest.kt b/tools/chatgui-android/app/src/test/java/com/utun/chat/data/RadioTalkStateTest.kt new file mode 100644 index 00000000..b3ae8863 --- /dev/null +++ b/tools/chatgui-android/app/src/test/java/com/utun/chat/data/RadioTalkStateTest.kt @@ -0,0 +1,52 @@ +package com.utun.chat.data + +import org.junit.Assert.* +import org.junit.Test +import java.nio.ByteBuffer +import java.nio.ByteOrder + +class RadioTalkStateTest { + private fun event(group: Long = 7, node: Long = 42, on: Boolean = true): RadioTalkEvent { + val bytes = ByteBuffer.allocate(19).order(ByteOrder.LITTLE_ENDIAN) + .putLong(group).putLong(node).putShort(65535.toShort()).put(if (on) 1.toByte() else 0.toByte()).array() + return requireNotNull(parseRadioTalkEvent(bytes)) + } + + @Test fun stopRemovesOnlyItsSourceAndMuteDoesNotSuppressSpeech() { + var state = RadioTalkState(7).onTalk(event()).onTalk(event(node = 43)) + assertEquals(setOf(42L, 43L), state.speakers) + val muted = ChatMember(42, "Alice", radioMuted = true) + assertTrue(muted.radioMuted && muted.nodeId in state.speakers) + assertSame(state, state.onTalk(event())) + state = state.onTalk(event(on = false)) + assertEquals(setOf(43L), state.speakers) + assertSame(state, state.onTalk(event(on = false))) + assertTrue(state.onTalk(event(node = 43, on = false)).speakers.isEmpty()) + } + + @Test fun activeGroupOwnsSpeakersIndependentlyOfDisplayedMemberSnapshots() { + val group = 0xfedcba9876543210uL.toLong() + val state = RadioTalkState(group).onTalk(event(group)) + assertEquals(setOf(42L), state.speakers) + assertSame(state, state.onTalk(event(group = 8))) + assertSame(state, state.onTalk(event(group = 8, on = false))) + val refreshed = ChatMember(42, "Updated", radioActive = false, radioMuted = true) + assertTrue(refreshed.nodeId in state.speakers) + val switched = RadioTalkState(8) + assertSame(switched, switched.onTalk(event(group))) + val stopped = RadioTalkState() + assertSame(stopped, stopped.onTalk(event(group))) + assertTrue(RadioTalkState(group).speakers.isEmpty()) + } + + @Test fun malformedEventsCannotChangeTheSpeakerState() { + assertNull(parseRadioTalkEvent(null)); assertNull(parseRadioTalkEvent(ByteArray(18))) + assertNull(parseRadioTalkEvent(ByteArray(20))); assertNull(parseRadioTalkEvent(ByteArray(19))) + val bytes = ByteBuffer.allocate(19).order(ByteOrder.LITTLE_ENDIAN).putLong(7).putLong(42).putShort(1).put(2).array() + assertNull(parseRadioTalkEvent(bytes)) + bytes[18] = 1 + assertEquals(1, requireNotNull(parseRadioTalkEvent(bytes)).stream) + assertEquals(65535, event().stream) + assertNull(parseRadioTalkEvent(ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).putLong(0, 0).array())) + } +}