OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / test / simulation / blind-fleet-simulation.test.js

253 lines · javascript ref:
import test from 'brittle'
import {
  assertBlindFleetEvidence,
  runBlindFleetSimulation,
  stableStringify,
  verifyBlindFleetEvidenceDigest
} from '../../scripts/simulate-blind-fleet.mjs'

const QUICK_CONFIG = {
  seed: 'blind-fleet-test-v1',
  durationSeconds: 36,
  relayCount: 12,
  operatorCount: 6,
  regionCount: 3,
  churnEventsPerRelayHour: 0,
  rateScale: 0.45,
  repairScanPerTick: 800,
  invalidAdmissionProbeEvery: 31
}

test('blind fleet evidence is byte-deterministic, digest bound, and covers every generic family', t => {
  const first = runBlindFleetSimulation(QUICK_CONFIG)
  const second = runBlindFleetSimulation(QUICK_CONFIG)

  t.is(stableStringify(first), stableStringify(second))
  t.is(first.evidenceDigest, second.evidenceDigest)
  t.is(verifyBlindFleetEvidenceDigest(first), true)
  t.is(assertBlindFleetEvidence(first), first)
  t.is(first.ok, true)
  t.is(first.topology.independentFailureDomain, 'operatorId')
  t.is(first.topology.operatorCount, 6)

  for (const familyName of ['CELL', 'INBOX', 'CORE', 'FORWARD']) {
    const family = first.workload.families[familyName]
    t.ok(family.writes.generated > 0, `${familyName} writes were simulated`)
    t.ok(family.writes.committed > 0, `${familyName} commits were simulated`)
    t.ok(family.placement.operatorDiverse > 0, `${familyName} used independent operators`)
    if (familyName === 'FORWARD') t.ok(family.forward.dataFrames > 0, 'FORWARD data frames were streamed')
    else t.ok(family.reads.attempted > 0, `${familyName} reads were simulated`)
  }

  const altered = structuredClone(first)
  altered.capacity.finalUsedBytes++
  t.is(verifyBlindFleetEvidenceDigest(altered), false)
  t.exception(() => assertBlindFleetEvidence(altered), /digest does not verify/)
})

test('exact family semantics keep padded stores, leased MIRROR corpora, upstream children, and ephemeral paths separate', t => {
  const evidence = runBlindFleetSimulation({
    ...QUICK_CONFIG,
    families: { INBOX: { allocationLeaseClass: 2, retentionClass: 2 } }
  })
  const cell = evidence.workload.families.CELL
  const inbox = evidence.workload.families.INBOX
  const core = evidence.workload.families.CORE
  const forward = evidence.workload.families.FORWARD

  t.alike(evidence.semanticModel.CELL.sizeClasses, { 1: 4096, 2: 16384, 3: 65536, 4: 262144, 5: 1048576 })
  t.alike(evidence.semanticModel.INBOX.frameClasses, { 1: 4096, 2: 16384, 3: 65536 })
  t.ok(cell.writes.generatedPaddingBytes > 0)
  t.ok(cell.writes.initialPaddingBytes > cell.writes.generatedPaddingBytes)
  t.ok(Object.keys(cell.resourceClasses.committed).every(value => Number(value) >= 1 && Number(value) <= 5))
  t.ok(inbox.writes.generatedPaddingBytes > 0)
  t.ok(Object.keys(inbox.resourceClasses.committed).every(value => Number(value) >= 1 && Number(value) <= 3))
  t.ok(inbox.leaseExpiry.items > 0)
  t.is(inbox.inboxRetention.logicalInboxes, 16)
  t.ok(inbox.inboxRetention.inboxesRenewed > 0)
  t.is(core.coreReplication.mirror.persistentForLease, true)
  t.ok(core.coreReplication.mirror.logicalCores > 0)
  t.is(core.coreReplication.mirror.mirrorsCommitted, core.writes.committed)
  t.ok(core.coreReplication.openReplication.sessionsOpened > 0)
  t.ok(core.coreReplication.openReplication.bytesTransferred > 0)
  t.is(core.coreReplication.openReplication.durableApplicationBodyBytes, 0)
  t.is(core.leaseExpiry.items, 0)
  t.is(forward.durableStorage.enabled, false)
  t.is(forward.durableStorage.initialPhysicalBytes, 0)
  t.is(forward.repair.attempted, 0)
  t.ok(forward.forward.bytesForwarded > 0)
  t.ok(forward.forward.relayByteHops >= forward.forward.bytesForwarded * 2)
  t.is(forward.reads.attempted, 0)
  t.is(assertion(evidence, 'families.fixed-and-persistent-shapes-exact').pass, true)
  t.is(assertion(evidence, 'forward.no-durable-storage-or-repair').pass, true)
  t.is(assertion(evidence, 'forward.active-reservations-accounted').pass, true)
  t.is(assertion(evidence, 'core.open-replication-reservations-accounted').pass, true)
  t.is(assertion(evidence, 'core.open-replication-has-no-durable-application-body').pass, true)
  t.is(assertion(evidence, 'forward.window-credit-conserved').pass, true)
})

