Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion bitchat/Utils/Color+Peer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,22 @@ import SwiftUI

extension Color {
private static var peerColorCache: [String: Color] = [:]


#if DEBUG
/// Counts cache-miss computations; exposed only so regression tests can
/// verify a repeated seed hits the cache instead of recomputing.
static var _peerColorComputeCountForTesting = 0
#endif

init(peerSeed: String, isDark: Bool) {
let cacheKey = peerSeed + (isDark ? "|dark" : "|light")
if let cached = Self.peerColorCache[cacheKey] {
self = cached
return
}
#if DEBUG
Self._peerColorComputeCountForTesting += 1
#endif
let h = peerSeed.djb2()
var hue = Double(h % 1000) / 1000.0
let orange = 30.0 / 360.0
Expand Down
45 changes: 45 additions & 0 deletions bitchatTests/Utils/ColorPeerTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// ColorPeerTests.swift
// bitchatTests
//
// Tests for Color(peerSeed:isDark:) caching
//

import Testing
import SwiftUI
@testable import bitchat

struct ColorPeerTests {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Serialize tests using the shared color counter

Because this Swift Testing suite is not marked serialized, its @Test methods can run concurrently under the repo's swift test --parallel CI path, but they all assert deltas against the same process-global Color._peerColorComputeCountForTesting. If differentAppearanceForSameSeedIsNotCachedTogether increments the counter between this test's reads, afterSecond == afterFirst can fail even when the cache behavior is correct; make this suite/test serialized or avoid assertions based on a shared global counter.

Useful? React with 👍 / 👎.


@Test func repeatedSeedHitsCacheInsteadOfRecomputing() {
let seed = "cache-hit-\(UUID().uuidString)"

let before = Color._peerColorComputeCountForTesting
let first = Color(peerSeed: seed, isDark: true)
let afterFirst = Color._peerColorComputeCountForTesting
let second = Color(peerSeed: seed, isDark: true)
let afterSecond = Color._peerColorComputeCountForTesting

#expect(afterFirst == before + 1)
#expect(afterSecond == afterFirst)
#expect(first == second)
}

@Test func differentAppearanceForSameSeedIsNotCachedTogether() {
let seed = "appearance-\(UUID().uuidString)"

let before = Color._peerColorComputeCountForTesting
_ = Color(peerSeed: seed, isDark: true)
_ = Color(peerSeed: seed, isDark: false)
let after = Color._peerColorComputeCountForTesting

#expect(after == before + 2)
}

@Test func sameSeedProducesSameColor() {
let seed = "deterministic-\(UUID().uuidString)"
let a = Color(peerSeed: seed, isDark: false)
let b = Color(peerSeed: seed, isDark: false)
#expect(a == b)
}
}
Loading