|
- $ErrorActionPreference = 'Stop'
- $root = Split-Path -Parent $PSScriptRoot
- $work = Join-Path $root ('temp\dispatch-flow-' + [guid]::NewGuid().ToString('N'))
- $templateRoot = Join-Path $work 'templates'
- $dbPath = Join-Path $work 'test.mdb'
- $configPath = Join-Path $work 'test.ini'
- $requestPath = Join-Path $work 'request.json'
- $pickup = Join-Path $work 'pickup'
- $scriptHost = Join-Path $env:SystemRoot 'SysWOW64\cscript.exe'
- $powerShellX86 = Join-Path $env:SystemRoot 'SysWOW64\WindowsPowerShell\v1.0\powershell.exe'
-
- function Call-X86([string]$File, [string[]]$Arguments) {
- $result = & $powerShellX86 -NoProfile -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot $File) @Arguments
- if ($LASTEXITCODE -ne 0) { throw "$File failed" }
- return $result
- }
- function Count-Messages {
- return @(Get-ChildItem -LiteralPath $pickup -Filter '*.eml' -File).Count
- }
- function Expect-Failure([string]$File, [string[]]$Arguments) {
- $ErrorActionPreference = 'Continue'
- $null = & $powerShellX86 -NoProfile -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot $File) @Arguments 2>$null
- $failed = $LASTEXITCODE -ne 0
- $ErrorActionPreference = 'Stop'
- if (-not $failed) { throw "Expected $File to reject the action" }
- }
-
- try {
- $null = New-Item -ItemType Directory -Path $templateRoot -Force
- $null = New-Item -ItemType Directory -Path $pickup -Force
- $example = Get-Content -LiteralPath (Join-Path $root 'config.example.ini') -Raw
- $example.Replace('DB_PATH=data/MassMailer.mdb', ('DB_PATH=' + $dbPath)).Replace(
- 'TEMPLATE_ROOT=templates', ('TEMPLATE_ROOT=' + $templateRoot)).Replace(
- 'SMTP_TEST_TO=', 'SMTP_TEST_TO=owner@example.invalid').Replace(
- 'BUSINESS_POSTAL_ADDRESS=', 'BUSINESS_POSTAL_ADDRESS=123 Example Street, Test City, NY 10001') |
- Set-Content -LiteralPath $configPath -Encoding UTF8
- & $scriptHost //nologo (Join-Path $PSScriptRoot 'init-db.vbs') $configPath
- if ($LASTEXITCODE -ne 0) { throw 'MDB setup failed' }
- $null = Call-X86 'test-campaign-db.ps1' @('-ConfigPath',$configPath,'-Mode','Seed')
- $templatePath = Join-Path $templateRoot 'offer.html'
- [System.IO.File]::WriteAllText($templatePath, '<html><body><h1>Postcard offer</h1></body></html>',
- [System.Text.Encoding]::UTF8)
- $null = Call-X86 'import-template.ps1' @('-Path',$templatePath,'-ConfigPath',$configPath)
- $request = @{ Name = 'Dispatch fixture'; Subject = 'Postcard advertising';
- TemplateId = 1; ReviewToken = ''; TestReceived = $false }
- $request | ConvertTo-Json -Compress | Set-Content -LiteralPath $requestPath -Encoding UTF8
- $review = (Call-X86 'review-campaign.ps1' @('-RequestPath',$requestPath,'-ConfigPath',$configPath,
- '-OutputRoot',(Join-Path $work 'previews'))) | ConvertFrom-Json
- if ($review.Count -ne 3) { throw 'Expected three eligible contacts' }
- $request.ReviewToken = $review.Token
- $request | ConvertTo-Json -Compress | Set-Content -LiteralPath $requestPath -Encoding UTF8
- $null = Call-X86 'send-campaign-test.ps1' @('-RequestPath',$requestPath,'-ConfigPath',$configPath,'-PickupDirectory',$pickup)
- $request.TestReceived = $true
- $request | ConvertTo-Json -Compress | Set-Content -LiteralPath $requestPath -Encoding UTF8
- $null = Call-X86 'approve-campaign.ps1' @('-RequestPath',$requestPath,'-ConfigPath',$configPath)
- $null = Get-ChildItem -LiteralPath $pickup -File | Remove-Item -Force
-
- $null = Call-X86 'dispatch-control.ps1' @('-Action','Recover','-ConfigPath',$configPath)
- $null = Call-X86 'dispatch-control.ps1' @('-Action','ReviewOptOut','-ConfigPath',$configPath)
- $null = Call-X86 'dispatch-control.ps1' @('-Action','Resume','-CampaignId','1','-ConfigPath',$configPath)
- $t0 = [DateTime]::UtcNow.AddSeconds(5)
- Expect-Failure 'dispatch-once.ps1' @('-ConfigPath',$configPath,'-Send','-SessionPid','999999','-SessionToken','00000000000000000000000000000000')
- $first = Call-X86 'dispatch-once.ps1' @('-ConfigPath',$configPath,'-PickupDirectory',$pickup,
- '-TestNowUtc',$t0.ToString('o'))
- if ($first -notmatch 'accepted' -or (Count-Messages) -ne 1) { throw 'First queued attempt failed' }
- $settings = Get-Content -LiteralPath $configPath -Raw
- $settings.Replace('QUEUE_INTERVAL=300', 'QUEUE_INTERVAL=600') |
- Set-Content -LiteralPath $configPath -Encoding UTF8
- $early = Call-X86 'dispatch-once.ps1' @('-ConfigPath',$configPath,'-PickupDirectory',$pickup,
- '-TestNowUtc',$t0.AddSeconds(300).ToString('o'))
- if ($early -notmatch 'Next attempt allowed' -or (Count-Messages) -ne 1) {
- throw 'Longer interval did not protect the reserved slot'
- }
- $null = Call-X86 'test-campaign-db.ps1' @('-ConfigPath',$configPath,'-Mode','SuppressSecond')
- $null = Call-X86 'dispatch-control.ps1' @('-Action','Recover','-ConfigPath',$configPath)
- $closed = Call-X86 'dispatch-once.ps1' @('-ConfigPath',$configPath,'-PickupDirectory',$pickup,
- '-TestNowUtc',$t0.AddSeconds(1200).ToString('o'))
- if ($closed -notmatch 'paused' -or (Count-Messages) -ne 1) {
- throw 'Recovery failed to pause dispatch after reopen'
- }
- $null = Call-X86 'dispatch-control.ps1' @('-Action','Resume','-CampaignId','1','-ConfigPath',$configPath)
- $second = Call-X86 'dispatch-once.ps1' @('-ConfigPath',$configPath,'-PickupDirectory',$pickup,
- '-TestNowUtc',$t0.AddSeconds(1200).ToString('o'),'-TestSimulateUnknownAfterSend')
- if ($second -notmatch 'uncertain' -or (Count-Messages) -ne 2) {
- throw 'Injected uncertain response did not pause after the second due attempt'
- }
- $sameSlot = Call-X86 'dispatch-once.ps1' @('-ConfigPath',$configPath,'-PickupDirectory',$pickup,
- '-TestNowUtc',$t0.AddSeconds(1200).ToString('o'))
- if ($sameSlot -notmatch 'paused' -or (Count-Messages) -ne 2) {
- throw 'Uncertain outcome did not stop further sends'
- }
- Expect-Failure 'dispatch-control.ps1' @('-Action','Resume','-CampaignId','1','-ConfigPath',$configPath)
- $status = (Call-X86 'dispatch-control.ps1' @('-Action','Status','-ConfigPath',$configPath)) | ConvertFrom-Json
- if ($status.Counts.accepted -ne 1 -or $status.Counts.suppressed -ne 1 -or
- $status.Counts.uncertain -ne 1) { throw 'Uncertain delivery counts are wrong' }
- $null = Call-X86 'dispatch-control.ps1' @('-Action','ResolveAccepted','-DeliveryId','3','-ConfigPath',$configPath)
- $status = (Call-X86 'dispatch-control.ps1' @('-Action','Status','-ConfigPath',$configPath)) | ConvertFrom-Json
- if ($status.Counts.accepted -ne 2 -or $status.Counts.uncertain -ne 0) {
- throw 'Manual uncertain reconciliation failed'
- }
- $reportFolder = Join-Path $work 'reports'
- $null = Call-X86 'export-report.ps1' @('-CampaignId','1','-ConfigPath',$configPath,'-OutputRoot',$reportFolder)
- $deliveryReport = @(Get-ChildItem -LiteralPath $reportFolder -Filter '*-deliveries.csv' -File)
- $attemptReport = @(Get-ChildItem -LiteralPath $reportFolder -Filter '*-attempts.csv' -File)
- if ($deliveryReport.Count -ne 1 -or $attemptReport.Count -ne 1) {
- throw 'Campaign report files were not created'
- }
- $deliveryRows = @(Import-Csv -LiteralPath $deliveryReport[0].FullName)
- $attemptRows = @(Import-Csv -LiteralPath $attemptReport[0].FullName)
- if ($deliveryRows.Count -ne 3 -or $attemptRows.Count -ne 2 -or
- @($deliveryRows | Where-Object Status -eq 'suppressed').Count -ne 1 -or
- @($attemptRows | Where-Object Outcome -eq 'uncertain').Count -ne 1) {
- throw 'Campaign report content is wrong'
- }
- $null = Call-X86 'dispatch-control.ps1' @('-Action','PauseAll','-ConfigPath',$configPath)
- Write-Output 'Session guard, recovery, pacing, suppression, uncertainty, and reports passed'
- }
- finally {
- $resolvedWork = [System.IO.Path]::GetFullPath($work)
- $resolvedTemp = [System.IO.Path]::GetFullPath((Join-Path $root 'temp'))
- if ($resolvedWork.StartsWith($resolvedTemp + [System.IO.Path]::DirectorySeparatorChar,
- [StringComparison]::OrdinalIgnoreCase) -and (Test-Path -LiteralPath $resolvedWork)) {
- Remove-Item -LiteralPath $resolvedWork -Recurse -Force
- }
- }
|