526 lines
21 KiB
PowerShell
526 lines
21 KiB
PowerShell
param(
|
|
[string]$BackendApiBase = "http://192.168.200.61:8080/api/v1",
|
|
[string]$BackendWsBase = "ws://192.168.200.61:8080/api/v1/gateway/ws",
|
|
[string]$DockerSshAlias = "docker-test",
|
|
[string]$WorkerContainerName = "rap_worker_smoke",
|
|
[string]$WorkerImage = "rap-rdp-worker:stage5-drive-visible",
|
|
[string]$ResourceName = "Windows Smoke Default Resource",
|
|
[string]$Email = "windows-smoke@example.local",
|
|
[string]$Password = "SmokePass!123",
|
|
[string]$OutputLog = "artifacts/stage5-file-upload-smoke.log"
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$log = [System.Collections.Generic.List[string]]::new()
|
|
|
|
function Write-SmokeLog {
|
|
param([string]$Message)
|
|
$line = "[$(Get-Date -Format o)] $Message"
|
|
$log.Add($line)
|
|
Write-Host $line
|
|
}
|
|
|
|
function Invoke-RemoteSqlScalar {
|
|
param([string]$Sql)
|
|
$encoded = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($Sql))
|
|
$output = ssh $DockerSshAlias "printf '%s' '$encoded' | base64 -d | docker exec -i rap_postgres psql -U rap_user -d remote_access_platform -t -A -v ON_ERROR_STOP=1"
|
|
return (($output | Select-Object -Last 1) -as [string]).Trim()
|
|
}
|
|
|
|
function Set-FileTransferMode {
|
|
param([ValidateSet("disabled", "client_to_server")][string]$Mode)
|
|
$enabled = if ($Mode -eq "disabled") { "FALSE" } else { "TRUE" }
|
|
$escapedName = $ResourceName.Replace("'", "''")
|
|
$sql = @"
|
|
UPDATE resource_policies rp
|
|
SET file_transfer_mode = '$Mode',
|
|
file_transfer_enabled = $enabled,
|
|
updated_at = NOW()
|
|
FROM resources r
|
|
WHERE rp.resource_id = r.id
|
|
AND r.name = '$escapedName';
|
|
SELECT COALESCE(MAX(rp.file_transfer_mode), '<missing>')
|
|
FROM resource_policies rp
|
|
JOIN resources r ON r.id = rp.resource_id
|
|
WHERE r.name = '$escapedName';
|
|
"@
|
|
$actual = Invoke-RemoteSqlScalar -Sql $sql
|
|
if ($actual -ne $Mode) {
|
|
throw "file_transfer_mode was not set. Expected=$Mode actual=$actual"
|
|
}
|
|
Write-SmokeLog "policy file_transfer_mode=$Mode"
|
|
}
|
|
|
|
function Invoke-Api {
|
|
param(
|
|
[ValidateSet("Get", "Post")][string]$Method,
|
|
[string]$Path,
|
|
[object]$Body = $null
|
|
)
|
|
$uri = "$BackendApiBase/$Path"
|
|
if ($null -eq $Body) {
|
|
return Invoke-RestMethod -Method $Method -Uri $uri
|
|
}
|
|
return Invoke-RestMethod -Method $Method -Uri $uri -ContentType "application/json" -Body ($Body | ConvertTo-Json -Depth 12)
|
|
}
|
|
|
|
function New-GatewayWebSocket {
|
|
param([string]$AttachToken)
|
|
$ws = [Net.WebSockets.ClientWebSocket]::new()
|
|
$uri = [Uri]::new("${BackendWsBase}?attach_token=$([Uri]::EscapeDataString($AttachToken))")
|
|
$null = $ws.ConnectAsync($uri, [Threading.CancellationToken]::None).GetAwaiter().GetResult()
|
|
return $ws
|
|
}
|
|
|
|
function Receive-Envelope {
|
|
param(
|
|
[Net.WebSockets.ClientWebSocket]$WebSocket,
|
|
[int]$TimeoutMilliseconds = 30000
|
|
)
|
|
$buffer = [byte[]]::new(1024 * 1024)
|
|
$segment = [ArraySegment[byte]]::new($buffer)
|
|
$stream = [IO.MemoryStream]::new()
|
|
while ($true) {
|
|
$cts = [Threading.CancellationTokenSource]::new($TimeoutMilliseconds)
|
|
try {
|
|
$result = $WebSocket.ReceiveAsync($segment, $cts.Token).GetAwaiter().GetResult()
|
|
}
|
|
finally {
|
|
$cts.Dispose()
|
|
}
|
|
if ($result.MessageType -eq [Net.WebSockets.WebSocketMessageType]::Close) {
|
|
throw "websocket closed"
|
|
}
|
|
$stream.Write($buffer, 0, $result.Count)
|
|
if ($result.EndOfMessage) {
|
|
break
|
|
}
|
|
}
|
|
$text = [Text.Encoding]::UTF8.GetString($stream.ToArray())
|
|
return $text | ConvertFrom-Json
|
|
}
|
|
|
|
function Receive-EnvelopeOfType {
|
|
param(
|
|
[Net.WebSockets.ClientWebSocket]$WebSocket,
|
|
[string[]]$Types,
|
|
[int]$TimeoutSeconds = 30
|
|
)
|
|
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
|
|
while ((Get-Date) -lt $deadline) {
|
|
$envelope = Receive-Envelope -WebSocket $WebSocket -TimeoutMilliseconds 10000
|
|
if ($Types -contains [string]$envelope.type) {
|
|
return $envelope
|
|
}
|
|
Write-SmokeLog "skipping ws event type=$($envelope.type)"
|
|
}
|
|
throw "timed out waiting for envelope type: $($Types -join ',')"
|
|
}
|
|
|
|
function Send-Envelope {
|
|
param(
|
|
[Net.WebSockets.ClientWebSocket]$WebSocket,
|
|
[object]$Envelope
|
|
)
|
|
$json = $Envelope | ConvertTo-Json -Depth 16 -Compress
|
|
$bytes = [Text.Encoding]::UTF8.GetBytes($json)
|
|
$null = $WebSocket.SendAsync(
|
|
[ArraySegment[byte]]::new($bytes),
|
|
[Net.WebSockets.WebSocketMessageType]::Text,
|
|
$true,
|
|
[Threading.CancellationToken]::None
|
|
).GetAwaiter().GetResult()
|
|
}
|
|
|
|
function Get-PayloadProperty {
|
|
param(
|
|
[object]$Payload,
|
|
[string]$Name
|
|
)
|
|
if ($null -eq $Payload) {
|
|
return ""
|
|
}
|
|
if ($Payload.PSObject.Properties.Name -contains $Name) {
|
|
return $Payload.$Name
|
|
}
|
|
return ""
|
|
}
|
|
|
|
function Wait-SessionActive {
|
|
param([Net.WebSockets.ClientWebSocket]$WebSocket)
|
|
$deadline = (Get-Date).AddSeconds(90)
|
|
while ((Get-Date) -lt $deadline) {
|
|
$envelope = Receive-Envelope -WebSocket $WebSocket -TimeoutMilliseconds 30000
|
|
Write-SmokeLog "ws event type=$($envelope.type) state=$($envelope.payload.state)"
|
|
if ($envelope.type -eq "session.state" -and $envelope.payload.state -eq "active") {
|
|
return
|
|
}
|
|
}
|
|
throw "session did not become active"
|
|
}
|
|
|
|
function Start-SmokeSession {
|
|
param([string]$UserId, [string]$DeviceId, [string]$ResourceId)
|
|
return Invoke-Api -Method Post -Path "sessions" -Body @{
|
|
resource_id = $ResourceId
|
|
user_id = $UserId
|
|
device_id = $DeviceId
|
|
}
|
|
}
|
|
|
|
function Stop-SmokeSession {
|
|
param([string]$SessionId, [string]$UserId)
|
|
try {
|
|
Invoke-Api -Method Post -Path "sessions/$SessionId/terminate" -Body @{
|
|
user_id = $UserId
|
|
reason = "stage5_file_upload_smoke_cleanup"
|
|
} | Out-Null
|
|
}
|
|
catch {
|
|
Write-SmokeLog "terminate skipped session=$SessionId reason=$($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
function Restart-SmokeWorker {
|
|
Write-SmokeLog "restarting worker container=$WorkerContainerName"
|
|
$cmd = "docker rm -f $WorkerContainerName 2>/dev/null || true; docker run -d --name $WorkerContainerName --network host -e RDP_WORKER_ID=rdp-worker-1 -e RDP_WORKER_REDIS_HOST=127.0.0.1 -e RDP_WORKER_REDIS_PORT=6379 -e RDP_WORKER_TRANSFER_ROOT=/tmp/rap-rdp-worker-transfers -e RDP_WORKER_CAPABILITIES=adaptive-quality,dirty-rects,clipboard,file-transfer $WorkerImage"
|
|
$output = ssh $DockerSshAlias $cmd
|
|
Write-SmokeLog "worker restart output=$($output -join ' ')"
|
|
Start-Sleep -Seconds 5
|
|
}
|
|
|
|
function Stop-SmokeWorker {
|
|
Write-SmokeLog "stopping worker container=$WorkerContainerName"
|
|
ssh $DockerSshAlias "docker rm -f $WorkerContainerName 2>/dev/null || true" | Out-Null
|
|
}
|
|
|
|
function Wait-SessionState {
|
|
param(
|
|
[string]$SessionId,
|
|
[string]$ExpectedState,
|
|
[int]$TimeoutSeconds = 90
|
|
)
|
|
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
|
|
while ((Get-Date) -lt $deadline) {
|
|
$escaped = $SessionId.Replace("'", "''")
|
|
$state = Invoke-RemoteSqlScalar -Sql "SELECT state FROM remote_sessions WHERE id = '$escaped' LIMIT 1;"
|
|
Write-SmokeLog "session_state session=$SessionId state=$state expected=$ExpectedState"
|
|
if ($state -eq $ExpectedState) {
|
|
return
|
|
}
|
|
Start-Sleep -Seconds 3
|
|
}
|
|
throw "session $SessionId did not reach state $ExpectedState"
|
|
}
|
|
|
|
function Assert-UploadBlockedOnConnection {
|
|
param(
|
|
[Net.WebSockets.ClientWebSocket]$WebSocket,
|
|
[string]$Label
|
|
)
|
|
try {
|
|
Send-Envelope -WebSocket $WebSocket -Envelope @{
|
|
type = "file_upload.start"
|
|
payload = @{
|
|
direction = "client_to_server"
|
|
transfer_id = [guid]::NewGuid().ToString("D")
|
|
file_name = "$Label.txt"
|
|
file_size = 5
|
|
total_chunks = 1
|
|
content_hash = ""
|
|
}
|
|
}
|
|
$response = Receive-EnvelopeOfType -WebSocket $WebSocket -Types @("file_upload.blocked", "session.taken_over", "transport.closed", "session.state") -TimeoutSeconds 20
|
|
$reason = Get-PayloadProperty -Payload $response.payload -Name "reason"
|
|
$state = Get-PayloadProperty -Payload $response.payload -Name "state"
|
|
Write-SmokeLog "$Label upload gate response type=$($response.type) state=$state reason=$reason"
|
|
if ($response.type -eq "file_upload.progress") {
|
|
throw "$Label upload was accepted unexpectedly"
|
|
}
|
|
if ($response.type -eq "session.state" -and $state -eq "active") {
|
|
throw "$Label upload gate returned active session state"
|
|
}
|
|
}
|
|
catch {
|
|
Write-SmokeLog "$Label upload blocked by closed/failed transport: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
function Upload-Bytes {
|
|
param(
|
|
[Net.WebSockets.ClientWebSocket]$WebSocket,
|
|
[string]$FileName,
|
|
[byte[]]$Bytes
|
|
)
|
|
$transferId = [guid]::NewGuid().ToString("D")
|
|
$chunkSize = 256 * 1024
|
|
$totalChunks = [int64][Math]::Ceiling($Bytes.Length / $chunkSize)
|
|
Write-SmokeLog "client upload start transfer_id=$transferId file=$FileName bytes=$($Bytes.Length)"
|
|
Send-Envelope -WebSocket $WebSocket -Envelope @{
|
|
type = "file_upload.start"
|
|
payload = @{
|
|
direction = "client_to_server"
|
|
transfer_id = $transferId
|
|
file_name = $FileName
|
|
file_size = [int64]$Bytes.Length
|
|
total_chunks = $totalChunks
|
|
content_hash = ""
|
|
}
|
|
}
|
|
$startResponse = Receive-EnvelopeOfType -WebSocket $WebSocket -Types @("file_upload.progress", "file_upload.blocked") -TimeoutSeconds 20
|
|
$startStatus = Get-PayloadProperty -Payload $startResponse.payload -Name "status"
|
|
$startReason = Get-PayloadProperty -Payload $startResponse.payload -Name "reason"
|
|
Write-SmokeLog "client upload response type=$($startResponse.type) status=$startStatus reason=$startReason"
|
|
if ($startResponse.type -ne "file_upload.progress" -or $startResponse.payload.status -ne "started") {
|
|
throw "upload was not accepted by gateway"
|
|
}
|
|
$offset = 0
|
|
$chunkIndex = 0
|
|
while ($offset -lt $Bytes.Length) {
|
|
$take = [Math]::Min($chunkSize, $Bytes.Length - $offset)
|
|
$chunk = [byte[]]::new($take)
|
|
[Array]::Copy($Bytes, $offset, $chunk, 0, $take)
|
|
Send-Envelope -WebSocket $WebSocket -Envelope @{
|
|
type = "file_upload.chunk"
|
|
payload = @{
|
|
direction = "client_to_server"
|
|
transfer_id = $transferId
|
|
chunk_index = [int64]$chunkIndex
|
|
offset = [int64]$offset
|
|
chunk_size = $take
|
|
chunk_bytes = [Convert]::ToBase64String($chunk)
|
|
}
|
|
}
|
|
$progress = Receive-EnvelopeOfType -WebSocket $WebSocket -Types @("file_upload.progress", "file_upload.blocked") -TimeoutSeconds 20
|
|
$progressStatus = Get-PayloadProperty -Payload $progress.payload -Name "status"
|
|
$progressReceived = Get-PayloadProperty -Payload $progress.payload -Name "received"
|
|
$progressTotal = Get-PayloadProperty -Payload $progress.payload -Name "total"
|
|
Write-SmokeLog "client upload progress type=$($progress.type) status=$progressStatus received=$progressReceived total=$progressTotal"
|
|
$offset += $take
|
|
$chunkIndex++
|
|
}
|
|
return $transferId
|
|
}
|
|
|
|
function Get-RemoteFileEvidence {
|
|
param(
|
|
[string]$SessionId,
|
|
[string]$TransferId,
|
|
[string]$FileName,
|
|
[string]$ExpectedSha256
|
|
)
|
|
$path = "/tmp/rap-rdp-worker-transfers/$SessionId/visible/$FileName"
|
|
$remoteScript = "p='$path'; ls -l ""`$p""; wc -c < ""`$p""; sha256sum ""`$p"""
|
|
$output = $null
|
|
$deadline = (Get-Date).AddSeconds(20)
|
|
while ((Get-Date) -lt $deadline) {
|
|
$output = ssh $DockerSshAlias "docker exec $WorkerContainerName sh -lc '$remoteScript'" 2>$null
|
|
if ($LASTEXITCODE -eq 0 -and (($output -join "`n") -like "*$ExpectedSha256*")) {
|
|
break
|
|
}
|
|
Start-Sleep -Milliseconds 500
|
|
}
|
|
foreach ($line in $output) {
|
|
Write-SmokeLog "worker_fs $line"
|
|
}
|
|
if ((($output -join "`n") -notlike "*$ExpectedSha256*")) {
|
|
throw "remote sha256 mismatch for $FileName"
|
|
}
|
|
}
|
|
|
|
function Get-Sha256 {
|
|
param([byte[]]$Bytes)
|
|
$stream = [IO.MemoryStream]::new($Bytes)
|
|
try {
|
|
return (Get-FileHash -Algorithm SHA256 -InputStream $stream).Hash.ToLowerInvariant()
|
|
}
|
|
finally {
|
|
$stream.Dispose()
|
|
}
|
|
}
|
|
|
|
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $OutputLog) | Out-Null
|
|
|
|
$login = Invoke-Api -Method Post -Path "auth/login" -Body @{
|
|
email = $Email
|
|
password = $Password
|
|
trust_device = $true
|
|
device_fingerprint = "stage5-file-upload-a"
|
|
device_label = "stage5-file-upload-a"
|
|
}
|
|
$userId = [string]$login.user.ID
|
|
if ([string]::IsNullOrWhiteSpace($userId)) {
|
|
$userId = [string]$login.user.id
|
|
}
|
|
$deviceId = [string]$login.device.ID
|
|
if ([string]::IsNullOrWhiteSpace($deviceId)) {
|
|
$deviceId = [string]$login.device.id
|
|
}
|
|
|
|
$escapedResourceName = $ResourceName.Replace("'", "''")
|
|
$resourceSql = "SELECT id::text FROM resources WHERE name = '$escapedResourceName' LIMIT 1;"
|
|
$resourceId = Invoke-RemoteSqlScalar -Sql $resourceSql
|
|
if ([string]::IsNullOrWhiteSpace($resourceId)) {
|
|
throw "resource not found: $ResourceName"
|
|
}
|
|
Write-SmokeLog "smoke user=$userId device=$deviceId resource=$resourceId"
|
|
Restart-SmokeWorker
|
|
|
|
$sessions = Invoke-Api -Method Get -Path "sessions?user_id=$([Uri]::EscapeDataString($userId))"
|
|
foreach ($session in @($sessions.sessions)) {
|
|
if ($session.state -in @("starting", "active", "detached", "reconnecting")) {
|
|
Stop-SmokeSession -SessionId $session.id -UserId $userId
|
|
}
|
|
}
|
|
|
|
Set-FileTransferMode -Mode disabled
|
|
$disabled = Start-SmokeSession -UserId $userId -DeviceId $deviceId -ResourceId $resourceId
|
|
$disabledSessionId = [string]$disabled.session.ID
|
|
$disabledAttachToken = [string]$disabled.attach_token.token
|
|
Write-SmokeLog "disabled session=$disabledSessionId"
|
|
$disabledWs = New-GatewayWebSocket -AttachToken $disabledAttachToken
|
|
try {
|
|
Wait-SessionActive -WebSocket $disabledWs
|
|
$blockedTransferId = [guid]::NewGuid().ToString("D")
|
|
Send-Envelope -WebSocket $disabledWs -Envelope @{
|
|
type = "file_upload.start"
|
|
payload = @{
|
|
direction = "client_to_server"
|
|
transfer_id = $blockedTransferId
|
|
file_name = "blocked.txt"
|
|
file_size = 5
|
|
total_chunks = 1
|
|
content_hash = ""
|
|
}
|
|
}
|
|
$blocked = Receive-EnvelopeOfType -WebSocket $disabledWs -Types @("file_upload.blocked") -TimeoutSeconds 20
|
|
$blockedReason = if ($blocked.payload.PSObject.Properties.Name -contains "reason") { $blocked.payload.reason } else { "" }
|
|
Write-SmokeLog "disabled upload response type=$($blocked.type) reason=$blockedReason"
|
|
if ($blocked.type -ne "file_upload.blocked") {
|
|
throw "disabled policy did not block upload"
|
|
}
|
|
}
|
|
finally {
|
|
$disabledWs.Dispose()
|
|
Stop-SmokeSession -SessionId $disabledSessionId -UserId $userId
|
|
}
|
|
|
|
Set-FileTransferMode -Mode client_to_server
|
|
$allowed = Start-SmokeSession -UserId $userId -DeviceId $deviceId -ResourceId $resourceId
|
|
$sessionId = [string]$allowed.session.ID
|
|
$attachmentId = [string]$allowed.attachment.ID
|
|
$attachToken = [string]$allowed.attach_token.token
|
|
Write-SmokeLog "allowed session=$sessionId attachment=$attachmentId"
|
|
$ws = New-GatewayWebSocket -AttachToken $attachToken
|
|
try {
|
|
Wait-SessionActive -WebSocket $ws
|
|
Send-Envelope -WebSocket $ws -Envelope @{ type = "input"; payload = @{ kind = "mouse"; action = "move"; normalized_x = 0.5; normalized_y = 0.5; surface_width = 1024; surface_height = 768 } }
|
|
Send-Envelope -WebSocket $ws -Envelope @{ type = "input"; payload = @{ kind = "keyboard"; action = "key_down"; scan_code = 30; is_extended = $false } }
|
|
Send-Envelope -WebSocket $ws -Envelope @{ type = "input"; payload = @{ kind = "keyboard"; action = "key_up"; scan_code = 30; is_extended = $false } }
|
|
Send-Envelope -WebSocket $ws -Envelope @{ type = "clipboard"; payload = @{ direction = "client_to_server"; text = "stage5 clipboard regression"; sequence_id = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds(); origin = $attachmentId; content_hash = "" } }
|
|
Start-Sleep -Seconds 2
|
|
|
|
$textBytes = [Text.Encoding]::UTF8.GetBytes("Stage 5.1 text upload`nрусский текст`n")
|
|
$textSha = Get-Sha256 -Bytes $textBytes
|
|
$textTransfer = Upload-Bytes -WebSocket $ws -FileName "stage5-upload-text.txt" -Bytes $textBytes
|
|
Get-RemoteFileEvidence -SessionId $sessionId -TransferId $textTransfer -FileName "stage5-upload-text.txt" -ExpectedSha256 $textSha
|
|
|
|
$binaryBytes = [byte[]]::new(4096)
|
|
[Security.Cryptography.RandomNumberGenerator]::Fill($binaryBytes)
|
|
$binarySha = Get-Sha256 -Bytes $binaryBytes
|
|
$binaryTransfer = Upload-Bytes -WebSocket $ws -FileName "stage5-upload-binary.bin" -Bytes $binaryBytes
|
|
Get-RemoteFileEvidence -SessionId $sessionId -TransferId $binaryTransfer -FileName "stage5-upload-binary.bin" -ExpectedSha256 $binarySha
|
|
|
|
Invoke-Api -Method Post -Path "sessions/$sessionId/detach" -Body @{
|
|
attachment_id = $attachmentId
|
|
user_id = $userId
|
|
reason = "stage5_file_upload_detach_gate"
|
|
} | Out-Null
|
|
Start-Sleep -Seconds 2
|
|
try {
|
|
Send-Envelope -WebSocket $ws -Envelope @{
|
|
type = "file_upload.start"
|
|
payload = @{
|
|
direction = "client_to_server"
|
|
transfer_id = [guid]::NewGuid().ToString("D")
|
|
file_name = "after-detach.txt"
|
|
file_size = 5
|
|
total_chunks = 1
|
|
content_hash = ""
|
|
}
|
|
}
|
|
$detachGate = Receive-Envelope -WebSocket $ws -TimeoutMilliseconds 8000
|
|
Write-SmokeLog "detach upload response type=$($detachGate.type) reason=$($detachGate.payload.reason)"
|
|
}
|
|
catch {
|
|
Write-SmokeLog "detach upload blocked by closed transport: $($_.Exception.Message)"
|
|
}
|
|
|
|
Stop-SmokeSession -SessionId $sessionId -UserId $userId
|
|
|
|
$takeoverSession = Start-SmokeSession -UserId $userId -DeviceId $deviceId -ResourceId $resourceId
|
|
$takeoverSessionId = [string]$takeoverSession.session.ID
|
|
$takeoverAttachmentId = [string]$takeoverSession.attachment.ID
|
|
$takeoverAttachToken = [string]$takeoverSession.attach_token.token
|
|
Write-SmokeLog "takeover session=$takeoverSessionId old_attachment=$takeoverAttachmentId"
|
|
$takeoverOldWs = New-GatewayWebSocket -AttachToken $takeoverAttachToken
|
|
$takeoverNewWs = $null
|
|
try {
|
|
Wait-SessionActive -WebSocket $takeoverOldWs
|
|
$loginB = Invoke-Api -Method Post -Path "auth/login" -Body @{
|
|
email = $Email
|
|
password = $Password
|
|
trust_device = $true
|
|
device_fingerprint = "stage5-file-upload-b"
|
|
device_label = "stage5-file-upload-b"
|
|
}
|
|
$deviceB = [string]$loginB.device.ID
|
|
if ([string]::IsNullOrWhiteSpace($deviceB)) {
|
|
$deviceB = [string]$loginB.device.id
|
|
}
|
|
$takeoverResult = Invoke-Api -Method Post -Path "sessions/$takeoverSessionId/takeover" -Body @{
|
|
user_id = $userId
|
|
device_id = $deviceB
|
|
reason = "stage5_file_upload_takeover_gate"
|
|
}
|
|
$newAttachmentId = [string]$takeoverResult.attachment.ID
|
|
$newAttachToken = [string]$takeoverResult.attach_token.token
|
|
Write-SmokeLog "takeover complete new_attachment=$newAttachmentId"
|
|
$takeoverNewWs = New-GatewayWebSocket -AttachToken $newAttachToken
|
|
Wait-SessionActive -WebSocket $takeoverNewWs
|
|
Assert-UploadBlockedOnConnection -WebSocket $takeoverOldWs -Label "takeover_old_client"
|
|
}
|
|
finally {
|
|
if ($null -ne $takeoverNewWs) {
|
|
$takeoverNewWs.Dispose()
|
|
}
|
|
$takeoverOldWs.Dispose()
|
|
Stop-SmokeSession -SessionId $takeoverSessionId -UserId $userId
|
|
}
|
|
|
|
$failureSession = Start-SmokeSession -UserId $userId -DeviceId $deviceId -ResourceId $resourceId
|
|
$failureSessionId = [string]$failureSession.session.ID
|
|
$failureAttachToken = [string]$failureSession.attach_token.token
|
|
Write-SmokeLog "worker_failure session=$failureSessionId"
|
|
$failureWs = New-GatewayWebSocket -AttachToken $failureAttachToken
|
|
try {
|
|
Wait-SessionActive -WebSocket $failureWs
|
|
Stop-SmokeWorker
|
|
Wait-SessionState -SessionId $failureSessionId -ExpectedState "failed" -TimeoutSeconds 120
|
|
Assert-UploadBlockedOnConnection -WebSocket $failureWs -Label "worker_failure"
|
|
}
|
|
finally {
|
|
$failureWs.Dispose()
|
|
Restart-SmokeWorker
|
|
Stop-SmokeSession -SessionId $failureSessionId -UserId $userId
|
|
}
|
|
}
|
|
finally {
|
|
$ws.Dispose()
|
|
Stop-SmokeSession -SessionId $sessionId -UserId $userId
|
|
$log | Set-Content -LiteralPath $OutputLog -Encoding UTF8
|
|
Write-SmokeLog "wrote $OutputLog"
|
|
}
|