Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Tools/windows/Invoke-MatchedActionSupplement.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ $journalBinding=New-CapJournalBinding -RunId ([IO.Path]::GetFileName($runDirecto
-ModuleSha256 $moduleHash -WorkerSha256 $workerHash `
-SupervisorSha256 $supervisorHash -Identity $selfIdentity
$journalState=New-CapJournalState -Root $root -Directory $journalPath `
-Binding $journalBinding -DeadlineUtc $leaseWindow.ExpiresUtc.UtcDateTime
-Binding $journalBinding -DeadlineUtc $leaseWindow.ExpiresUtc
Write-CapWorkerJournalSnapshot -Kind 'Bootstrap'
$startedUtc=[DateTime]::UtcNow
$primaryFailure=$null
Expand Down
32 changes: 31 additions & 1 deletion Tools/windows/Tests/UiCaptureDriver.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,35 @@ function Assert-CapRejects {
$path = Join-Path $c.State.Directory $reference.name
$null = Assert-CapRejects { Write-CapImmutableJson -Root $c.Root -Path $path -Value @{ invalid = $true } } 'SequenceConflict'
Assert-CapTest ((Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash -ceq $reference.sha256) 'Collision changed prior bytes.'
return @{ subcases = 1; priorBytesUnchanged = $true; retainedStagingFault = $true }
$newState = {
param([string]$Name, $Deadline)
$directory = Join-Path $c.Root $Name
$null = New-Item -ItemType Directory -Path $directory
New-CapJournalState -Root $c.Root -Directory $directory -Binding $c.Binding -DeadlineUtc $Deadline
}
$deadlineNow = [DateTime]::UtcNow
$lease = Get-CapLeaseWindow -GrantedUtc $deadlineNow.AddMinutes(-1).ToString('o') `
-ExpiresUtc $deadlineNow.AddMinutes(10).ToString('o') -MaximumMinutes 15 `
-NowUtc $deadlineNow
$dateTimeState = & $newState 'datetime' $lease.ExpiresUtc
$offsetDeadline = ([DateTimeOffset]$lease.ExpiresUtc).ToOffset([TimeSpan]::FromHours(7))
$offsetState = & $newState 'offset' $offsetDeadline
Assert-CapTest ($dateTimeState.DeadlineUtc.Kind -eq [DateTimeKind]::Utc -and
$offsetState.DeadlineUtc.Kind -eq [DateTimeKind]::Utc -and
$offsetState.DeadlineUtc -eq $dateTimeState.DeadlineUtc) `
'Journal deadline boundary did not preserve DateTime and DateTimeOffset UTC instants.'
$null = Assert-CapRejects { & $newState 'null' $null } 'Journal deadline is required'
foreach ($kind in @([DateTimeKind]::Local,[DateTimeKind]::Unspecified)) {
$null = Assert-CapRejects {
& $newState "kind-$kind" ([DateTime]::SpecifyKind($lease.ExpiresUtc,$kind))
} 'explicitly UTC'
}
$null = Assert-CapRejects {
& $newState 'expired' ([DateTime]::UtcNow.AddSeconds(-1))
} 'JournalExpired'
return @{ subcases = 6; priorBytesUnchanged = $true; retainedStagingFault = $true
dateTimeUtc = $dateTimeState.DeadlineUtc; dateTimeOffsetUtc = $offsetState.DeadlineUtc
nullRefused = $true; nonUtcKindsRefused = 2; hardDeadlineRefused = $true }
}
Invoke-CapTest 'numbered journal reader retries only transient Open failures within count and deadline' {
$progress = Invoke-JournalConcurrentContract -Name 'retry-to2' -LockedFirst -Publications 2
Expand Down Expand Up @@ -3026,6 +3054,8 @@ function Invoke-CapMatchedContracts {
$actionInvokeSource.Contains('-DefinitionsOnly') -and
$actionInvokeSource.Contains('$actionSupplementMode=$true') -and
$actionInvokeSource.Contains('$journalState=New-CapJournalState') -and
$actionInvokeSource.Contains('-DeadlineUtc $leaseWindow.ExpiresUtc') -and
-not $actionInvokeSource.Contains('$leaseWindow.ExpiresUtc.UtcDateTime') -and
$actionInvokeSource.Contains("Write-CapWorkerJournalSnapshot -Kind 'Bootstrap'") -and
$actionInvokeSource.Contains("Write-CapWorkerJournalSnapshot -Kind 'Terminal'") -and
$workerSource.Contains("'s-tabs-hover-close-action-result'") -and
Expand Down
5 changes: 5 additions & 0 deletions Tools/windows/UI-CAPTURE-SCENARIOS.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ publication is written only after held cleanup and stream EOF collection, and
the sanitized action manifest retains its binding, publication chain and
terminal hash without changing the static-capture inventory.

Journal state creation normalizes an accepted `DateTimeOffset` to its UTC
instant and accepts `DateTime` only when its `Kind` is explicitly UTC. Null,
local/unspecified `DateTime`, foreign types and already-expired deadlines fail
before any numbered publication or launcher release.

The focused contract reproduces the C8R terminal scale with exactly 679 process
entries and a numbered terminal larger than 1.48 MB, then injects more than one
second of post-copy validation. It also retains explicit refusals for a copy
Expand Down
26 changes: 24 additions & 2 deletions Tools/windows/UiCaptureDriver.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -5167,6 +5167,24 @@ function ConvertTo-CapUtcInstant {
}
}

function ConvertTo-CapUtcDateTime {
param(
[Parameter(Mandatory)][AllowNull()]$Value,
[Parameter(Mandatory)][string]$Field
)
Write-CapTrace -Command $MyInvocation.MyCommand.Name -Parameters $PSBoundParameters

if ($null -eq $Value) { throw "$Field is required." }
if ($Value -is [DateTime]) {
if ($Value.Kind -ne [DateTimeKind]::Utc) {
throw "$Field must be an explicitly UTC DateTime."
}
return $Value
}
if ($Value -is [DateTimeOffset]) { return $Value.UtcDateTime }
throw "$Field must be a UTC DateTime or DateTimeOffset."
}

function Get-CapLeaseWindow {
[CmdletBinding()]
param(
Expand Down Expand Up @@ -5322,8 +5340,12 @@ function Assert-CapJournalBinding {
function New-CapJournalState {
[CmdletBinding()]
param([string]$Root, [string]$Directory, [Parameter(Mandatory)]$Binding,
[Parameter(Mandatory)][DateTime]$DeadlineUtc, [string]$ObservationPath = '')
[Parameter(Mandatory)][AllowNull()]$DeadlineUtc, [string]$ObservationPath = '')
Write-CapTrace -Command $MyInvocation.MyCommand.Name -Parameters $PSBoundParameters
$normalizedDeadline = ConvertTo-CapUtcDateTime -Value $DeadlineUtc -Field 'Journal deadline'
if ($normalizedDeadline -le [DateTime]::UtcNow) {
throw (New-CapJournalFailure 'JournalExpired' 'Journal deadline reached before state initialization.')
}
$directoryPath = Assert-CapArtifactPath -Root $Root -Path $Directory
if (-not ([IO.File]::GetAttributes($directoryPath) -band [IO.FileAttributes]::Directory)) {
throw 'Journal requires an existing dedicated directory.'
Expand All @@ -5334,7 +5356,7 @@ function New-CapJournalState {
Assert-CapJournalBinding $Binding $Binding
return [pscustomobject]@{
Root = [IO.Path]::GetFullPath($Root); Directory = $directoryPath; Binding = $Binding
DeadlineUtc = $DeadlineUtc; ObservationPath = $ObservationPath
DeadlineUtc = $normalizedDeadline; ObservationPath = $ObservationPath
HighestObserved = 0L; LastApplied = 0L; Sequence = 0L; PreviousHash = ('0' * 64)
Published = [Collections.Generic.List[object]]::new()
Accepted = [Collections.Generic.Dictionary[long,string]]::new()
Expand Down
Loading