mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 06:05:20 +00:00
Integration test fixes: reconcile SyncTypeFlags phantom-bit assertions and sync-round counts
- SyncTypeFlags phantom-bit tests used bits 8/9/10 as unmapped examples; board/prekey/group now map those, so use bits 11+ (still unmapped). - rawValueInitNormalizesPhantomBits: highest known bit is now 10, so the flags serialize to 2 bytes, not 1. - Board/fragment/announce sync tests silence the prekey round (added by the prekeys feature; default 60s schedule fires at the maintenance barrier). - DiagnosticsMockContext: conform to the CommandContextProvider members added by private-groups (group*) and cashu-chips (sendPublicMessage). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -370,6 +370,8 @@ struct GossipSyncManagerTests {
|
|||||||
config.messageSyncIntervalSeconds = 0
|
config.messageSyncIntervalSeconds = 0
|
||||||
config.fragmentSyncIntervalSeconds = 0
|
config.fragmentSyncIntervalSeconds = 0
|
||||||
config.fileTransferSyncIntervalSeconds = 0
|
config.fileTransferSyncIntervalSeconds = 0
|
||||||
|
// Silence the prekey round so the maintenance barrier below emits nothing.
|
||||||
|
config.prekeyBundleSyncIntervalSeconds = 0
|
||||||
|
|
||||||
let requestSyncManager = RequestSyncManager()
|
let requestSyncManager = RequestSyncManager()
|
||||||
let manager = GossipSyncManager(myPeerID: myPeerID, config: config, requestSyncManager: requestSyncManager)
|
let manager = GossipSyncManager(myPeerID: myPeerID, config: config, requestSyncManager: requestSyncManager)
|
||||||
@@ -543,6 +545,8 @@ struct GossipSyncManagerTests {
|
|||||||
config.messageSyncIntervalSeconds = 0
|
config.messageSyncIntervalSeconds = 0
|
||||||
config.fragmentSyncIntervalSeconds = 0
|
config.fragmentSyncIntervalSeconds = 0
|
||||||
config.fileTransferSyncIntervalSeconds = 0
|
config.fileTransferSyncIntervalSeconds = 0
|
||||||
|
// Silence the prekey round so the maintenance barrier isolates fragments.
|
||||||
|
config.prekeyBundleSyncIntervalSeconds = 0
|
||||||
|
|
||||||
let requestSyncManager = RequestSyncManager()
|
let requestSyncManager = RequestSyncManager()
|
||||||
let manager = GossipSyncManager(myPeerID: myPeerID, config: config, requestSyncManager: requestSyncManager)
|
let manager = GossipSyncManager(myPeerID: myPeerID, config: config, requestSyncManager: requestSyncManager)
|
||||||
|
|||||||
@@ -276,9 +276,15 @@ private final class DiagnosticsMockContext: CommandContextProvider {
|
|||||||
func clearCurrentPublicTimeline() {}
|
func clearCurrentPublicTimeline() {}
|
||||||
func clearPrivateChat(_ peerID: PeerID) {}
|
func clearPrivateChat(_ peerID: PeerID) {}
|
||||||
func sendPublicRaw(_ content: String) {}
|
func sendPublicRaw(_ content: String) {}
|
||||||
|
func sendPublicMessage(_ content: String) {}
|
||||||
func addLocalPrivateSystemMessage(_ content: String, to peerID: PeerID) {}
|
func addLocalPrivateSystemMessage(_ content: String, to peerID: PeerID) {}
|
||||||
func addPublicSystemMessage(_ content: String) {}
|
func addPublicSystemMessage(_ content: String) {}
|
||||||
func toggleFavorite(peerID: PeerID) {}
|
func toggleFavorite(peerID: PeerID) {}
|
||||||
|
func groupCreate(named name: String) -> CommandResult { .handled }
|
||||||
|
func groupInvite(nickname: String) -> CommandResult { .handled }
|
||||||
|
func groupRemove(nickname: String) -> CommandResult { .handled }
|
||||||
|
func groupLeave() -> CommandResult { .handled }
|
||||||
|
func groupList() -> CommandResult { .handled }
|
||||||
|
|
||||||
func currentCommandDestination() -> CommandOutputDestination {
|
func currentCommandDestination() -> CommandOutputDestination {
|
||||||
if let peerID = selectedPrivateChatPeer {
|
if let peerID = selectedPrivateChatPeer {
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ struct GossipSyncBoardTests {
|
|||||||
config.messageSyncIntervalSeconds = 0
|
config.messageSyncIntervalSeconds = 0
|
||||||
config.fragmentSyncIntervalSeconds = 0
|
config.fragmentSyncIntervalSeconds = 0
|
||||||
config.fileTransferSyncIntervalSeconds = 0
|
config.fileTransferSyncIntervalSeconds = 0
|
||||||
|
// Silence the prekey round (added by the prekeys feature; groupMessage
|
||||||
|
// rides the message schedule, already off) so board is isolated.
|
||||||
|
config.prekeyBundleSyncIntervalSeconds = 0
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,9 +38,10 @@ struct SyncTypeFlagsBoardTests {
|
|||||||
/// decode path accepts the bytes and simply maps unknown bits to no
|
/// decode path accepts the bytes and simply maps unknown bits to no
|
||||||
/// message type, so a board-only request reads as "nothing I can serve".
|
/// message type, so a board-only request reads as "nothing I can serve".
|
||||||
@Test func unknownBitsDecodeToNoTypes() throws {
|
@Test func unknownBitsDecodeToNoTypes() throws {
|
||||||
// Bits 9-15 are unassigned; a future (or unknown) two-byte bitfield
|
// Bits 11-15 are unassigned after the feature integration (bit 8 is
|
||||||
|
// board, 9 prekey, 10 group); a future (or unknown) two-byte bitfield
|
||||||
// must decode without error and yield no known types.
|
// must decode without error and yield no known types.
|
||||||
let decoded = try #require(SyncTypeFlags.decode(Data([0x00, 0xFE])))
|
let decoded = try #require(SyncTypeFlags.decode(Data([0x00, 0xF8])))
|
||||||
#expect(decoded.toMessageTypes().isEmpty)
|
#expect(decoded.toMessageTypes().isEmpty)
|
||||||
for type in [MessageType.announce, .message, .fragment, .fileTransfer, .boardPost] {
|
for type in [MessageType.announce, .message, .fragment, .fileTransfer, .boardPost] {
|
||||||
#expect(!decoded.contains(type))
|
#expect(!decoded.contains(type))
|
||||||
@@ -48,8 +49,8 @@ struct SyncTypeFlagsBoardTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test func mixedKnownAndUnknownBitsKeepKnownTypes() throws {
|
@Test func mixedKnownAndUnknownBitsKeepKnownTypes() throws {
|
||||||
// Known low-byte flags survive alongside unknown high bits.
|
// Known low-byte flags survive alongside unknown high bits (11-15).
|
||||||
let decoded = try #require(SyncTypeFlags.decode(Data([0x03, 0xFE])))
|
let decoded = try #require(SyncTypeFlags.decode(Data([0x03, 0xF8])))
|
||||||
#expect(decoded.contains(.announce))
|
#expect(decoded.contains(.announce))
|
||||||
#expect(decoded.contains(.message))
|
#expect(decoded.contains(.message))
|
||||||
#expect(Set(decoded.toMessageTypes()) == Set([.announce, .message]))
|
#expect(Set(decoded.toMessageTypes()) == Set([.announce, .message]))
|
||||||
|
|||||||
@@ -13,17 +13,19 @@ struct SyncTypeFlagsTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test func decodeDropsPhantomBits() {
|
@Test func decodeDropsPhantomBits() {
|
||||||
// Bits 8+ map to no message type. They must not survive decode as
|
// Bits 11+ map to no message type (bits 8/9/10 are board/prekey/group
|
||||||
|
// after the feature integration). They must not survive decode as
|
||||||
// phantom membership.
|
// phantom membership.
|
||||||
let phantom = Data([0x00, 0xFF]) // bits 8..15 set, no known type
|
let phantom = Data([0x00, 0xF8]) // bits 11..15 set, no known type
|
||||||
let decoded = SyncTypeFlags.decode(phantom)
|
let decoded = SyncTypeFlags.decode(phantom)
|
||||||
#expect(decoded?.rawValue == 0)
|
#expect(decoded?.rawValue == 0)
|
||||||
#expect(decoded?.toMessageTypes().isEmpty == true)
|
#expect(decoded?.toMessageTypes().isEmpty == true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test func phantomBitsAreStrippedButKnownBitsSurvive() {
|
@Test func phantomBitsAreStrippedButKnownBitsSurvive() {
|
||||||
// Low byte = announce(0) + message(1); high byte = phantom.
|
// Low byte = announce(0) + message(1); high byte = phantom (bits 11+,
|
||||||
let mixed = Data([0b0000_0011, 0xFF])
|
// which map to no known type).
|
||||||
|
let mixed = Data([0b0000_0011, 0xF8])
|
||||||
let decoded = SyncTypeFlags.decode(mixed)
|
let decoded = SyncTypeFlags.decode(mixed)
|
||||||
#expect(decoded?.contains(.announce) == true)
|
#expect(decoded?.contains(.announce) == true)
|
||||||
#expect(decoded?.contains(.message) == true)
|
#expect(decoded?.contains(.message) == true)
|
||||||
@@ -33,11 +35,12 @@ struct SyncTypeFlagsTests {
|
|||||||
|
|
||||||
@Test func rawValueInitNormalizesPhantomBits() {
|
@Test func rawValueInitNormalizesPhantomBits() {
|
||||||
let flags = SyncTypeFlags(rawValue: 0xFFFF_FFFF_FFFF_FFFF)
|
let flags = SyncTypeFlags(rawValue: 0xFFFF_FFFF_FFFF_FFFF)
|
||||||
// Every known type bit is set; nothing above them survives, so the
|
// Every known type bit is set; nothing above them survives. The
|
||||||
// field serializes to a single byte.
|
// highest known bit is 10 (groupMessage), so the field serializes to
|
||||||
|
// two bytes.
|
||||||
#expect(flags.contains(.announce))
|
#expect(flags.contains(.announce))
|
||||||
#expect(flags.contains(.fileTransfer))
|
#expect(flags.contains(.fileTransfer))
|
||||||
let data = flags.toData()
|
let data = flags.toData()
|
||||||
#expect(data?.count == 1)
|
#expect(data?.count == 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user