Zum Inhalt

apple/PhysarumApp/Tests/SimFormatTests.swift

import XCTest
@testable import Physarum

final class SimFormatTests: XCTestCase {
    func testSquareViewGivesSquareField() {
        XCTAssertEqual(fieldSize(viewWidth: 800, viewHeight: 800), FieldSize(width: 720, height: 720))
    }

    func testPortraitViewIsTallField() {
        // 402x874 ≈ 1:2.17 → short edge 720, long edge ~1564 (under the 1600 cap)
        let f = fieldSize(viewWidth: 402, viewHeight: 874)
        XCTAssertEqual(f.width, 720)
        XCTAssertTrue(f.height > 1400 && f.height <= 1600, "got \(f.height)")
        XCTAssertTrue(f.height > f.width)
    }

    func testLandscapeViewIsWideField() {
        let f = fieldSize(viewWidth: 874, viewHeight: 402)
        XCTAssertEqual(f.height, 720)
        XCTAssertTrue(f.width > f.height)
    }

    func testLongEdgeIsCapped() {
        // extreme aspect → long edge clamped to maxLong (1600)
        let f = fieldSize(viewWidth: 200, viewHeight: 4000)
        XCTAssertEqual(f.width, 720)
        XCTAssertEqual(f.height, 1600)
    }

    func testDegenerateViewFallsBackToSquare() {
        XCTAssertEqual(fieldSize(viewWidth: 0, viewHeight: 0), FieldSize(width: 720, height: 720))
    }

    func testDensityScalesWithArea() {
        // baseline area → unchanged
        XCTAssertEqual(densityScaledAgentCount(10_000, fieldWidth: 512, fieldHeight: 512), 10_000)
        // 2× area → ~2× count
        XCTAssertEqual(densityScaledAgentCount(10_000, fieldWidth: 512, fieldHeight: 1024), 20_000)
    }

    func testDensityRespectsTierMaxAndFloor() {
        XCTAssertEqual(densityScaledAgentCount(400_000, fieldWidth: 1024, fieldHeight: 1024), 500_000) // capped
        XCTAssertGreaterThanOrEqual(densityScaledAgentCount(50, fieldWidth: 512, fieldHeight: 512), 100) // floor
    }

    func testTargetFieldSizeAutoUsesViewAspect() {
        XCTAssertEqual(targetFieldSize(viewWidth: 800, viewHeight: 800, format: .auto),
                       fieldSize(viewWidth: 800, viewHeight: 800))
    }

    func testTargetFieldSizeFixedIgnoresView() {
        XCTAssertEqual(targetFieldSize(viewWidth: 800, viewHeight: 800, format: .square),
                       FieldSize(width: 720, height: 720))
        let p = targetFieldSize(viewWidth: 800, viewHeight: 800, format: .portrait)
        XCTAssertTrue(p.height > p.width)
        let l = targetFieldSize(viewWidth: 800, viewHeight: 800, format: .landscape)
        XCTAssertTrue(l.width > l.height)
    }

    func testSimFormatRawRoundTrip() {
        for f in SimFormat.allCases {
            XCTAssertEqual(SimFormat(rawValue: f.rawValue), f)
        }
    }

    // MARK: - FieldTier (live-path device tiers; capture stays untiered)

    func testPhoneTierStaysNearPresetTuningBaseline() {
        XCTAssertEqual(FieldTier.phone.base, 512)
        XCTAssertEqual(FieldTier.phone.maxLong, 1280)
        XCTAssertEqual(FieldTier.phone.agentCap, 250_000)
    }

    func testDesktopTierKeepsPreTierValues() {
        XCTAssertEqual(FieldTier.desktop.base, 720)
        XCTAssertEqual(FieldTier.desktop.maxLong, 1600)
        XCTAssertEqual(FieldTier.desktop.agentCap, 500_000)
    }

    func testCurrentTierOnMacIsDesktop() {
        #if os(macOS)
        XCTAssertEqual(FieldTier.current, .desktop)
        #endif
    }

    func testTabletTierIsConservative() {
        XCTAssertEqual(FieldTier.tablet.base, 512)
        XCTAssertEqual(FieldTier.tablet.maxLong, 1280)
        XCTAssertEqual(FieldTier.tablet.agentCap, 250_000)
        // Distinct identity from the phone tier despite identical workload values today,
        // so the seam is real and `== .phone` checks never accidentally match iPad.
        XCTAssertNotEqual(FieldTier.tablet, FieldTier.phone)
    }

    func testFieldTierMapsIdiomToTier() {
        XCTAssertEqual(fieldTier(for: .phone), .phone)
        XCTAssertEqual(fieldTier(for: .pad), .tablet)
        XCTAssertEqual(fieldTier(for: .mac), .desktop)
    }

    func testTargetFieldSizeHonorsTier() {
        // iPhone portrait aspect (~1:2.17) on the phone tier: short edge 512, long ≈ 1113.
        let f = targetFieldSize(viewWidth: 402, viewHeight: 874, format: .auto, tier: .phone)
        XCTAssertEqual(f.width, 512)
        XCTAssertTrue(f.height > 1000 && f.height <= FieldTier.phone.maxLong, "got \(f.height)")
        // Fixed formats honor the tier base too.
        XCTAssertEqual(targetFieldSize(viewWidth: 800, viewHeight: 800, format: .square, tier: .phone),
                       FieldSize(width: 512, height: 512))
        // Desktop tier reproduces the untiered defaults exactly.
        XCTAssertEqual(targetFieldSize(viewWidth: 402, viewHeight: 874, format: .auto, tier: .desktop),
                       targetFieldSize(viewWidth: 402, viewHeight: 874, format: .auto))
    }

    func testDensityScaledAgentCountHonorsTierCap() {
        XCTAssertEqual(densityScaledAgentCount(400_000, fieldWidth: 1024, fieldHeight: 1024, tier: .phone),
                       250_000)
        XCTAssertEqual(densityScaledAgentCount(400_000, fieldWidth: 1024, fieldHeight: 1024, tier: .desktop),
                       500_000)
        // Below the cap the tier changes nothing — density scaling is identical.
        XCTAssertEqual(densityScaledAgentCount(10_000, fieldWidth: 512, fieldHeight: 1024, tier: .phone),
                       20_000)
    }
}