test('partitions, operator outage, crash, disk loss, repair, churn, and retention preserve invariants', t => {
  const evidence = runBlindFleetSimulation({
    ...QUICK_CONFIG,
    seed: 'blind-fleet-fault-test-v1',
    durationSeconds: 54,
    churnEventsPerRelayHour: 120,
    faults: [
      { id: 'partition', type: 'partition', atSeconds: 8, durationSeconds: 7, regionIds: ['region-0'] },
      { id: 'operator', type: 'operator-outage', atSeconds: 18, durationSeconds: 5, operatorId: 'operator-00' },
      { id: 'crash', type: 'relay-crash', atSeconds: 28, durationSeconds: 4, relayId: 'relay-001' },
      { id: 'disk', type: 'disk-loss', atSeconds: 38, durationSeconds: 4, relayId: 'relay-002' }
    ],
    families: {
      FORWARD: { circuitClass: 1, wireClass: 2, pathHops: 3 },
      INBOX: { allocationLeaseClass: 3, retentionClass: 1 }
    }
  })

  t.ok(evidence.faults.partitionMillis > 0)
  t.ok(evidence.faults.churnEvents > 0)
  t.is(evidence.faults.diskLossEvents, 1)
  t.ok(evidence.faults.diskLossCopies > 0)
  t.ok(evidence.reliability.repairs.succeeded > 0)
  t.ok(evidence.admissionAndRetention.expiredItems > 0)
  t.ok((evidence.workload.families.FORWARD.forward.terminalReasons.PATH_FAILURE || 0) > 0)
  t.is(assertion(evidence, 'storage.capacity-not-exceeded').pass, true)
  t.is(assertion(evidence, 'storage.accounting-exact').pass, true)
  t.is(assertion(evidence, 'retention.expired-copies-inaccessible').pass, true)
  t.is(assertion(evidence, 'repair.requires-reachable-source').pass, true)
  t.is(assertion(evidence, 'placement.prefers-unused-operator').pass, true)
})

test('saturation fails objectives honestly while capacity, accounting, and class admission fail closed', t => {
  const evidence = runBlindFleetSimulation({
    ...QUICK_CONFIG,
    seed: 'blind-fleet-saturation-test-v1',
    durationSeconds: 30,
    relayCount: 6,
    operatorCount: 3,
    regionCount: 2,
    relayCapacityBytes: 512 * 1024,
    relayBandwidthMbps: 1,
    relayMaxAdmissionsPerSecond: 20,
    rateScale: 5,
    faults: false
  })

  const rejected = evidence.admissionAndRetention.rejections
  t.ok((rejected.WRITE_BANDWIDTH || 0) > 0)
  t.ok((rejected.STORAGE_CAPACITY || 0) > 0)
  t.ok(evidence.workload.commitRate < 1)
  t.is(evidence.ok, false)
  t.is(assertion(evidence, 'storage.capacity-not-exceeded').pass, true)
  t.is(assertion(evidence, 'storage.accounting-exact').pass, true)
  t.is(assertion(evidence, 'admission.invalid-resource-class-fails-closed').pass, true)
  t.is(assertion(evidence, 'admission.attempts-accounted').pass, true)
  t.exception(() => assertBlindFleetEvidence(evidence), /simulation failed/)
})

test('every scheduled read has a per-family outcome even when no eligible object exists', t => {
  const evidence = runBlindFleetSimulation({
    ...QUICK_CONFIG,
    durationSeconds: 10,
    faults: false,
    families: { CELL: { writesPerSecond: 0, readsPerSecond: 10 } }
  })
  const reads = evidence.workload.families.CELL.reads

  t.ok(reads.scheduled > 0)
  t.is(reads.attempted, reads.scheduled)
  t.is(reads.succeeded, 0)
  t.is(reads.failed, reads.scheduled)
  t.is(reads.failureReasons.NO_ELIGIBLE_ITEM, reads.scheduled)
  t.is(assertion(evidence, 'reads.scheduled-outcomes-accounted').pass, true)
})

