Files
kst4contest/src/main/java/kst4contest/controller/On4KstProtocolTest.java
T

142 lines
4.8 KiB
Java

package kst4contest.controller;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import kst4contest.model.ChatPreferences;
class On4KstProtocolTest {
@Test
void buildsLoginWithReplayOverlap() {
assertEquals(
"LOGINC|DL1ABC|secret|2|KST4Contest v1.2.3|25|0|1|12344|0|",
On4KstProtocol.login(
"DL1ABC", "secret", 2,
"KST4Contest v1.2.3", 12_344L));
}
@Test
void buildsContextSafeSecondChatFrames() {
assertEquals("SDONE|2|", On4KstProtocol.settingsDone(2));
assertEquals("ACHAT|3|25|10|2|100|0|",
On4KstProtocol.addChat(3, 100L));
assertEquals("MSG|2|0|/SETLOC JO31AA|0|",
On4KstProtocol.setLocator(2, "jo31aa"));
assertEquals("MSG|3|0|/SETNAME 10G 10368.200|0|",
On4KstProtocol.setName(3, "10G 10368.200"));
}
@Test
void stripsOnlyTrailingLineEndings() {
assertEquals("CK|", On4KstProtocol.normalizeRawFrame("CK|\r\n"));
assertThrows(IllegalArgumentException.class,
() -> On4KstProtocol.normalizeRawFrame("CK|\rBROKEN"));
}
@Test
void rejectsValuesThatCouldCreateASecondProtocolFrame() {
assertThrows(IllegalArgumentException.class,
() -> On4KstProtocol.chatMessage(2, "hello|0|"));
assertThrows(IllegalArgumentException.class,
() -> On4KstProtocol.chatMessage(2, "hello\r\nQUIT|"));
assertThrows(IllegalArgumentException.class,
() -> On4KstProtocol.login(
"DL1ABC", "bad|password", 2, "client", 0L));
}
@Test
void rejectsInvalidLocatorAndCategoryBeforeTheyReachTheServer() {
assertThrows(IllegalArgumentException.class,
() -> On4KstProtocol.setLocator(2, "JO31"));
assertThrows(IllegalArgumentException.class,
() -> On4KstProtocol.settingsDone(99));
}
@Test
void convertsBothHistoryAndLiveMessageTimestampsForReconnect() {
assertEquals(1_186_819_108L,
On4KstConnectionManager.parseMessageTimestamp(
"CR|2|1186819108|EA6VQ|Gabriel|0|msg|0|"));
assertEquals(
LocalDateTime.of(2026, 8, 13, 12, 34, 56)
.toEpochSecond(ZoneOffset.UTC),
On4KstConnectionManager.parseMessageTimestamp(
"CH|2|20260813123456|DL1ABC|Op|0|msg|0|"));
}
@Test
void resolvesBeaconVariablesBeforeApplyingProtocolValidation() {
ChatPreferences preferences = new ChatPreferences();
preferences.setMYQRGFirstCat("144.300");
ChatController controller = new ChatController();
controller.setChatPreferences(preferences);
controller.validateBeaconTemplate(
"calling cq at MYQRG"
);
assertEquals(
"calling cq at 144.300",
controller.resolveAndValidateBeaconText(
"calling cq at MYQRG"
)
);
}
@Test
void acceptsTemporarilyUnresolvedVariableOnlyBeaconTemplate() {
ChatPreferences preferences = new ChatPreferences();
preferences.setMYQRGFirstCat("");
ChatController controller = new ChatController();
controller.setChatPreferences(preferences);
assertDoesNotThrow(
() -> controller.validateBeaconTemplate("MYQRG")
);
assertThrows(
IllegalArgumentException.class,
() -> controller.resolveAndValidateBeaconText("MYQRG")
);
}
@Test
void rejectsEmptyOverlongAndProtocolBreakingBeaconText() {
ChatPreferences preferences = new ChatPreferences();
ChatController controller = new ChatController();
controller.setChatPreferences(preferences);
assertThrows(
IllegalArgumentException.class,
() -> controller.validateBeaconTemplate(" ")
);
assertThrows(
IllegalArgumentException.class,
() -> controller.validateBeaconTemplate(
"cq at 144.300|0|QUIT"
)
);
assertThrows(
IllegalArgumentException.class,
() -> controller.validateBeaconTemplate(
"x".repeat(
ChatController.MAX_BEACON_TEXT_LENGTH
+ 1
)
)
);
}
}