mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-27 11:25:20 +00:00
The hygiene guard bans `TestConstants.shortTimeout` at every wait site and the last users were converted, so Periphery correctly flagged the constant itself as dead and failed CI. Remove it from both TestConstants copies; the banned-name entry stays so the symbol cannot quietly return. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
70 lines
3.1 KiB
Swift
70 lines
3.1 KiB
Swift
//
|
|
// TestConstants.swift
|
|
// bitchatTests
|
|
//
|
|
// This is free and unencumbered software released into the public domain.
|
|
// For more information, see <https://unlicense.org>
|
|
//
|
|
|
|
import Foundation
|
|
@testable import bitchat
|
|
|
|
struct TestConstants {
|
|
static let defaultTimeout: TimeInterval = 5.0
|
|
/// For positive waits on work that hops through `Task.detached` or
|
|
/// background queues: those contend with every parallel test worker for
|
|
/// the global executor, so a loaded CI runner can exceed
|
|
/// `defaultTimeout`. `waitUntil` returns as soon as the condition holds,
|
|
/// so passing runs never pay the longer timeout.
|
|
static let longTimeout: TimeInterval = 10.0
|
|
|
|
/// **Default deadline for any "wait until this async thing settles" helper.**
|
|
///
|
|
/// Four separate tests flaked on CI during July 2026 with the same root
|
|
/// cause, and it is worth stating the rule rather than re-learning it a
|
|
/// fifth time: *a wait deadline is not a latency budget.* It exists so a
|
|
/// genuine hang eventually fails the suite. Size it for the worst-case
|
|
/// scheduler, never for how long the operation "should" take.
|
|
///
|
|
/// A CI runner executes many suites at once. Work behind `@MainActor`,
|
|
/// `Task.detached(priority: .utility)`, or a `DispatchQueue.asyncAfter` can
|
|
/// be starved for seconds — one observed run took 3.75 s for a 1 s
|
|
/// operation. Deadlines sized to the operation (the old 1 s defaults) turn
|
|
/// that starvation into a red build that reads like a product bug.
|
|
///
|
|
/// This costs nothing when tests pass, because every helper returns as soon
|
|
/// as its condition holds. It only extends the genuine-failure case.
|
|
///
|
|
/// `TestTimingHygieneTests` enforces that wait helpers default to at least
|
|
/// `minimumSettleTimeout`.
|
|
static let settleTimeout: TimeInterval = 30.0
|
|
|
|
/// Floor enforced by `TestTimingHygieneTests`. Anything below this is a
|
|
/// latency assumption in disguise.
|
|
static let minimumSettleTimeout: TimeInterval = 10.0
|
|
|
|
/// For waits whose **expected outcome is `false`** — "prove this does not
|
|
/// happen".
|
|
///
|
|
/// The floor above is wrong for these, and inverted: a negative wait always
|
|
/// runs its deadline out, so `settleTimeout` would spend 30 s per case
|
|
/// proving nothing extra. Starvation cannot cause a false failure here
|
|
/// either — a starved runner only makes the thing *less* likely to happen,
|
|
/// so the assertion still holds. Short is correct, and naming it says the
|
|
/// polarity out loud instead of leaving a bare literal that reads like the
|
|
/// mistake this file exists to prevent.
|
|
///
|
|
/// `TestTimingHygieneTests` accepts this by name. Using it for a wait you
|
|
/// expect to succeed reintroduces exactly the flake class it sits next to.
|
|
static let negativeWaitWindow: TimeInterval = 1.0
|
|
|
|
|
|
static let testNickname1 = "Alice"
|
|
static let testNickname2 = "Bob"
|
|
static let testNickname3 = "Charlie"
|
|
static let testNickname4 = "David"
|
|
|
|
static let testMessage1 = "Hello, World!"
|
|
static let testLongMessage = String(repeating: "This is a long message. ", count: 100)
|
|
}
|