test('accepted demand cannot disappear at tick boundaries and a growing resource backlog fails closed', t => {
  const evidence = runBlindFleetSimulation({
    ...QUICK_CONFIG,
    seed: 'blind-fleet-resource-overload-v1',
    durationSeconds: 12,
    rateScale: 3,
    faults: false,
    relayDiskIopsPerSecond: 0.1,
    relayFsyncsPerSecond: 0.1,
    maxResourceBacklogSeconds: 1,
    maxGrowingBacklogTicks: 3
  })

  t.ok(evidence.resourceQueues.byResource.diskIops.finalBacklog > 0)
  t.ok(evidence.resourceQueues.byResource.fsyncs.finalBacklog > 0)
  t.ok(evidence.resourceQueues.maximumGrowthStreak >= 3)
  t.is(assertion(evidence, 'resources.no-growing-backlog').pass, false)
  t.is(assertion(evidence, 'resources.backlog-within-bound').pass, false)
  t.is(evidence.ok, false)
})

test('target replica recovery is an explicit sampled and final release gate', t => {
  const recovered = runBlindFleetSimulation({
    ...QUICK_CONFIG,
    seed: 'blind-fleet-target-recovery-v1',
    durationSeconds: 30,
    faults: [{ id: 'disk', type: 'disk-loss', atSeconds: 12, durationSeconds: 2, relayId: 'relay-001' }]
  })
  t.ok(recovered.reliability.targetReplicaRecovery.degradationEvents > 0)
  t.is(assertion(recovered, 'reliability.target-replica-rate').pass, true)
  t.is(assertion(recovered, 'reliability.final-target-replica-rate').pass, true)
  t.is(assertion(recovered, 'reliability.target-replica-recovery-rate').pass, true)

  const lateLoss = runBlindFleetSimulation({
    ...QUICK_CONFIG,
    seed: 'late',
    durationSeconds: 30,
    repairScanPerTick: 1,
    faults: [{ id: 'late-disk', type: 'disk-loss', atSeconds: 28, durationSeconds: 1, relayId: 'relay-001' }]
  })
  t.is(assertion(lateLoss, 'reliability.target-replica-rate').pass, true)
  t.is(assertion(lateLoss, 'reliability.final-target-replica-rate').pass, false)
  t.is(assertion(lateLoss, 'reliability.target-replica-recovery-rate').pass, false)
  t.is(lateLoss.ok, false)
})

test('FORWARD reports completion against every opened circuit and conserves explicit WINDOW credit', t => {
  const evidence = runBlindFleetSimulation(QUICK_CONFIG)
  const forward = evidence.workload.families.FORWARD.forward

  t.ok(forward.circuitsActiveFinal > 0)
  t.ok(forward.completionAmongOpened < forward.completionAmongTerminal)
  t.is(forward.terminalCoverageAmongOpened,
    Math.round(forward.circuitsTerminal / forward.circuitsOpened * 1_000_000) / 1_000_000)
  t.ok(forward.window.updates > 0)
  t.ok(forward.window.bytesConsumed <= forward.window.bytesGranted)
  t.ok(forward.window.maximumOutstandingBytes <= evidence.semanticModel.FORWARD.maximumOutstandingWindowBytes)
  t.is(assertion(evidence, 'forward.completion-among-opened').pass, true)
})

test('scenario manifest binds realized relay resources and explicit family load', t => {
  const evidence = runBlindFleetSimulation(QUICK_CONFIG)
  t.is(evidence.scenarioManifest.schema, 'hiverelay/blind-scenario-manifest/v1')
  t.is(evidence.scenarioManifest.relayCount, 12)
  t.is(evidence.scenarioManifest.relays.length, 12)
  t.is(evidence.scenarioManifest.durabilityByFamily.CELL.replicas, 3)
  t.is(evidence.scenarioManifest.offeredLoad.families.CORE.openReplicationsPerSecond, 0.225)
  t.is(typeof evidence.scenarioDigest, 'string')
  t.is(evidence.scenarioDigest.length, 64)
})

test('changing seed or operator count changes evidence and placement remains operator-aware', t => {
  const baseline = runBlindFleetSimulation(QUICK_CONFIG)
  const otherSeed = runBlindFleetSimulation({ ...QUICK_CONFIG, seed: 'blind-fleet-test-v2' })
  const fewerOperators = runBlindFleetSimulation({ ...QUICK_CONFIG, operatorCount: 3 })

  t.not(baseline.evidenceDigest, otherSeed.evidenceDigest)
  t.not(baseline.evidenceDigest, fewerOperators.evidenceDigest)
  t.is(baseline.reliability.placement.selectionViolations, 0)
  t.is(fewerOperators.reliability.placement.selectionViolations, 0)
  t.is(fewerOperators.topology.operatorCount, 3)
  t.is(fewerOperators.parameters.families.CELL.replicas, 3)
  t.exception(() => runBlindFleetSimulation({ families: { FORWARD: { circuitClass: 4 } } }), /not registered/)
})

function assertion (evidence, id) {
  return evidence.assertions.find(assertion => assertion.id === id)
}