diff --git a/corpus/conflict-page/README.md b/corpus/conflict-page/README.md index ffe296770ee5a58ef7a9d29c5301215a1dbf9bfa..b540b343d993dd2cbdaaa87cdd456213cefbe955 100644 --- a/corpus/conflict-page/README.md +++ b/corpus/conflict-page/README.md @@ -58,6 +58,11 @@ holding A's edit, in a new series where A had it; B's version stays in the recyc - `native-restore`: from One, Two, Target, Three, Four, A moved Four before One (re-seriesing One, Two, Target, Three) and B deleted Target: Four, One, Two, Target, Three. +`series-move` is `a_move_after_a_native_merge_drops_its_empty_series` +(`crates/onestore/tests/page_movement.rs`, `ONESTORE_EMPTY_SERIES_EXPORT`): Rust moves a +page of `native-pages/merged`, giving it a series of its own and dropping the empty +series; OneNote's cold read (`cold`) keeps every byte after the header. + `page_moves_and_a_removed_page_merge_as_onenote_merges_them` in `crates/notebook/tests/sync_pages.rs` replays both with Snowbound's queue, A's moves as moves of the pages A re-seriesed, and reaches OneNote's order. diff --git a/corpus/conflict-page/series-move/candidate/synthetic.one b/corpus/conflict-page/series-move/candidate/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..75084eb9bc4aa62589ed9ddc0c31d995a55099c2 Binary files /dev/null and b/corpus/conflict-page/series-move/candidate/synthetic.one differ diff --git a/corpus/conflict-page/series-move/cold/commands.jsonl b/corpus/conflict-page/series-move/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..1561461d6e8c2b377b7a80a0691cd691c30f190f --- /dev/null +++ b/corpus/conflict-page/series-move/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-BAB2A5E1 -ExpectedPages 6", "exit": 0, "stdout": "Read 1 sections and 6 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/conflict-page/series-move/cold/machine.json b/corpus/conflict-page/series-move/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..45e2ecbe277496ef6f63e165c9acb9a4ce2bdcbc --- /dev/null +++ b/corpus/conflict-page/series-move/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-bab2a5e1", "hostname": "ONE-M6-BAB2A5E1"} diff --git a/corpus/conflict-page/series-move/cold/notebook/Open Notebook.onetoc2 b/corpus/conflict-page/series-move/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..de4e9a08aee7794a4b7fac1aa4f3162c296f5df9 Binary files /dev/null and b/corpus/conflict-page/series-move/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/conflict-page/series-move/cold/notebook/synthetic.one b/corpus/conflict-page/series-move/cold/notebook/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..3f09b6bb6752e2e99baf53edb4dc3e2a39fd32d5 Binary files /dev/null and b/corpus/conflict-page/series-move/cold/notebook/synthetic.one differ diff --git a/corpus/conflict-page/series-move/cold/read/af1af4b8987109ce1e335e538910fb3860b7c57eb3b6110a06aa2114e06d69a7.attachment b/corpus/conflict-page/series-move/cold/read/af1af4b8987109ce1e335e538910fb3860b7c57eb3b6110a06aa2114e06d69a7.attachment new file mode 100644 index 0000000000000000000000000000000000000000..66b6151e91f90df6a61a19ef2f4447da278e07b2 --- /dev/null +++ b/corpus/conflict-page/series-move/cold/read/af1af4b8987109ce1e335e538910fb3860b7c57eb3b6110a06aa2114e06d69a7.attachment @@ -0,0 +1 @@ +Fictitious attachment for native corpus. \ No newline at end of file diff --git a/corpus/conflict-page/series-move/cold/read/environment.json b/corpus/conflict-page/series-move/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..558738690b859d204761f42546811b79ff46b25a --- /dev/null +++ b/corpus/conflict-page/series-move/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-BAB2A5E1", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/conflict-page/series-move/cold/read/hierarchy.xml b/corpus/conflict-page/series-move/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..8609425b71fd4757d515aaa6914ec0906881a10f --- /dev/null +++ b/corpus/conflict-page/series-move/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/conflict-page/series-move/cold/read/page-000.xml b/corpus/conflict-page/series-move/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..d71a7aa8e4c7c06da9f0db4de7495ba16ce0b28e --- /dev/null +++ b/corpus/conflict-page/series-move/cold/read/page-000.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/conflict-page/series-move/cold/read/page-001.xml b/corpus/conflict-page/series-move/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..1a0aaa3c40859abf0fc98bf04a71cb9d2d9448ba --- /dev/null +++ b/corpus/conflict-page/series-move/cold/read/page-001.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/conflict-page/series-move/cold/read/page-002.xml b/corpus/conflict-page/series-move/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..fee1f8cd287cf05959241a3982ec1da5d436d530 --- /dev/null +++ b/corpus/conflict-page/series-move/cold/read/page-002.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/conflict-page/series-move/cold/read/page-003.xml b/corpus/conflict-page/series-move/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..a7819ad6d77e22f21d49472f3cd29ad5bd21d739 --- /dev/null +++ b/corpus/conflict-page/series-move/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/conflict-page/series-move/cold/read/page-004.xml b/corpus/conflict-page/series-move/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..aab83066edbd248a1ec4e09bcc10d66aa68eb0ad --- /dev/null +++ b/corpus/conflict-page/series-move/cold/read/page-004.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/conflict-page/series-move/cold/read/page-005.xml b/corpus/conflict-page/series-move/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..79cbccdfc5a48a04dd373268dada7092acd1f1a7 --- /dev/null +++ b/corpus/conflict-page/series-move/cold/read/page-005.xml @@ -0,0 +1,26 @@ + +Fictitious: café, 東京, مرحبا]]>AK4FHQSiAaIBAWAqABofi0JwRYR1gL7QRdkE+oeVMvLsF0G4wBa/8yv0et67E4vlXrNInJuhJVq3 +URK/7HHMzCKxQYkOuxMs7nqhWM9UiuaXxU+PBvi60uGbIsRmbacNslhJmh1OQDQGbBADBkgQRSNG +IwUIC2VPZmdoZGkZFDIIAIAeAiHi4kEzCADwEAKLxeJBZAMVRgBACpUE/QGH81d3mq7mkzgM0mcB +mk1gEBgEBgEBgE1mUAgMzmUAmsygE1mUzmkBmc0gMzmk1mUAmsyTOaTWZQCazKZgALSmiazKATWZ +QCAwCAwBAZpM4DAJlNYBMprAJlNZpM4DNJmmU1mkzgM0mcBmkzmU1gEyAAFpTSAzOaQGZzRAYBAY +BAYBMprAIDNJnAZpM0yms0mcBmkzgM0mcymsAmU1gEyms0maZAACZTSawCZTWATKawCAoBAYBAZn +NIDAJrMoBNZlAJrMpnMoBNZlAJrMpnNIDM5pAZnNJrMkzmk1AACH8C7XgWnmkzgM0msAmU1gEBgE +BgEBTOaQGATWZQCazKATWZTOaTWZTNNJrMpmmUzTSaplM00mqZTOaTVMpmmk1TKATKazSawCAzSZ +wGAQFAIDAJrMoBAZnNIDM5pAZnMpnNJrMpmmk1mUzTSaplM00mqZTNNJrMpmmk1TKZplhuAzKATW +ZQCazKAIDAIDAIDNJnAYBMprAJlM4DNJnMprNJnMk1mkzmSazRM5kms0TOZJnMprNEzmSazQtKaQ +GZzRNZlAIDAIDAIDAJlNYAmU1gEymsAmU1mkzmU1miZzKazRM5kmcyTWaJnMk1mkzmSazRM5kAUU +RgBAAAAJBAUURgAAAAASABEgXhT+65lz/EiPi+8SFvjqCAk+gEcDAa/89Qd0AxVGAEAKABEg2R87 +QQrSFUA=AOECHQJSegFgKgAaH4tCcEWEdYC+0EXZBPqHlTLy7BdBuMAWv/Mr9HreuxOL5V6zSJyboSVat1ES +v+xxzMwisUGJDrsTLO56oVjPVIrml8VPjwb4utLhmyLEZm2nDbJYSZodTkA0BmwQAwZIEEUjRiMF +CAtlT2ZnaGRpGRQyCACAHgIh4uJBMwgA8BACi8XiQWQDFUYAQArKAUuH88s3nkzmkzgM0mcBmkzg +KAQGAQGATWZQCAzOaQGZzKATWZTOaQGZzSAzOaTWZQCazJM5pNZlAJrMpmAAAACH8D9XgeBJlM0z +mRNZpNZpM4DAJlNYBAUAgMAgMzmkBgE1mUAmsyTOaTWZTOaTVMpnNJqmUzTSaplM00mqZTOZTNNJ +qmUzTSagBRRGAIAAAAkEBRRGAAAAABIAESDPTQ4xwIZyTqQ8FVDbHxeKCj9AI5rARvPPUDugAxVG +AEAKABEgLMlfQdkfI0A=iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAusB9Y9J1uoA +AAAASUVORK5CYII= diff --git a/corpus/conflict-page/series-move/cold/read/payloads.json b/corpus/conflict-page/series-move/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..229effe100aa68119db3065f5255bd77f368ae3a --- /dev/null +++ b/corpus/conflict-page/series-move/cold/read/payloads.json @@ -0,0 +1,10 @@ +[ + { + "sha256": "af1af4b8987109ce1e335e538910fb3860b7c57eb3b6110a06aa2114e06d69a7", + "name": "fictitious-attachment.txt", + "object": "{15F5F520-9712-4630-BDC9-C9932963E8D2}{11}{B0}", + "kind": "InsertedFile", + "page": "{9CBAF166-4FD0-45B3-BB50-0BCAAA4F6E47}{1}{B0}", + "bytes": 43 + } +] \ No newline at end of file diff --git a/corpus/conflict-page/series-move/cold/run.json b/corpus/conflict-page/series-move/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..254fa4a9b489333970a43599550ca41987e27e79 --- /dev/null +++ b/corpus/conflict-page/series-move/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/Users/clo/dev/one/evidence/series/empty-series", + "expected_pages": 6, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/conflict-page/series-move/cold/scripts/cold.ps1 b/corpus/conflict-page/series-move/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/conflict-page/series-move/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/conflict-page/series-move/cold/scripts/read.ps1 b/corpus/conflict-page/series-move/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/conflict-page/series-move/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/conflict-page/series-move/cold/source.json b/corpus/conflict-page/series-move/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..200d0ed30d5bde12015795462984fa4e0b6d62e1 --- /dev/null +++ b/corpus/conflict-page/series-move/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "synthetic.one", + "bytes": 67768, + "sha256": "7c55e483f464d329e7bb394813d202bc1295f0a24ecc895a3c81fa3b582a02bd", + "mtime_ns": 1790524980196111805 + } +] diff --git a/corpus/conflict-page/series-move/cold/teardown.json b/corpus/conflict-page/series-move/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/conflict-page/series-move/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/notebook-management/README.md b/corpus/notebook-management/README.md new file mode 100644 index 0000000000000000000000000000000000000000..740888260d744b036414238a591958a4aad90288 --- /dev/null +++ b/corpus/notebook-management/README.md @@ -0,0 +1,38 @@ +# Notebook management + +`candidate` is the notebook `a_notebook_is_managed_as_onenote_manages_one` in +`crates/snowbound/src/manage.rs` makes through the calls the app makes: `Notebook::create` +(a table of contents in the notebook colour OneNote gave new notebooks, and "New Section 1" +holding a page with OneNote's title date and time fields); new sections in OneNote's +new-section colour order and groups; pages created with `SectionOp::Create`, titled with +`Text`, given our Ivy art as a background picture (`template_ops`) or the Teal page colour +(`PageOp::Color`), and made a subpage; a page given Informal Meeting Notes (the art and +the template's outlines, lowered to ops from the page model `meeting.rs` builds); a page deleted to the recycle bin +(`Notebook::recycle_pages`, then `SectionOp::Delete`); a page moved to another section +as a drop on its tab moves it (`notebook::session::moved`, then `SectionOp::Delete`); a section renamed and moved into a +group, the group renamed, a group and a section deleted to the recycle bin, and the root +reordered. + +`cold` is its fresh OneNote 2010 read: the hierarchy lists every section, group and page +where the app put it, with its colour; the recycle bin holds "Deleted Pages" +(`isDeletedPages`) with the deleted page, and the deleted group's and section's files; the +Teal page reads back `color="#D4F9F2"`, the Ivy page one background image, the Meeting +page OneNote's four outlines with their numbering, to-do tag and bullets, and the +screenshots show the art, the colour and each title's date and time. OneNote left the +files' identities as written. `tools/test_notebook_management.py` checks this without a VM. + +`native` is what OneNote 2010 did through its own interface on the VM. `new-notebook`: +File, New made "New Section 1" with an "Untitled page" titled with the date and time +(`created`); New Section named sections "New Section N"; a section dragged onto a group +moved into its folder (`moved`); deleting a page copied it into +`OneNote_RecycleBin/OneNote_DeletedPages.one` (grey) with its identity, title and +creation time, and deleting a group moved its sections into the recycle bin and removed +its folder (`final`). `section-colors`: sixteen sections made with New Section, whose +colours are the order new sections take. `page-color`: View, Page Color stores +`0x14001d2a` (COLORREF) on the page node and "No color" removes it; `colors.txt` is each +of the sixteen colours as the page XML reports it, in the menu's order. `meeting-template` +is the page XML of a page made from Business, Informal Meeting Notes. + +Regenerate with `SNOWBOUND_MANAGEMENT_EXPORT` set to a new directory while running the +test, then `tools/native_runner.py OUTPUT COLD --expected-pages -1 --collect-notebook +--screenshots`. diff --git a/corpus/notebook-management/candidate/Archive/Inner.one b/corpus/notebook-management/candidate/Archive/Inner.one new file mode 100644 index 0000000000000000000000000000000000000000..3c2ba163fbc30575f8b08d0b11d986535f61a681 Binary files /dev/null and b/corpus/notebook-management/candidate/Archive/Inner.one differ diff --git a/corpus/notebook-management/candidate/Archive/Kitchen.one b/corpus/notebook-management/candidate/Archive/Kitchen.one new file mode 100644 index 0000000000000000000000000000000000000000..5962d483ac23f9553469c62a67f46989809d1955 Binary files /dev/null and b/corpus/notebook-management/candidate/Archive/Kitchen.one differ diff --git a/corpus/notebook-management/candidate/Archive/Open Notebook.onetoc2 b/corpus/notebook-management/candidate/Archive/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..dedfd5215945f6ad75e1fccb1a8177b8e10d922e Binary files /dev/null and b/corpus/notebook-management/candidate/Archive/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/candidate/New Section 1.one b/corpus/notebook-management/candidate/New Section 1.one new file mode 100644 index 0000000000000000000000000000000000000000..e0165ec08fc5def1d657b30a897322c8cec67ed3 Binary files /dev/null and b/corpus/notebook-management/candidate/New Section 1.one differ diff --git a/corpus/notebook-management/candidate/OneNote_RecycleBin/Binned.one b/corpus/notebook-management/candidate/OneNote_RecycleBin/Binned.one new file mode 100644 index 0000000000000000000000000000000000000000..58c3ded0a9e206b0cfa74314573980d4a8b80d5a Binary files /dev/null and b/corpus/notebook-management/candidate/OneNote_RecycleBin/Binned.one differ diff --git a/corpus/notebook-management/candidate/OneNote_RecycleBin/Gone.one b/corpus/notebook-management/candidate/OneNote_RecycleBin/Gone.one new file mode 100644 index 0000000000000000000000000000000000000000..323c0959345c375689929e184e118bba7c2bbdc9 Binary files /dev/null and b/corpus/notebook-management/candidate/OneNote_RecycleBin/Gone.one differ diff --git a/corpus/notebook-management/candidate/OneNote_RecycleBin/OneNote_DeletedPages.one b/corpus/notebook-management/candidate/OneNote_RecycleBin/OneNote_DeletedPages.one new file mode 100644 index 0000000000000000000000000000000000000000..5d5029ff8df9d995ccae84c336437513a8d124d2 Binary files /dev/null and b/corpus/notebook-management/candidate/OneNote_RecycleBin/OneNote_DeletedPages.one differ diff --git a/corpus/notebook-management/candidate/OneNote_RecycleBin/Open Notebook.onetoc2 b/corpus/notebook-management/candidate/OneNote_RecycleBin/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..77840fd4927a26d842ce933e6ad13199191d6e62 Binary files /dev/null and b/corpus/notebook-management/candidate/OneNote_RecycleBin/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/candidate/Open Notebook.onetoc2 b/corpus/notebook-management/candidate/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..78a587ca72eb2b4e4a34dd6e3da20a93b5a4399a Binary files /dev/null and b/corpus/notebook-management/candidate/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/cold/commands.jsonl b/corpus/notebook-management/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..bdc582b97c968d6bba445f644c38bfe888998749 --- /dev/null +++ b/corpus/notebook-management/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-C64C87EA -ExpectedPages -1 -KeepOpen", "exit": 0, "stdout": "Read 6 sections and 11 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/notebook-management/cold/machine.json b/corpus/notebook-management/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..aef822426d5ea4ba407e22b013a346495a932367 --- /dev/null +++ b/corpus/notebook-management/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-c64c87ea", "hostname": "ONE-M6-C64C87EA"} diff --git a/corpus/notebook-management/cold/notebook/Archive/Inner.one b/corpus/notebook-management/cold/notebook/Archive/Inner.one new file mode 100644 index 0000000000000000000000000000000000000000..3c2ba163fbc30575f8b08d0b11d986535f61a681 Binary files /dev/null and b/corpus/notebook-management/cold/notebook/Archive/Inner.one differ diff --git a/corpus/notebook-management/cold/notebook/Archive/Kitchen.one b/corpus/notebook-management/cold/notebook/Archive/Kitchen.one new file mode 100644 index 0000000000000000000000000000000000000000..5962d483ac23f9553469c62a67f46989809d1955 Binary files /dev/null and b/corpus/notebook-management/cold/notebook/Archive/Kitchen.one differ diff --git a/corpus/notebook-management/cold/notebook/Archive/Open Notebook.onetoc2 b/corpus/notebook-management/cold/notebook/Archive/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..dedfd5215945f6ad75e1fccb1a8177b8e10d922e Binary files /dev/null and b/corpus/notebook-management/cold/notebook/Archive/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/cold/notebook/New Section 1.one b/corpus/notebook-management/cold/notebook/New Section 1.one new file mode 100644 index 0000000000000000000000000000000000000000..0c4cdcb43cf46c6558336ae39699c6bfa2712a05 Binary files /dev/null and b/corpus/notebook-management/cold/notebook/New Section 1.one differ diff --git a/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Binned.one b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Binned.one new file mode 100644 index 0000000000000000000000000000000000000000..58c3ded0a9e206b0cfa74314573980d4a8b80d5a Binary files /dev/null and b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Binned.one differ diff --git a/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Gone.one b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Gone.one new file mode 100644 index 0000000000000000000000000000000000000000..323c0959345c375689929e184e118bba7c2bbdc9 Binary files /dev/null and b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Gone.one differ diff --git a/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/OneNote_DeletedPages.one b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/OneNote_DeletedPages.one new file mode 100644 index 0000000000000000000000000000000000000000..5d5029ff8df9d995ccae84c336437513a8d124d2 Binary files /dev/null and b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/OneNote_DeletedPages.one differ diff --git a/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Open Notebook.onetoc2 b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..77840fd4927a26d842ce933e6ad13199191d6e62 Binary files /dev/null and b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/cold/notebook/Open Notebook.onetoc2 b/corpus/notebook-management/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..78a587ca72eb2b4e4a34dd6e3da20a93b5a4399a Binary files /dev/null and b/corpus/notebook-management/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/cold/read/environment.json b/corpus/notebook-management/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..f7eb402d6aa1a310167f9d76ccc2b8ff049c8835 --- /dev/null +++ b/corpus/notebook-management/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-C64C87EA", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/notebook-management/cold/read/hierarchy.xml b/corpus/notebook-management/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..f695994113f6b0f0bf7dd261ee60615c00802ea9 --- /dev/null +++ b/corpus/notebook-management/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/notebook-management/cold/read/page-000.navigation.json b/corpus/notebook-management/cold/read/page-000.navigation.json new file mode 100644 index 0000000000000000000000000000000000000000..ac6854758e1c1c8293a873d4b0e7f108b6dd562c --- /dev/null +++ b/corpus/notebook-management/cold/read/page-000.navigation.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Ivy page - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/notebook-management/cold/read/page-000.png b/corpus/notebook-management/cold/read/page-000.png new file mode 100644 index 0000000000000000000000000000000000000000..f81b30607798ee8a9aa453077d6a7bdcf98f7ce2 Binary files /dev/null and b/corpus/notebook-management/cold/read/page-000.png differ diff --git a/corpus/notebook-management/cold/read/page-000.xml b/corpus/notebook-management/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..a68f4ab1bcb13e59b26ff556fa55e650fc679fd0 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-000.xml @@ -0,0 +1,353 @@ + +/9j/4AAQSkZJRgABAgAAAQABAAD//gAYU25vd2JvdW5kIHRlbXBsYXRlIGl2ef/AABEIAxgA2AMB +EQACEQEDEQH/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsL +EBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQU +FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQID +BAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHB +FVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2 +d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna +4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1 +EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ0 +4SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeI +iYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery +8/T19vf4+fr/2gAMAwEAAhEDEQA/AP1ToAKAOS8f+KbvwbFYamkX2nThL5V3EB8wDfdcH2wRjoc1 +5GYYqpg+SqleN7NfkzGtV9jDnauup0el6nbazp8F7aSCW2nUOjjuK9KlVhXgqkHdM1TUldbHK/Cf +/kW7r/sIXH/odeblf8F/4pfmcGB/hv1Z2leuegFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQBW1HTrbVrGazu4lntpl2PG3QisqtKFaDpzV0xNKSszmNP0uP4X+ENUZLh7y1t +vMuIUkGCgxwme/PfjrXlU6X9l4ao+bmSu1/l95lCEcPTstlf/Mz/AIM3Dt4GM03+ta6mZsjHzFuf +1qMok3hOZ73Zx4Bv2Lb7s7yBzJErHqRXtxd0ekSVQBQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFADZHWJGdyFVQSWPQCk2oq7ASGZLiJZInWSNxlXQ5DD1BpRkppSi7oDn4/FunXmt +3+g6gi211EC3lXGDHPFjO5SeDx1HbB64zXmrGUZ1Z4asrNd9mt7/AHb/APAJU1z8iepj/C8ed4Su +9ufmv7gjj/brDLfew7a/mf5nDg1+6a83+Z3ESeXGq+gr2krI9AZ9oVpNi5Y98dBU82tkFyarAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgBCAwIIyD2NG4HkFrf6j8J/GI0+5Ly+F7+ +U+Q7ZIhLHoD2weCO45r46E6mUYn2Uv4Unp5f8N17rU83mnh63LL4JbeT7eh1/ivwtb+MNQSVVMd1 +puDFdREK3mnDKpJB+UDkjB+9x3B9PGYVY6p7u8Ovnul6Ld+unVP03Sg+WUt07ry/4crfClhH4cnE +gDZv7gb8cZ31eWaUXzfzP8zz8F/Dfq/zOz3gswUHaOCe1evfsd5IkaxjCgCrSS2AfTAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDGu/GGi6fqDWN3qMFrdLg+XO2zIPcE4B/CuGeNw +9Obpzmk/PQlyinZtXIPFHiPw/p2j+bq9xay2UudsbYk83H91ec1ni8VhIUr12nF9N7+iCUlTXNJ2 +RzHgb4mw6/dw6fY6PfTb2Lz3QVRHGWJJJ56DOB344FeTl2ZKs1ShTbb1b0sr6v5L/hjOOJhXn7id +u9tC98Kw58Pz44UX9znHf5+ld2Wp+yf+KX5nLgf4b9WdkgckqfuZyDjH4V6yu9D0AnhkY5jkK+3a +nJN7CYsJlHEij/eFC5uoK/UmqxhQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBzPjfw +Hp/jiwEVyPJuowfJukHzJ7e49q83G4CnjY2lpJbP+uhz16EMRHlmeG6r4L8WeA5J9kU01kwKtLbf +vIXU/wB5e34ivhcRgsTg+bmT5e61X9eqPHjRxuDlej7y/rp/ke3fD3xUfFGjbpdPk027gIWWExFE +J7FMjpx07fln7bLsX9apax5Wt9LL5f1oe3SqSqwUpRafZlD4USn+w7iMDj7dckn/AIGajLH+6a/v +S/M48C/3b9X+Z2lyWWIsnVea9eV7aHoMdE/mRq3qKad1cY+mAUAFABQAUAFABQAUAFABQAUAFABQ +AUAFABQAUAFABQAUAFAFW81Oz05d11dQWw9ZpAv86xqVqdL+JJL1dgMbU/Eujalpt3bQavYtPJEw +QC4TO7HHf1xXn4jFYetRnCFRXadtVv0KpySktTctLpb2yhuYsMssYkT3BGRXo06iq01Uj1VxNcrs +zi/g3E8fhKTzcGYXk6uR6huf1rycoTWH97e7POwX8N+rO6r2z0BEQRrgdKSVgHUwCgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgDP1zSTrenvai8urAtz51pJsce2fSubEUPrEOTmcfNOzB +q6seN678AtXed5bPVYr7P/P2WV/z5zXyFbIq6d6clL10f6niVsulUd1Ub9f6/Qx4PgP4mlkCv9jh +Xu7TZx+QrmWS4xuzSXzOVZVUvrJfieo/DTwZL4Ma7tLjUp7qbapEOSIAp/iVT3yCPw96+hyvBywc +pwnLXt0s+q873X/Dnv0KHsKaXM5evQn+E/8AyLd1/wBhC4/9Drpyv+C/8UvzOXA/w36s7OvXPQFo +AKACgBKAFoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAKl9ZtP5csJCXMOTG56c9V +Psf8D1Arnq03O0oaSW3+T8n/AMHdFRdtHscp8JCW8MXBKlSb+4yp7fP0rz8qd6Dv/M/zPNwX8N+r +OuvSRASOCCDmvVnsd72FtbgTp/tDqKIyuCdyerGFAFO5nxcxoOgIzWUnrYlvWxcrUoKAEoAiNyvm +BF+Zj6dqhy6IVyarGFABQAUAFABQAUAFABQAUAFABQAUAFABQAnSgBEdZEDIwZT0KnINJNSV0Bxv +wn/5Fu6/7CFx/wCh15OV/wAF/wCKX5nn4H+G/VnYTp5kLj2r1ZK6PQ3MuGUwyBh26iudOxinZmur +BlBHQ11J3NhaAMkHzbr6tXNuzLeRrV0mohOBk0AZ11eGQ7U4T+dYSlczcuxLYQYHmHv0qoLqOKLt +alhQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHnGreDtd8Ma2dU8JzB7WVt1xpMr4jJ77AeB+hH6 +V8zVwWIwlX22B2e8en9fijknTqxnz03p1T2+XY0PhE5k8LTsylGa+uCUPVTv6V3ZU70G3/M/zMsF +/Dfqztq9g9Ay7uHyZT/dPIrnkrMykrFuwfdDj+6a0g9C47FqtCijbW5FyxPRTxWMY6kJa3L1bFlL +UJsARjvyaym+hEmQWtqZmyeEH61EY3JjG5pgYGB0FdBqLQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQBn63rdr4esGvb0ulshAeRELbM9yBzj3rnxGIhhoe0qbfeJtRTb2OX+EM6XHhaaSNgyPezup +9QX4NedlUlKg2u7/ADODAu9J+rO4r2T0BksSyptYUmrhuRW0P2bcCc5PGKiK5dxJWJdzHov5mqu+ +wxcsP4R+Bo1AAwJx0PoadwImtFklLtk+1TyXd2KxMBgYHAqxi0AJmgAoAWgAoAKACgAoAKACgAoA +KACgAoAKACgAoAjngjuYXilRZIpFKsjDIYHqDUyippxkrpgeffC61+zeF5BCCI4rydBjsA/FeHls +eWg0tk3+Z5eDVqbt3Z21tfHIWTkf3q9iM+56Cl3LrHHTqa1bNAC4+vrQkA6mAUAV/PEk/ljkDqaz +vd2FfUmU84PX+dWuwxJZREhY0N2DYzpbySQ8HaPQVg5NmTk2JHBLMeAfqaSTYWbLtvaiHkks1bRh +Y0SsWKsYUAFABQAUAFABQAUAFABQAUAFABQAUAFAHFfCf/kW7r/r/uP/AEOvIyz+C/8AFL8zz8D/ +AA36s657SKQ524PtXqOCZ3tJj4l2jvgcDPpTihjLgyoN0ZzjquKUrrVCd+hFFqAJxINvuKlT7kqR +PcSbIGYenBq5PS5T0INPiIBkPfgVEF1Jiiy/GD6GrfcsdVAJsA7ClZAOpgFABQAUAFABQAUAFABQ +AUAFABQAUAFABQAUAFAHF/Cf/kW7r/sIXH/odeRlf8F/4pfmefgf4b9WdnXrnoABgUALQBC0Ecjs +WUcVHKmwsL+78j/pnRpbyAEuI3OFYfSmpJivcc/QD1IoYx1UBEbuJT98fhU8yFdDkmST7rA+1Ckm +MkqgCgAoAKACgAoAKACgAoAKACgAoAKAGSyLDE8jnCICxPoBSk1FNvoBwt98bfC1lKUW4nuSDgmG +E4/XFeFPO8JF2V36L/OxxTxmHg7OX5mn4e+Jvh7xNcLb2l8EuW4WGdSjMfQZ4P4GunD5nhsTLkjK +z7PT/gGtPEUq2kJXKvwn/wCRbuv+whcf+h1OV/wX/il+Zz4H+G/VnaV656AUAFAFK/kK/IP4utYz +ZMn0LFumyBVPpWkVZDWhXmsB95G2+xqJQ7EuPYltllHEnOOhpxv1KV+pPWgynLZeYMpww4IPeseS ++xMo3KjwvEfmUj3rNpozs0TQXrRnDfMv6iqUmilLuaEciyLuU5Fbp3NB1MAoAKACgAoAKACgAoAK +ACgAoAKAOC8Y/B3R/FMz3URbTb5+WlhAKOfVl/qMV4OLyijiXzwfLL8Pu/yOKvg6WI1krPujk7D9 +ndku1a71oGBSDiCHa5/Ek4/WvLhkEub36mnktTjhlcIyu5v8jsvhFH5XhadMs22+uBljkn5+5r2s +qXLQa/vP8zpwP8N+rO1ZwgyxAHvXrt2PQI1uo3farZJ9BU8yYromqxkBtg9wZG5x0FRy3d2K2tyX +YO2R9DTsMAgB9frTsA6mAxZVZioI3DtSumADh2HrzQtwHUwGmND1UH8KVkAqoqdAB9KEkgHUwCgA +oAKACgAoAKACgAoAKACgAoAKACgDg/hhdCDw1cgcub+4/wDQ68XLpWov/FL8zzcG7Un6s6XEly/d +j/KvR1kdmsi/a2ogGTy571tGNjRKxYqyhMjOM8jtRcBaAEyM47+lAC0AZ19GUl3jv396wmrMzl3J +bS58xlVvvDIz604yu9SoyuXK2KCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAEoA4f4TW8f/AAjU ++Ru231wAWOT9+vGyuK9g/wDE/wAzz8F/DfqzuAAowBge1eyegLQBXu7nyFwPvn9KiUrEt2ItOyzS +Mec4qICiXa2LM6ecpebv7vFYN+8Zt2ZoA5Fbmg2WMSoVPek1cNzMkje1lHtyD61ztOLMbcrNSN/M +QMO4roTujYdTAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4v4T/wDIt3X/AGELj/0OvIyv+C/8 +UvzPPwP8N+rO0r1z0BCcCgDImkM0pb16Vyt3MW7s0rWHyYgO55NdEVZGqViaqGZV4u24euaW5lLc +0of9Un0FdEdjUfTAjmQSBVYZBNTJXDcIYvJTbnIHSiKsGxJVAFABQAUAFABQAUAFABQAUAFABQBz +/h3xZDr2qa3ZABJNNuPKP+0uPvfmGH4V52FxixFSrT/kdvl/w9yIzjJtLp/w5e/tC5vObG3Vou1x +cMVVh6qACWHucA9ia09tUq/wY6d3ovkt3+CfRm/Ko/Ewxq8fzbrKb/pmFeM/99Zb+VH+1R191+Wq +/G7/ACD3PMsWd+l0zRlWhuE5eGT7w9/Qj3HH45ranWVT3WrSW6f9arzRLjbXocr8J/8AkW7r/sIX +H/odeflf8F/4pfmebgf4b9WdpXrnoEN2+y3b34qJ7CexBZ2m3DuOewqYx6smMbF2tSwoAo6hFl0Y +d+KxmtbkSVy6o2qB6CtVoWLTAY331/E1L3QD6oAoAKACgAoAKACgAoAKACgAoAKACgDyjwp4dng+ +KniiGTJsZAJ3x0k3MGVD7cnP0IPBNfH4XDN5jWpv4d353aaX+fe1tmzmowlSr1J20la34nq9fYHS +FAFe8slu1Xlo5UOY5U+8h/z26GsalJVLdGtn1RSlY5H4S5Hhm43EFvt9xkjjJ315uV39g7/zP8zz +sF/Dfqztq9g7xGUNjIzjmi1wFoAKACgBrKG69uaTVwHUwCgBg5kPsKnqA+qAKAI5bhIfvHn0qXJI +Tdiq+o/3U/E1m59ieciN/KT2H4VPOyedifbpf7w/KjmYczHLqEg67T+FPnY+clTUR/En5VSn3Hzo +mS7if+LHsapTTKTTJutWMWgAoAKAOO0PU9OTXdVhuLK3spLS6EFvcvDjePLU/wCsI5YknvnBr57D +VcPDEVIzgouLsnby/m7/ADvqa805J32/roa/ijxdpvhDTftmoTbVbiONOXkPoo/r0r1MVjKWEhz1 +HvsurOapUhRjzTdkeX3Hx81C6Mr6docf2eMZaWeQkKP9rGAPzr5eefVXd06at53f+R5yx7nrTpu3 +duyOa8Q/GXxF4jRLW0xp6twRZbt8h+vUfQYrgr5tisQuW/L6f57/AHHFWzCpVfJQX+fy/q/oem/B +KBl8Gq0u7zVuJVYN1B3c596+nyeP+zK/dnfl6ao673Z6FXunphQAUAFABQAUAFABQAxORn15qV3A +dVAUrm95Kx/99VjKfYhy7FInJ5rMyCkAUAFABQA6ONpGwoJppXGlcvQWKpy/zH07VsodzVRsWq0K +FoAKACgDzt9EXX9VbRpdPe70a1t4mguNQjcvG5dvMO6QbmJAAx06dq+UdH61V+rcjcIpWck7rXXV +6u+1ttuhfIl8aTX366nRXF94WNzHpNxLpfnW+ES0l8vMfTgKenavXlPA3VCfLeOlnbQzcle19Sv4 +j+Hem+KBbx3Mk8NjBylnalY4i394gDJOOP5dTU4jLaWJaTbUV0VkvXYzq0oVlyz1Rd0DwRofhk7t +O06KGXGPOI3P/wB9HJrfD4DD4bWnDXvu/wARwpQpK0FYyPhP/wAi3df9hC4/9Drnyv8Agv8AxS/M +48D/AA36s7SvXPQCgAoAKACgAoAKAGv0x3PFJ9gFAwKYEV0kkkeEIHr71Ek3sJmY8Txn5lIrBqxi +00NpCCgA60ASx20knRT9TxVKLZSiy1Fp4HLnPsK0UO5aii0iKgwoAHtWiVix1MAoAKACgAoA4S98 +ezaV8UYdBuAv2C6t0ETY5WU7sHPcH7v4D3rwJ4+VLMPq8/haX3/8HY5pV+WuqL6q/wAyLx78OrPx +3dS9NP1eBAY5xys8Z6bh7HI45HHYipx2AhjpyS92a69GvP0enlp3QsTg4YiKb0fcyvAw8X+B71NM +1izm1HR3bZHc2583yPfj5tvqCOO3cHkwTxuAmqVaDcO61t+tvL7vPLDxxFJ8lT3l0f8Ameq19Yd5 +xfwn/wCRbuv+whcf+h15GV/wX/il+Z5+B/hv1Z2leuegFABQAUAFABQAUAMX5ju/KktdQH0wCgBC +M0AMaCNuqL+VTyoBBbRD+BaOVBYeqKvRQPoKdkgHUwCgAoAKACgAoAKACgDzn4meEpr/AMQeG9at +ELPbXkMU+3rsMgIb8Dkf8Cr5rNMLKdaliIdGk/v0Zy1qLqVKc1vF/gdxqkEjRpcQLuubc7kUfxr/ +ABJ+I/UA9q9vEQk0qkPijt5918/zs+h2xfR7MtW86XUEc0Tbo5FDKfUGt4TVSKnHZktWdmSVYji/ +hP8A8i3df9hC4/8AQ68jK/4L/wAUvzPPwP8ADfqztK9c9AKACgAoAKACgBrfMdv50nroAtMBaACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKAM2w/wBE1C6s/wCA/wCkRD0DE7h+DZP/AAMVxUf3dWdH +p8S+e6+/X5mktUpfIZd+JbG112z0cuZL+5DMIk52IATub0HGKc8VThWjQ3lL8PNmPNHm5b6mB8J/ ++Rbuv+whcf8AodcmV/wX/il+Zw4H+G/VnaV656AUAFABQAUANY46dTSbAUDAoSsAtMAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoA5/xdqY8PWqawV3C2SVWX1UoWA/76RPzrysfV+rKOJ7XX3q/5 +pFppQlfor/ccR8G/D9/eXt94r1bcbm9BWEyDkqTkt7DgAew+leTk+HqTnLGVt3t593/keVg4TfNX +qby/I6P4T/8AIt3X/YQuP/Q69TK/4L/xS/MrA/w36s7SvXPQCgAoAKAEJx/hSbsBFJMsHLnlvSpb +5dwbsM+3xep/KlzonmRItzE/Rx+NVzJjumSVQxaACgAoAKACgAoAKACgAoAKACgAoAKACgAoAyfF +MEdxoV0Jo1liQLIyOMghWDEEenFefj4xlh5cyulZ/c7/AKGlP4rGqqhVAAAA4AHavQStojM4z4T/ +APIt3X/YQuP/AEOvIyv+C/8AFL8zz8D/AA36s7SvXPQCgAoAazY9z6UmwADHJ60WAhvo98Ge681E +1oTJXRmVgYhQBJHO8R+Vj9KpNopSaL0F6svDfK36VrGd9zRSuWa0KCgAoAKACgAoAKACgAoAKACg +AoAKACgClrSeZo98vXdBIMf8BNc2KXNQqLyf5Fw0kie0fzbWF+u5FP6VrTfNBPyJejOR+E//ACLd +1/2ELj/0OvMyv+C/8UvzPOwP8N+rO0r1z0AoAbuzwv5+lK/YBQuP8aErALTAQjIxQBk3EPkyle3a +uZqzMZKxHUkhQAUAXLS8x8jn6E1rGVtGaxl0ZfrYsKACgAoAKACgAoAKACgAoAKACgBgmjL7A6lh +/CDzU88W7XHZlXWn8vR75s42wSHP/ATWGKfLQqPyf5FQ1kie0j8q1hTptRR+la01ywS8iXqzkfhP +/wAi3df9hC4/9DrzMs/gv/FL8zzsD/DfqzsTIB05r1eZHoABv6nj0FG+4DulUAtABQAUAQ3MAnTH +8Q6GplG4mrmW6FGKkYIrn2MWrCUhBQAUAX7K53jY3UdD61tCXQ1i7lytSwoAKACgAoAKACgAoAKA +CgAoA4/xn8M9N8XSfagz6fqYGBdwcFh6MO/16142Nyuji3zr3Z9/8zCrRjV6tPutynpHh7XvD2iX +djqmsJq1rNsghLIfNUs4XGSeRg9DnHrXJHD4nD0JUq1Tmi7Jb31aX3am2GhOm/flzW8rHeV9IM4f +4Wxeb4YugGKn7fcdP9+vGy1c1B/4pfmefgv4T9WdDNA8R+YH616DTR1NMYCVPBI+lSK5PFeyRnk7 +h71ak0UpF2G5SfpwfQ1spJmidyaqGFABQBDcWyzr6MOhqJRuJq5myxNC2GFYNWMWrDKQgoAVWKMC +OopjWhrQSiaMN+Yroi7o2TuSVQwoAKACgAoAKACgAoAKACgAoAzdS/f6jp1t/ttcMP8AZQY/9CZf +yrir+/Vp0/Nv5Jf5tGkdItmlXaZnE/CpxH4ZumY4A1C4/wDQ68fLHag/8T/M8/Bfwn6s7JZo5OAy +n2r1uZM9Aa1rE/VB+HFLlTFZDPsEXofzo5ELlQ5bOJTkA5+tHIh2SJqsYtABQAUANdFkXDAEe9Jq +4FKbTyOYzn2NZOHYhx7FR0ZDhgQfes9jNqwlIRZsZtku09G/nWkHZmkX0NKtzQKACgAoAKACgAoA +KACgAoAQkKMkgAdzRsBm6d/pt7c33BjP7iEjoUX7zfi2fwUVw0P3tSVbpsvRbv5v8EjSXupRNOu4 +zOE+GYz4SvP+whcf+h14uXf7vL/E/wAzzsH/AAn6v8zoK7zpJI7mSLo3HoapNopSaLsF8snDfK36 +Vqp33NFJMs1oULQAUAFABQAUAFADWUOMEAj3oauBBJYRv0yp9qzcETyogbT3U5VgcfhUcjJ5bbF5 +CSoyMHuK2WxoOpgFABQAUAFABQAUAFABQB5r4l8Ia54t1uCPVNTW2093Jj0+xLcRj7zuxxk9B0PL +DpXyuLwmKxlWMK07J7RXZbt7frq1sZOi6kuaUvdXRaX9Wei2trFY2sVvBGsUESBEReiqBgAV9PCE +aUVCCslojUlqwOH+Fy7/AArej1vrn/0OvGy3WhL/ABS/M8/Bfwn6s3a7joCgAoAs2t4YjtblP5Vp +GVjSMu5oghhkcg1uaC0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBm6Z/pV3eXh/ifyI/ +ZEJB/Nt34Y9K4qH7yc6z72Xov+Df8DSWiUTSrtMwoA4r4T/8i3df9f8Acf8AodeRln8F/wCKX5nn +4H+G/Vm9cR+VMy+/FdzVmdUlZkdSSFABQBasrny22N909PatIytoaRfQ0a3NAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAQnAoAzvDo/4kdk3eSISn6t8x/nXFgv92g+6v8AfqaVPjZpV2mYUAcX +8J/+Rbuv+whcf+h15GV/wX/il+Z5+B/hv1Z1F/DuXzB1HX6V6U11O2SKFYmQUAFABQBpWU/mx4P3 +lreDvobRd0Wa0KCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAIbttlrM3ojH9KzqO0G/Ia3INGXZ +o9ivpBGP/HRWWFVqFNeS/IqfxMi0nX7TWrrUYLZi7WM/2eU9t20E4/PH1BpUcTCvKcYfZdn/AF+B +mmnsaVdQzi/hP/yLd1/2ELj/ANDryMr/AIL/AMUvzPPwP8N+rOzI3DB6GvXPQMq5gMEmP4T0NczV +mYyViKpJCgAoAkt5fJlB7dDVJ2ZUXZmtXSbC0AFABQAUAFABQAUAFABQAUAFABQAUAFABQA1lDqV +YBlIwQehFJpNWYEF7L9h06eSNQPJiZlUcDgcCsqj9lSk49F+Q+p5d+z550+na3dykt51wvzn+JsE +sf8Ax4V8zkCk41JPrb79b/meXl7lKnKcusn+h3/i3xdp/g3SzeX7nk7Y4U+/K3oB/M9q9/F4ung4 +c9T5Lqzuq1YUY883ocx8H7iS/wDCxkXMaS3U0pA7ZbOM152VSdShfu2/xOHAPmpXXdnoPSvePTGT +QiZNp/A+lS1cTVzLliaF9rVztWMWrDKQgoAKANS0k8yAeo4rog7o3TuierGFABQAUAFABQAUAFAB +QAUAFABQAUAFABQB5z8M/iuni1/7O1FUttWUfKV4WYDrgdiPT8q+dy3NPrT9lV0l08/+CefhcWsR +7slaS6HoF2kslu6wtGsh4BlUsvvkAjt7171RSlFqFr+eq/NHoqyepznhfSv+EWsZNO0/7NdwW0p8 +6OIFJVZsN3JBOCOOOMV5OEpSwcHSp2kovW2ju9eraeluw4wpxXLFWOO8R/DjVPiN4pfULu9jtdGT +EduqHfJsHX5eiknOc8joRxXl1sBXzGu60pJQ6dXb06fPY8zE4N4ir+8laK6HQ/B63W08JywpnZHe +zoueuA2K9XKYqGHcV0b/ADDAK1Jpd2dzXsnohQBFPAs64PXsfSpcbiauZk0LQthh9D61g1YyasMq +SQoAuac+HZfXmtYPU0gX62NAoAKACgAoAKACgAoAKACgAoAKACgAoAKAMK68D6HeatFqb6fGl/E4 +kWeIlGLA5ydpGfxrz54DDTqKq4+8ne60/Ihwg5c7Sv3M7xJ8RbPQL5bD7Jey3bnCsLVzH7kHHzY/ +2c/UVyYvNIYefslFuXo7f8H5FOUYtKV/kmzN0e9tfA+q61d69qlvB/atws9ujBlYrtHJQ5K8nHP9 +2ubD1I4GpVnippc7TW+3pq1vbXsZtxpNylKyb6+iRsw66HTVLnQ401lTHHcRxQTKFZ23Kw3dBwgO +PUn1rqhiburLCrn0Tsn1d0/yvb/M6JO8FJa7mJ8JLuc+FXZoCrveTs6c/KxbkVGVzl9Xu11f5nlY +Fv2T06s76KQyDlCn1r207npElUAUANeNZFwwyKTVwM+4smiyV+Zf1FYyjYycexWrMgltW2XCfXFV +HRlR3Nauk2CgAoAKACgAoAKACgAoAKACgAoAKACgAoA848AeGPGdjeLca5rb/Zh1sywmZ/qx+7+F +fN4DC4+E1OvUaXa97/5fI48PCvHWtO/lb9Tur+2kM0F1AoeaDcPLJxvRsbgD2PAI+mOM5HtVoSco +1Ybx6d09/ns16W03XfFrVM4vwSJptAeDWdNn1C8F5OyJcW2QoLn+Nht65714OAk5UHCvTcpczteP +n3em9+pMISS99rd/m7fgbV94h0zwS0H9qyraPfMcPGhMSbQAEyBwAD1wM8njOK9B16WAa9vo59lo +rW0+X46vS9iatWELczsttSh8I3WXwxcOhDK1/cEMOhG+jK2nQbX8z/M4MD/Dfqztq9g9AKACgAoA +KAK89mkvI+VvUVm4JkuKZRkgeBskcDuKyaaIs0aoORXSai0AFABQAUAFABQAUAFABQAUAFABQAUA +FAHK/ETxvB4J0Rpid17NlLaIdS3dvoP8B3rycyxqwdH3fie3+fyMa1eGHjzz+7uZPwl1rW/FFrf6 +vq0pMErrHbRKoVFC53ED6kDPtXJlNXEYnnrVno9F203McLVqVoe0mrX29C94l8fDw/400PRmRTDe +g+a56qWO2PH4g5+tb4rMPq+Lp0Oj3+eiNZ1lCpCm/tXNHx14Qh8aeH5bCRhHMD5kEpH3HHTPt2P1 +rqx2EWMouns90/MK1KNem6cupzXwZL2HhJLeXAKXMqMB2IbFcGUXhh+V92cWX+7S5X3Z6LXvnqC0 +AFABQAUAFACEZFAABgUALQAUAFABQAUAFABQAUAFABQAUAFABQAUAePz+Bb/AOJ3i+61TVWey0a3 +kNvBCeJXRT2H8OTkknnnpXxywdTNMRKtV92Cdl3svyPOrYSVerzVfhWy7+fz/I9ZsrKDTrSK1tol +gt4VCJGgwFA7V9dTpxpRUIKyR6CVlZHkfxU0ia6+JvhVkB2ztGgI7FJMt+hr5DNaUpY6lbrb8Ged +iYOWIoyXd/hqex19kekcR8K4ll8NXQYZ/wCJhcf+h14+WJOg/wDFL8zz8F/CfqztVXaoGc47mvXW +h6A6mAmecUALQAUAJQAtABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAGb4f/wCQWhP3jJKW/wB7 +zGz+ua4sH/BXq/vu7mlT4jSrtMypdaXbXt5Z3U0Yae0Zmhb+6WXaf0rGdGFScaklrHb56AW62A4v +4T/8i3df9hC4/wDQ68jK/wCC/wDFL8zz8D/DfqztK9c9AKAKd45hmjkH0NZS0dyZOxaRg6hh0NaJ +3KBmCKSegobsBWs5DNLI59gKzg7tslO5brUoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAzdNP2 +a9vrQ9n+0R+6vkn/AMeDfmPWuKh7lSdLzuvR/wDBuaS1SkaVdpmFABQBxfwn/wCRbuv+whcf+h15 +GV/wX/il+Z5+B/hv1Z2IlQnG4Z9M1610egOpgR3EPnx7e/UVMldCauMswyxbWGCDilDYFsF8SLc4 +7kUT2CWwtnD5UPPU8miCsgSsierGFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAUNTjeJoryFS8k +GdyKMl4z94AdzwCPcY71yV4uLVaCu4/iuv8AmvS3U0i7+6y5FKk8SSRsHjcBlZTkEHoa6YyU0pRd +0zNq2jH1QBQBxfwn/wCRbuv+whcf+h15GV/wX/il+Z5+B/hv1Z1txarPz0b1r1JRud7VyCNLi3bg +b19M1CUokpNF3Py5x+FaljRIpUEEYPSi6AXKv6GjRgKTgUwKkl/822Ndx9TWTn2J5uxYh37cyYye +w7Vcb9SiSqAKACgAoAKACgAoAKACgAoAKACgAoAKACgDPeCXTpGltk823YlpLYdQTyWTtz3Xv1GD +nPG4Tovmpq8eq/Vfquu6s730upaMs2t5Fexb4X3AHBBBBU+hB5B9jXRTqRqrmg/6810IacdyetBH +F/Cf/kW7r/sIXH/odeRlf8F/4pfmefgf4b9WdpXrnoBQAlAFe3jaHfjlTyPr6VlFNBawLBI775G5 +HRR0o5W9WJEroJ48HIB9Ku3MhtBFbpD91efWhRSFaxJVDCgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgCnd6alxL50bNb3QGBPF1I9GHRh7H8MVzVKCm+eLtLuv17r1+RalbToQ/2jNY8X8WEH/LzA +CYz7kclP1HvWft50tK607rb5rdfivMfKpfCc58JWD+Gbkggg39wQR3+euTK3eg2v5n+Z5eC/hv1Z +2tewegRSzqh27vm7AVDlYBXZyn7vGT69qbba0AZDb7Ad7FmbqaSjbcENt2aMOj87eh9RSi7aMSJH +kFvGC2T9Kd+VDbI1v4ie4+opc6J5kTq4cZUgj2q07lDqYBQAUAFABQAUAFABQAUAFABQAUAFABQA +UAFABQAUAcV8Jhjw1c/9f9x/6HXkZX/Bf+KX5nn4L+G/VnX3DOF2xglj39K9STeyO9kdvaeW29zu +f+VKMbasSVidyEBbOMcmqehQBmYZAU575ouwELBXAZhuPQUddQHkZGDVAV3sY2PGV+lZuCJcUwis +/JbKyMKFC3UaVizWgwoAKACgAoAKACgAoAKACgAoAKACgAoAKAIJL6CK7itXlVbiZWaOMnlwuM4+ +mRWbqQjNU29Xt8gJ60AKAOL+E/8AyLd1/wBhC4/9DryMr/gv/FL8zz8D/DfqztK9c9AQnAoApXzk +Io7tyaxmTN6Fm1/490+laR2GtiO9hMseR95amauKSuOtJvOi5+8ODTg7oad0T1YwoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoA4f4s+HLvW/D8d3pvmDU9Ok+0QmIkOR/EFx36H8K8PNsNOtRVSl8 +UHdW387fn8jlxNOU6f7v4lqix8MPGreM/D/mXGBqFs3lXAAxuOOGx2z/ADBrTLMa8ZR974o7/o/m +GGre3p8z32fqdLdXbiUW9uA9wRklvuxL/eb+g6n2GSPQqVHf2dP4vwXm/wBF18ldrsS6vY5T4SDb +4ZuASWIv7j5j1Pz15+Vq1B/4n+Z5uC/hv1Z21ewegMb5mA/E1L10AqXyGSaNR34rOauyJK9i4q7F +AHbitUrFjqYDFjCMxHG7rSSs7gPpgFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHlvw18dtq3 +jPxDps8m5Jrh57XJ7KdpUf8AAQp/A18rlmNdTE1acnpJtr+vT8jho4n2tWpTfR6em39ep20WlWWl +apdPpdrHFqF4Fa4dc7FAJw7LnGTk4xgt+BI9j2VOjVl7CNpy37Jd2v6b+Ta9CMEry/pmraWiWcWx +SzEnc7vyzt3JPr/+oYArtp01TVl9/Vvu/wCvJaCbucl8J/8AkW7r/sIXH/odeblf8F/4pfmedgf4 +b9WdmTtGfSvX2PQEQYGT1PNJABUFg2ORRbqA6mAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQA2TPltjrg0pbMEfJvhnVptF8YWd7G2JEucEvnGCcHP4E1+VYerKjVjUjumfKUJ+zxt31bX3s ++rLO0WziKgl3Y75JG+87ep/QewAA4Ar9QpU1SjbdvVvu+/8AWy0Wh9a3csVsScX8J/8AkW7r/sIX +H/odeRlf8F/4pfmefgf4b9Wdi3zMB6cmvVersegPqgCgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAgvLtLK3aV8kDACr1Yk4Cj3J4rKpUVKLlL+vL5jS5nY+V/FuhXGheMrmzljCO04k +RVORtc5AB79cfhX5hiaM6FWVOa1/zPlcTS9njbLZtNfNn1bGCI1B6gCv1NbI+pY6mBxXwnOPDV1/ +1/3H/odeRln8CX+KX5nn4H+G/VnZoOMnqea9ZHoDqYBQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAZbSpc6i80rqlrZHYCxwDKRyfwBAHuzelcHMqlVyk/dhp/28/wDJaLzb7Gnwxt3/ +ACM/xN4EsPE+q6XqE+UubGVX3AZ8xAc7D7Z5z9fWs8VgKeKqQqy0cX967HNOlCpKMpLWOx0lemah +QBxPwpGfDlyO39oXGf8AvuvHyzWi1/el+ZwYH+G/VnbV7B3hQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFAHiX/AAkVx4y+IGl6BZTM+k2Fx500g4+0Oh3tI3sW6D3r4ZVpYvFU8NB3 +hF39Wndt+r2POliHXxfs4fDHf5dPkz22vuT0RCQoyTgepobsAUAcZ8J/+Rbuv+whcf8AodeRlf8A +Bf8Ail+Z5+B/hv1Z2leuegFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcB8Kf +hwfBllJd3uG1W5UBwDkRJ12g9z3J/wAOfAyvLvqkfaVPjf4Lt/mcOEw31eLvrJ7nf1753EN3aQ31 +tLb3EaywyqVeNxkMD2qJwjUi4TV0wPMn8K+LvA2q+d4euW1jR2bJ0+5lG5R/dG79CD9RXy7wmNwF +Tmwr54dm/wCvvRw+zr053py5o9nv8mbnwiYv4XnYqUJvrglT1Hz9K9PKneg3/ef5k4L+G/Vnb17B +6AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBz8vi+zu7FrjR7i31YxyIjxW8q +knccKM5wCTjr715c8fBw58O1OzSaXnovxKhaezv6HDXfxA8etfNHb+EjEgPCPG78f7wIFeNLMMxc +7Ro2+Tf4nmyrYnmtGlp6o77wvf61qFkX1rTIdNm4wkc/mZ+oxx+Zr3sJUxNSN8RBRfr+nT7zui24 +3krP7zbrvKOL+E//ACLd1/2ELj/0OvIyv+C/8UvzPPwP8N+rO0r1z0AoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgDAgbT5riztLMQW1orGZEQBBMy9Ai8ZAJBLdOAOeceTF0ak4U6 +VlFa9rtdu6W7fpa+ttbci8zfr1jIKACgDi/hP/yLd1/2ELj/ANDryMr/AIL/AMUvzPPwP8N+rO0r +1z0AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDzb44aFc33h+21SzLi402QyE +xnDBD1YH2IB/Ovm87oSnSjWhvD8n1+RwY2E5UuanvHUufCTx4/jDR3gvGB1Kzwsjf89FPR/r2P8A +9etspxzxVNwqfFH8V3/zHg8R9Yp3e63O9r3juCgDi/hP/wAi3df9hC4/9DryMr/gv/FL8zz8D/Df +qztK9c9AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAbJGsqMjqHRgQysMgj0N +JpSVmB5tpHw8n8E/EGHUNKDPot4HimiHJt8jI+q7gMHqOh9T8zSy+eCxsalHWDun5f8AAvbX7+74 +qWGVGs5w2a1Xmel19OdoUAcX8J/+Rbuv+whcf+h15GV/wX/il+Z5+B/hv1Z2leuegFABQAUAFABQ +AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHF/Cf/kW7r/sIXH/odeRlf8F/4pfm +efgf4b9WdmTgV656AUALQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAMeVI3RWdVZ +zhFJwWOM4HrwCfwqXJJpN7gPqgCgAoA4v4T/APIt3X/YQuP/AEOvIyv+C/8AFL8zz8D/AA36s6e/ +nx+7H416M30O2T6FwdBWyLFoAhln8uWNO7Hn6VDlZ2FcmqxhQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAeafHW+udL0PSLy0dop4L9XWRf4SEevmc8lKFOnOLs1L9GcGOqSpUlOG6a/U6/wZ4m +i8XeHbXUo8K7jbLGP4JB94f1+hFexgsSsXQVXr19TqpVFVgpx6m5XcahQBxPwpbZ4Zuz6X9z/wCh +14+WO1CX+KX5nn4H+G/Vm7kyyZPVjXdudW7Niuo2CgDLeTzLnd/tcVzN3dzK/vGrXSahQAUAFABQ +AUAFABQAUAFABQAUAFABQAUAFABQAUAcb8WfD7+IfBN5HCpe4tyLiNR1JXqP++S1eNm1B18K+XeO +v+f4HNiaXtqMoLc4b9nfVH83V9OJJTalwo9D91v/AGX8q8XIKr550ujV/wBP8jzcrm3CUH0f5/8A +DHtdfZnthQBw3wx/5FO9/wCv+4/9Drxsu/3eX+J/medgv4T9WdNYxb5s9l5r0Yq7OyKNOug1Gv8A +cb6UnsBlW6750HvXOldmMdzXrpNgoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAEoA5nQfAN +h4b8Sahq1lmIXkYU2wHyoc5Yj2PHHbn6V5eHy+nhsRKtT2a27d/+GMYUYU5SnFay3Onr1DYKAOJ+ +FK7/AAzdqe9/cj/x+vHyxXoS/wAUvzPPwX8N+rOyhiEKbR+frXrpWPQSsPzzTAKAK9ta+S7MfoPp +WcY2YkrE7MEUknAFW3YYkUnmoGAwDQndXAfTAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAQkKCScAdzRsBxXwkYP4ZuWUgqb+4II7jfXj5W06Da/mf5nn4L+G/VnbV7B6BTaYpf47HC1le0 +ib62LlalCE4GTQBmXE5uJMD7vQCueT5jJu7saMaeXGq+grdKyNR9MAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKAKupmMafcCWZrdGQp5sZIZSeBtxznJ4x3xWFdxVOXM7Lv117efbzHFNvQ8Xs +PitqGiau2keLYZLmG3fYzooVz6M69HGOcDHXvxXxdPMqtOfscam0t+/z7+n56HlLHvD1XSrL5rt/ +XY7v4QzJceFZpYzuR76dlPqC+RX0eVNSoNr+Z/maYF3pP1Z29ewegZt4uy6z64Nc8tzOW5oiug0K +9/Jshx/eOKzm9CZOyK9jBvfefujp7mogr6kxXU0a3NAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKAI5547aF5ZWCRoMkmonONOLlJ6IaV3ZFS1t3upVu7pdrDPkwH/lkDxk/wC2R1PYHA7luenC +VSXtai9F2/4L69tl1bpu3uo8++Mvw6fxDbDWNOi36hbriWJBzMg9PVh+o+grxM3y91l7ekveW67r +/NfkeTjsL9YjzR+Jfj5D/gpcGDwXB/d86TI/GtcnlbDL1ZGXvlor1Z6YrBlBHQ19DuesRTwLNtJ4 +KnrUyjcVrkm9f7w/OndDsMmgE+3J4HYd6TjzCauSKoUYAwB2qthjZJViXLHFJtINiq+ojPyoT9az +dQjmRYgeSRcuoUdh3q4tvcpEtUMKACgAoAKACgAoAKACgAoAKACgAoAKACgDNh/4mt15x/49IHIi +XtI44L/Qcge+T6GuKP8AtE+f7MdvN9/RbLz17Gj9xW6s0q7TMKAOD+F9os3hu5IO0i/uAPT75rxc +tjei/wDE/wAzzcEr036s7W3RoY9jYJ7Yr1leOh6KViXZ68n3q7dxkV3J5UOR16VMnZCbsPUZUMvG +RnFNd0MeDkVSdwKcllJM+5nH4dqycG9yXG5LDZpFz95vU1SgkNJIsVYwoAKACgAoAKACgAoAKACg +AoAKACgAoAKAM/VpXKRWsTFZrltgZeqJ1ZvwHA9yK5MTJ2VKD1lp6Lq/u/Fo0gur6F2KJIIkjjUJ +GgCqq9AB0FdMYqCUYqyRm3fVjbi6htULzSpCg/ikYKP1pSnGCvJ2CxmnxdoYk2HWLHd6faE/xrl+ +u4W9vaR+9CutrmB8JGD+GbllIZTf3BBHQjfXJlbvQbX8z/M4MD/Dfqzs1PVia9Zdz0BjXcSn74/C +lzoV0MuQLmD92d2D2pS95aA9UTouxFHoMVa0QxF4dvwNJbgPqgCgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgDNtf9K1q7m/htlFunsSA7n8coP+A1xU/3mInP+X3V+b/T7jR6RS76mlXaZmH4o8Ga +T4vtxHqVsJGUYSZPlkT6H+h4rgxWBoYxfvVr36ozqU41Y8s1dHlurfs8TrITpmqxvH2S6Qgj8Vzn +8hXzVXIaif7qaa89PyuePPKoP4JW9dTq/g1YyW3hERmQKYbqaNtvchsV62UwccPbs2dOXx5aVvNn +oCDKfnXuLY9Nkb2kbZ+QZpOCFZCCVIXjjVQA36Uk0rJBtoNlsvMYt5jfjScL9RNXH28HlZO5jn1p +xjbUq1h08bSJhWKmqkrgzOdZoTzuHvmsHdGT5kSRX7p975x+tUptDUu5eimWZcqfwrZNMtO5JTGF +ABQAUAFABQAUAFABQAUAFABQAUAZvh/59NE3e4kkmz6hmJH6YH4VxYPWlz/zNv73p+FjSp8VuxoS +P5aMxBIUE4UZP5V2N2VzM4m5+M3ha0uWglup0kQlWDWsgKkdiCM14jzrCJ2bf3M5Z4qhTlyylZ/P +/I2tC8c6F4kcR6fqUM0x58kkq/8A3ycGu2hj8NiXanPXts/xNoVYVPgkmZPwn/5Fu6/7CFx/6HXP +lf8ABf8Ail+Zx4H+G/VnZ1656AtAFSeItdREd+9ZSXvCa1RZ2+pJrS3cYpOBk8CmAA5FABQA0xIf +4V/KlZAKqKnRQPoKEkgHUwCgAoAKACgAoAKACgAoAKACgAoAKAKWiJ5WjWCf3beMf+OiuXCrlw9N +eS/IuesmXa6iDnvEvgLRPFgzqFkrTDpPGdkg/EdfxzXnYnL8Pitakde60f8AXqZVKNOsrVFc5GL4 +A6JDdLMmoaiu1gwCugIPsdua8pZDRTvzy/D/ACOOOX0IS5o3+82PhIoi8LzrknF/cDLHJPz967sr +92g1/ef5jwP8N+rO26V7B6BGk6SOVU5x3qVJN2C5JVAAYEkdx1ouAjLuUj1GKTVwM2OZ7WQqegPI +NYJuLMr8rsaSMHUMOhrdO5qOpgFABQAUAFABQAUAFABQAUAFABQAUAFABQBS0R/N0awf+9bxn/x0 +Vy4V82HpvyX5Fz0ky7XUQFABQBxPwpGfDN2P+n+4/wDQ68fLdaEv8UvzPPwP8N+rOmvLrf8AIvA7 +16MpX2O2T6EthFsjLn+Lp9KqC6jirItVqUZ9rKTdn/azWEX7xCepo1uWVru184bl++P1rOUb6ktX +I7CQgtG3BHODSg+go9i7WpYUAFABQAUAFABQAUAFABQAUAFABQAUAFAGb4f+TThB3t5Hhx6BWIH6 +YP41xYPSlyfytr7np+FjSp8V+5pV2mYUAFAHDfC+TyvCt43f7fcY/wC+68bLXahL/FL8zzsE7Un6 +s6e1tTK25+FHb1r0Yxudqj1ZogYFdBoBoAzbVf8ASwPQmueO5nFamnXQaBQAwxqXDY+Yd6VtbgPp +gFABQAUAFABQAUAFABQAUAFABQAUAFABQBm23+i61dw/w3Ki4T3IAR/ywh/4FXFT/d4icP5veXy0 +f6feaPWKfbQ0q7TMKACgDifhSgfw3c5Gcahcdf8Afrx8sV6L/wAUvzPPwX8N+rO06P8AUV62zPQH +VQBQBBFBsuJH9elQo2dxW6k9WMKACgAoAKACgBCdoyego2AAdwBHQ0bgLQAUAFABQAUAFABQAUAF +ABQB5pBoXirwlrkHkyya9oaSFk82QG4hQ8MvP3uOw9AeOlfKPD43BVYuF6kE++qXVa+Xy0vpsZUl +UhNxbvF991/mvxPSIpUniSSNg8bgMrL0IPQ19TGSmlKLumbNW0Y+qEFAHF/Cf/kW7r/sIXH/AKHX +kZX/AAX/AIpfmefgf4b9Wdk/3c+nNesz0BaYC0AFABQAUAFABQBXluDBMA3+rbv6Vm5crE3YnByM +itBle+fbBj+8cVnN6Ey0RJbHMCfSqjsUiWqAKACgAoAKACgAoAKACgAoAKAM2H/iVXfkni0uGJiP +aNzyU+h5I98j0FcUf9nnyfZlt5Pt89153XY0fvq/VGlXaZhQBxfwn/5Fu6/7CFx/6HXkZX/Bf+KX +5nn4H+G/VnaV656AxOMr6dPpUrTQY+qEFABQAUAFABQBFPCJ02nr2PpUyVxNXG2qPGhR+x4PtSim +tGC0FuoTPHgdQaJK6Bq5Iq7FAHQVaVhkFxeCI7V+Z/5VnKdtiXKxJAH2ZkPzHt6VUb9SkS1QBQAU +AFABQAUAFABQAUARXNsl3bvDICUcYODgj3B7H3rOpCNSLhLZjTs7or6dcyMZLa4IN1Bjc2MeYp+6 +4+uDn0INY0Zyd6dT4o/iuj+f53Kkuq2LtdRBxfwn/wCRbuv+whcf+h15GV/wX/il+Z5+B/hv1Z2l +euegNYdx1FJgRzljFujOCOamW10DIIdQzxIMe4qVPuQpdy2rBxkHI9RWt7ljqACgAoATPNAATgZo +egENtMZIskE8nms4y0BakpOV+UjPY1e60AghsxG25jvb1qIwtuSlYs1oUFABQAUAFABQAUAFABQA +UAFAFHUbeQ+Xc24zcwZwv/PRT95PxwMe4FcteEtKlP4o/iuq+fTzsXF9HsWba4ju4EmiO6NxkGt4 +TjUipx2ZLVnZnIfCf/kW7r/sIXH/AKHXl5X/AAX/AIpfmedgf4b9WdpXrnoBQA0jByPxHrSsBm3U +HlvuX7h/T2rCSsZSVhsFw0DccjuKSdhJ2NSNxIgYdDXQnc2Bs7flxn3od+gFVkumP3gv0rO0mTqT +xqyH5m3Njr0qldPUroMZ5i4/dDAPrSbk+gailSQUicIV6jFFuiAWFXQsGYN36U4prcBHvIozgtk+ +1DmkK6Q6O5jkOAwz6GmpJgnclqhhQAUAFABQAUAFABQAlAFK41zTrN9k9/awt/dkmVT+prnliaMH +aU0vmg2C21vTrxtsF/bTN6RzKx/Q0QxNGekZp/NBuR/8gy/9LS6b8I5T/Rv/AEL/AHqy/gVf7svw +l/wfz9TT4l5r8jnfhP8A8i3df9hC4/8AQ65cr/gv/FL8zy8D/DfqztK9c9AKACgBkkYcHjr1HrUt +XAoS2TLkp8y+ncVi49jNx7D7ByjmNgRn19aqDs7DjpoX62LCgCJ5V8xUB+f2qG1ewXH7x34Poaq/ +cCGJdk0rdd2MYqFo2FiZRjr1NWkA14UkPzKD70nFMLAsEadEA/ChRSAkqgCgAoAKACgAoAKACgD5 +N1vx5r3iFm+26nOyH/llG2xP++RgV+W1sXXxH8Wbf5fdsfHVMdXqfat6aGCeTnvXHaxwtt7gpKsC +CQR0I7UDUnHVM6LR/iBrmixNBHfST2rDBt7hi6/h3U+hBFdlPF1qcXCMnZ9On/A+Vj0aGY16LTvf +1PcPgrctd+DPOf78l1M5x0yWzX2+TycsNd73Z7mAfNRv5s76vbPRCgAoAKAGsMHI/EUn3AUc80wF +oAr3k/kx8febpUTdiW7EVjARmRup6ZqYLqEVbVlmd/LiZvT1q5OyK2FicSRqw7007oNyveB4mEqE +gdxWcrrVEyutUS21wJ19GHUVUZXGncmqxhQAUAFABQAUAFABQAUAfF9fkR+fhQAUAdN4H8A6h431 +ARwKYbND++u2HyoPQere38q78HgquMnyw26vov8Ag+R6GFwcsQ7vSPf/ACPcfg7braeEpIEzsivZ +0XPXAbFfa5THkw7iujf5nv4BWpNLuzua9k9EKACgAoAKAGD5Wx2PSltoMfTEQvCpfzG+YjoDUNdQ +sSqNqgVSVgI7ld8Dj2pSV0J6iWq7bdPpRHYFsSkZFUMgFr5UoeM49VrPls7oVrFitBhQAUAFABQA +UAFABQAUAfP91+z7rsZ/cXtjMP8AaZ0/9lNfByyPFL4XF/N/5Hzzyl/Zn+A22/Z+1+Rv313YQj1D +u3/sopRyPFPdpfN/5CWUy6zX3HW+H/gDpdi6y6pdyaiw58pB5ceffnJ/MV6lDIqcda8ubyWi/wA/ +yO6ll1GnrL3n5/5Hp1lY2+m2sdvawx28EYwscahVH4V9LTpwpRUIKyR6m2hyXwn/AORbuv8AsIXH +/odeZlf8F/4pfmefgf4b9WdpXrnoBQAUAFABQA1hkUmrgKp3DNCdwEblgPxpPsMdVCEoAOlAC0AF +ABQAUAFABQAUAFABQAUAFABQAUAFABQBxfwn/wCRbuv+whcf+h15GV/wX/il+Z5+B/hv1Z2leueg +FABQAUAFABQAwfK/1qdmAq8sT+FNdwHUwCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4v4 +T/8AIt3X/YQuP/Q68jK/4L/xS/M8/A/w36s7SvXPQCgAoAjlnSEfMfwqXJIG7DLe6FwzADGPWlGX +MJO5PVjGuPlyOo5pPYECjCihbAOpgFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBxfwn/5F +u6/7CFx/6HXkZX/Bf+KX5nn4H+G/VnZswUZJAHvXrt2PQK0l+i/dBY/pWbmuhLkkLNdGKFTgb2HT +0ocrIbdjOZi7ZJyT3rExbuXdOXCu3rxWtM0jsXa1LCgBkf3cenFJAPpgFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFAFHV9asdBs2utQuo7WBf4pD19gOpPsKwrV6eHjz1ZWQpSUVeTsji/hVqIfwr +JJDykt5PIrEdi/FeTllS9BtdW/zPNwUv3Tt3Z1LyNIcsSfrXp3udjdwiXc4B6d/pQNK7FlkMshY9 +6G7ibuNRDIwVRkmjcErmtDEIYwo7V0pWRvsSUwCgBi8O350luwH0wCgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKAPP8A4gfFux8I+ZZ2gW+1UcGMH5Ij/tn19h+leBj82hhb06fvT/Bev+Rw4nGQwytv +Lt/meA6/4k1HxPem61K6e4k7A8Kg9FHQCvh61epiJc9WV2fLV8RUxDvN/Loe2fBz/kSIP+u0n86+ +0yn/AHVerPewH8BfM7evYPRJFG2It/e+UUy1ohIoWmbCjPvQlcSVzSt7YQL6sepreMbGqViarGFA +BQAwf6w/QVPUB9UAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHkfxW+LR0xpdG0SX/Sxlbi7Q/wCq +9VX/AGvU9vr0+TzTNeS9DDvXq+3kvPz6eu3kY3G+x/d0/i/L/gnhjMXYsxLMTkk8kmvjj5dtyd2J +QI9++Dn/ACJEH/XaT+dfdZT/ALqvVn0+A/gL5ncAFiAOpr2T0tzSFmpVA2SFHT3rbkNrEyqEGAAB +7VaVhjqYBQAUAFADP+Wn4UuoD6YBQAUAFABQAUAFABQAUAFABQAUAFABQB518X/iEfCumjT7GTbq +l0p+ZesKdN31PQfia+dzbHvDx9jTfvP8F/m+h5+NxP1eGnxPb/M+dCSxJJJJ6k18IfINtu7CgQUA +fQHwgTZ4It/eRz+tfd5UrYVerPqMB/AR6BYQbm8w9B0+te3BX1PUiupoVuaBQAUAFABQAUAMH+sP +0FT1AfVAFABQAUAFABQAUAFABQAUAFABQAUAFAHyB4i1248S61d6jck+ZO5bbnhV7KPYDivyitVl +XqSqz3Z8RiKzr1HN/wBIzqxOYKACgD6J+EcBfwdZKO5Y199la/2aKPq8Ar0UeiogjQKOgr3krHqj +qYBQAUAFABQAUAMX77fgKlbsB9UAUAFABQAUAFABQAUAFABQAUAFABQAUAfF9fkR+fhQAUAWNO06 +41a+hs7SJpriZtqRr1Jq4QlUkoQV2zWnTlVkoQ3Z9NfC+wbTfCkNvJjzYnaNivTI4r9Gy2Dp4dRe +6PrsHHkpcvY66vUO0KACgAoAKACgAoAan8X1qUA6qAKACgAoAKACgAoAKACgAoAKACgAoAKAPi+v +yI/PwoA0dB8PX/ibUEs9Ot2uJm64+6g9WPYVtRo1K81Tpq7Omhh6mIlywR9G/D34bWfge18w7bnU +5FxLckfd/wBlPQfzr7/L8uhg1zPWb6/oj6zDYaGGjaO/Vmv4TTy9NlH/AE8SH/x6u3Cq0H6sugrR ++bNuus6AoAKACgAoAKACgBqjaKSVgHUwCgAoAKACgAoAKACgAoAKACgAoAKACgD440/S7zVrgQWV +rNdTH+CFCx/SvySEJVJcsFd+R8NToVK3wRuem+FPgNqF+Vm1uYafD18iMhpW/HoP1r6HC5JWq613 +yr8f8kezQyvrWfyX+Z7PoHhvTvDFiLXTbVLaIdSOWc+rHqT9a+ww+GpYWPJSVv19T3YQjTXLBWRp +11FmZ4fj8uycf9NnP61z0FaPzZjSVomnXQbBQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFAEFpY29hEIraCK3jHRIkCj8hWcKcKS5YJJeQE9aAFABQBT0xPLt2H+2x/WsqasiIaIuVq +WFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAEcKeWpHuTSSsJKxJT +GFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAf/2Q== diff --git a/corpus/notebook-management/cold/read/page-001.navigation.json b/corpus/notebook-management/cold/read/page-001.navigation.json new file mode 100644 index 0000000000000000000000000000000000000000..20e0221bdcf96d641ed39c1832eccfa918ed7e69 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-001.navigation.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Untitled page (Read-Only - Recycle Bin) - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/notebook-management/cold/read/page-001.png b/corpus/notebook-management/cold/read/page-001.png new file mode 100644 index 0000000000000000000000000000000000000000..ed8d73fac0ceab73e50d4a6f264d051e90fd7563 Binary files /dev/null and b/corpus/notebook-management/cold/read/page-001.png differ diff --git a/corpus/notebook-management/cold/read/page-001.xml b/corpus/notebook-management/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..d4cb0a4dd2f3587fce7410f767e477baf2e6acec --- /dev/null +++ b/corpus/notebook-management/cold/read/page-001.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/notebook-management/cold/read/page-002.navigation.json b/corpus/notebook-management/cold/read/page-002.navigation.json new file mode 100644 index 0000000000000000000000000000000000000000..a3ec3aa40d7375c559da1ef012a98cc97da4412c --- /dev/null +++ b/corpus/notebook-management/cold/read/page-002.navigation.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Untitled page - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/notebook-management/cold/read/page-002.png b/corpus/notebook-management/cold/read/page-002.png new file mode 100644 index 0000000000000000000000000000000000000000..5b95aede972f80028ddd390c5c0cb7107cc7fd25 Binary files /dev/null and b/corpus/notebook-management/cold/read/page-002.png differ diff --git a/corpus/notebook-management/cold/read/page-002.xml b/corpus/notebook-management/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..d2c26e6002845b90cdf8fe649a3eb28ad87bb0da --- /dev/null +++ b/corpus/notebook-management/cold/read/page-002.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/notebook-management/cold/read/page-003.navigation.json b/corpus/notebook-management/cold/read/page-003.navigation.json new file mode 100644 index 0000000000000000000000000000000000000000..a3ec3aa40d7375c559da1ef012a98cc97da4412c --- /dev/null +++ b/corpus/notebook-management/cold/read/page-003.navigation.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Untitled page - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/notebook-management/cold/read/page-003.png b/corpus/notebook-management/cold/read/page-003.png new file mode 100644 index 0000000000000000000000000000000000000000..414786112e263cf616c5da191808e6450a83ba67 Binary files /dev/null and b/corpus/notebook-management/cold/read/page-003.png differ diff --git a/corpus/notebook-management/cold/read/page-003.xml b/corpus/notebook-management/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..194401d5f5f29be6d2b415ffbf73cc80fa4ffaf6 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/notebook-management/cold/read/page-004.navigation.json b/corpus/notebook-management/cold/read/page-004.navigation.json new file mode 100644 index 0000000000000000000000000000000000000000..757040e961a0fe5e54443e3ab577881b6b8568bc --- /dev/null +++ b/corpus/notebook-management/cold/read/page-004.navigation.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Deleted page (Read-Only - Recycle Bin) - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/notebook-management/cold/read/page-004.png b/corpus/notebook-management/cold/read/page-004.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce36b51d4cd1c7c4305a7a7629fa2c3c8c9d02a Binary files /dev/null and b/corpus/notebook-management/cold/read/page-004.png differ diff --git a/corpus/notebook-management/cold/read/page-004.xml b/corpus/notebook-management/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..d576a32c4e28a1c822f1aa024db30149cdceb1b0 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-004.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/notebook-management/cold/read/page-005.navigation.json b/corpus/notebook-management/cold/read/page-005.navigation.json new file mode 100644 index 0000000000000000000000000000000000000000..20e0221bdcf96d641ed39c1832eccfa918ed7e69 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-005.navigation.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Untitled page (Read-Only - Recycle Bin) - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/notebook-management/cold/read/page-005.png b/corpus/notebook-management/cold/read/page-005.png new file mode 100644 index 0000000000000000000000000000000000000000..4ce88073d57856c4b9a2ccbd55b975b56f0d2015 Binary files /dev/null and b/corpus/notebook-management/cold/read/page-005.png differ diff --git a/corpus/notebook-management/cold/read/page-005.xml b/corpus/notebook-management/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..841e9fb04117ed54b846dd560f50b2cbdd25a611 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/notebook-management/cold/read/page-006.navigation.json b/corpus/notebook-management/cold/read/page-006.navigation.json new file mode 100644 index 0000000000000000000000000000000000000000..2fa796696208f53a7e0ea8c6c71d646a15d6e2bd --- /dev/null +++ b/corpus/notebook-management/cold/read/page-006.navigation.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Moved page - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/notebook-management/cold/read/page-006.png b/corpus/notebook-management/cold/read/page-006.png new file mode 100644 index 0000000000000000000000000000000000000000..ffeb407e94c8d18ea0f03c6ce91bf5e00571b426 Binary files /dev/null and b/corpus/notebook-management/cold/read/page-006.png differ diff --git a/corpus/notebook-management/cold/read/page-006.xml b/corpus/notebook-management/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..c1d46ea159d32ee8cdcebc4cfe0f780a6c75208c --- /dev/null +++ b/corpus/notebook-management/cold/read/page-006.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/notebook-management/cold/read/page-007.navigation.json b/corpus/notebook-management/cold/read/page-007.navigation.json new file mode 100644 index 0000000000000000000000000000000000000000..64dd2a7d5c176e5251e86cd9c7806550d101baaa --- /dev/null +++ b/corpus/notebook-management/cold/read/page-007.navigation.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Subpage - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/notebook-management/cold/read/page-007.png b/corpus/notebook-management/cold/read/page-007.png new file mode 100644 index 0000000000000000000000000000000000000000..4ff4506a271959248a80170f8dee03ca707f0034 Binary files /dev/null and b/corpus/notebook-management/cold/read/page-007.png differ diff --git a/corpus/notebook-management/cold/read/page-007.xml b/corpus/notebook-management/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..57cfc811a3a9d564f17afc25ef1031028802dedc --- /dev/null +++ b/corpus/notebook-management/cold/read/page-007.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/notebook-management/cold/read/page-008.navigation.json b/corpus/notebook-management/cold/read/page-008.navigation.json new file mode 100644 index 0000000000000000000000000000000000000000..f70a181359d1b0b864f1b599b34955e5b50a3929 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-008.navigation.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Teal page - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/notebook-management/cold/read/page-008.png b/corpus/notebook-management/cold/read/page-008.png new file mode 100644 index 0000000000000000000000000000000000000000..fff8b2d52036abe34fd4d510a2f320ea316966f4 Binary files /dev/null and b/corpus/notebook-management/cold/read/page-008.png differ diff --git a/corpus/notebook-management/cold/read/page-008.xml b/corpus/notebook-management/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..bdcf9695fcdb9332b7c7d840bb9c59940c89bfc9 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/notebook-management/cold/read/page-009.navigation.json b/corpus/notebook-management/cold/read/page-009.navigation.json new file mode 100644 index 0000000000000000000000000000000000000000..546ea1cbdf4f48c614748b7e3e8bf00339cd4541 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-009.navigation.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Garden plan - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/notebook-management/cold/read/page-009.png b/corpus/notebook-management/cold/read/page-009.png new file mode 100644 index 0000000000000000000000000000000000000000..3711d76195cba4e60fd064d8bb610fc8972343ff Binary files /dev/null and b/corpus/notebook-management/cold/read/page-009.png differ diff --git a/corpus/notebook-management/cold/read/page-009.xml b/corpus/notebook-management/cold/read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..b2c0ff6de0d913c81c9acfba464843e0f228e123 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-009.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/notebook-management/cold/read/page-010.navigation.json b/corpus/notebook-management/cold/read/page-010.navigation.json new file mode 100644 index 0000000000000000000000000000000000000000..74254503daba42e8020fe5a0fe571b3faf618fe0 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-010.navigation.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Meeting page - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/notebook-management/cold/read/page-010.png b/corpus/notebook-management/cold/read/page-010.png new file mode 100644 index 0000000000000000000000000000000000000000..01580be61f561c37ae680d012379751a38befbdb Binary files /dev/null and b/corpus/notebook-management/cold/read/page-010.png differ diff --git a/corpus/notebook-management/cold/read/page-010.xml b/corpus/notebook-management/cold/read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..9d9851076f835702c16f7d40a5e43ffab099d102 --- /dev/null +++ b/corpus/notebook-management/cold/read/page-010.xml @@ -0,0 +1,345 @@ + +/9j/4AAQSkZJRgABAgAAAQABAAD//gAkU25vd2JvdW5kIHRlbXBsYXRlIHNtYWxsLXB1c2gtcGlu +c//AABEIAxgCZAMBEQACEQEDEQH/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsK +CwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQU +FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/xAAfAAABBQEBAQEB +AQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEH +InEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFla +Y2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbH +yMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQID +BAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJ +IzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1 +dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY +2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AP1ToAKACgAoAa7rGjO7BVUZLMcAD1oS +vogOF1j4tWFjcGKztnvwpwZN+xPw4JP5V61PLpzV5uxyyxEU9NTsdK1KHWNOgvLc5imUMM9R6g+4 +PH4V5tSDpycJdDojJSV0W6zKCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDzb4u65c24ttNi3RwTJ5kjj+PnAX8OpHuK +9rLqUZXqPdHFiJNe6eYV7xwnoHws8VR6fLNpt5MsVvJmSJ5GAVW7jJ9R/L3rx8fh3NKpBanZQqW9 +1npNtrum3kojg1C0nkPRI51Yn8Aa8SVKpFXlFr5HapxezL9ZFBQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAFHWNGtNdsmt +byISxnkHup9QexrWnVlSlzQZMoqaszxfxh4LufCs4YnzrKRsRzD167WHY/zr6bDYqOIVtmebUpOn +6HO12mA6NGkkVUVmdiAqqMkn2pNpLUZ754Ph1G38P2seqEm6UH7xywXPAY+uK+RxLpuq3T2PWpqS +iuY2q5jQKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKAEoAM0AAbNABQAZoA8z+Msz/8SqLkRnzG9iflH6Z/WvcyxL336HFiXsed2FhcandJ +bWsTTTOcKi/54HvXsznGmuaTsjjScnZHpvw50Sz0rVb60vYCuu23zDzOVMR6PH6jqCeo6cZxXz+L +xEqsU4/C/wCtTvpQUXrueiV5R1BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAQzSiJcmmlcVzGu/EMcDEbq6o0WzNzsFpr6Tt1FEqLQl +O5l/ETVpYfBt+9nPLb3A8vbLC5Vh+8XOCOema6MFTTrx51da/kzOvJqm7Mzm8Kov/MzeIT/3EP8A +7GtvrDf/AC6h9xHsv77+8z9V8B2mqwbJdf1mV15Rri5EgU/Qj+tawxcqb0px+SsRKipfaf3jtK+H +lhpq5g1zWYJmADvBdCPd+S9PbNFTGzn8VOLXmrjVCK2kyxf/AA5jvgs8HiXXF1GFW+zzy3u7YSOh +wucHvisfrbWjpxt6Fex/vP7y1pHg0anbbm8SeJILiM7JoDqOTG/cZ28juD3BFTPF8r/hQ/8AAf8A +gjVG/wBt/eX/APhXP/U0eJP/AAYf/Y1n9d/6dQ/8B/4JXsP77+8X/hXH/U0eJP8AwYf/AGNH13/p +1D/wH/gh7D+/L7w/4Vx/1NHiT/wYf/Y0fXf+nUP/AAH/AIIew/vy+8P+Fcf9TR4k/wDBh/8AY0fX +f+nUP/Af+CHsP78vvD/hXH/U0eJP/Bh/9jR9d/6dQ/8AAf8Agh7D+/L7w/4Vx/1NHiT/AMGH/wBj +R9d/6dQ/8B/4Iew/vy+8P+Fcf9TR4k/8GH/2NH13/p1D/wAB/wCCHsP78vvD/hXH/U0eJP8AwYf/ +AGNH13/p1D/wH/gh7D+/L7w/4Vx/1NHiT/wYf/Y0fXf+nUP/AAH/AIIew/vy+8P+Fcf9TR4k/wDB +h/8AY0fXf+nUP/Af+CHsP78vvD/hXH/U0eJP/Bh/9jR9d/6dQ/8AAf8Agh7D+/L7w/4Vx/1NHiT/ +AMGH/wBjR9d/6dQ/8B/4Iew/vy+8P+Fcf9TR4k/8GH/2NH13/p1D/wAB/wCCHsP78vvD/hXH/U0e +JP8AwYf/AGNH13/p1D/wH/gh7D+/L7w/4Vx/1NHiT/wYf/Y0fXf+nUP/AAH/AIIew/vy+8P+Fcf9 +TR4k/wDBh/8AY0fXf+nUP/Af+CHsP78vvD/hXH/U0eJP/Bh/9jR9d/6dQ/8AAf8Agh7D+/L7w/4V +x/1NHiT/AMGH/wBjR9d/6dQ/8B/4Iew/vy+8P+Fcf9TR4k/8GH/2NH13/p1D/wAB/wCCHsP78vvD +/hXH/U0eJP8AwYf/AGNH13/p1D/wH/gh7D+/L7w/4Vx/1NHiT/wYf/Y0fXf+nUP/AAH/AIIew/vy ++8P+Fcf9TR4k/wDBh/8AY0fXf+nUP/Af+CHsP78vvD/hXH/U0eJP/Bh/9jR9d/6dQ/8AAf8Agh7D ++/L7w/4Vx/1NHiT/AMGH/wBjR9d/6dQ/8B/4Iew/vy+8P+Fcf9TR4k/8GH/2NH13/p1D/wAB/wCC +HsP78vvD/hXH/U0eJP8AwYf/AGNH13/p1D/wH/gh7D+/L7w/4Vx/1NHiT/wYf/Y0fXf+nUP/AAH/ +AIIew/vy+8P+Fcf9TR4k/wDBh/8AY0fXf+nUP/Af+CHsP78vvD/hXH/U0eJP/Bh/9jR9d/6dQ/8A +Af8Agh7D++/vFHw6x/zM/iP/AMGH/wBjR9d/6dQ+7/gj9h/ff3ij4eY/5mbxF/4H/wD2NL67/wBO +ofd/wQ9h/ff3i/8ACvv+pl8Q/wDgf/8AY0fXP+nUPuD2H95/eO/4QD/qZPEH/gd/9jS+uf8ATuP3 +B7H+8/vFHgLH/Mx6/wD+B3/2NH1z/p3H7g9j/ef3ijwHj/mYte/8Df8A7Gl9b/6dx+4fsf7z+8Ue +Bcf8zBrv/gb/APY0fW/+ncfuD2P95/eOHgfH/Mf1z/wN/wDsaX1r/p3H7g9j/ef3ijwTj/mPa5/4 +Gf8A2NH1r/p3H7h+y/vP7xR4Lx/zHdb/APAz/wCtS+tf9O4/cHsv7z+8UeDcf8xzWv8AwL/+tR9Z +/wCncfuD2X95/eOHg/H/ADG9Z/8AAv8A+tS+s/3I/cHsv7z+8UeEcf8AMa1j/wACv/rUfWf7kfuH +7L+8/vF/4RL/AKjOr/8AgV/9al9Y/uR+4PZ/3n947/hFP+oxq3/gV/8AWo+sf3I/cHs/7z+8X/hF +v+ovqv8A4E//AFqX1j+5H7h+z82KPDGP+Ytqn/gT/wDWo9v/AHF9wez82O/4Rr/qK6n/AOBH/wBa +l7f+4vuD2fmxR4cx/wAxTUv/AAI/+tR7b+6vuDk82L/wj3/US1H/AL//AP1qXtv7q+4OTzYo0DH/ +ADEdQ/7/AP8A9aj2391fcPk82O/sL/qIX/8A3/8A/rUvbf3V9wcnmxRomP8Al/vv+/3/ANaj2v8A +dX3ByebHf2N/0/Xv/f7/AOtR7X+6vuHy+bFGkY/5fbz/AL+//Wpe0/ur7g5fNi/2V/0+Xf8A39/+ +tS9p/dQcvmKNMx/y93X/AH8/+tR7TyQcvmO/s7/p6uf+/n/1qXP5IfL5ijT8f8vNx/33Rz+SDl8x +RY4/5eJ/++6OfyQco4WeP+W03/fdLm8gsKLXH/LWX/vqjm8h2FFvj/lpJ/31S5vILCiHH8b/AJ0r +hYcI8fxN+dFwsKFx3NAxcUgFoAKAM3Vg3kNitqe5Ejy/XLiVJ2BPFe9SSaOCbGabqLxnrRUgmEZF +rxDfNd6NPGT8rbf/AEIVFGPLUTHN3iXGu3Pc1lyl3G/aXz1oshXHLduD1o5R3LMGqPGetZuCZSka +lnqaidZ9wRwNrE8bl9D9O31PqawnT6GikdVbTiZMiuCUbGyZPUlC0AFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBUvseS2cVpDclnl3igL55x6 +171DY4am5gRS7GrraMEWb253adKPp/MVEI+8im9DbBzXIzUWpAKACmBXklLybecCtErIlnR+HNea +wIiny0B790/+tXFXo8+q3N4TtozauPGMEcmIoGlUfxE7a5o4Ztas1dRGvpuoR6naiaMMozghuxrn +nB03ZmkXzK5arMoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKAM7VS3kHFbU9yJHm2s2EtxO3Br26c0kcUk2Zq6NKT901r7ZEcg3V9Me00meRgQBt/ +9CFOlUUppClG0bm6LN1HSuXmNrB9mfPSldBYcto57UcyCxZh0t5D0qHNIpRJP+ETnOWjYN32txS+ +sR6h7N9CrPayWMnlzIUbGcGtFJT1RDVtyNHVnVSyoGIG5jgDPFN6K4LU7yzuIbK2jhjxtQY+vvXk +yTk7s607aE66gpPWp5CrkiXit3qXFoLkyyBqixQ6gBaACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKAIpohKuDTTsKxnyaNE+SVrb2rRPKUpdKRH+6Kr2jYuUwv +iTarbeBNSlUYK+Vz/wBtUFduBlzYmK9fyZz4hWpNnUPoyHtXD7VnRykf9iJn7tP2rFykqaOg7UnU +HylmPT0TtUObY7EV3KLdTinFcwPQ47xE7TyrMMkAbT7V6VBWVjmnqVtPt0eFzKiyK4xtcZGPpV1H +0QookijmsOLWQtD/AM8JTkL/ALp6j6HI+lZ2T3K2LkOoM4/iVh1VuCKlwHcsR6gw71DgO5qWGoly +BWE4GiZuRNuTNcr0NCSkMKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoASgAIzQBWmi3GmmI5P4rrt+Herf9sv8A0clell3+9Q+f5M5sT/Cf9dTtcV5h1BigAxQA +UAUb61MoNawlYhowbjTWyeK64zMnEqtZMvatOYVhhtX9DT5hWFFmxP3aOYLEsensx6VDmOxqWGnF +CDzWE5miRuRLsTFcrNCSkMKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgBpXNAHH/Fsf8W81X/tl/6OSvSy7/eofP8AJnLiv4T/AK6nZV5p1BQAUAJQAEZF +AETW6t2p3FYiawU9qvnYrDP7NX0FPnCwo05R2FLnCxIlmq9qlybHYmWML2qbjHUALQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBx/xc/5J5qv/bL/ +ANHJXpZd/vUPn+TOXFfwn/XU7CvNOoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4/4uf8AJPNV/wC2X/o5K9LL +v96h8/yZy4r+E/66nYV5p1BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHH/ABc/5J5qv/bL/wBHJXpZd/vUPn+T +OXFfwn/XU7CvNOoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4/4uf8k81X/tl/6OSvSy7/AHqHz/JnLiv4T/rq +dhXmnUFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAcf8XP8Aknmq/wDbL/0clell3+9Q+f5M5cV/Cf8AXU7CvNOo +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoA4/wCLn/JPNV/7Zf8Ao5K9LLv96h8/yZy4r+E/66nYV5p1BQAUAFAB +QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFAHH/Fz/knmq/8AbL/0clell3+9Q+f5M5cV/Cf9dTsK806goAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgDj/i5/yTzVf+2X/o5K9LLv96h8/wAmcuK/hP8ArqdhXmnUFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAc +f8XP+Sear/2y/wDRyV6WXf71D5/kzlxX8J/11OwrzTqCgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAOP+Ln/ACTz +Vf8Atl/6OSvSy7/eofP8mcuK/hP+up2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBx/wAXP+Sear/2y/8A +RyV6WXf71D5/kzlxX8J/11OwrzTqCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAOP+Ln/JPNV/7Zf+jkr0su/wB6 +h8/yZy4r+E/66nYV5p1BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHH/Fz/AJJ5qv8A2y/9HJXpZd/vUPn+TOXF +fwn/AF1OwrzTqCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAOP8Ai5/yTzVf+2X/AKOSvSy7/eofP8mcuK/hP+up +2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA +UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ +AUAFABQAUAFABQAUAFABQAUAFABQBx/xc/5J5qv/AGy/9HJXpZd/vUPn+TOXFfwn/XU7CvNOoKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoA4/4uf8k81X/tl/6OSvSy7/eofP8AJnLiv4T/AK6nYV5p1BQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA +UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ +AUAFABQAUAFAHH/Fz/knmq/9sv8A0clell3+9Q+f5M5cV/Cf9dTsK806goAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgDj/i5/wAk81X/ALZf+jkr0su/3qHz/JnLiv4T/rqdhXmnUFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA +UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcf8A +Fz/knmq/9sv/AEclell3+9Q+f5M5cV/Cf9dTsK806goAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDj/i5/yTzVf+ +2X/o5K9LLv8AeofP8mcuK/hP+up2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA +UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBx/xc/wCSear/ANsv/RyV +6WXf71D5/kzlxX8J/wBdTsK806goAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDj/AIuf8k81X/tl/wCjkr0su/3q +Hz/JnLiv4T/rqdhXmnUFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcf8XP+Sear/wBsv/RyV6WXf71D5/kzlxX8 +J/11OwrzTqCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKAOP+Ln/JPNV/7Zf+jkr0su/3qHz/ACZy4r+E/wCup2Fe +adQUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQBx/xc/5J5qv/bL/ANHJXpZd/vUPn+TOXFfwn/XU7CvNOoKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoA4/4uf8AJPNV/wC2X/o5K9LLv96h8/yZy4r+E/66nYV5p1BQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFAHH/ABc/5J5qv/bL/wBHJXpZd/vUPn+TOXFfwn/XU7CvNOoKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oA4/4uf8k81X/tl/6OSvSy7/AHqHz/JnLiv4T/rqdhXmnUFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcf8XP8A +knmq/wDbL/0clell3+9Q+f5M5cV/Cf8AXU7CvNOoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4/wCLn/JPNV/7 +Zf8Ao5K9LLv96h8/yZy4r+E/66nYV5p1BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ +AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHH/Fz/knmq/8AbL/0clel +l3+9Q+f5M5cV/Cf9dTsK806goAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDj/i5/yTzVf+2X/o5K9LLv96h8/wAm +cuK/hP8ArqdhXmnUFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ +AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcf8XP+Sear/2y/wDRyV6WXf71D5/kzlxX8J/1 +1OwrzTqCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKAOP+Ln/ACTzVf8Atl/6OSvSy7/eofP8mcuK/hP+up2FeadQ +UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ +AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFABQBx/wAXP+Sear/2y/8ARyV6WXf71D5/kzlxX8J/11OwrzTqCgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKAOP+Ln/JPNV/7Zf+jkr0su/wB6h8/yZy4r+E/66nYV5p1BQAUAFABQAUAFABQA +UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ +AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFAHH/Fz/AJJ5qv8A2y/9HJXpZd/vUPn+TOXFfwn/AF1OwrzTqCgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +OP8Ai5/yTzVf+2X/AKOSvSy7/eofP8mcuK/hP+up2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBx/xc/5J +5qv/AGy/9HJXpZd/vUPn+TOXFfwn/XU7CvNOoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4/4uf8k81X/tl/6O +SvSy7/eofP8AJnLiv4T/AK6nYV5p1BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHH/Fz/knmq/9sv8A0clell3+ +9Q+f5M5cV/Cf9dTsK806goAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDj/i5/wAk81X/ALZf+jkr0su/3qHz/JnL +iv4T/rqdhXmnUFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcf8AFz/knmq/9sv/AEclell3+9Q+f5M5cV/Cf9dT +sK806goAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgDj/i5/yTzVf+2X/o5K9LLv8AeofP8mcuK/hP+up2FeadQUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQBx/xc/wCSear/ANsv/RyV6WXf71D5/kzlxX8J/wBdTsK806goAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgDj/AIuf8k81X/tl/wCjkr0su/3qHz/JnLiv4T/rqdhXmnUFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAcf8XP+Sear/wBsv/RyV6WXf71D5/kzlxX8J/11OwrzTqCgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAOP+ +Ln/JPNV/7Zf+jkr0su/3qHz/ACZy4r+E/wCup2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBx/xc/5J5qv +/bL/ANHJXpZd/vUPn+TOXFfwn/XU7CvNOoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4/4uc/D3Vf+2X/o1K9L +Lv8AeofP8mcuJ/hP+up2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQByHxZ5+H+q/8AbL/0alejl3+9Q+f5 +M5sT/Cf9dTr6846QoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDkvitz4B1T/tl/6NSvRy//AHmPz/JnNif4T/rq +dbXnHSFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAcn8VBnwFqn/AGy/9GpXoZf/ALzH5/kzmxH8J/11OsrzzpCg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKAOU+KXPgTU/+2X/o1K9DAf7zH5/kzmxH8J/11OrrzzpCgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKAOV+J4z4G1L/tl/6NSu/Af7xH5/kznxH8JnVVwHQFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA +UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcv8A +E0Z8Eal/2y/9GpXfgP8AeI/P8mc+I/hs6iuA6AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDmPiUM+CdR/7Z/8A +oxa7sD/vEfn+TOfEfw2dPXCdAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBzPxIGfBeo/8AbP8A9GLXdgv94j8/ +yZhX/hs6auE3CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAOa+Ioz4N1D/tn/wCjFrtwX8ePz/JmFf8Ahs6WuI3C +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKAOc+IYz4P1D/tn/AOjFrtwX8ePz/JmFf+Gzo64jcKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoA534gDPhG/wD+2f8A6MWu3B/x4/P8jCv/AA2dFXEbhQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHPePh +nwlff9s//Ri12YP+PH5/kYVv4bOhrjNwoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDA8djPhS+/4B/6MWuvCfxo +/P8AIxrfAzfrkNgoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDB8cjPha9/4B/6GtdeE/jR+f5GNb4Gb1chsFABQ +AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAYXjcZ8MXv/AP/AENa68L/ABo/10Ma3wM3a5DYKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAw/Ggz4ZvP+Af+hrXVhf4y/roZVfgZuVymoUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBi+MRnw5d/wDAP/Q1 +rpw38Vf10MqvwM2q5jUKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAxvF/8AyLt3/wAA/wDQ1rpw38Vf10MqvwM2 +a5jUKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAyPFgz4fuv+Af+hiunD/xV/XQyq/AzXrmNQoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgDJ8Vc6Ddf8B/9DFdGH/iIzqfCzWrnNAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDK8TjOh3P/Af/QhX +Rh/4iM6nws1a5zQKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAy/Eozolz/wH/0IVvQ/iIzqfCzUrA0CgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKAM3xEM6Pcf8B/8AQhW9H+IiJ/CaVYFhQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAGd4g50if8A +4D/6EK2o/GiJ/CaNYlhQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ +AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB +QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAGfrozpU/wDwH/0IVtR+NET+E0KxLCgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKAKOtjOmTf8B/9CFa0vjRE/hL1ZFhQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAFLWBnTpfw/m +K1pfGiJ7F2siwoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgCnqwzp8v4fzFaU/iRMti5WZQUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQBV1MZsZPw/mK0p/EiZbFqsygoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgCtqIzZyfh/MVcPiJlsWagoKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAr3wzav8Ah/Orh8RMtixUFBQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA +BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAEF4M27/h/Oqj +uJ7E9SMKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAiuRmBvw/nVR3EyWpGFABQAUAFABQAUAFABQAUAFABQAUAF +ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA +FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUARz8xGm +txMkpDCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKAGScoaaEx9IYUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU +AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA +UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAjcigBaACgAoAK +ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA +KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo +AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA +oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg +AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC +gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA +CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//2Q==Agenda]]>Action Items]]>Important Dates]]>Meeting Details]]>Announcements]]>Discussion]]>Summary]]>Next Meeting]]> diff --git a/corpus/notebook-management/cold/read/payloads.json b/corpus/notebook-management/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/notebook-management/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/notebook-management/cold/run.json b/corpus/notebook-management/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..a7cfb7953b3888a98f58d04ce3ffe59d6b344dba --- /dev/null +++ b/corpus/notebook-management/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/tmp/mgmt4/candidate", + "expected_pages": -1, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/notebook-management/cold/scripts/cold.ps1 b/corpus/notebook-management/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/notebook-management/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/notebook-management/cold/scripts/read.ps1 b/corpus/notebook-management/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/notebook-management/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/notebook-management/cold/source.json b/corpus/notebook-management/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..3f9864a1a8f8f931ed3c2a8fcdc2eff837b51972 --- /dev/null +++ b/corpus/notebook-management/cold/source.json @@ -0,0 +1,56 @@ +[ + { + "path": "Archive/Inner.one", + "bytes": 6816, + "sha256": "4947149bfe3af5bdf0224e01a0ce95a9849ffad5cbe7d5af4771c6c644850cde", + "mtime_ns": 1790521518477003662 + }, + { + "path": "Archive/Kitchen.one", + "bytes": 9992, + "sha256": "ea8fea880e9f42ff4999c6d7fd1a90c0977ab2efd0501aa1e4bcee85c6279f55", + "mtime_ns": 1790521519374324319 + }, + { + "path": "Archive/Open Notebook.onetoc2", + "bytes": 4200, + "sha256": "5a0c4e1078e51e3fdea8660b1ecb73f76048e556d5ae21691428fd798801e5d8", + "mtime_ns": 1790521519426971739 + }, + { + "path": "New Section 1.one", + "bytes": 85232, + "sha256": "9e903193b2ae555d1aaeeef01b21e749204a0f6a5f9560b18e835f8bc1655097", + "mtime_ns": 1790521519332264376 + }, + { + "path": "OneNote_RecycleBin/Binned.one", + "bytes": 6816, + "sha256": "d2cb20d7cb2238b5525ce6c5b378323eacc265688b6d78cb32a6bdc7f8db9570", + "mtime_ns": 1790521519520939028 + }, + { + "path": "OneNote_RecycleBin/Gone.one", + "bytes": 6816, + "sha256": "976f0b7e524ac877d3ced0f803f50a812b5747a9edf8bccc387276f9ccbc16c0", + "mtime_ns": 1790521519461432928 + }, + { + "path": "OneNote_RecycleBin/OneNote_DeletedPages.one", + "bytes": 6888, + "sha256": "b005c3a26c475d717d87ec66d72eccdfa1d35c72000966fd132728bd086bb860", + "mtime_ns": 1790521519201361387 + }, + { + "path": "OneNote_RecycleBin/Open Notebook.onetoc2", + "bytes": 4592, + "sha256": "a4784bb35ecae53b6f6ad576c3c0687078e72ace4fba47d004d6498aadfae8b2", + "mtime_ns": 1790521519539400089 + }, + { + "path": "Open Notebook.onetoc2", + "bytes": 9392, + "sha256": "cbeebc6c391f65d834f819f9ed90077f36ddbcf7f7e41ff72614200a659b2fef", + "mtime_ns": 1790521519587646429 + } +] diff --git a/corpus/notebook-management/cold/teardown.json b/corpus/notebook-management/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/notebook-management/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/notebook-management/native/meeting-template/meeting.xml b/corpus/notebook-management/native/meeting-template/meeting.xml new file mode 100644 index 0000000000000000000000000000000000000000..4932875680b34645c17451f81d8d99b96247276d --- /dev/null +++ b/corpus/notebook-management/native/meeting-template/meeting.xml @@ -0,0 +1,12 @@ + +Meeting Title]]>Agenda]]>Action Items]]>Important Dates]]>Meeting Details]]>Announcements]]>Discussion]]>Summary]]>Next Meeting]]> + diff --git a/corpus/notebook-management/native/new-notebook/created/New Section 1.one b/corpus/notebook-management/native/new-notebook/created/New Section 1.one new file mode 100644 index 0000000000000000000000000000000000000000..869fe4f7b0c9fba22790f3fb20893cd18ad25d36 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/created/New Section 1.one differ diff --git a/corpus/notebook-management/native/new-notebook/created/New Section 2.one b/corpus/notebook-management/native/new-notebook/created/New Section 2.one new file mode 100644 index 0000000000000000000000000000000000000000..8409d9ac2349c5239335854199604cb39b3f1b67 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/created/New Section 2.one differ diff --git a/corpus/notebook-management/native/new-notebook/created/New Section 3.one b/corpus/notebook-management/native/new-notebook/created/New Section 3.one new file mode 100644 index 0000000000000000000000000000000000000000..a693ccabf3b07854958984699d903b377aff7096 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/created/New Section 3.one differ diff --git a/corpus/notebook-management/native/new-notebook/created/New Section Group/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/created/New Section Group/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..f240ab3a1f7a795f2827834d668ad74d5f0085e4 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/created/New Section Group/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/native/new-notebook/created/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/created/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..9e9e8ce40149c700f970e5a8f715658b906c4423 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/created/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/native/new-notebook/final/New Section 1.one b/corpus/notebook-management/native/new-notebook/final/New Section 1.one new file mode 100644 index 0000000000000000000000000000000000000000..869fe4f7b0c9fba22790f3fb20893cd18ad25d36 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/New Section 1.one differ diff --git a/corpus/notebook-management/native/new-notebook/final/New Section 2.one b/corpus/notebook-management/native/new-notebook/final/New Section 2.one new file mode 100644 index 0000000000000000000000000000000000000000..3587519af681696c5d87f3f03f344fe822a3dd6c Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/New Section 2.one differ diff --git a/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/New Section 3.one b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/New Section 3.one new file mode 100644 index 0000000000000000000000000000000000000000..dab7f1460a27e217a45f02f7d09e82dc01e45b15 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/New Section 3.one differ diff --git a/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/OneNote_DeletedPages.one b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/OneNote_DeletedPages.one new file mode 100644 index 0000000000000000000000000000000000000000..eb2cb978197b94e1f5cbde8137c24bcdfe5668e3 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/OneNote_DeletedPages.one differ diff --git a/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..88f4d60a185e0f22faf8c54e06f282e8a839e5a4 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/native/new-notebook/final/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/final/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..284899a7f0245d741916124775ccbb860657f992 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/native/new-notebook/moved/Kept/New Section 3.one b/corpus/notebook-management/native/new-notebook/moved/Kept/New Section 3.one new file mode 100644 index 0000000000000000000000000000000000000000..9e733c7f8eb1ed5361073be90bdf114f57ce095e Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/Kept/New Section 3.one differ diff --git a/corpus/notebook-management/native/new-notebook/moved/Kept/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/moved/Kept/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..0a81bd5f41952f8152100c0646efaea29f39aa25 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/Kept/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/native/new-notebook/moved/New Section 1.one b/corpus/notebook-management/native/new-notebook/moved/New Section 1.one new file mode 100644 index 0000000000000000000000000000000000000000..869fe4f7b0c9fba22790f3fb20893cd18ad25d36 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/New Section 1.one differ diff --git a/corpus/notebook-management/native/new-notebook/moved/New Section 2.one b/corpus/notebook-management/native/new-notebook/moved/New Section 2.one new file mode 100644 index 0000000000000000000000000000000000000000..d1bc4afdcf9d6d7d11316d85739654eb77891df4 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/New Section 2.one differ diff --git a/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/OneNote_DeletedPages.one b/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/OneNote_DeletedPages.one new file mode 100644 index 0000000000000000000000000000000000000000..eb2cb978197b94e1f5cbde8137c24bcdfe5668e3 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/OneNote_DeletedPages.one differ diff --git a/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..1bd3b23b1bdf08c0c77eea881bb5f0c43c483c48 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/native/new-notebook/moved/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/moved/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..284899a7f0245d741916124775ccbb860657f992 Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/Open Notebook.onetoc2 differ diff --git a/corpus/notebook-management/native/page-color/Garden.one b/corpus/notebook-management/native/page-color/Garden.one new file mode 100644 index 0000000000000000000000000000000000000000..afa9553362c03b4eb8422404aa3c831ebd3f5b70 Binary files /dev/null and b/corpus/notebook-management/native/page-color/Garden.one differ diff --git a/corpus/notebook-management/native/page-color/colors.txt b/corpus/notebook-management/native/page-color/colors.txt new file mode 100644 index 0000000000000000000000000000000000000000..5bb9e648c50fd28ed757836ad70567c8796be51f --- /dev/null +++ b/corpus/notebook-management/native/page-color/colors.txt @@ -0,0 +1,16 @@ +#EDF5FE +#FFEEEF +#FDFDDD +#ECF9E5 +#E5EDF3 +#FBEDF6 +#FFFADF +#ECF0E5 +#E9E9ED +#F3E9FF +#F9F4E7 +#E5EFEB +#E8E3EB +#EFDEDE +#FBF2E1 +#D4F9F2 diff --git a/corpus/notebook-management/native/section-colors/New Section 1.one b/corpus/notebook-management/native/section-colors/New Section 1.one new file mode 100644 index 0000000000000000000000000000000000000000..ea5d31cd300313a1a7eebf5c6c3ac21bc3798b19 Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 1.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 10.one b/corpus/notebook-management/native/section-colors/New Section 10.one new file mode 100644 index 0000000000000000000000000000000000000000..d61a0d002e5d4e107eb9d731609e9c152b371158 Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 10.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 11.one b/corpus/notebook-management/native/section-colors/New Section 11.one new file mode 100644 index 0000000000000000000000000000000000000000..b71b7513bb332dc57c04a255fb03f623234a78ed Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 11.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 12.one b/corpus/notebook-management/native/section-colors/New Section 12.one new file mode 100644 index 0000000000000000000000000000000000000000..15df53c12a8ed7cbfafadb8849a6ac70a63af64b Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 12.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 13.one b/corpus/notebook-management/native/section-colors/New Section 13.one new file mode 100644 index 0000000000000000000000000000000000000000..ba6fd26a09fe5c1dc9619e6a9de19ee0c51c71fe Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 13.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 14.one b/corpus/notebook-management/native/section-colors/New Section 14.one new file mode 100644 index 0000000000000000000000000000000000000000..e421f0d23b0161f8c7d38364c7dc51899d421556 Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 14.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 15.one b/corpus/notebook-management/native/section-colors/New Section 15.one new file mode 100644 index 0000000000000000000000000000000000000000..23b9457bb1f6b32123e71eb39b363b29260e0439 Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 15.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 16.one b/corpus/notebook-management/native/section-colors/New Section 16.one new file mode 100644 index 0000000000000000000000000000000000000000..e34fc568fe8b6ae4ab0c6d3886dc2f273d4eb1d8 Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 16.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 2.one b/corpus/notebook-management/native/section-colors/New Section 2.one new file mode 100644 index 0000000000000000000000000000000000000000..606ed706060e7289435ba7174919f19c1850e73c Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 2.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 3.one b/corpus/notebook-management/native/section-colors/New Section 3.one new file mode 100644 index 0000000000000000000000000000000000000000..ec71d360a990470ef670f1d3681322bed14e95e5 Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 3.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 4.one b/corpus/notebook-management/native/section-colors/New Section 4.one new file mode 100644 index 0000000000000000000000000000000000000000..a82da67e28b900ebe62d51814f0503eb7b78667e Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 4.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 5.one b/corpus/notebook-management/native/section-colors/New Section 5.one new file mode 100644 index 0000000000000000000000000000000000000000..8ed83908d225f85734ec4fcafcada255f0b91333 Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 5.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 6.one b/corpus/notebook-management/native/section-colors/New Section 6.one new file mode 100644 index 0000000000000000000000000000000000000000..168e1a95f2e27efad1a0ffbbdd54c74337e10aa3 Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 6.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 7.one b/corpus/notebook-management/native/section-colors/New Section 7.one new file mode 100644 index 0000000000000000000000000000000000000000..51a48f512bb59e79193e68b078e071bce39045ec Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 7.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 8.one b/corpus/notebook-management/native/section-colors/New Section 8.one new file mode 100644 index 0000000000000000000000000000000000000000..b6536430d73a94a9999fa7ece6187727b8b7fc10 Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 8.one differ diff --git a/corpus/notebook-management/native/section-colors/New Section 9.one b/corpus/notebook-management/native/section-colors/New Section 9.one new file mode 100644 index 0000000000000000000000000000000000000000..58b87fb2f4314caf90a26e713ecdf887e4283979 Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 9.one differ diff --git a/corpus/notebook-management/native/section-colors/Open Notebook.onetoc2 b/corpus/notebook-management/native/section-colors/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..638cf0a165bdc1557fc5d43e0734b3ce9f01e3dc Binary files /dev/null and b/corpus/notebook-management/native/section-colors/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/README.md b/corpus/page-lifecycle/offline-edits-series/README.md new file mode 100644 index 0000000000000000000000000000000000000000..223bb2c20f2efcb5fa948af996c05f5d9b9469d8 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/README.md @@ -0,0 +1,22 @@ +# Offline page batches merged as page series + +`../offline-edits` regenerated since page lists merge as OneNote merges page series +(`../../conflict-page/native-pages`): a page the remote moved keeps the remote's place. +In every native movement state OneNote gave the pages the offline batch places series of +their own, so all eighteen keep OneNote's placement and publish the body edit alone. +`twelve-clients` moves disjoint pages, each into a series of its own; each client's +batch publishes whole, twelve publications, all merged. + +Every candidate reopened in a fresh OneNote 2010 clone without changes beyond the header, +except two native repairs of inputs OneNote wrote: `indent-02-promoted-parent` refreshes the +stale section metadata level that `../movement/02-promoted-parent` left (MS-ONE 2.2.81, +note 9), and `twelve-clients` fills the seed page's absent optional metadata copy. The +verifier accounts for both. `provenance.json` records the captures (`evidence/series`) and +removed clones. + +```sh +ONESTORE_OFFLINE_PAGE_EDIT_OUTPUT=/tmp/one-page-edits cargo test -p notebook --all-features --test sync_pages native_page_changes_reconcile_with_atomic_offline_batches -- --exact +python tools/offline_page_edits.py /tmp/one-page-edits /tmp/one-page-edits-cold --workers 4 +ONESTORE_OFFLINE_PAGE_CLIENT_OUTPUT=/tmp/one-page-clients cargo test -p notebook --all-features --test sync_pages twelve_disjoint_page_batches_merge_with_dependent_bodies_without_review -- --exact +python tools/native_runner.py /tmp/one-page-clients /tmp/one-page-clients-cold --expected-pages 37 --collect-notebook +``` diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..72126bfae93f5df61d58ff5735c3288825b9786f Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..d45628bfbabca2d0ea68bcfc5da4d20c22c71bf8 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/manifest.json @@ -0,0 +1,87 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "group", + "original": [ + { + "guid": [ + 201, + 10, + 106, + 102, + 142, + 247, + 18, + 79, + 177, + 108, + 120, + 98, + 206, + 193, + 214, + 20 + ], + "level": 1, + "position": { + "Before": null + }, + "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1" + }, + { + "guid": [ + 115, + 33, + 106, + 78, + 121, + 140, + 215, + 65, + 186, + 48, + 82, + 176, + 47, + 20, + 4, + 78 + ], + "level": 2, + "position": { + "Before": null + }, + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + }, + { + "guid": [ + 73, + 55, + 27, + 125, + 117, + 195, + 180, + 79, + 166, + 201, + 36, + 230, + 140, + 154, + 66, + 37 + ], + "level": 3, + "position": { + "Before": null + }, + "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [220, 211, 38, 107, 179, 97, 114, 74, 158, 104, 66, 109, 244, 125, 212, 30], n: 1 } })", + "phase": "01-demoted-parent", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [220, 211, 38, 107, 179, 97, 114, 74, 158, 104, 66, 109, 244, 125, 212, 30], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..f2cf56d820b2200bfb7658d3874ea15bff95a709 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-228507E9 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..c457190cbd8e0f9d62e1f5efb25f49ef151caf65 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-228507e9", "hostname": "ONE-M6-228507E9"} diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..97d3aff4ff3f838f88251df68089844e1a8747a7 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..53d7e88f6e6295e632e9c61853b87740cb0a41ee Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..c13d34785e20b80736284859f8152cf4606cc6c5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-228507E9", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..1a29a6844ad637156aed12f8b4ba6171f26531f2 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..858b57d24d8518ebb2120b54e9b78db065b93787 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..c3a23280e16c1127d057fa54d3d650b8067b479f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..032d51926ae215ddaa9897f2abe0b1747de89f5e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec9cbb4839dc9cd9d8817db9b12211d69045c38e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..a052490e8fe062827b2bea34a1113964796efb7c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..661378ce8c297500e2e812275c29d57b4e68f785 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..ea3f6b2e40f8fa832624da6a9796b1b4db96e588 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-006.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..8f01c14273f7647c78dd08a18dbd761786c79931 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..922b0f3af9455f44b47fb7ba5ca70d82b4652131 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..cc7dd9496cc00b8cd86aac836717cf9c4af17420 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpxbgzk4zk", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..a8f3b6ee4359c4fb18b3256a3d88cea0f7a1460a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 58888, + "sha256": "9a3b4662022dc604139192a1ce6e89e0a86fb2f4f28d612d0b21fc39cbb0321b", + "mtime_ns": 1790522182582306261 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..431142b312654c6e1d461efb98317156d5e56962 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..0372d7523bcc49b3ac641cff3a8cff18352ac546 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/manifest.json @@ -0,0 +1,87 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "group", + "original": [ + { + "guid": [ + 1, + 158, + 214, + 127, + 88, + 144, + 125, + 70, + 142, + 160, + 108, + 163, + 26, + 254, + 139, + 224 + ], + "level": 1, + "position": { + "Before": null + }, + "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1" + }, + { + "guid": [ + 246, + 145, + 67, + 226, + 173, + 106, + 84, + 66, + 166, + 80, + 187, + 112, + 214, + 75, + 197, + 145 + ], + "level": 2, + "position": { + "Before": null + }, + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + }, + { + "guid": [ + 208, + 245, + 172, + 222, + 94, + 188, + 190, + 76, + 137, + 17, + 74, + 122, + 80, + 23, + 13, + 147 + ], + "level": 3, + "position": { + "Before": null + }, + "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [73, 133, 222, 97, 87, 220, 209, 73, 167, 94, 12, 96, 167, 99, 69, 216], n: 1 } })", + "phase": "02-promoted-parent", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [73, 133, 222, 97, 87, 220, 209, 73, 167, 94, 12, 96, 167, 99, 69, 216], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..8d7be41c10e77e795253d0dc7ef37d87ccc10bac --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-59E6B833 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..e3329b44275f980cc4be994edf8ba1650a44140a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-59e6b833", "hostname": "ONE-M6-59E6B833"} diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..437694f7b53895ced50da43039ca1bbe13221932 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..535921a8f2262dd6c7f64a4cfdc7347d3785d16b Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..15e02e27889409e561dccc7134045d3b029be439 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-59E6B833", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..b3b69165374f37ab320117f43adf55d6f2716f64 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..58f1d73cec228c77df1ba009dc2467a8ad04ed44 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..a42f077dc6706dd0f0434422bd3ac405367f5d55 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..f4b37154b12e28613809e81fdf97ddf0d21229ad --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-002.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..895a2a70ed73d1916f9efdc88f052fad64d6ee74 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..6a0ae873830d6e54c81b002ea36ddebbaaebd037 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..d818291f29f362527fc01b8d71f094ad336bbac5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..2064b9282a977f12c810ead80dc126e12b0aeb9c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..9b1a6a4973666a0b48a1e76eb427d6eee3c34026 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..c4a42b9bfd207b87c4f67c50321227d8fd108f85 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..6c9319f0e654777b82a6b67ac3fd8f37192f5285 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp2tw32xod", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..f99bc48bf502212594222780fb91e0945a5b79bb --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 60864, + "sha256": "dac0d3baff9cba15171a7a49ad5e3fe5ae4f1d9486a282f73eca7bf12a4302cf", + "mtime_ns": 1790522182571809194 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..1587d4cc88a634e365cc77340853aabf9c33efa1 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..ee1b2e0da4c9171ba3fdcbbcf2c7091df9aa770f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/manifest.json @@ -0,0 +1,87 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "group", + "original": [ + { + "guid": [ + 230, + 73, + 229, + 66, + 147, + 157, + 254, + 73, + 141, + 167, + 232, + 94, + 176, + 115, + 2, + 69 + ], + "level": 1, + "position": { + "Before": null + }, + "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1" + }, + { + "guid": [ + 161, + 23, + 180, + 51, + 0, + 216, + 36, + 72, + 157, + 74, + 208, + 42, + 195, + 215, + 100, + 23 + ], + "level": 2, + "position": { + "Before": null + }, + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + }, + { + "guid": [ + 131, + 50, + 221, + 188, + 200, + 84, + 156, + 73, + 132, + 49, + 39, + 179, + 247, + 214, + 250, + 204 + ], + "level": 3, + "position": { + "Before": null + }, + "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [141, 148, 26, 99, 137, 196, 192, 74, 138, 245, 125, 174, 49, 216, 252, 21], n: 1 } })", + "phase": "03-selected-group-move", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [141, 148, 26, 99, 137, 196, 192, 74, 138, 245, 125, 174, 49, 216, 252, 21], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..80e422fc9196b61b1179c46d07d695167ad21cd5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-2F0CFD28 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..c9549d43bac69dfab31855178bd352ecbe775f31 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-2f0cfd28", "hostname": "ONE-M6-2F0CFD28"} diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..115c5eeeab32230bf7d6acd35282c20fbc8f7e6c Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..3f77ceaff7126fa4e1a1df9a79e7ef9f5652f00e Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..aec98400f3af82d1746045cfdee917871d54b62c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-2F0CFD28", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..1dcee9ce61a6f025bc05980a80700f15d75bd65a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..c624f125c2036f984f28614438febf6e9b370dd7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..5ff6487e8b772cfa44d0602163009c7a9dd67aac --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..cd656860b05a008df92b0a6643527617892b911b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..d43f03b1eba66f2197870f98fc60f8a7bc3d8dcf --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-003.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..35086a6b786f970077c97fd17650662e1cf36ebb --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-004.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..2ff0182fc3ca1e510675080786cf707edae35387 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..407acf7d0ed2f396612a995136c9dc242426dafb --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..29333ee95284b0b4384ff07b7dd10c1952ad82b8 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..f0060b4e811957e0bd10c4d974d8b0becaf20c4e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..b8621b526dd1682702024eb4c5658d8046059de8 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpqu8gvf97", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..133eb197277ea5d9bed9a5a4d119c647f369a633 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 62448, + "sha256": "e8227277e0b943d76ff7f1317a204bc1c90d83edb14d57c1e4fc4b6025572d5a", + "mtime_ns": 1790522182601367622 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..69f04d26d12abaf31536f7de4fb00d9628af3ae2 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..11c96fa3739bceaffd24195e823e6e4b911bfff7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/manifest.json @@ -0,0 +1,87 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "group", + "original": [ + { + "guid": [ + 78, + 38, + 62, + 248, + 116, + 109, + 88, + 72, + 144, + 98, + 203, + 126, + 141, + 180, + 205, + 201 + ], + "level": 1, + "position": { + "Before": null + }, + "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1" + }, + { + "guid": [ + 11, + 136, + 4, + 10, + 224, + 67, + 69, + 67, + 170, + 135, + 131, + 23, + 217, + 9, + 214, + 1 + ], + "level": 2, + "position": { + "Before": null + }, + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + }, + { + "guid": [ + 42, + 95, + 98, + 74, + 100, + 10, + 90, + 66, + 190, + 78, + 156, + 145, + 230, + 147, + 236, + 168 + ], + "level": 3, + "position": { + "Before": null + }, + "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [124, 112, 85, 50, 117, 173, 10, 69, 136, 197, 175, 234, 251, 205, 20, 89], n: 1 } })", + "phase": "04-subpage-move", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [124, 112, 85, 50, 117, 173, 10, 69, 136, 197, 175, 234, 251, 205, 20, 89], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..426ea04c16448bade9f23017ac63fbed33e58e32 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-1F7DB150 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..8e7f3c818af58549ca65e3171afe3605bd8a2736 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-1f7db150", "hostname": "ONE-M6-1F7DB150"} diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..fe6ef49298fea0ae4a0e9e3764fcbe249c34cd6d Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..6cad571062f841ae6c2591834e0a84b2057dbd99 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..eeab5e3904cba8ce0b498dfef7312bf16996f814 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-1F7DB150", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..b2e59a0ed49eade85c8df218ff44cbe44beb71e0 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..44d60ce47a187806674b4093a138b8ef1db49b34 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-000.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..f99f97578095dbb044f1a0af8468dfad6373073c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..6c2fa4227fa6d1b487eb577dcc58b0d834de6b58 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..bd19c898bf1050b2de7cdc579b6afee1b171f23e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..3dbba2c05f8fade039b622de918c0b7d9100b64d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-004.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e9611af66427a25f5d05480f0d6ea9b7e15c9d2 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-005.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..c4deb02accd80acb440a8a9af8a0101e14b8d15d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..9f538388a6952f3c6b75a7c83964b05444762d62 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..5310d3d905a30e533d1786fb52627608a3e039c0 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..8f75f8f639907082b39d5f10c4c98be68226a7a4 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp6no75z1i", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..3831a7e7b30492ebd4cbe77b57e8258502c0fc6b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 65000, + "sha256": "44eca1c10b54a10f3b8d08487d222d94aaac3b9a28f6b6f52ffd5d0d702aaf63", + "mtime_ns": 1790522182581472144 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..6c5becbe1d9eca0dc4d37947bb8ce1eedf9e7a49 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..6467cdfe02be9a206458ed70cd13b2de9a25b258 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/manifest.json @@ -0,0 +1,87 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "group", + "original": [ + { + "guid": [ + 14, + 220, + 221, + 208, + 175, + 223, + 224, + 67, + 190, + 81, + 164, + 165, + 98, + 194, + 13, + 106 + ], + "level": 1, + "position": { + "Before": null + }, + "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1" + }, + { + "guid": [ + 108, + 13, + 33, + 174, + 169, + 6, + 175, + 72, + 175, + 126, + 38, + 95, + 230, + 228, + 176, + 104 + ], + "level": 2, + "position": { + "Before": null + }, + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + }, + { + "guid": [ + 60, + 228, + 133, + 219, + 247, + 75, + 15, + 69, + 149, + 161, + 85, + 245, + 196, + 175, + 27, + 0 + ], + "level": 3, + "position": { + "Before": null + }, + "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [30, 166, 117, 224, 142, 251, 179, 74, 189, 198, 122, 150, 170, 50, 122, 155], n: 1 } })", + "phase": "05-insert-before-subpage", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [30, 166, 117, 224, 142, 251, 179, 74, 189, 198, 122, 150, 170, 50, 122, 155], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..067e27b3f30be03d273062961a4a280fe0d4209b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-4A72E5A4 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..d5bb7718c6d6c57e369b8696e24ed51b98ddefff --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-4a72e5a4", "hostname": "ONE-M6-4A72E5A4"} diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..7bf0ecf6fa12cf6320bd762ce301e01c19febecd Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..a18363df5cce0fcc4fa8ce380c53242e871d69ed Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..4328d79c9e31665cba40eb393b711ff3ef1e26ad --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-4A72E5A4", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..df24741812b7fadf3f8e95b2d8c27f090644d1e7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..faf3743c0934ddc4767e433e65592c6a9b081bee --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..b4827900da71e06888a05e0ba1a25bcb833f09c6 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..01675b458dc319d694d8737b74bb08cd110b56c4 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..69f24e0782b8b589619684491cf6da74f6d94039 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..65c0edbf10b00fac83abcbce139658380ab9415c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..a2fb638b608f7585f077b82fbf513857d088fbf4 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..d0a42e4a53a0e4224a715c560b921d684113bd80 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..20cc4b19cf5f77ea0f80e96c59d6a3d5ecefef4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..a833ffcec4860293c2c429353cb976d618d552d4 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..da74f669b403adca3647484ec2e3db1520278765 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpy26z3j6d", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..2b708373e12ac9e29f5a9be07748c65243226099 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 66944, + "sha256": "2f144e06946d6424cb548a4b51fdd58c2be2be35fb93ddb8f80808dce7ef8ed8", + "mtime_ns": 1790522182575647033 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..689fec86d62375f695029bd2d6e4e86717432374 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..5741c0e4c35c5dc6c899ede5709a2d8ef7f72f25 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/manifest.json @@ -0,0 +1,87 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "group", + "original": [ + { + "guid": [ + 191, + 13, + 164, + 227, + 82, + 236, + 26, + 68, + 190, + 184, + 125, + 92, + 176, + 151, + 92, + 109 + ], + "level": 1, + "position": { + "Before": null + }, + "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1" + }, + { + "guid": [ + 56, + 89, + 41, + 215, + 48, + 19, + 73, + 75, + 153, + 165, + 39, + 124, + 235, + 93, + 47, + 90 + ], + "level": 2, + "position": { + "Before": null + }, + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + }, + { + "guid": [ + 175, + 208, + 247, + 122, + 131, + 58, + 148, + 64, + 189, + 66, + 158, + 33, + 255, + 61, + 102, + 224 + ], + "level": 3, + "position": { + "Before": null + }, + "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [13, 174, 2, 173, 50, 101, 29, 74, 170, 248, 125, 169, 18, 82, 231, 129], n: 1 } })", + "phase": "06-promoted-level-two", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [13, 174, 2, 173, 50, 101, 29, 74, 170, 248, 125, 169, 18, 82, 231, 129], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..a41f19f8dde5632abc91260a1d9413da602b79aa --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-2D9428EA -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..aa6b9bfa79fedcb3d28e3d1055ff2d4c05d1864b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-2d9428ea", "hostname": "ONE-M6-2D9428EA"} diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..4efbd49e287a84892027b8af86da0b55bd8252f2 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..e13f001048a6b65598288dfbe4c5dda176cc624b Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..5347a62104fa3d0d06ed9b5a3b3c5927103feb18 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-2D9428EA", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..c8771f96700c7f5f22b5f86115ee2d1dfdf8a101 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..321bce3401e39a406739e159b8c3c39dec7da5b5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..f84fb6bb541c28f4f1c8391695240c00f9f3a22e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..db868d00b5cb83450627bde6404eaae4c2b9532c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..dd6875c098c938c4a89f7e54a8d29008ae9ec7cf --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-003.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..cd0d6a902cfe5da28f893968263a5980b827dcab --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..b19a47a0873abe679ba86d5dc2887c11f0aa4764 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..9270a65e790c1e8638cfdfee82c931c87cb9c7ba --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-006.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..bc1320729fdbb14b6aac1f86e5e99e06c8029679 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..195af6d10c4b8251e8645aecad80de3c36ebd3a3 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..a012636809e78b528641b06f077b7926ea3edd24 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp7i0tqm4j", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..7d0988aa41e18888d02fa1e4401f65c9fc50b767 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 70296, + "sha256": "30860c7715ac247a1f77d1d0c8c27edfcc248e719183cb7990381f5ad5230d89", + "mtime_ns": 1790522182588156289 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..1e513db665ef80e44ca910f46ae945196b516541 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..b4d80b5e2451e38b169636679e1ee8c1df2ff11a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/manifest.json @@ -0,0 +1,87 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "group", + "original": [ + { + "guid": [ + 55, + 220, + 38, + 71, + 47, + 170, + 53, + 66, + 139, + 104, + 24, + 238, + 194, + 96, + 177, + 2 + ], + "level": 1, + "position": { + "Before": null + }, + "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1" + }, + { + "guid": [ + 140, + 13, + 145, + 79, + 63, + 166, + 77, + 73, + 158, + 26, + 254, + 232, + 198, + 149, + 101, + 89 + ], + "level": 2, + "position": { + "Before": null + }, + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + }, + { + "guid": [ + 18, + 181, + 156, + 40, + 205, + 204, + 124, + 69, + 153, + 67, + 16, + 116, + 216, + 205, + 169, + 116 + ], + "level": 3, + "position": { + "Before": null + }, + "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [28, 191, 204, 103, 192, 238, 143, 72, 160, 21, 202, 184, 111, 209, 202, 133], n: 1 } })", + "phase": "07-promoted-root", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [28, 191, 204, 103, 192, 238, 143, 72, 160, 21, 202, 184, 111, 209, 202, 133], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..3d83743d7bf3eaaa763096b062c79aa7da098bc7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-A2C6CE60 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..f9e0355e2e8401c9ee10e51c81eb07e6db9b63c7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-a2c6ce60", "hostname": "ONE-M6-A2C6CE60"} diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..807c9aa65807aecf61a7b00e4db18a9bd0ecf255 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..bf722526d9d8a33e73e81e3f180d5e4fb1e9d8f1 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..5a85ccbf0449658639e1f86e48983510593fee35 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-A2C6CE60", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..880eb154cbc57ce0896cdbfb7c011e9698fc5243 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..9b3db3eb84dd1feae69a8953a3e8b0e504652b5e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..073ef166cc94c0dedb7d65bf8abe3e7a422dfa9d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-001.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..dabd964dc71754f2b21930d2cd5388a3c3b2cf2c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-002.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..e9be811f3cfbedc4f2438bf5cc3996a0a06114e2 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-003.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..6326c4e89b431037a71496126f9f944c697d544d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..650940eb76e0d3c15c3f7b61afeb4c4d6e2eeff2 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..61daa4e1f11077f6637519f0c8115aa15939315a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..41124192e79acb3269d17dd9b5122ebd2765d9b5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..d72292dc950e2afd5d64fff840b3ac92a0ebfed5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..fd55e663833ab31b3804f71f8b32cfb5c550c6c7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpfsvvpr33", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..1831786687fa6174c1e9cf6f78efece384070843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 72360, + "sha256": "550991e8db44ff19e287605df0548e26e03d5f4b02ea3c56b37206fd4a122974", + "mtime_ns": 1790522182583277710 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..5bf316916c183d18b4aa5107ec0a87f4fdf49b7f Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..c74c072fd5bbb81ebfb09112823296e5ad9c78ae --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/manifest.json @@ -0,0 +1,87 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "group", + "original": [ + { + "guid": [ + 94, + 111, + 203, + 102, + 137, + 5, + 1, + 65, + 179, + 170, + 125, + 232, + 204, + 23, + 163, + 106 + ], + "level": 1, + "position": { + "Before": null + }, + "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1" + }, + { + "guid": [ + 229, + 103, + 227, + 76, + 55, + 67, + 28, + 66, + 188, + 213, + 158, + 204, + 32, + 66, + 155, + 181 + ], + "level": 2, + "position": { + "Before": null + }, + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + }, + { + "guid": [ + 71, + 45, + 134, + 175, + 49, + 202, + 56, + 76, + 130, + 139, + 137, + 23, + 7, + 208, + 7, + 1 + ], + "level": 3, + "position": { + "Before": null + }, + "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [49, 49, 147, 226, 188, 223, 28, 78, 185, 7, 77, 190, 226, 242, 41, 152], n: 1 } })", + "phase": "08-collapsed-group-move", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [49, 49, 147, 226, 188, 223, 28, 78, 185, 7, 77, 190, 226, 242, 41, 152], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..57af14945e8fb227758860c660563fdbf97d5b86 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-150CFDA8 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..7fe8cc6e93463aa707cd26df67b3fee734765a52 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-150cfda8", "hostname": "ONE-M6-150CFDA8"} diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..d29d893b909f014d8060a109ba63bf0982d5763b Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..6bd7ccbb1de681b9a66a8e2a8eefe0b4425bb6f6 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..621383846820371b866e81612d88773fdfde47a9 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-150CFDA8", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b86eb21979e2157e39eb8f36ab91f65df21ca14 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..d7d23890a7623ef59aa23e852a5b04605e9cf83f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..7a9f9a91079456831fae18ad06e6a9a4c07ff07f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..5d1e7bb650c1aac13b93736955b595152e826b59 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b2a6384f919ee508f05065763dde63ff0561d1b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..48ae3e9224cd8a511bc32c49cdfee6c68e0fc825 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..491a4b519310b767edc73bdb7e12c967f0bb1e3b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-005.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..a984c9fff8620cff291601a45d0ab01b1c2ba259 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-006.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..83972288bca3c5e30f0448fc75bf1c3d22613e21 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..7e622faf5845b57b7ca8b55283db8021dccc0730 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..344bfc8207eff473c53886b77733172a13d59338 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpfwhuw46n", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..dca465583aeef623347b5f3b090aff8892dc545f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 73840, + "sha256": "b68abccdc4c7c98c65311b2924f3903540b22c7f6e0bb8153b31bbe34fdf2c05", + "mtime_ns": 1790522182560292804 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..38bb2887e0a99b3648f71cad9663b170007c7a82 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..caf57b62e3cdea172688f7b4bcd733e7d21c2ac1 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/manifest.json @@ -0,0 +1,87 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "group", + "original": [ + { + "guid": [ + 106, + 239, + 107, + 240, + 178, + 128, + 132, + 68, + 153, + 189, + 143, + 39, + 201, + 121, + 23, + 95 + ], + "level": 1, + "position": { + "Before": null + }, + "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1" + }, + { + "guid": [ + 153, + 239, + 1, + 102, + 46, + 96, + 32, + 70, + 136, + 164, + 197, + 78, + 35, + 85, + 187, + 83 + ], + "level": 2, + "position": { + "Before": null + }, + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + }, + { + "guid": [ + 235, + 105, + 29, + 79, + 205, + 140, + 16, + 65, + 169, + 123, + 14, + 62, + 80, + 183, + 253, + 48 + ], + "level": 3, + "position": { + "Before": null + }, + "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [110, 9, 150, 21, 87, 116, 176, 73, 135, 91, 48, 29, 75, 28, 84, 177], n: 1 } })", + "phase": "single-page", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [110, 9, 150, 21, 87, 116, 176, 73, 135, 91, 48, 29, 75, 28, 84, 177], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..c8ab9010abeb1131d737894eeb3fb44c8b715169 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-93A16790 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..7ddeca58dd2c7b57e11825dc0a319284a29f716d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-93a16790", "hostname": "ONE-M6-93A16790"} diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..38eba53e6a5a657b4d7c0c1bb9a0ce4d50a1caf5 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..cdc2ab5593dc55a3583872109eb6c7070af6dec3 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..57a43504b4c77928e5198d82427aaad8a8704f6e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-93A16790", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..44b1566221c50e6821525f93f72d60bc81136993 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..3b0ec2f216a8f9b6dafadcd7f1ccecfe70156526 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-000.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..6652fbe50f3749095636734b9746ce21875c814f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-001.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..7603d49c667430797f145b901e97fe781127821b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..8ac5e637cee0704db2a92d5ec24a120f5e2dd405 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-003.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..7cd99d7cd5414a0e5e6ccb59393f5b9e7d14649d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-004.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..ee409bcc0cd27d3edcb508053f8dcd03e5c36afa --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-005.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..8f9d5c7603940d983b8dab24891c621dc0f5ee4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..9b55e22ed8ee2882b92983e7789193a45f9214dd --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..d7c64626a68eecfb4c95ee16e7af8971246b22cb --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..8cce9c0afa10af22b296e58c55baec431642ed41 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3_04860j", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..b6eda15f2ba61ad31cd3d765445a07fda7b6a6c3 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 63080, + "sha256": "58f87ab34c5e56426faed56429ab10a15e3df0673851e8c9b4587cb107a13295", + "mtime_ns": 1790522182573126515 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..27b774b93f4e911e9b29c796b14ded69bb8968a3 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..29c027f0e4c048c77e3f1e3427ae7242d1b02710 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/manifest.json @@ -0,0 +1,35 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "indent", + "original": [ + { + "guid": [ + 0, + 239, + 121, + 46, + 116, + 217, + 98, + 67, + 148, + 55, + 113, + 147, + 21, + 237, + 19, + 130 + ], + "level": 3, + "position": "Keep", + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [56, 236, 133, 176, 92, 155, 147, 69, 157, 167, 5, 193, 82, 10, 39, 239], n: 1 } })", + "phase": "01-demoted-parent", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [56, 236, 133, 176, 92, 155, 147, 69, 157, 167, 5, 193, 82, 10, 39, 239], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..13d9803e370508d145bba3acfcd6f1098965734a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-2B44159D -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..1419dbb69e537148cbcf91335695d91227521f03 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-2b44159d", "hostname": "ONE-M6-2B44159D"} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..bd8534ad4a898d49e486e64afd9582c598365214 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..eb66531356dca116be95c967e3a71eb8ced5ca27 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..ea8a016887547bd561053fd5fb7822b3dd385e8c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-2B44159D", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..884bb5dff3e757bb2ebfc17b59966a6dfb370c39 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..223b148ad261559b0ded332bc8a02e217213360c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-000.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..cf67465ec21a41467a6911497a6174d66e6d0c5b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-001.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..ea1408fe42305ce467e90739acfb708dba8c3059 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..9f3cf6b2f12b2ff448956f3822b3aad0612c8c45 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-003.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..a5316232454e3de14e7dd9e1e3378c269cd98bf5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-004.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..a604ef660606605f623262e2bbda9496c220a1f5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-005.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..1fa01ed8490190767b503692570ed3249b3f209a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..56147df3ff8e101d7126550984c9b36fb6bcbc43 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..9d6a1daba41df165f72a549e68d1e70975eb231d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..b1d85b3f1cebf4cce67daba890ed0256154bc858 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmppgtomrlh", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..6234df699295ae77cdb87435f897f8a11fa1dbcf --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 58888, + "sha256": "c19272d0b0a52889647b23a6eb10381e7d90d5d5d7ca2ad3be868aa585a8b21c", + "mtime_ns": 1790522182595778175 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..83037b20ff2a5422b2b5edf136b86070a08170cc Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..70608549d8be3d4aed60977d9b403c549e295512 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/manifest.json @@ -0,0 +1,35 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "indent", + "original": [ + { + "guid": [ + 70, + 179, + 162, + 143, + 72, + 227, + 248, + 64, + 159, + 7, + 0, + 166, + 131, + 166, + 211, + 72 + ], + "level": 3, + "position": "Keep", + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [144, 208, 130, 2, 184, 145, 30, 67, 154, 106, 180, 175, 85, 128, 40, 126], n: 1 } })", + "phase": "02-promoted-parent", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [144, 208, 130, 2, 184, 145, 30, 67, 154, 106, 180, 175, 85, 128, 40, 126], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..601ef63aa978f183c731122bcb67efef88bf5957 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-3F9D5E9E -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..7c44e47be5abc71b9d390dbf46e7e754d1c67d0e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-3f9d5e9e", "hostname": "ONE-M6-3F9D5E9E"} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..7a22fe1fea5cae151dfc4699eb40e1f716c6cb0a Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..da9e9cf3fd46d9c1b5356199c39409e04de3e62b Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..c32f092ab133cbf25d9df26b1d8f577fea24ab1f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-3F9D5E9E", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..fc67ee981f1fc7a783681767c027c16011346e2e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..4f3b59d45e8ade7e51b7fc198c78fecaac82aded --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..d2536aed6db5af01476e31a77dcfc53ab728098f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-001.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..5bc1809f3032a875b2eff2acbe983cea7eb98d39 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-002.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..f600e9d6c3bfb7bfeba63b05068945a3a908204e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-003.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..34b5167cf2f30decae00735ffd5690f483737202 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..9cd88f0e2070945a938c5878519dfb3efe6bc301 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..e1f3a0e49d37dc423dcf066a1063354b56ab25c2 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..b6d37a2ac2a93aa2c8ec2e420c749f10e190c7c9 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..514f4ba4c5beaa18f1c73a3f0cc1791cd0c690c0 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..c7e71c5c8614f475d76fd944f2e20828e6e63a8b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpsa22lkkc", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..bf1cf882f890eb1bcad81bf39a499d2118cd27ee --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 60864, + "sha256": "02983cdd10e8f6ac52dfdd27ef63858d4d3351c2c78822c0f5c20794298fb0ca", + "mtime_ns": 1790522182572487438 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..4d3c53e6a34bb1d31c1129dd25b84e011a65ced7 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..777cdbf0c63e88b48828f05408a9e0b1b20b4bce --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/manifest.json @@ -0,0 +1,35 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "indent", + "original": [ + { + "guid": [ + 206, + 208, + 7, + 135, + 27, + 66, + 90, + 66, + 171, + 221, + 251, + 160, + 36, + 192, + 100, + 24 + ], + "level": 3, + "position": "Keep", + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [226, 195, 144, 213, 163, 25, 255, 79, 131, 63, 105, 93, 194, 6, 124, 135], n: 1 } })", + "phase": "03-selected-group-move", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [226, 195, 144, 213, 163, 25, 255, 79, 131, 63, 105, 93, 194, 6, 124, 135], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..61999dc5997e36f31def71338ba1c6d81c0e9876 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-6DEF4909 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..3b72cde8c9d253751c8d3ecae94ff8e0d8ad935e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-6def4909", "hostname": "ONE-M6-6DEF4909"} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..7c31334b86632d1e2e411a67419e85043105ea36 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..97a68a855cd820b192e1686c7452edcfba6b1465 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..f8d2d784b9271833d3f1ac376684a7ace2704f55 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-6DEF4909", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..5e09e8cc01044f2c5b5999d3af82f640bd282236 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..ab66442d740dd9c24a5bf4064cf3f912ac726f0f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..a29a8e403028a0bd84dfdc9c8103f25ffd424cb4 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..1e83854e5dde7d447ae93e9242f1da891224ed07 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..ca5c7e87a6540e104c9bb270fb3056ee0d44fc65 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..ba392e376ae515d227f9ed62b6fb9c033829412f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..0bcdd096e1147bd7109e3774fa1df4760cb370bd --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-005.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..d1fafdc28a3e9bffb0eda4603b42157dfefd88d2 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-006.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..8e7952c17ced9dfd0b8d0c2be78cbbdb3a22a9db --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-007.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..9433ea271ea67e2185b2d17d89b825576439c58b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..51c469570222c8a0d8a9e308e65fec862f4ef9b5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpb5gki0t4", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..c7262f9a9220989fa11dd8fbd6e4bf5a10fc2ff7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 62448, + "sha256": "62f0d051077351cfee81931153467cbf510700e94b46347a78e287801943f37c", + "mtime_ns": 1790522182574538544 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..1d80bacb71ba9862f61a0b13af1347493b5d5655 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..6c9a24bada80ed825620b3cc32a9a9dc34273113 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/manifest.json @@ -0,0 +1,35 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "indent", + "original": [ + { + "guid": [ + 112, + 19, + 103, + 0, + 67, + 152, + 215, + 75, + 186, + 173, + 109, + 239, + 32, + 173, + 18, + 173 + ], + "level": 3, + "position": "Keep", + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [140, 1, 52, 173, 83, 155, 53, 75, 176, 124, 221, 5, 197, 47, 143, 47], n: 1 } })", + "phase": "04-subpage-move", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [140, 1, 52, 173, 83, 155, 53, 75, 176, 124, 221, 5, 197, 47, 143, 47], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..dcb0a33c23f893dd8fba613922160025f9f6b797 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-3CF1AD85 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..46c491524477cec3a99dfb29a236c699527483c3 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-3cf1ad85", "hostname": "ONE-M6-3CF1AD85"} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..25d4d179185ebbc3bee48a0bf5fdbddb77bab2a4 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..610aedc033e729db8371a9c2b0a7d37469c4e400 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..96d3617f583420e31494ab51f7782a84ec17c1a2 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-3CF1AD85", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..7f8345069445685fe2b1607bdca4865385906503 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..87130397ed72ddd4878037e90f0e1018d6fa7013 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..ee0ac0b06c18e3a9e51b023cfc7d0a750d49c0be --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..b9107dce7edb3244ff790a9c24f237ae5e7d64e5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-002.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..9695c4cd9b7f9e4052ec42114cec7ec6e22502f9 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a8e30e608c1e97d03fe964434fe9e89fef00d34 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..2e5736fc07e325b75f2ade2f71560d7210351823 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..816056af81bec106ed6ca1a579b1889f55c0e6ab --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..60a38d166e4b9e050ed505aa5e9d858fb890ac7d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..9dc35b289323796144a4f8653bd956ff83fdd30e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..eab5635be86890d2ae326f88257995790a790ff7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmplfmc8y5c", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..7663db594fff53e1cc95ace536274a251cf167d3 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 65000, + "sha256": "e61b424191b7ddde476e498953e5fedb01566f5fdcf5ec5ad85b75dc81ae4b81", + "mtime_ns": 1790522182580783526 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..b2b6360bc5062df7c96bf226f306caf0b8a3fa31 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..b3484217fbef1cfc70dd3bb20e7d1229c4283432 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/manifest.json @@ -0,0 +1,35 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "indent", + "original": [ + { + "guid": [ + 4, + 56, + 164, + 224, + 230, + 112, + 75, + 69, + 132, + 225, + 72, + 65, + 90, + 35, + 245, + 82 + ], + "level": 3, + "position": "Keep", + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [217, 51, 175, 155, 204, 150, 117, 70, 128, 20, 45, 123, 132, 193, 234, 183], n: 1 } })", + "phase": "05-insert-before-subpage", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [217, 51, 175, 155, 204, 150, 117, 70, 128, 20, 45, 123, 132, 193, 234, 183], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..cfeb35ba8aab8bd68324d85c515d3b3d69c526bf --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-C302208F -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..ee9e011fab2148891a4787fc6b3f4a44be8ebb7c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-c302208f", "hostname": "ONE-M6-C302208F"} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..70e5bac896b69b68f12d446cb63597d87e621788 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..423f577f570bce6c3ea2e9073a224e33070b1ab7 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..ddb51fb0a7f9cd078002b9e57d7575b008a81486 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-C302208F", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..71991079f49f2c1ddafd353f13e5e8b125a19002 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..64d071860c3d1520f7e14765330b6f9d2f180ffa --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..e628a80f579de1275765701fd94913d62e03a353 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..f7d490717e9c7e344efb0aa64b76b4bdc23b595a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..cf4fe64ebd434b161390cf59a1f1030a34a80af1 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-003.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..605d70cbb5a5abd6a4ac3f64c65a269ea072b59e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-004.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..570934618e08cb988d19f2141a0c851d402def0c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..9bb13c7a601eaf2cd5de29da476359e1ea7c9377 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..90cdad99119bddd3683c30c7c020b0611db60cc0 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..5ad32730e6b27b544536b8a479475b7b8b07ca41 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..ca3ec51ef5025f8fb69e2e93608fb334e7fc3ebb --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3bp2l4t4", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..610fe367a14ab912261e04c38cad39e7f9bf2348 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 66944, + "sha256": "b1f5d19ffee4ff89ab2a14066a729b5585179339be2b18227f92c0bf2b44c42e", + "mtime_ns": 1790522182565951458 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..b4edff4d616f4235c59cf77726019a5da2e3d133 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..fe02d500178e58df64e1ae1c70caa782ba363cbf --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/manifest.json @@ -0,0 +1,35 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "indent", + "original": [ + { + "guid": [ + 178, + 31, + 183, + 138, + 26, + 221, + 93, + 78, + 173, + 192, + 148, + 78, + 69, + 246, + 210, + 44 + ], + "level": 3, + "position": "Keep", + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [113, 37, 105, 136, 152, 116, 183, 79, 158, 85, 240, 239, 61, 75, 67, 196], n: 1 } })", + "phase": "06-promoted-level-two", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [113, 37, 105, 136, 152, 116, 183, 79, 158, 85, 240, 239, 61, 75, 67, 196], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..828e0ffc48099a11e9d203523f258545dc6e3935 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-BC497350 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..15c098bee852e17dccf82334414d8be9628320a5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-bc497350", "hostname": "ONE-M6-BC497350"} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..3e6224ce30540ad4ceb32a0578aeb0f001c5634a Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..c5385581db8f6fcdf22ce6c46c9db7bf9877af09 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..42a8ef3731bff67846cd100b951bef1289994587 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-BC497350", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..7795c8becf6e0ea65a3c8df80b6380e85a5c175b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..43146345a943425cfc6931b8c7e4423e9ad7aea3 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..bf17f047a37098ce5f4d0efd7381599df9d2438a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..ab8daee0aec9a1393daa96839a707411c5dfd073 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-002.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..7717be7a2d8f3c354c5fdcacaa133c136ad9449d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..c792f281a18d1eb32184af0682865ac6c0f28997 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..43d6cf1d69a5f71126208d261dc3df712f6385e3 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a499c003ac019e80793cb5b745471b6e049c11e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..847bd38902c23d6aed977038bb541f3d29603005 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..7c06778085230bac3a32af7764cac7333339cec6 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..c827019ff6d8edea81626bfaabeca391c8ca8eb3 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpjja19zue", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..7387099b51ea7ade63dc4536ab46bea7133f1417 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 70296, + "sha256": "8fa8fc3275cfb17da80d2f9e08baebd8c70b8489b5721460e17c771998226876", + "mtime_ns": 1790522182589845898 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..9e45d245a1a466237c648776c19d51af99c06c60 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..723b466d45eeb6c3eea61e63a98da62758c4495c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/manifest.json @@ -0,0 +1,35 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "indent", + "original": [ + { + "guid": [ + 73, + 128, + 226, + 10, + 127, + 157, + 145, + 66, + 185, + 120, + 232, + 117, + 193, + 31, + 151, + 68 + ], + "level": 3, + "position": "Keep", + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [20, 1, 234, 89, 89, 254, 82, 68, 168, 79, 107, 96, 254, 118, 67, 34], n: 1 } })", + "phase": "07-promoted-root", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [20, 1, 234, 89, 89, 254, 82, 68, 168, 79, 107, 96, 254, 118, 67, 34], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..d2b6fd6bfcd237078a4e35cc355f31718920c4cb --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-90980D00 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..75aea416a80b9a9435bb0648d195ec398eec159e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-90980d00", "hostname": "ONE-M6-90980D00"} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..ea9c659626bf01f1187ab0d3fa6a303221dd131b Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..91b10b51e1a279a68fb31613efef1795e12831d6 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..ef0dceca8124105875065f229b56297db0497fcf --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-90980D00", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..8ded209958e8a836904b0b56d57f9a6bdc1be87c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..6c370677c832f4642634e27827eeca9ef82eecb5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-000.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..7262db8713c5d9b65f39b8ed56e071aae3a8f0e8 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..7e1083135472dcd2cfe53bd0654c8956921daab7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-002.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..8eef9cd19c8d4e7f2834de65040504e5a490ae9b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-003.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..245bb2899d67d8cffd466f0284b94285f085d8ed --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..0c5786d7468d46e4992029b3c54616674c44b763 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4ddff2703af96b31719c4719573178eac804c5c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e1a8f675e640d3992eed7c2b539eca9ea381909 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..b3e1d4b8235888aeb7307e938d94484c60369a68 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..0abe6d30e322c523c516eeaa4f580de375739b32 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpn_4nbhkc", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..1777198c063fb1cde72dd2224b50dd5e8bf5d660 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 72360, + "sha256": "1ed669cc3afe6b391e13bab16f666b63900511499844b18e12a7e6f2abe89bad", + "mtime_ns": 1790522182573809675 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..323762dd8afdccf23cda30f8c317f123f350c043 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..93dbdaaec9527bd01dad042b3aa2df60bc8704ac --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/manifest.json @@ -0,0 +1,35 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "indent", + "original": [ + { + "guid": [ + 22, + 254, + 80, + 182, + 231, + 93, + 89, + 72, + 151, + 171, + 141, + 14, + 152, + 171, + 237, + 165 + ], + "level": 3, + "position": "Keep", + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [153, 10, 0, 185, 105, 82, 19, 78, 149, 135, 202, 5, 72, 113, 230, 157], n: 1 } })", + "phase": "08-collapsed-group-move", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [153, 10, 0, 185, 105, 82, 19, 78, 149, 135, 202, 5, 72, 113, 230, 157], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..43e8da07c5d43b11a2449c00dc2f6e4b8109f1e1 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-FADEB6C0 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..35bba73a78f5a44a7d33e4741e96eccfbdd4617b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-fadeb6c0", "hostname": "ONE-M6-FADEB6C0"} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..80a9059986d243feb9eca115d3802a5d9b0529b2 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..c7dc4940476d8120f4a41dae2f6ab4f75ba21756 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..0035c5e5d41aaba579b520391868a391ba9f9966 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-FADEB6C0", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..fe9f720c325910530179de77762c4eb4b80b68a7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..c4e667a8f4fb3e90eea4cdeaad4b6267375b923f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-000.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..0363cf4430845b13a5baf37b702e2fee74a13d71 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4bfbe28495f9c5af9562a15040dddadca7b525e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..2566e17ffa1776b619b45ae779bd5e3e35c3fae5 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..70b2dbcfe6690848d9989255938c9946cfce074b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-004.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..40d75de72b23cc587a6188c58f89730ea5174c23 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-005.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..ee7e58e6a41127040df2b7813e6a3a7b223b15a8 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..dd9af6c2137444328464db933ed7d81c685ea2a4 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..576a361e162ab5fc40d1cd34f378fda7601c316b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..3830017edfccf911ed254efe4aa41ad837227834 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3g6qdqvi", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..5d57260487bfcbe5e554461bf05992ac6d81bab7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 73840, + "sha256": "18ac2501a9fd0d09d043b23d41f6d3a04a47c3866f9fd8114c2a76c773d71fcd", + "mtime_ns": 1790522182570877495 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..9860520ee087972770fe42b27551ca7a128394f1 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..299b2015277e4f6bbe0f4f4da3a350edde854411 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/manifest.json @@ -0,0 +1,35 @@ +{ + "confirmations": 0, + "conflict": true, + "mode": "indent", + "original": [ + { + "guid": [ + 5, + 235, + 87, + 66, + 187, + 139, + 97, + 68, + 186, + 227, + 174, + 187, + 142, + 150, + 54, + 216 + ], + "level": 3, + "position": "Keep", + "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1" + } + ], + "page_receipt": "Some(Published { revision: ExGuid { guid: [141, 54, 145, 86, 191, 101, 228, 72, 142, 5, 46, 211, 83, 3, 119, 106], n: 1 } })", + "phase": "single-page", + "publications": 1, + "reviewed": [], + "text_receipt": "Some(Published { revision: ExGuid { guid: [141, 54, 145, 86, 191, 101, 228, 72, 142, 5, 46, 211, 83, 3, 119, 106], n: 1 } })" +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..b53324c443f6bcf3dc31f50d7d2d3904717fe8d1 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-B0D47B05 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..34b10cecc361b61b539da1e1665c090911118d84 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-b0d47b05", "hostname": "ONE-M6-B0D47B05"} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..027e07817f57d91b1b9f13824b71b837727e0d64 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..80e19ce98b03933b881e8921d97228358a1f7881 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..1a0dc4867908a574efb3981983aa855d51df7973 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-B0D47B05", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..a17f17c8b9bd67be3a4454e5cc48a4518dc38e89 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..3ba28c1c51c2ece5c192a9d5fdfa83795d6484fb --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Offline Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..105863c907f43c5e417b0b9da5bc7ff368cc1264 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..1d3eebd12fe777bcb6e38b24673066aee40b21f4 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-002.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..cd48f98a22e0b2ced75c099865258b0e6e6d909b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..6f897cd30900a1c2f76f0b697aa9c00504772fa1 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..4db0ff889d334dca5d81a5394bf245f101dd3098 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..d618e189642e21894d27750d3266e526d1308994 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..836beb5e9e1865d869b970a4c337a67acdea1929 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..6451ddb5ec49cac502e9b1c20e65f9ee4668e95a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..e8cd958fea863b97d0ceaee427ce3aa71f076e6d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp7q_s9zzh", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..765d902708f46c9a7f9ff3f67be3585dd6037caf --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 63080, + "sha256": "81f1eecbaee6e55e8a6c3af4eb875fe943ab387e7b1e0c6ea76a32d7ed01d5b8", + "mtime_ns": 1790522182589020156 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/offline-edits-series/provenance.json b/corpus/page-lifecycle/offline-edits-series/provenance.json new file mode 100644 index 0000000000000000000000000000000000000000..50ef6a11bad6ace2b431976c4a232b893a49a005 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/provenance.json @@ -0,0 +1,674 @@ +{ + "generator": [ + "crates/notebook/tests/sync_pages.rs::native_page_changes_reconcile_with_atomic_offline_batches", + "crates/notebook/tests/sync_pages.rs::twelve_disjoint_page_batches_merge_with_dependent_bodies_without_review" + ], + "evidence": "evidence/series", + "cold": { + "group-01-demoted-parent": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpxbgzk4zk", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-228507e9", + "hostname": "ONE-M6-228507E9" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 58888, + "sha256": "9a3b4662022dc604139192a1ce6e89e0a86fb2f4f28d612d0b21fc39cbb0321b", + "mtime_ns": 1790522182582306261 + } + ] + }, + "group-02-promoted-parent": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp2tw32xod", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-59e6b833", + "hostname": "ONE-M6-59E6B833" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 60864, + "sha256": "dac0d3baff9cba15171a7a49ad5e3fe5ae4f1d9486a282f73eca7bf12a4302cf", + "mtime_ns": 1790522182571809194 + } + ] + }, + "group-03-selected-group-move": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpqu8gvf97", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-2f0cfd28", + "hostname": "ONE-M6-2F0CFD28" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 62448, + "sha256": "e8227277e0b943d76ff7f1317a204bc1c90d83edb14d57c1e4fc4b6025572d5a", + "mtime_ns": 1790522182601367622 + } + ] + }, + "group-04-subpage-move": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp6no75z1i", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-1f7db150", + "hostname": "ONE-M6-1F7DB150" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 65000, + "sha256": "44eca1c10b54a10f3b8d08487d222d94aaac3b9a28f6b6f52ffd5d0d702aaf63", + "mtime_ns": 1790522182581472144 + } + ] + }, + "group-05-insert-before-subpage": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpy26z3j6d", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-4a72e5a4", + "hostname": "ONE-M6-4A72E5A4" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 66944, + "sha256": "2f144e06946d6424cb548a4b51fdd58c2be2be35fb93ddb8f80808dce7ef8ed8", + "mtime_ns": 1790522182575647033 + } + ] + }, + "group-06-promoted-level-two": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp7i0tqm4j", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-2d9428ea", + "hostname": "ONE-M6-2D9428EA" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 70296, + "sha256": "30860c7715ac247a1f77d1d0c8c27edfcc248e719183cb7990381f5ad5230d89", + "mtime_ns": 1790522182588156289 + } + ] + }, + "group-07-promoted-root": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpfsvvpr33", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-a2c6ce60", + "hostname": "ONE-M6-A2C6CE60" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 72360, + "sha256": "550991e8db44ff19e287605df0548e26e03d5f4b02ea3c56b37206fd4a122974", + "mtime_ns": 1790522182583277710 + } + ] + }, + "group-08-collapsed-group-move": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpfwhuw46n", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-150cfda8", + "hostname": "ONE-M6-150CFDA8" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 73840, + "sha256": "b68abccdc4c7c98c65311b2924f3903540b22c7f6e0bb8153b31bbe34fdf2c05", + "mtime_ns": 1790522182560292804 + } + ] + }, + "group-single-page": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3_04860j", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-93a16790", + "hostname": "ONE-M6-93A16790" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 63080, + "sha256": "58f87ab34c5e56426faed56429ab10a15e3df0673851e8c9b4587cb107a13295", + "mtime_ns": 1790522182573126515 + } + ] + }, + "indent-01-demoted-parent": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmppgtomrlh", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-2b44159d", + "hostname": "ONE-M6-2B44159D" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 58888, + "sha256": "c19272d0b0a52889647b23a6eb10381e7d90d5d5d7ca2ad3be868aa585a8b21c", + "mtime_ns": 1790522182595778175 + } + ] + }, + "indent-02-promoted-parent": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpsa22lkkc", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-3f9d5e9e", + "hostname": "ONE-M6-3F9D5E9E" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 60864, + "sha256": "02983cdd10e8f6ac52dfdd27ef63858d4d3351c2c78822c0f5c20794298fb0ca", + "mtime_ns": 1790522182572487438 + } + ] + }, + "indent-03-selected-group-move": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpb5gki0t4", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-6def4909", + "hostname": "ONE-M6-6DEF4909" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 62448, + "sha256": "62f0d051077351cfee81931153467cbf510700e94b46347a78e287801943f37c", + "mtime_ns": 1790522182574538544 + } + ] + }, + "indent-04-subpage-move": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmplfmc8y5c", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-3cf1ad85", + "hostname": "ONE-M6-3CF1AD85" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 65000, + "sha256": "e61b424191b7ddde476e498953e5fedb01566f5fdcf5ec5ad85b75dc81ae4b81", + "mtime_ns": 1790522182580783526 + } + ] + }, + "indent-05-insert-before-subpage": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3bp2l4t4", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-c302208f", + "hostname": "ONE-M6-C302208F" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 66944, + "sha256": "b1f5d19ffee4ff89ab2a14066a729b5585179339be2b18227f92c0bf2b44c42e", + "mtime_ns": 1790522182565951458 + } + ] + }, + "indent-06-promoted-level-two": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpjja19zue", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-bc497350", + "hostname": "ONE-M6-BC497350" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 70296, + "sha256": "8fa8fc3275cfb17da80d2f9e08baebd8c70b8489b5721460e17c771998226876", + "mtime_ns": 1790522182589845898 + } + ] + }, + "indent-07-promoted-root": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpn_4nbhkc", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-90980d00", + "hostname": "ONE-M6-90980D00" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 72360, + "sha256": "1ed669cc3afe6b391e13bab16f666b63900511499844b18e12a7e6f2abe89bad", + "mtime_ns": 1790522182573809675 + } + ] + }, + "indent-08-collapsed-group-move": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3g6qdqvi", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-fadeb6c0", + "hostname": "ONE-M6-FADEB6C0" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 73840, + "sha256": "18ac2501a9fd0d09d043b23d41f6d3a04a47c3866f9fd8114c2a76c773d71fcd", + "mtime_ns": 1790522182570877495 + } + ] + }, + "indent-single-page": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp7q_s9zzh", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-b0d47b05", + "hostname": "ONE-M6-B0D47B05" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 63080, + "sha256": "81f1eecbaee6e55e8a6c3af4eb875fe943ab387e7b1e0c6ea76a32d7ed01d5b8", + "mtime_ns": 1790522182589020156 + } + ] + }, + "twelve-clients": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpqs9m09lz", + "expected_pages": 37, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-d9f15303", + "hostname": "ONE-M6-D9F15303" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "pages.one", + "bytes": 159240, + "sha256": "dba31b100d591e034dd53a5eaca768b2d104c6c7e005c1ab9d3fee9a9791bcfd", + "mtime_ns": 1790522182609793250 + } + ] + } + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..006be63b4d70d92ba3fa55b246fe693d1e8ab5a8 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/manifest.json @@ -0,0 +1,2304 @@ +{ + "expected_order": [ + [ + "{7F455609-2BEF-4BCB-A94A-0FEECE61F2D1},1", + 1 + ], + [ + "{B9E9B75B-7B33-4C60-A3D1-0BE78F314485},1", + 1 + ], + [ + "{C4B5EAED-3ABF-4B34-A1B5-06C8A6E2259F},1", + 1 + ], + [ + "{1C26F613-1AD8-417F-837C-6A2EB606D092},1", + 2 + ], + [ + "{F31C990F-D1E1-4840-BB4F-46ED372732A9},1", + 1 + ], + [ + "{021A914B-C467-4FDE-BF44-B4D695410F0B},1", + 1 + ], + [ + "{B0559E07-BA1D-4B20-B7AA-906C04AA5DFE},1", + 2 + ], + [ + "{544121FD-0E61-4A76-8191-A02ABA23A314},1", + 1 + ], + [ + "{4A597354-6867-49AB-B740-4C1E39E40E2E},1", + 1 + ], + [ + "{7F7E3DAF-B98B-4BBD-9EB2-4534A3C74123},1", + 2 + ], + [ + "{303BACE6-CEFC-4107-AC1E-D6F3BBC7D1AE},1", + 1 + ], + [ + "{8D4454DE-21E6-49FB-9438-B48408E348E4},1", + 1 + ], + [ + "{214F33C4-3F0A-4CEF-9BC9-F8D69687830E},1", + 2 + ], + [ + "{CE4D4557-358A-4401-8426-C7C794F5F2BE},1", + 1 + ], + [ + "{64E10720-B6D7-46D7-B810-BA636020102D},1", + 1 + ], + [ + "{FF359729-6EDF-4577-A968-7774CD55FB52},1", + 2 + ], + [ + "{3E3C7041-7C7E-4104-8755-CE045D331F8F},1", + 1 + ], + [ + "{3DDB5E8B-3245-43D0-B001-93E5BC5C8374},1", + 1 + ], + [ + "{7B267536-B0AE-4744-B0E4-C5628174834D},1", + 2 + ], + [ + "{1F097AAE-D72E-4A7A-8359-6DCE136F0E21},1", + 1 + ], + [ + "{BC956E6C-D057-409D-A618-A6BF06DD9AFC},1", + 1 + ], + [ + "{39C7177D-715E-417F-A5B2-596DCDE13027},1", + 2 + ], + [ + "{2C70EAEB-A51D-448F-8955-89156506CF95},1", + 1 + ], + [ + "{F924B8C7-66CA-4FEA-ADD7-5ECD6910D5AA},1", + 1 + ], + [ + "{95B02C61-106C-47DC-AC71-563A6AE3F6BE},1", + 2 + ], + [ + "{907D9244-8140-4F4C-8BA9-6E42C8F2F5CC},1", + 1 + ], + [ + "{232109B4-E38E-4D7A-AB6B-2C52BCD49511},1", + 1 + ], + [ + "{1A4EE170-3A3E-4E9E-9CDC-8DD17C510B26},1", + 2 + ], + [ + "{8679521F-8046-4611-A5A3-AB151635E26D},1", + 1 + ], + [ + "{CF289176-0CDB-4163-8A44-C51958D8B8A1},1", + 1 + ], + [ + "{99334A81-D662-4AC6-A49D-A0860B4E0DD8},1", + 2 + ], + [ + "{7BAB3EDA-868E-4B41-AD61-B32D463AB3E0},1", + 1 + ], + [ + "{BDFF266F-D35B-4408-B624-B3C5DE9DECED},1", + 1 + ], + [ + "{458A27E7-608E-467D-87C0-540AA0AF5AB6},1", + 2 + ], + [ + "{9F7A4423-B568-4CA7-BE9D-8003FAF044AD},1", + 1 + ], + [ + "{2EDB6F23-646D-4B69-A92A-14293B52E874},1", + 1 + ], + [ + "{E455C07B-77AB-4D41-91AE-3CAD15027F85},1", + 2 + ] + ], + "operations": [ + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 137, + 65, + 46, + 153, + 28, + 23, + 191, + 78, + 179, + 39, + 162, + 124, + 151, + 204, + 247, + 54 + ], + "level": 1, + "position": { + "Before": "{C4B5EAED-3ABF-4B34-A1B5-06C8A6E2259F},1" + }, + "space": "{B9E9B75B-7B33-4C60-A3D1-0BE78F314485},1" + }, + { + "guid": [ + 214, + 18, + 186, + 71, + 69, + 135, + 163, + 67, + 162, + 241, + 219, + 185, + 146, + 144, + 160, + 212 + ], + "level": 2, + "position": "Keep", + "space": "{1C26F613-1AD8-417F-837C-6A2EB606D092},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951600000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},2", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},1", + "tags": [], + "text": { + "spans": [ + { + "end": 16, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 0 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},3", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{B9E9B75B-7B33-4C60-A3D1-0BE78F314485},1" + } + } + ] + }, + "id": 2 + } + ], + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 232, + 190, + 205, + 38, + 113, + 7, + 97, + 70, + 142, + 69, + 28, + 16, + 219, + 74, + 94, + 170 + ], + "level": 1, + "position": { + "Before": "{021A914B-C467-4FDE-BF44-B4D695410F0B},1" + }, + "space": "{F31C990F-D1E1-4840-BB4F-46ED372732A9},1" + }, + { + "guid": [ + 240, + 152, + 226, + 6, + 125, + 5, + 59, + 78, + 159, + 199, + 217, + 224, + 167, + 207, + 69, + 206 + ], + "level": 2, + "position": "Keep", + "space": "{B0559E07-BA1D-4B20-B7AA-906C04AA5DFE},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951600000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},5", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},4", + "tags": [], + "text": { + "spans": [ + { + "end": 16, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 1 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},6", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{F31C990F-D1E1-4840-BB4F-46ED372732A9},1" + } + } + ] + }, + "id": 2 + } + ], + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 128, + 150, + 44, + 239, + 75, + 40, + 93, + 71, + 139, + 44, + 144, + 149, + 3, + 225, + 194, + 105 + ], + "level": 1, + "position": { + "Before": "{4A597354-6867-49AB-B740-4C1E39E40E2E},1" + }, + "space": "{544121FD-0E61-4A76-8191-A02ABA23A314},1" + }, + { + "guid": [ + 77, + 215, + 146, + 157, + 207, + 140, + 1, + 70, + 160, + 237, + 173, + 17, + 181, + 152, + 129, + 117 + ], + "level": 2, + "position": "Keep", + "space": "{7F7E3DAF-B98B-4BBD-9EB2-4534A3C74123},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951610000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},8", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},7", + "tags": [], + "text": { + "spans": [ + { + "end": 16, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 2 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},9", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{544121FD-0E61-4A76-8191-A02ABA23A314},1" + } + } + ] + }, + "id": 2 + } + ], + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 60, + 24, + 102, + 131, + 237, + 125, + 96, + 68, + 140, + 15, + 56, + 134, + 76, + 94, + 75, + 241 + ], + "level": 1, + "position": { + "Before": "{8D4454DE-21E6-49FB-9438-B48408E348E4},1" + }, + "space": "{303BACE6-CEFC-4107-AC1E-D6F3BBC7D1AE},1" + }, + { + "guid": [ + 43, + 187, + 225, + 181, + 143, + 57, + 100, + 71, + 156, + 65, + 221, + 123, + 106, + 144, + 24, + 42 + ], + "level": 2, + "position": "Keep", + "space": "{214F33C4-3F0A-4CEF-9BC9-F8D69687830E},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951610000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},11", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},10", + "tags": [], + "text": { + "spans": [ + { + "end": 16, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 3 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},12", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{303BACE6-CEFC-4107-AC1E-D6F3BBC7D1AE},1" + } + } + ] + }, + "id": 2 + } + ], + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 237, + 166, + 115, + 62, + 6, + 126, + 122, + 71, + 165, + 0, + 132, + 211, + 66, + 36, + 104, + 34 + ], + "level": 1, + "position": { + "Before": "{64E10720-B6D7-46D7-B810-BA636020102D},1" + }, + "space": "{CE4D4557-358A-4401-8426-C7C794F5F2BE},1" + }, + { + "guid": [ + 20, + 190, + 251, + 94, + 101, + 42, + 0, + 68, + 150, + 161, + 251, + 52, + 113, + 3, + 175, + 41 + ], + "level": 2, + "position": "Keep", + "space": "{FF359729-6EDF-4577-A968-7774CD55FB52},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951610000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},14", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},13", + "tags": [], + "text": { + "spans": [ + { + "end": 16, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 4 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},15", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{CE4D4557-358A-4401-8426-C7C794F5F2BE},1" + } + } + ] + }, + "id": 2 + } + ], + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 148, + 253, + 150, + 142, + 238, + 167, + 15, + 78, + 187, + 244, + 152, + 219, + 101, + 253, + 64, + 204 + ], + "level": 1, + "position": { + "Before": "{3DDB5E8B-3245-43D0-B001-93E5BC5C8374},1" + }, + "space": "{3E3C7041-7C7E-4104-8755-CE045D331F8F},1" + }, + { + "guid": [ + 121, + 181, + 255, + 117, + 85, + 146, + 190, + 70, + 147, + 88, + 216, + 245, + 1, + 13, + 103, + 107 + ], + "level": 2, + "position": "Keep", + "space": "{7B267536-B0AE-4744-B0E4-C5628174834D},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951610000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},17", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},16", + "tags": [], + "text": { + "spans": [ + { + "end": 16, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 5 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},18", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{3E3C7041-7C7E-4104-8755-CE045D331F8F},1" + } + } + ] + }, + "id": 2 + } + ], + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 156, + 157, + 179, + 162, + 123, + 147, + 117, + 70, + 181, + 60, + 138, + 82, + 124, + 75, + 38, + 187 + ], + "level": 1, + "position": { + "Before": "{BC956E6C-D057-409D-A618-A6BF06DD9AFC},1" + }, + "space": "{1F097AAE-D72E-4A7A-8359-6DCE136F0E21},1" + }, + { + "guid": [ + 3, + 209, + 128, + 197, + 70, + 248, + 104, + 70, + 162, + 92, + 200, + 5, + 82, + 16, + 182, + 46 + ], + "level": 2, + "position": "Keep", + "space": "{39C7177D-715E-417F-A5B2-596DCDE13027},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951610000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},20", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},19", + "tags": [], + "text": { + "spans": [ + { + "end": 16, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 6 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},21", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{1F097AAE-D72E-4A7A-8359-6DCE136F0E21},1" + } + } + ] + }, + "id": 2 + } + ], + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 207, + 242, + 85, + 164, + 205, + 114, + 120, + 73, + 145, + 29, + 194, + 242, + 8, + 34, + 144, + 124 + ], + "level": 1, + "position": { + "Before": "{F924B8C7-66CA-4FEA-ADD7-5ECD6910D5AA},1" + }, + "space": "{2C70EAEB-A51D-448F-8955-89156506CF95},1" + }, + { + "guid": [ + 38, + 126, + 122, + 127, + 151, + 38, + 229, + 76, + 135, + 62, + 181, + 209, + 254, + 240, + 31, + 157 + ], + "level": 2, + "position": "Keep", + "space": "{95B02C61-106C-47DC-AC71-563A6AE3F6BE},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951610000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},23", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},22", + "tags": [], + "text": { + "spans": [ + { + "end": 16, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 7 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},24", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{2C70EAEB-A51D-448F-8955-89156506CF95},1" + } + } + ] + }, + "id": 2 + } + ], + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 215, + 122, + 231, + 63, + 33, + 23, + 153, + 71, + 146, + 55, + 135, + 108, + 108, + 25, + 220, + 189 + ], + "level": 1, + "position": { + "Before": "{232109B4-E38E-4D7A-AB6B-2C52BCD49511},1" + }, + "space": "{907D9244-8140-4F4C-8BA9-6E42C8F2F5CC},1" + }, + { + "guid": [ + 147, + 175, + 210, + 70, + 177, + 159, + 86, + 67, + 169, + 228, + 21, + 200, + 173, + 16, + 23, + 190 + ], + "level": 2, + "position": "Keep", + "space": "{1A4EE170-3A3E-4E9E-9CDC-8DD17C510B26},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951620000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},26", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},25", + "tags": [], + "text": { + "spans": [ + { + "end": 16, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 8 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},27", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{907D9244-8140-4F4C-8BA9-6E42C8F2F5CC},1" + } + } + ] + }, + "id": 2 + } + ], + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 114, + 248, + 161, + 39, + 180, + 234, + 235, + 74, + 172, + 83, + 92, + 166, + 243, + 74, + 0, + 10 + ], + "level": 1, + "position": { + "Before": "{CF289176-0CDB-4163-8A44-C51958D8B8A1},1" + }, + "space": "{8679521F-8046-4611-A5A3-AB151635E26D},1" + }, + { + "guid": [ + 161, + 154, + 81, + 212, + 11, + 138, + 231, + 74, + 178, + 141, + 20, + 210, + 107, + 144, + 145, + 81 + ], + "level": 2, + "position": "Keep", + "space": "{99334A81-D662-4AC6-A49D-A0860B4E0DD8},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951620000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},29", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},28", + "tags": [], + "text": { + "spans": [ + { + "end": 16, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 9 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},30", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{8679521F-8046-4611-A5A3-AB151635E26D},1" + } + } + ] + }, + "id": 2 + } + ], + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 141, + 40, + 59, + 48, + 97, + 31, + 212, + 65, + 153, + 12, + 89, + 90, + 90, + 202, + 68, + 159 + ], + "level": 1, + "position": { + "Before": "{BDFF266F-D35B-4408-B624-B3C5DE9DECED},1" + }, + "space": "{7BAB3EDA-868E-4B41-AD61-B32D463AB3E0},1" + }, + { + "guid": [ + 71, + 27, + 109, + 113, + 163, + 222, + 41, + 74, + 134, + 176, + 81, + 84, + 203, + 181, + 219, + 203 + ], + "level": 2, + "position": "Keep", + "space": "{458A27E7-608E-467D-87C0-540AA0AF5AB6},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951620000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},32", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},31", + "tags": [], + "text": { + "spans": [ + { + "end": 17, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 10 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},33", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{7BAB3EDA-868E-4B41-AD61-B32D463AB3E0},1" + } + } + ] + }, + "id": 2 + } + ], + [ + { + "edit": { + "at": 133000000000000000, + "ops": [ + { + "Section": { + "Pages": [ + { + "guid": [ + 141, + 240, + 28, + 163, + 72, + 70, + 7, + 72, + 187, + 241, + 188, + 124, + 179, + 164, + 65, + 183 + ], + "level": 1, + "position": { + "Before": "{2EDB6F23-646D-4B69-A92A-14293B52E874},1" + }, + "space": "{9F7A4423-B568-4CA7-BE9D-8003FAF044AD},1" + }, + { + "guid": [ + 134, + 79, + 134, + 224, + 23, + 71, + 222, + 68, + 132, + 196, + 140, + 39, + 58, + 135, + 58, + 234 + ], + "level": 2, + "position": "Keep", + "space": "{E455C07B-77AB-4D41-91AE-3CAD15027F85},1" + } + ] + } + } + ] + }, + "id": 1 + }, + { + "edit": { + "at": 134349951620000000, + "ops": [ + { + "Page": { + "op": { + "Add": { + "before": null, + "object": { + "Outline": { + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},35", + "indents": [], + "layout": { + "max_height": null, + "max_width": null, + "reserved_width": null, + "width_set_by_user": null, + "x": 36.0, + "y": 36.0 + }, + "min_width": null, + "paragraphs": [ + { + "collapsed": false, + "content": { + "Text": { + "date_field": null, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},34", + "tags": [], + "text": { + "spans": [ + { + "end": 17, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": "Calibri", + "font_size": 11.0, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": 1033, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + } + } + ], + "text": "Actor 11 🦀 é" + } + } + }, + "format": { + "alignment": null, + "bold": null, + "color": null, + "embedded_object": null, + "font": null, + "font_size": null, + "hidden": null, + "highlight": null, + "hyperlink": null, + "hyperlink_label": null, + "italic": null, + "language": null, + "line_spacing": null, + "list_spacing": null, + "math": null, + "math_object": null, + "rtl": null, + "space_after": null, + "space_before": null, + "strike": null, + "subscript": null, + "superscript": null, + "underline": null + }, + "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},36", + "level": 1, + "lists": [], + "media": { + "recordings": [], + "time_ms": null + }, + "parent": null, + "style": null, + "tags": [] + } + ], + "title": false, + "unsupported": [] + } + } + } + }, + "space": "{9F7A4423-B568-4CA7-BE9D-8003FAF044AD},1" + } + } + ] + }, + "id": 2 + } + ] + ], + "pages": 37, + "publications": 12 +} \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/pages.one b/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/pages.one new file mode 100644 index 0000000000000000000000000000000000000000..a07687258692a91cc8859b73e0451eb576e26fa3 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/pages.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..02b59bcbcb66de5148ea66c4be94497e0fccd757 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-D9F15303 -ExpectedPages 37", "exit": 0, "stdout": "Read 1 sections and 37 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..aea0658156ef2f41c4f06c96d842519a48035b28 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-d9f15303", "hostname": "ONE-M6-D9F15303"} diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..a97d8ec4557e250e16ecaec059688cebb3eb6826 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/pages.one b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/pages.one new file mode 100644 index 0000000000000000000000000000000000000000..35734e5e858bc1119b182e977c32cc01f39e8262 Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/pages.one differ diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..c54f03df5a38e25576176b34741a9eefea13cc9e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-D9F15303", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..c1aa135b7c8263e1548d955afd6d1e2350cc1dea --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..9728db3b902284b2bbf8294d27a8cdb4ee334a3d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-000.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..5d5aba6035a311dd12f0eff0af8b6b8f4df3c87b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-001.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..ddb165926d17e008176ca57ba8deade0eababab8 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-002.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..dad7cae105ed24535759e0c6b93f030aba8823ed --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..8404a1947cd1573644028528327a6ec0d18d489a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-004.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..594f89a36912ee18d9afee260f7cdb9968604c14 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..c79c9b7fb5302e95caf3db8637f1d248a6000d66 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-006.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..81c6beec493dd338a48ad4091044b239ee2150f2 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-007.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..64bec87fa2e8b8bf47b8eea002beb866bda491d0 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-009.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..44b9036f45f840e10c39dc1f3f2ea7e2229a8aed --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-009.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-010.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..b434321a62020c4ec6a2cbf95bb912c8a8a084b2 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-010.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-011.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-011.xml new file mode 100644 index 0000000000000000000000000000000000000000..116dc6f41446aa830747a67a3366bb5088feb76d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-011.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-012.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-012.xml new file mode 100644 index 0000000000000000000000000000000000000000..8daadce17f8c369cc9285fb9af3e2fb4513caf9b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-012.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-013.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-013.xml new file mode 100644 index 0000000000000000000000000000000000000000..14730456f24f6a35f9d4c2af510f6dd4f8d4f9cb --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-013.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-014.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-014.xml new file mode 100644 index 0000000000000000000000000000000000000000..f9745fef6c629d585c9bff07889e44f3e525cae7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-014.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-015.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-015.xml new file mode 100644 index 0000000000000000000000000000000000000000..843125cebe4a565f6a7cfb13f0b397c29e45f2ae --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-015.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-016.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-016.xml new file mode 100644 index 0000000000000000000000000000000000000000..a9a225cef68a128ecc556fb5fe93dc48c7d54f02 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-016.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-017.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-017.xml new file mode 100644 index 0000000000000000000000000000000000000000..554eabda19f7a561eb20762b134c7fd56ff54f39 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-017.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-018.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-018.xml new file mode 100644 index 0000000000000000000000000000000000000000..5d2f023a51172c9234930edfb709ea3180eb391d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-018.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-019.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-019.xml new file mode 100644 index 0000000000000000000000000000000000000000..ce512da5fbe6c02e2c55746e70c3a07792b8050d --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-019.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-020.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-020.xml new file mode 100644 index 0000000000000000000000000000000000000000..9863fedb7d2d66dd0b660d1a66aa4885c9847471 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-020.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-021.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-021.xml new file mode 100644 index 0000000000000000000000000000000000000000..348177c0bfbe5fd7361a678251ad7c59a5b02e2c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-021.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-022.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-022.xml new file mode 100644 index 0000000000000000000000000000000000000000..180dec41de7f2df76a70d546f60a145973fc1ae1 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-022.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-023.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-023.xml new file mode 100644 index 0000000000000000000000000000000000000000..909a3517147689a89b71f40937a657b5b42818d8 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-023.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-024.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-024.xml new file mode 100644 index 0000000000000000000000000000000000000000..2deb0ec5e7287198981ef9d06fdd422ebe9db91e --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-024.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-025.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-025.xml new file mode 100644 index 0000000000000000000000000000000000000000..d954632900e313640c4134f27777f742116468bf --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-025.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-026.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-026.xml new file mode 100644 index 0000000000000000000000000000000000000000..e2b2406bcd6493361666be0a542743508b05b56a --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-026.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-027.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-027.xml new file mode 100644 index 0000000000000000000000000000000000000000..0c0a166d0b02ace36c765aeed192932e84274537 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-027.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-028.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-028.xml new file mode 100644 index 0000000000000000000000000000000000000000..eb56ae3b6fa399326e25db7d6f0d89e17dec1c1c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-028.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-029.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-029.xml new file mode 100644 index 0000000000000000000000000000000000000000..2adcb4ba1b3f24c862991f3d1f3de0646e8a91a4 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-029.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-030.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-030.xml new file mode 100644 index 0000000000000000000000000000000000000000..0f74cca2fc4c7a27c2eae9a5b2e3d654720e4ee3 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-030.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-031.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-031.xml new file mode 100644 index 0000000000000000000000000000000000000000..4f588a17b941a05eb10ca60db6e211dda7705ab7 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-031.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-032.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-032.xml new file mode 100644 index 0000000000000000000000000000000000000000..9421a43e81b9b46ea59c6698ea97c6d344a9311c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-032.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-033.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-033.xml new file mode 100644 index 0000000000000000000000000000000000000000..3f8296db5ff2d251715f449a9ec8ad677419c4a6 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-033.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-034.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-034.xml new file mode 100644 index 0000000000000000000000000000000000000000..3a659a3ee6da1aeeafdc430423e584ded0acbbbe --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-034.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-035.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-035.xml new file mode 100644 index 0000000000000000000000000000000000000000..f6e892435b4818c0887be4319a432a69c88a9669 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-035.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-036.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-036.xml new file mode 100644 index 0000000000000000000000000000000000000000..bc9f7a8459f15fffcda7f6f42e9da22248b4e166 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-036.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/run.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..d8c3884b0335e33acbbadcdd0a65236751e497f6 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpqs9m09lz", + "expected_pages": 37, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/source.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..e1004464b3b866e34c9bb2bdfc6c7783c71fa48c --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "pages.one", + "bytes": 159240, + "sha256": "dba31b100d591e034dd53a5eaca768b2d104c6c7e005c1ab9d3fee9a9791bcfd", + "mtime_ns": 1790522182609793250 + } +] diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..54ba8a6290af552de506cb822f37cfeb2d7d1fa1 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..2dec7c4d07e35807302e338afef5ca75f957c2ed --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-161C24F1 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/machine.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..9583a6399f786e7b306579ab51e9d2be4ac963a4 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-161c24f1", "hostname": "ONE-M6-161C24F1"} diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..dd3adcb4f551b4776b55ff22756a63f6392eb148 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..a855452db2626b491b6feb1d205424e9bd140755 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..6db32dd36fda0b0dcd96f17440f23079eb8ca2b9 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-161C24F1", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..22a818b828b4e8abda8458ff58433f1483d37ef6 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..5686641379a99dc2e8144275022c249879cad8b0 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..23484b43650c63b553f7427dec462318bf8a41b8 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..fe4c723bf5aaf8c9ee667bde404a96a695e93396 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..e642f2c912a19a0322b1bfb418e42d6b03f16c07 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..d80e102d9bb9c45bfd03a92ebde503d7fe8ba969 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..624d266d03482767b76444fa82f4d7113a3ba183 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..75f5996b23fbf5191a3de9a565f89ef896a54e58 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-006.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..6da652f1205ac1a27138e7fc821d9b344b7bbda1 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..d18c0a0cad935285f6076ebc7c170f266d2cfa23 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/run.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..3b07b74848a9114a75212459fccb8ae4d7785931 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpn80ah_uu", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/source.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..9bab0d0182cda202b65ba15347055ca20a2838c1 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 58424, + "sha256": "e7065e4e043857c74bb8fa2ce6291c87378e3dc2224fad2fefe25e0396f645c4", + "mtime_ns": 1790522182627846620 + } +] diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/04-subpage-move/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..837c947f6ef2a46a44cbfe40272d0f20ff2ddeec Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/04-subpage-move/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..efe16cb85428c7c6a359443d437086719c5d97ee --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-24B26E2E -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/machine.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..6fb2a4d03ee5e86792162d28d5fcc845c8955d4b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-24b26e2e", "hostname": "ONE-M6-24B26E2E"} diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..d4f5dc7f31f75c852ba1ba9d08fe625a783e7642 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..b9aae4580851528248c007b1e54ed303f43621fb Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..8827e90e09bb9e80a60b9b936e4f9809f3a57bf2 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-24B26E2E", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..d7eccff8143f3c603590038a615e2215700472fc --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec831c81a9a53fa0cfd58b5dc84016e493c9ff15 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..69597a914d3506d880b1d777ad0656d4e251173a --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..d464237b73e1c2c4c66e63f82161d1f0a317b84f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..40e7d9b96a119dedde23d1330c5ca7d5bc08a977 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-003.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..609b6b45f77a6df6a9e2ea6f77046e4be8650820 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-004.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..16d1782363372443f82c1de631474c4ed61ab884 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-005.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a12694197949fae823d3030d32c90a05cce4dc9 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..0b24e00b0e829cbad9f0d0c4f708ff865bbb44f7 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-007.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..27115ed9b6c5f39ed294a8be02f96f9dd43a1df4 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/run.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..f8b69c3de736a586827f4c1d59c9f1931cd86543 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp6we9ek5d", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/source.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..6232fb01897f23543f9a2ae8e6640329232fe429 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 60208, + "sha256": "1b91cd7a7b6d225d52155246d1913a5c94b96b3f834a9f75529af349cc598983", + "mtime_ns": 1790522182669188978 + } +] diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..60324e05a077b20372090f4e51ce6798a086cca7 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..a6e14c258355f69ef1e9c817f44efa51eb869043 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-88FBA3A0 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/machine.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..b49f4cd9d52041c26b92dc76dd452a1059d4fb12 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-88fba3a0", "hostname": "ONE-M6-88FBA3A0"} diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..af4524373a05e6423894c3fac1b92c575535d5da Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..0f6f5f76653c5b4ffc77bc28cb7cdf2c6493233a Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..0f67aee843ea2efdf639ae24c4d83effa5764489 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-88FBA3A0", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..2a28f308af31c527f14d9c02de4063202c4009c9 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..e0505d826034374f2bcfebfd0555f20ac003ead3 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..c61896d4a5b681e1854cd5f5316c0e950b54ee60 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..8fbf7cc17652281521b071048f8e0dfaa9280c98 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..b1de2a0ef039e91841c3f2035f2e1bbcb9261f7d --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..07da5fe2caac138351acf1aca2a5b6f97f68077f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-004.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..a648feea3cc9d7b5f16213d59ba370effeb33261 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-005.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..e2e8d021eeb5d3edb70c85eadf73f58f0c894f22 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..3764c976a846847a36835a4a6cc740fcbbbc76e4 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-007.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..9cb21221b6b95ffe316aa0c190328799dbb4d800 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/run.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..d3d52ef58e2829c430d1fea245403275d71aad00 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpbkgvgbin", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/source.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..be80f82db4a89ea31253dfcbd65a41d20a0662fc --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 61944, + "sha256": "28d85faa977ed919a90b237e93ee7aec55a4d988fafa1994dd5fbfa2e5d038a3", + "mtime_ns": 1790522182622519129 + } +] diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..83f0dc5b48b730cc6238dea64b50f9545e02b248 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..9bd0480a051c39dc7d6788149c0f398d3d1b0cee --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-4CCC9DAE -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/machine.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..a91f11a466576e66ca88b1b846ed9eb26612d36f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-4ccc9dae", "hostname": "ONE-M6-4CCC9DAE"} diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..9f895785005c1199309fd44fef250abd4e310fbf Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..0efcd41819e8cbd4e6d5b93802941d4a2843e682 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..a46d5f6214d7ca4ca19392b498b4f2f45e55400e --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-4CCC9DAE", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..45b8311e0ae35657b193817306ffb457aa1f89d0 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..6387932e9b2557d9b942f5f8d42985e35ee9ede5 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..61f5f1908dfbb69d17fa20f693a793eabea205cf --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..aaa46fd0102e5ed3f7bb9e7f22b726f4f0fbf64f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-002.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..f48bb3be6853ef0d7cfd5c0c359cf20e6f89ff4e --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..209c2495f44c051b3321dc268858c77d9767e1c9 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..71b1783e7669bdff3b3651e73a762ef1effe72b3 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..5f69b2102248a85d4a521dc7b04c24d676a47f4d --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..8dcdda7130c17d177890d97d3ed274184954c335 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..ce67a4efc2c16546817f24cf0e6fa78797d23e89 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-008.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/run.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..26c570223ead39d1bdfff0f65093570429523616 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpsvr31me6", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/source.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..340874609e470c5b2ce0ffca2b911e788f86fe1d --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 62696, + "sha256": "90732ec43728d3485a4ff5da2bb2960201961361ef084e8d97b93965875baa0d", + "mtime_ns": 1790522182647666599 + } +] diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/07-promoted-root/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..957c361021c8a283d3be75168e737f59b0ff9f87 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/07-promoted-root/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..ee749b9055a7fe15a12326c4f73c873e031efc5e --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-AF60A95D -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/machine.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..66a0996903a512e15a33004f46c15c5e1b9fe114 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-af60a95d", "hostname": "ONE-M6-AF60A95D"} diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..f141c21e4e92ff53aaa53d51a3a308c396861003 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..996f9ae9b63bc2f62d3ed3abf7d78b71ca26d8e2 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..cf48a92d1a1137787922b699951aee2d52d6ea0d --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-AF60A95D", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..f4f3581285bb967cf222f34296faa28690870e41 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..001f2a50a2492a78addfa8c8b9a16847b719934d --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..cbe45bb7adc6b68492da8c30741b856c1311b7fc --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..2a3d3243f44caa5a989364fedba148ba61a423c0 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..cfcc8e338fd95a4e5efeb9bddbac3fbc9fd71d4c --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..38181c0da71e262777021b4a7de30d0a3478f56a --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..4c5bf22811f36c29e5aabea3661a8874710b6bd1 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-005.xml @@ -0,0 +1,4 @@ + +Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..7c41a0f0e378d5556f3a80471d7c4d0b86901166 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-006.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..f014a4e81b6ed9f7b61e3acf8b697003bbafb90b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..d0b0bb47a6a00d4456af26336269550998fa87e0 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/run.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..7b81ffee964972df2d8755c82cca16d39df649e0 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpm0pgu6fk", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/source.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..ce34acb1d8ffc40ee4998b2f6f602edc4e10a58b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 64480, + "sha256": "eb79d7824c9c1135ef3b8aaaa111cdb1277ccf8175729a2d0637a4031742d74f", + "mtime_ns": 1790522182638013566 + } +] diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..92020091770b2828bf26c2462d040849d6b2feca Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..275773a3f6ba208389772666aef406e24d410233 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-5DB5D160 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/machine.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..23f12c2b1637172ac8ea917b0ef329b8d5f731a0 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-5db5d160", "hostname": "ONE-M6-5DB5D160"} diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..2a3269838f3677db68016ca936ab6f642babc39a Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..a4344f8d1273f715d22fce77d4d245bbc8d7408e Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..4f04a100f94baf8fbd97e49e0cb8b38a5ef6d01b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-5DB5D160", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..42d9a69942412cc5f7198cf7d1ca219f2c44f82f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..91f8e020d77185a7938d137649d2a7aa076a72f0 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..b99efe530dd60a94f85632e91ea2086bb4d56d6f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..0595b4f9c3930b38f40770404430b14e27964179 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..c2f99a6bb4f4f185e0386fd129835eb44cacd058 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..05e89837882ed2d25524673de4f67160362323c9 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..1d3d638457c2ed6f8cb39de56f9317d6c55049ee --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..94f6755437ef7c621d327b76649fa6db4d6b5a4d --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-006.xml @@ -0,0 +1,4 @@ + +Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..15d1818e89854f859403990286fa1488d38cb8ed --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..cc468e2e228622439b00ad0e6c2f000f5cd2173e --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/run.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..6bea9926e97ec0d2d2d053b6d15a33f4b82950b9 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3lrvn0ah", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/source.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..49cc642d338d9e00d9a3de42da0885a6eaff137b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 65584, + "sha256": "7ba31fe2131d88523503fe1ca412b74fe301d6668a8fcdc691209bf9243db10c", + "mtime_ns": 1790522182626875088 + } +] diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-lifecycle/page-edits-series/README.md b/corpus/page-lifecycle/page-edits-series/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d583620ac73d47ff86765e72d2ff699e2de4cad7 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/README.md @@ -0,0 +1,11 @@ +# Rust page moves in series of their own + +`../page-edits` regenerated since a moved page heads a new page series, as OneNote's +drag gives the dragged pages one (`../movement`); its following subpages join the series +before it. `01` and `02` only indent and are unchanged. Each candidate reopened in a fresh +OneNote 2010 clone with every byte after the header and every active graph unchanged; +`provenance.json` records the captures (`evidence/series`) and removed clones. + +Export with `ONESTORE_PAGE_MOVEMENT_OUTPUT` on `explicit_page_edits_match_native_selection_and_indentation` +in `crates/onestore/tests/page_movement.rs`, then capture each with `tools/native_runner.py +INPUT OUTPUT --expected-pages 9 --collect-notebook`. diff --git a/corpus/page-lifecycle/page-edits-series/provenance.json b/corpus/page-lifecycle/page-edits-series/provenance.json new file mode 100644 index 0000000000000000000000000000000000000000..55de19db688cd6dd78d590cbb08c21203cf8e787 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/provenance.json @@ -0,0 +1,253 @@ +{ + "generator": [ + "crates/onestore/tests/page_movement.rs::explicit_page_edits_match_native_selection_and_indentation" + ], + "evidence": "evidence/series", + "cold": { + "03-selected-group-move": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpn80ah_uu", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-161c24f1", + "hostname": "ONE-M6-161C24F1" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 58424, + "sha256": "e7065e4e043857c74bb8fa2ce6291c87378e3dc2224fad2fefe25e0396f645c4", + "mtime_ns": 1790522182627846620 + } + ] + }, + "04-subpage-move": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp6we9ek5d", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-24b26e2e", + "hostname": "ONE-M6-24B26E2E" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 60208, + "sha256": "1b91cd7a7b6d225d52155246d1913a5c94b96b3f834a9f75529af349cc598983", + "mtime_ns": 1790522182669188978 + } + ] + }, + "05-insert-before-subpage": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpbkgvgbin", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-88fba3a0", + "hostname": "ONE-M6-88FBA3A0" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 61944, + "sha256": "28d85faa977ed919a90b237e93ee7aec55a4d988fafa1994dd5fbfa2e5d038a3", + "mtime_ns": 1790522182622519129 + } + ] + }, + "06-promoted-level-two": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpsvr31me6", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-4ccc9dae", + "hostname": "ONE-M6-4CCC9DAE" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 62696, + "sha256": "90732ec43728d3485a4ff5da2bb2960201961361ef084e8d97b93965875baa0d", + "mtime_ns": 1790522182647666599 + } + ] + }, + "07-promoted-root": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpm0pgu6fk", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-af60a95d", + "hostname": "ONE-M6-AF60A95D" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 64480, + "sha256": "eb79d7824c9c1135ef3b8aaaa111cdb1277ccf8175729a2d0637a4031742d74f", + "mtime_ns": 1790522182638013566 + } + ] + }, + "08-collapsed-group-move": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3lrvn0ah", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-5db5d160", + "hostname": "ONE-M6-5DB5D160" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 65584, + "sha256": "7ba31fe2131d88523503fe1ca412b74fe301d6668a8fcdc691209bf9243db10c", + "mtime_ns": 1790522182626875088 + } + ] + }, + "single-page": { + "run": { + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpbiygu3ji", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } + }, + "machine": { + "name": "m6-231ec95d", + "hostname": "ONE-M6-231EC95D" + }, + "teardown": { + "absent": true + }, + "source": [ + { + "path": "Lifecycle.one", + "bytes": 55032, + "sha256": "eed7365c2054ffe32321b599ac4456d583130d3cb2e3aed41bf0baac4e27d8d2", + "mtime_ns": 1790522182633015571 + } + ] + } + } +} diff --git a/corpus/page-lifecycle/page-edits-series/single-page/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/single-page/candidate/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..e1498b42342b06bb3cb8d92cfc45cb785b192118 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/single-page/candidate/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/single-page/cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..744a57e574f73f5ad72e7e1620143814e0f07254 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-231EC95D -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/machine.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..36f6b55cd29d91a9951c18307046073f52013df0 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-231ec95d", "hostname": "ONE-M6-231EC95D"} diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Lifecycle.one new file mode 100644 index 0000000000000000000000000000000000000000..a73626f63da589d306c759454573a14db8b66e5b Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Lifecycle.one differ diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..ecc0f9942014f028b3e497ac2ad1ad86ad165646 Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..81d12688904d4bf0ac2be7e0124283cedbe63c3e --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-231EC95D", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..0ce54f65d111733335fb5a39f3bced8509b256c6 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..db4c21c92de9605679ba9e1b363c41f15d66a1c9 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Body trailing 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..c0898826d8ad249633826d0bf2c51c75bb57b402 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Body duplicate 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..ce8fcc7575bc0e45e748e35d3093ef5ccbdfa00a --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-002.xml @@ -0,0 +1,4 @@ + +Body automatic 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..4d010e983f9243d22579f4c0e25b092bdba74526 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-003.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..a6ecd5ea63736042842ee723b04580958696d16c --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Body parent 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..0a35d05f727ea9a2e51c247852e3e3c7417759a8 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-005.xml @@ -0,0 +1,4 @@ + +Body grandchild 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..a21385b0be8e3662a80a859714c46e790bf63146 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-006.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..80c39a2398c4238e30e92984e03d6f1aca88b041 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-007.xml @@ -0,0 +1,4 @@ + +Body child 🦀 é preserved]]> diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..a2bea51e9f276ad42a60a12067523b812b4abe0f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/run.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..7fa6227c595802656e26d090c4dae6b469031500 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpbiygu3ji", + "expected_pages": 9, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/source.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..98d198cb34329b050c99a0df79962d8b711be6a7 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "Lifecycle.one", + "bytes": 55032, + "sha256": "eed7365c2054ffe32321b599ac4456d583130d3cb2e3aed41bf0baac4e27d8d2", + "mtime_ns": 1790522182633015571 + } +] diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/crates/notebook/README.md b/crates/notebook/README.md index dd79930b674765da96546172bb80dfbba09d5144..e1e12b3928758918be6c3b00aa740fee0d30b9e5 100644 --- a/crates/notebook/README.md +++ b/crates/notebook/README.md @@ -242,12 +242,17 @@ directly from the core document model. ## Notebook structure -`Notebook::create_section`, `create_group`, `rename`, `set_section_color`, -`reorder` and `delete` change a notebook the way OneNote does: the table of -contents (`Open Notebook.onetoc2`, created when a folder has none) gains, -renames, reorders or loses entries; a section's colour lives in its own -metadata; a deleted section moves into `OneNote_RecycleBin`, a group with its -own TOC. Every created, renamed or moved file is placed with +`Notebook::create`, `create_section`, `create_group`, `rename`, `move_entry`, +`set_section_color`, `reorder` and `delete` change a notebook the way OneNote does: the +table of contents (`Open Notebook.onetoc2`, created when a folder has none) gains, +renames, reorders or loses entries; a new notebook holds "New Section 1", and a new +section an empty section's file plus the page its `PageCreation` makes, in OneNote's +new-section colour order; a section's colour lives in its own metadata; a deleted +section moves into `OneNote_RecycleBin`, a group with its own TOC, and a deleted group's +sections move there too before its folders go. `recycle_pages` keeps copies of pages a +section is about to delete in `OneNote_RecycleBin/OneNote_DeletedPages.one`, with their +identities, titles, dates and creation times, as OneNote does +(`corpus/notebook-management`). Every created, renamed or moved file is placed with `onestore::place_file`, which sets the header's ancestor to the parent TOC's identity and the name CRC OneNote checks on open; a file without them is re-identified and listed anew. They run over `Storage`: a mounted directory diff --git a/crates/notebook/src/merge.rs b/crates/notebook/src/merge.rs index f2f21fbb893ad8d4e23e8610011bb64d7c09838a..038402e7b264f2ebe92912cb17b499cba47b858b 100644 --- a/crates/notebook/src/merge.rs +++ b/crates/notebook/src/merge.rs @@ -37,6 +37,8 @@ pub(crate) struct Merged { /// Pages whose local version the remote could not take, with who made the first edit /// that did not replay and the objects the dropped ops named. pub conflicts: BTreeMap)>, + /// Pages the base listed that the remote moved (`moved`). + pub moved: BTreeSet, } /// Replays `edits` on `new`, the remote section; `old` is the base they were made on. @@ -54,7 +56,7 @@ pub(crate) fn rebase( before, after, local: orders.0.clone(), - unmoved: unmoved(old, new)?, + moved: moved(old, new)?, orders, created: BTreeSet::new(), diffs: BTreeMap::new(), @@ -62,6 +64,7 @@ pub(crate) fn rebase( let mut merged = Merged { rewritten: Vec::new(), conflicts: BTreeMap::new(), + moved: state.moved.clone(), }; for queued in edits { let mut ops = Vec::new(); @@ -117,14 +120,11 @@ pub(crate) fn rebase( } Op::Section(section_op) => { advance(&mut state.local, section_op); - // The first form of the edit the remote's page list takes, or none. - let mut kept = None; - for form in state.forms(new, section_op)? { - let form = Op::Section(form); - if apply(&mut state, new, &form)? { - kept = Some(form); - break; - } + let mut kept = state.form(new, section_op)?.map(Op::Section); + if let Some(form) = &kept + && !apply(&mut state, new, form)? + { + kept = None; } changed |= kept.as_ref() != Some(op); ops.extend(kept); @@ -179,15 +179,16 @@ fn named(op: &PageOp) -> Vec { } /// The edit keeping `page`, the version of page `space` the remote could not take, and -/// applies it to `new`: a conflict page under the remote's page marking `objects` where -/// `page` holds them, or, where the remote removed the page, the page put back as a copy -/// where `local`, the section as the queue leaves it, has it. Content outside the page -/// model stays on the remote's page only; `at` is now. +/// applies it to `new`, the merged section: a conflict page under the remote's page +/// marking `objects` where `page` holds them, or, where the remote removed the page, the +/// page put back as a copy before the next page after it in `local`, the section as the +/// queue leaves it, that the remote did not move (`moved`). Content outside the page model +/// stays on the remote's page only; `at` is now. #[allow(clippy::too_many_arguments)] pub(crate) fn conflict_page( new: &mut Section<'_>, - old: &mut Section<'_>, local: &mut Section<'_>, + moved: &BTreeSet, space: ExGuid, page: &Page, author: &str, @@ -217,7 +218,6 @@ pub(crate) fn conflict_page( })] } else { // A copy under fresh identities, as OneNote 2010 puts a removed page back. - let (base, unmoved) = (order(old)?, unmoved(old, new)?); let queued = order(local)?; let at = queued.iter().position(|(queued, _)| *queued == space); let before = at @@ -225,8 +225,7 @@ pub(crate) fn conflict_page( .iter() .map(|(next, _)| *next) .find(|next| { - listed.iter().any(|(listed, _)| listed == next) - && (unmoved.contains(next) || base.iter().all(|(page, _)| page != next)) + !moved.contains(next) && listed.iter().any(|(listed, _)| listed == next) }); let creation = PageCreation::new(before, Some(&page.title), author)?; let mut ops = vec![Op::Section(SectionOp::Import { @@ -246,19 +245,20 @@ pub(crate) fn conflict_page( Ok(edit) } -/// Pages the base and the remote both list that the remote left in place: in the same -/// series at the same level, in base order among themselves. OneNote 2010 gives a page it -/// moves a series of its own; a page moved within its series is out of base order. -fn unmoved(old: &mut Section<'_>, new: &mut Section<'_>) -> Result> { +/// Pages the base and the remote both list that the remote moved: into another series or +/// level, or out of base order among the rest. OneNote 2010 and this writer give a moved +/// page a series of its own; older builds of this writer moved a page within its series. +fn moved(old: &mut Section<'_>, new: &mut Section<'_>) -> Result> { let series = (old.series()?, new.series()?); let base: BTreeMap = order(old)? .into_iter() .enumerate() .map(|(at, (space, level))| (space, (at, level))) .collect(); - let kept: Vec<(ExGuid, usize)> = order(new)? - .into_iter() - .filter_map(|(space, level)| { + let listed = order(new)?; + let kept: Vec<(ExGuid, usize)> = listed + .iter() + .filter_map(|&(space, level)| { let (at, before) = base.get(&space)?; (*before == level && series.0.get(&space) == series.1.get(&space)).then_some((space, *at)) }) @@ -281,7 +281,11 @@ fn unmoved(old: &mut Section<'_>, new: &mut Section<'_>) -> Result, + /// Pages the base listed that the remote moved (`moved`). + moved: BTreeSet, /// Page spaces the replayed edits created. created: BTreeSet, /// Per page the remote changed, what it changed; `None` when it left the page alone. @@ -403,57 +407,52 @@ impl Replay { self.created.contains(&space) || self.orders.1.iter().any(|(page, _)| *page == space) } - /// Whether the remote moved or re-leveled a page the base listed. - fn placed(&self, page: ExGuid) -> bool { - !self.unmoved.contains(&page) && self.orders.0.iter().any(|(listed, _)| *listed == page) - } - /// Where a page the queue put before `before` goes on the remote: before the first page /// from `before` on, in the queue's order, that the remote lists where the base had it, /// or last, as OneNote 2010 places a page series only one side changed. fn anchor(&self, listed: &Order, page: ExGuid, before: Option) -> Option { let from = self.local.iter().position(|(space, _)| Some(*space) == before)?; self.local[from..].iter().map(|(space, _)| *space).find(|space| { - *space != page && !self.placed(*space) && listed.iter().any(|(listed, _)| listed == space) + *space != page && !self.moved.contains(space) && listed.iter().any(|(listed, _)| listed == space) }) } - /// Forms of a section op to try on the remote section, in order: a page placed by + /// A section op as it replays on the remote section, or `None`: a page placed by /// `anchor`, the page edits of pages the remote still has and did not move, removals of /// pages the remote still has (a page it changed is not removed), a conflict page's /// content as a page of its own where the remote removed its page. - fn forms(&self, new: &mut Section<'_>, op: &SectionOp) -> Result> { + fn form(&self, new: &mut Section<'_>, op: &SectionOp) -> Result> { let conflicts: BTreeSet = new .conflicts()? .into_iter() .flat_map(|(_, pages)| pages.into_iter().map(|page| page.space)) .collect(); let listed = order(new)?; - let placed = |creation: &PageCreation| { + let anchored = |creation: &PageCreation| { creation.reposition(self.anchor(&listed, creation.space(), creation.before())) }; Ok(match op { - SectionOp::Create(creation) => vec![SectionOp::Create(placed(creation)?)], - SectionOp::Import { creation, page } => vec![SectionOp::Import { - creation: placed(creation)?, + SectionOp::Create(creation) => Some(SectionOp::Create(anchored(creation)?)), + SectionOp::Import { creation, page } => Some(SectionOp::Import { + creation: anchored(creation)?, page: page.clone(), - }], - SectionOp::Color(_) => vec![op.clone()], + }), + SectionOp::Color(_) => Some(op.clone()), SectionOp::Conflict { of, creation, page, .. - } => vec![if self.listed(*of) { + } => Some(if self.listed(*of) { op.clone() } else { SectionOp::Import { creation: creation.clone(), page: page.clone(), } - }], + }), // A page the remote moved or re-leveled keeps the remote's placement. SectionOp::Pages(edits) => { let mut kept = Vec::new(); for edit in edits { - if self.placed(edit.space()) + if self.moved.contains(&edit.space()) || listed.iter().all(|(listed, _)| *listed != edit.space()) { continue; @@ -466,11 +465,7 @@ impl Replay { )?, }); } - if kept.is_empty() { - Vec::new() - } else { - vec![SectionOp::Pages(kept)] - } + (!kept.is_empty()).then_some(SectionOp::Pages(kept)) } SectionOp::Delete(deleted) => { let deleted: Vec = deleted @@ -481,11 +476,7 @@ impl Replay { }) .copied() .collect(); - if deleted.is_empty() { - Vec::new() - } else { - vec![SectionOp::Delete(deleted)] - } + (!deleted.is_empty()).then_some(SectionOp::Delete(deleted)) } }) } diff --git a/crates/notebook/src/session.rs b/crates/notebook/src/session.rs index 2e78dc28de2e40d27939f19b774898dd0e1041c9..b457a99ad59fec6e23bf8395ee78d6a4a06ca982 100644 --- a/crates/notebook/src/session.rs +++ b/crates/notebook/src/session.rs @@ -140,11 +140,12 @@ impl Storage for Directory { fn delete(&self, path: &str) -> Result<()> { let path = self.path(path); - Ok(if path.is_dir() { - std::fs::remove_dir(path)? + if path.is_dir() { + std::fs::remove_dir(path)?; } else { - std::fs::remove_file(path)? - }) + std::fs::remove_file(path)?; + } + Ok(()) } fn place(&self, path: &str, ancestor: [u8; 16], name: &str) -> Result<()> { @@ -259,6 +260,7 @@ impl Notebook { std::fs::create_dir(root.as_ref())?; let mut notebook = Self::open(root, cache)?; notebook.edit_toc("", &[onestore::TocEdit::Color(color)])?; + notebook.refresh()?; notebook.create_section("", "New Section 1", page)?; Ok(notebook) } @@ -368,8 +370,14 @@ impl Notebook { Some(toc) => Ok((catalog_path(folder, &toc.filename), toc.file_id)), None => { let path = catalog_path(folder, TOC); - let bytes = onestore::create_table_of_contents(TOC, &[])?; - self.storage.create(&path, &bytes)?; + // One this change already created, before the catalog was read again. + let bytes = if self.storage.exists(&path) { + self.storage.read(&path)? + } else { + let bytes = onestore::create_table_of_contents(TOC, &[])?; + self.storage.create(&path, &bytes)?; + bytes + }; Ok((path, onestore::Store::parse(&bytes)?.header.file_id)) } } @@ -632,17 +640,7 @@ impl Notebook { let mut section = onestore::Section::open(&arena, self.storage.read(&path)?)?; let mut ops = Vec::new(); for page in pages { - let mut creation = PageCreation::new(None, Some(&page.title), author)?; - if let (Some(identity), Some(created)) = (page.identity, page.created) { - creation = creation.keeping(identity, created)?; - } - if let Some([date, time]) = page.date_text() { - creation = creation.dated(&date, &time)?; - } - ops.push(Op::Section(SectionOp::Import { - creation, - page: page.copy()?, - })); + ops.push(moved(page, author)?); } section.apply(author, &Edit { at: crate::now(), ops })?; if let Some(transaction) = section.seal()? { @@ -802,6 +800,17 @@ impl Notebook { /// Opens a section of a mounted notebook by its catalog path. pub fn section(&self, path: &str, notify: impl Fn() + Send + 'static) -> Result
{ + self.section_with(path, |file| Ok(FileRemote(file.to_owned())), notify) + } + + /// `section`, reading and publishing through the remote `connect` makes for its file + /// (`Section::open_with`). + pub fn section_with( + &self, + path: &str, + connect: impl FnMut(&Path) -> io::Result + Send + 'static, + notify: impl Fn() + Send + 'static, + ) -> Result
{ let path = self.section_path(path)?.path.clone(); let Some(root) = &self.root else { return Err(io::Error::new( @@ -815,29 +824,39 @@ impl Notebook { if !file.starts_with(root) { return Err(io::Error::from(io::ErrorKind::PermissionDenied).into()); } - Section::open(file, &self.cache, notify) + Section::open_with(file, &self.cache, connect, notify) } } -/// The section colours OneNote 2010 gives new sections, COLORREF, in the order it gives -/// them (`evidence/notebook-management/new-notebook`). -const SECTION_COLORS: [u32; 3] = [0x00e4a88a, 0x0078b0f6, 0x00bba4d5]; +/// The colours OneNote 2010 gives a folder's first sixteen new sections, COLORREF, in the +/// order it gives them (`corpus/notebook-management/native/section-colors`: sixteen sections +/// made with New Section in a new notebook). +const SECTION_COLORS: [u32; 16] = [ + 0x00e4a88a, 0x0078b0f6, 0x00bba4d5, 0x00d2bb9b, 0x00b79cab, 0x0099d1e8, 0x006ff9f5, + 0x0092e7ad, 0x00cabc4d, 0x007575ba, 0x00aa9595, 0x00e4a88a, 0x0069d8ff, 0x0097c9b7, + 0x009795ee, 0x00de9eb4, +]; -/// The colour OneNote gives a new section in `folder`: the first of its colours none of -/// the folder's sections has, or the next in turn when all are taken. +/// The colour OneNote gives a new section in `folder`, by how many sections it holds. fn next_color(folder: &discover::Folder) -> u32 { - let taken: Vec = folder - .sections - .iter() - .filter_map(|section| match section.state { - discover::SectionState::Readable { color, .. } => color, - _ => None, - }) - .collect(); - SECTION_COLORS - .into_iter() - .find(|color| !taken.contains(color)) - .unwrap_or(SECTION_COLORS[folder.sections.len() % SECTION_COLORS.len()]) + SECTION_COLORS[folder.sections.len() % SECTION_COLORS.len()] +} + +/// The op putting `page` into another section as OneNote moves a page there, into the +/// recycle bin or another section: last, under fresh object identities, keeping its page +/// identity, title, date and creation time. +pub fn moved(page: &Page, author: &str) -> Result { + let mut creation = PageCreation::new(None, Some(&page.title), author)?; + if let (Some(identity), Some(created)) = (page.identity, page.created) { + creation = creation.keeping(identity, created)?; + } + if let Some([date, time]) = page.date_text() { + creation = creation.dated(&date, &time)?; + } + Ok(Op::Section(SectionOp::Import { + creation, + page: page.copy()?, + })) } fn component(name: &str) -> bool { @@ -896,9 +915,21 @@ impl Section { file: impl AsRef, cache: impl AsRef, notify: impl Fn() + Send + 'static, + ) -> Result { + Self::open_with(file, cache, |file| Ok(FileRemote(file.to_owned())), notify) + } + + /// `open`, reading and publishing the file through the remote `connect` makes for it, + /// as a host that coordinates file access with other processes (iOS's file providers) + /// needs. + pub fn open_with( + file: impl AsRef, + cache: impl AsRef, + mut connect: impl FnMut(&Path) -> io::Result + Send + 'static, + notify: impl Fn() + Send + 'static, ) -> Result { let file = file.as_ref().canonicalize()?; - let source = onestore::read_file(&file)?; + let source = connect(&file)?.read()?; let store = Store::parse(&source)?; let identity = RevisionIndex::parse(&store)?.root; let name: String = identity @@ -913,7 +944,8 @@ impl Section { } else { Replica::create(&cache, &source)? }; - Self::resume(file, replica, notify) + let remote = file.clone(); + Self::start(file, replica, move || connect(&remote), notify) } /// Resumes an owned local replica without reading the publication target. diff --git a/crates/notebook/src/working.rs b/crates/notebook/src/working.rs index 53c2f3fa7b83c31f06bc26a1baff499848736d96..bdefba27e3d473001d2e2b802c64b97c69925b38 100644 --- a/crates/notebook/src/working.rs +++ b/crates/notebook/src/working.rs @@ -642,8 +642,8 @@ fn rebase(connection: &Mutex, image: Option>) -> Result Result<(), Box> { - let args: Vec = std::env::args().skip(1).collect(); - let bytes = std::fs::read(&args[0])?; - let store = Store::parse(&bytes)?; - let index = RevisionIndex::parse(&store)?; - let pages = Document::parse(&index).and_then(|document| document.pages()).unwrap_or_default(); - let space = if args[1] == "root" { index.root } else { pages[args[1].parse::()?].0 }; - println!("space {space}; pages {:?}", pages.iter().map(|p| p.0).collect::>()); - let raw = index.resolve_active(space)?; - for (id, object) in &raw.objects { - println!("{id} jcid {:#x}", object.jcid); - if let ObjectData::Properties(data) = object.data { - let sets = PropertySets::parse(data)?; - for (n, set) in sets.sets.iter().enumerate() { - for p in set { - let v = match &p.value { - Value::NoData => "-".to_string(), - Value::Bytes(b) => b.iter().map(|x| format!("{x:02x}")).collect(), - Value::References { stream, compact_ids } => format!("{stream:?} {}", compact_ids.iter().map(|x| format!("{x:02x}")).collect::()), - Value::Sets(r) => format!("sets {r:?}"), - }; - println!(" [{n}] {:#010x} {v}", p.id); - } - } - } - } - Ok(()) -} diff --git a/crates/onestore/src/page/mod.rs b/crates/onestore/src/page/mod.rs index 2d7df2e8224223a168f389bc5994c7e846dd5c48..3c9c503e4be5fd3e1a795276399e69b0799f2756 100644 --- a/crates/onestore/src/page/mod.rs +++ b/crates/onestore/src/page/mod.rs @@ -52,7 +52,7 @@ mod payload { pub use text::Paragraph; /// The page node's colour (View, Page Color) as COLORREF, absent for "No color"; not in -/// MS-ONE, observed in OneNote 2010's pages (`evidence/notebook-management`). +/// MS-ONE, observed in OneNote 2010's pages (`corpus/notebook-management/native/page-color`). pub(crate) const PAGE_COLOR: u32 = 0x14001d2a; /// The role of a title-outline paragraph that displays the page's creation date or time. diff --git a/crates/onestore/src/pages.rs b/crates/onestore/src/pages.rs index d0a6782091ab9b112f18f5d3750c6f8861dde5ef..bb7ee6dda54e49426369dcabaa45017d9d6570e0 100644 --- a/crates/onestore/src/pages.rs +++ b/crates/onestore/src/pages.rs @@ -264,10 +264,12 @@ fn page_changes<'a>( let mut series_by_head = BTreeMap::new(); let mut copies = BTreeMap::new(); let mut copy_ids = BTreeSet::new(); + let mut stale = BTreeSet::new(); for oid in §ion_node.children { let series = &view.nodes[oid]; + // OneNote leaves the losing side's series empty after a merge; the rewrite drops it. let Some(head) = series.spaces.first() else { - return Err(invalid("A page series must contain at least one page")); + continue; }; if levels.get(head) != Some(&1) || series.spaces[1..] @@ -285,8 +287,11 @@ fn page_changes<'a>( let FieldValue::Objects(ids) = &field.value else { return Err(invalid("Page metadata copies must be object references")); }; - if ids.len() != series.spaces.len() { - return Err(invalid("Page metadata copies must match their series")); + // OneNote can leave a page's former copy beside its new one (MS-ONE 2.2.81, note + // 9): the last copy of each page stays and the series is rewritten to match. + let mismatched = ids.len() != series.spaces.len(); + if mismatched { + stale.insert(*oid); } for id in ids { if !copy_ids.insert(*id) @@ -303,7 +308,7 @@ fn page_changes<'a>( .ok_or_else(|| { invalid("Metadata copy must identify a page in its series") })?; - if copies.insert(*sid, *id).is_some() { + if copies.insert(*sid, *id).is_some() && !mismatched { return Err(invalid("Each page needs its own ordinary metadata copy")); } } @@ -372,7 +377,11 @@ fn page_changes<'a>( let mut children = Vec::new(); for spaces in groups { let head = spaces[0]; - let old_id = series_by_head.get(&head).copied(); + // A moved page heads a series of its own, as OneNote's drag gives one. + let moved = selected + .get(&head) + .is_some_and(|edit| matches!(edit.position, PagePosition::Before(_))); + let old_id = series_by_head.get(&head).copied().filter(|_| !moved); let (id, mut series) = if let Some(id) = old_id { (id, PropertyObject::from_object(&raw.objects[&id])?) } else { @@ -396,7 +405,8 @@ fn page_changes<'a>( ) }; children.push(id); - let membership_changed = old_id.is_none_or(|old| view.nodes[&old].spaces != spaces); + let membership_changed = old_id + .is_none_or(|old| view.nodes[&old].spaces != spaces || stale.contains(&old)); if !membership_changed && !spaces.iter().any(|sid| { levels[sid] != original_levels[sid] @@ -654,7 +664,7 @@ impl PageCreation { /// The title's second outline as OneNote 2010 writes it for a new page (object numbers, /// jcids and properties): a read-only outline of two paragraphs, the date then the /// time, in the `PageDateTime` style. - fn date_fields(&self, date: &str, time: &str) -> Vec<(u32, u32, Vec<(u32, Vec)>)> { + fn date_fields(&self, date: &str, time: &str) -> Vec<(u32, u32, crate::op::Values)> { let reference = |n: u32| n.to_le_bytes().to_vec(); let modified = || (0x14001d7a, self.created.to_le_bytes().to_vec()); let yes = |id: u32| (id | 1 << 31, Vec::new()); diff --git a/crates/onestore/tests/page_movement.rs b/crates/onestore/tests/page_movement.rs index fed316aac3be21bc7a789ace471b01cc87da864d..f463a29bd29fbf1f5f40c06a4c1079172304e67d 100644 --- a/crates/onestore/tests/page_movement.rs +++ b/crates/onestore/tests/page_movement.rs @@ -520,3 +520,43 @@ fn repeated_nesting_retains_series_history_across_revision_checkpoints() { std::fs::write(std::path::Path::new(&output).join("movement.one"), &source).unwrap(); } } + +/// A move on a section OneNote merged, which holds empty page series, rewrites the series +/// without them and gives the moved page one of its own. +#[test] +fn a_move_after_a_native_merge_drops_its_empty_series() { + let merged = include_bytes!( + "../../../corpus/conflict-page/native-pages/merged/notebook/synthetic.one" + ); + let series = |bytes: &[u8]| { + let store = Store::parse(bytes).unwrap(); + let index = RevisionIndex::parse(&store).unwrap(); + let document = Document::parse(&index).unwrap(); + let space = &document.spaces[&document.root]; + let view = &space.revisions[&space.contexts[&ExGuid::default()]]; + view.nodes[&view.roots[&1]] + .children + .iter() + .map(|id| (*id, view.nodes[id].spaces.clone())) + .collect::>() + }; + let before = series(merged); + assert!(before.iter().any(|(_, spaces)| spaces.is_empty())); + let ids = pages(merged); + let moved = ops::section_op( + merged, + SectionOp::Pages(vec![PageEdit::move_to(ids[1], None, 1).unwrap()]), + ) + .unwrap(); + let after = series(moved.as_bytes()); + assert!(after.iter().all(|(_, spaces)| !spaces.is_empty())); + let (id, spaces) = after.last().unwrap(); + assert_eq!(spaces, &vec![ids[1]]); + assert!(before.iter().all(|(old, _)| old != id)); + assert_eq!(pages(moved.as_bytes()), [&ids[..1], &ids[2..], &ids[1..2]].concat()); + if let Some(output) = std::env::var_os("ONESTORE_EMPTY_SERIES_EXPORT") { + let output = std::path::Path::new(&output); + std::fs::create_dir(output).unwrap(); + std::fs::write(output.join("synthetic.one"), moved.as_bytes()).unwrap(); + } +} diff --git a/tools/canvas/README.md b/tools/canvas/README.md index db8d615275c3f880c97e845b47b1777660446c0e..1bcfc9e0ff7a71d81edb30aa7e8abae707f046c3 100644 --- a/tools/canvas/README.md +++ b/tools/canvas/README.md @@ -50,9 +50,11 @@ snowbound title bar · toolbar · section frame · page tabs · the page as a `--notebook FOLDER` opens a notebook laid out as OneNote lays one out. The title bar shows the application's icon and the notebook's name; below it two rows of toolbar buttons follow the Home ribbon's Basic Text group, the first nine tags and zoom (only zoom acts yet). Readable top-level sections are tabs in the notebook's order, each leaning over the next at 45° with a faint highlight along its top, and the open one on top, casting a soft shadow and framing the page and the page tabs on the right in its colour, which shades slightly down the window; a tab that opens rises to meet the frame as its outline fades in. The frame's top corners and the page's corners are rounded concentric with the window's. The open page's tab is the page's colour and joins it with rounded inside corners; subpages are indented. The interface follows the system's light or dark appearance, and in the dark one the page's paper darkens and text left at OneNote's automatic colour turns light (except on a highlight), resolved when painting so nothing re-lays out; explicit colours, highlights, pictures and ink keep theirs, except that the background art of OneNote 2010's page templates, recognised by the picture's hash, paints from bundled vector recreations drawn for the paper. Sections take their stored colour's hue at a saturation and lightness chosen for each appearance. `--ui-font FONT_FILE_OR_FOLDER` sets the interface's typeface in place of the system's; fonts are not bundled. The section's colour is also the interface accent, easing to the next section's when another opens. The search box, New Page and the page-tab toggle sit above the page tabs. Command-F searches the page titles; Enter opens the first match and Escape clears it. A page that also changed on another computer shows Keep mine / Keep theirs above it. `--section FILE TITLE` opens one section the same way at that page. Section files must be regular files; discovery rejects symbolic links. +Launched without a file, the app reopens the notebooks open when it last closed, at the one shown last, or shows "No notebooks open" with New Notebook and Open Existing. Settings (the open notebooks, the sidebar and recent fonts) are JSON in `~/Library/Application Support/Snowbound/settings.json` or `$XDG_CONFIG_HOME/snowbound`; `--settings FILE` uses another file, `--notebook FOLDER` adds a notebook to them, and `--screenshot` never writes them. Open Existing takes a notebook folder, its `Open Notebook.onetoc2` or a section file, which opens in the notebook its folders make up. A notebook on a mounted SMB share opens through the mount; the embedded SMB client is not yet used for it. The notebook button left of the section tabs opens OneNote 2010's navigation bar: the open notebooks with their sections and section groups, the open section marked; dragging a row reorders a folder or, onto a group, moves into it, and right-clicking a row, a section tab or a page tab offers OneNote's commands (Rename, Delete to the notebook's recycle bin, New Section, New Section Group, Close This Notebook; Delete, New Page, Make Subpage, Promote Subpage). Page tabs drag to reorder. The `+` above the page tabs adds a page at the end of the section, titled with its date and time as OneNote titles one, and puts the caret in its title; until its body is typed in, templates offer our recreations of OneNote 2010's art (Ivy first), its page colours and Informal Meeting Notes' content, written as ops (`corpus/notebook-management`). + The `ui` crate builds every frame from the application's state. A cache keyed by stable box ids keeps hover, press, focus, scroll and animation values, and the previous frame's layout routes the frame's input before building, so a frame answers input one layout late and paints with its own. Sizes are solved per axis after building: fixed, label-sized, a fraction of an ancestor, or the sum of children, with overflow shared out by each box's strictness. The page is a custom box: `ui` routes it the pointer, wheel, key and input-method events that land on it, in order, and the host hands them to `PageView` and paints the page in a clipped layer of the same frame. Page scrollbars are `ui` widgets over that box; the canvas reports only its scroll bounds. Text fields edit through `draw::edit`, as the page does, so keys, clicks and drags select and move the same way in both. Work the frame asks for (page requests, saving) runs after the frame is painted and requests the frame that shows it. Opening a section or page reads it on a thread of its own while the current page stays live; the newest read is laid out and replaces the page once the pictures it shows first are drawn, or after 200 ms. -A covered window receives no redraws, so interaction can be scripted: `SNOWBOUND_REPLAY` names a file of `move X Y`, `press`, `release`, `wheel DX DY`, `key NAME`, `type TEXT`, `modifiers [shift] [command]`, `wait MS`, `snapshot PNG_PATH` and `appearance light|dark` lines in logical pixels, and each step and every 16 ms of a wait draws a frame. Snapshots omit the window's traffic lights, which AppKit draws. Replays edit and save like a user, so point them at a copy of a notebook. +A covered window receives no redraws, so interaction can be scripted: `SNOWBOUND_REPLAY` names a file of `move X Y`, `press [right]`, `release [right]`, `wheel DX DY`, `key NAME`, `type TEXT`, `modifiers [shift] [command]`, `wait MS`, `snapshot PNG_PATH`, `appearance light|dark` and `quit` lines in logical pixels, and each step and every 16 ms of a wait draws a frame. With `--screenshot` as well, the window stays hidden and only the replay's snapshots capture it. Snapshots omit the window's traffic lights, which AppKit draws. Replays edit and save like a user, so point them at a copy of a notebook. ```sh cp -RL SOURCE_NOTEBOOK /tmp/notebook-copy && chmod u+w /tmp/notebook-copy/*.one diff --git a/tools/test_conflict_page.py b/tools/test_conflict_page.py index d62754b775b6017557c4f5489a0a791067346ecd..309506b3a2562c384f477fa43073d92bc5dc5bfa 100644 --- a/tools/test_conflict_page.py +++ b/tools/test_conflict_page.py @@ -11,6 +11,7 @@ import hashlib from native_xml import pages, texts from document_model import EXPORTER, ordered_pages, view +from verify_page_creation import compare as compare_graphs ROOT = Path(__file__).resolve().parent.parent FIXTURE = ROOT / 'corpus/conflict-page' @@ -149,6 +150,13 @@ class ConflictPageTest(unittest.TestCase): for title in client: self.assertNotIn(owner(merged, title), {**initial, **published}, title) + def test_onenote_reads_a_rust_move_that_drops_empty_series(self): + root = FIXTURE / 'series-move' + self.assertEqual((root / 'candidate/synthetic.one').read_bytes()[1024:], + (root / 'cold/notebook/synthetic.one').read_bytes()[1024:]) + self.assertEqual(compare_graphs(root / 'candidate', root / 'cold'), 0) + self.assertTrue(all(series(model(root / 'candidate')).values())) + def test_a_page_edited_offline_and_deleted_online_comes_back_as_a_new_page(self): for capture in ('native-pages', 'native-restore'): root = FIXTURE / capture diff --git a/tools/test_notebook_management.py b/tools/test_notebook_management.py new file mode 100644 index 0000000000000000000000000000000000000000..1375d501c4e05b57d44ef93b0b0bbb0eb33c143f --- /dev/null +++ b/tools/test_notebook_management.py @@ -0,0 +1,105 @@ +from pathlib import Path +import runpy +import shutil +from tempfile import TemporaryDirectory +import unittest +import uuid +import xml.etree.ElementTree as ET + +from native_xml import ns + +ROOT = Path(__file__).resolve().parent.parent +FIXTURE = ROOT / 'corpus/notebook-management' +compare = runpy.run_path(str(ROOT / 'tools/verify-document.py'))['compare'] + + +def file_identity(path): + return uuid.UUID(bytes_le=path.read_bytes()[16:32]) + + +def tree(node): + """Sections, groups and pages as OneNote lists them, with what the app set on each.""" + out = [] + for child in node: + tag = child.tag.rsplit('}', 1)[-1] + if tag in ('Section', 'SectionGroup'): + out.append((tag, child.get('name'), child.get('color'), tree(child))) + elif tag == 'Page': + out.append((tag, child.get('name'), child.get('pageLevel'), child.get('isInRecycleBin'))) + return out + + +def page(title): + for path in sorted((FIXTURE / 'cold/read').glob('page-*.xml')): + root = ET.parse(path).getroot() + if root.get('name') == title: + return root + raise AssertionError(f'No page titled {title!r}') + + +class NotebookManagementTest(unittest.TestCase): + def test_the_managed_notebook_reopens_natively_as_written(self): + with TemporaryDirectory() as temporary: + read = Path(temporary) / 'read' + shutil.copytree(FIXTURE / 'cold/read', read) + compare(FIXTURE / 'candidate', read) + for candidate in sorted((FIXTURE / 'candidate').rglob('*.one*')): + relative = candidate.relative_to(FIXTURE / 'candidate') + self.assertEqual(file_identity(FIXTURE / 'cold/notebook' / relative), + file_identity(candidate), str(relative)) + + def test_sections_groups_and_pages_sit_where_the_app_put_them(self): + hierarchy = ET.parse(FIXTURE / 'cold/read/hierarchy.xml').getroot() + self.assertEqual(tree(hierarchy), [ + ('Section', 'New Section 1', '#8AA8E4', [ + ('Page', 'Garden plan', '1', None), + ('Page', 'Ivy page', '1', None), + ('Page', 'Teal page', '1', None), + ('Page', 'Subpage', '2', None), + ('Page', 'Meeting page', '1', None), + ]), + ('SectionGroup', 'Archive', None, [ + ('Section', 'Inner', '#8AA8E4', [('Page', 'Untitled page', '1', None)]), + ('Section', 'Kitchen', '#F6B078', [ + ('Page', 'Untitled page', '1', None), + ('Page', 'Moved page', '1', None), + ]), + ]), + ('SectionGroup', 'OneNote_RecycleBin', None, [ + ('Section', 'Deleted Pages', '#E1E1E1', [('Page', 'Deleted page', '1', 'true')]), + ('Section', 'Gone', '#8AA8E4', [('Page', 'Untitled page', '1', 'true')]), + ('Section', 'Binned', '#D5A4BB', [('Page', 'Untitled page', '1', 'true')]), + ]), + ]) + bin = hierarchy.find("one:SectionGroup[@name='OneNote_RecycleBin']", ns) + self.assertEqual(bin.get('isRecycleBin'), 'true') + deleted = bin.find("one:Section[@name='Deleted Pages']", ns) + self.assertEqual(deleted.get('isDeletedPages'), 'true') + + def test_pages_keep_their_date_colour_and_template_art(self): + teal = page('Teal page') + self.assertEqual(teal.find('one:PageSettings', ns).get('color'), '#D4F9F2') + # The title's second outline holds the date and the time. + title = teal.find('one:Title', ns) + texts = [t.text for t in title.iter('{%s}T' % ns['one'])] + self.assertEqual(len(texts), 1) + ivy = page('Ivy page') + images = ivy.findall('one:Image', ns) + self.assertEqual([image.get('backgroundImage') for image in images], ['true']) + self.assertEqual(page('Garden plan').find('one:PageSettings', ns).get('color'), 'automatic') + + def test_meeting_notes_content_reads_back_as_onenote_writes_it(self): + meeting = page('Meeting page') + self.assertEqual(len(meeting.findall('one:Image', ns)), 1) + outlines = meeting.findall('one:Outline', ns) + self.assertEqual(len(outlines), 4) + texts = [t.text or '' for t in meeting.iter('{%s}T' % ns['one'])] + for text in ('Agenda', 'Action Items', 'Important Dates', 'Meeting Details', 'Attendees:', 'Next Meeting'): + self.assertTrue(any(text in line for line in texts), text) + self.assertEqual(len(meeting.findall('.//one:Tag', ns)), 1) + self.assertEqual(len(meeting.findall('.//one:Number', ns)), 1) + self.assertEqual(len(meeting.findall('.//one:Bullet', ns)), 11) + + +if __name__ == '__main__': + unittest.main() diff --git a/tools/test_page_movement.py b/tools/test_page_movement.py index e96da2467061c19fb1f4ab6256424cb981cd4471..0101e0dd6ccc6606fc663be77655632f232b5ce0 100644 --- a/tools/test_page_movement.py +++ b/tools/test_page_movement.py @@ -90,6 +90,47 @@ class PageMovementTest(unittest.TestCase): (fixture / 'cold/notebook/Lifecycle.one').read_bytes()[1024:]) self.assertEqual(compare(fixture / 'candidate', fixture / 'cold'), 0) + def test_series_rows_survive_native_reopen(self): + """Rust moves heading series of their own, and offline batches merged as page series.""" + def series(one): + with TemporaryDirectory() as temporary: + subprocess.run([EXPORTER, one, Path(temporary) / 'm'], check=True, capture_output=True) + document = json.loads((Path(temporary) / 'm/document.json').read_text()) + _, root = view(document, document['root']) + section = root['nodes'][root['roots']['1']] + return {space: oid for oid in section['children'] for space in root['nodes'][oid]['spaces']} + edits = FIXTURE / 'page-edits-series' + before = series(FIXTURE / '04-nested/notebook/Lifecycle.one') + base, previous = list(before), before + # The page each phase moves; `05` moves a subpage into its parent's series. + moved = {'03-selected-group-move': 3, '04-subpage-move': 4, '08-collapsed-group-move': 4, 'single-page': 3} + for phase in sorted(p.name for p in edits.iterdir() if p.is_dir()): + with self.subTest(phase=phase): + fixture = edits / phase + self.assertEqual((fixture / 'candidate/Lifecycle.one').read_bytes()[1024:], + (fixture / 'cold/notebook/Lifecycle.one').read_bytes()[1024:]) + self.assertEqual(compare(fixture / 'candidate', fixture / 'cold'), 0) + after = series(fixture / 'candidate/Lifecycle.one') + if phase in moved: + start = before if phase == 'single-page' else previous + self.assertNotIn(after[base[moved[phase]]], start.values()) + if phase != 'single-page': + previous = after + offline = FIXTURE / 'offline-edits-series' + for case in sorted(p.name for p in offline.iterdir() if p.is_dir() and p.name != 'twelve-clients'): + with self.subTest(case=case): + source, cold = offline / case / 'candidate', offline / case / 'cold' + manifest = json.loads((source / 'manifest.json').read_text()) + self.assertEqual((manifest['conflict'], manifest['reviewed']), (True, [])) + repaired = case == 'indent-02-promoted-parent' + self.assertEqual(compare(source, cold, refresh_metadata=repaired), int(repaired)) + if not repaired: + self.assertEqual((source / 'Lifecycle.one').read_bytes()[1024:], + (cold / 'notebook/Lifecycle.one').read_bytes()[1024:]) + twelve = offline / 'twelve-clients' + self.assertEqual(compare(twelve / 'candidate', twelve / 'cold'), 0) + self.assertEqual(json.loads((twelve / 'candidate/manifest.json').read_text())['publications'], 12) + def test_repeated_page_nesting_survives_native_reopen_after_checkpoints(self): fixture = FIXTURE / 'page-edits/stress' self.assertEqual((fixture / 'candidate/movement.one').read_bytes()[1024:],