1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
<#
.SYNOPSIS
Start a frozen meshbay-node as a daemon and check it answers as the version
it claims to be.
.DESCRIPTION
`meshbay-node --help` imports the parser and nothing else, so it passes for
a bundle that cannot start the daemon at all. This starts the real daemon,
in a throwaway profile (its own LOCALAPPDATA, an unused port, a hub URL
nothing listens on -- it never touches a real hub or the developer's own
node), waits for its control API, and checks:
- /api/status answers, with the expected version;
- the Windows log file was written (a service-mode daemon has no console,
and this file is the only place its errors go).
Also useful against an installed build:
smoke-node-runtime.ps1 -Exe "$env:LOCALAPPDATA\Programs\MeshBay\resources\node-runtime\meshbay-node.exe" -ExpectVersion 0.16.0
.PARAMETER Exe
The meshbay-node.exe to start.
.PARAMETER ExpectVersion
The version /api/status must report.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)][string]$Exe,
[Parameter(Mandatory = $true)][string]$ExpectVersion,
[int]$TimeoutSeconds = 45
)
$ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
$profileDir = Join-Path ([IO.Path]::GetTempPath()) ("meshbay-smoke-" + [guid]::NewGuid().ToString("N"))
$meshbay = Join-Path $profileDir "meshbay"
New-Item -ItemType Directory -Force $meshbay | Out-Null
# A free loopback port, so a node already running here on 18000 is untouched.
$listener = [Net.Sockets.TcpListener]::new([Net.IPAddress]::Loopback, 0)
$listener.Start()
$port = $listener.LocalEndpoint.Port
$listener.Stop()
$bytes = New-Object byte[] 32
[Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
$unlock = Join-Path $meshbay "unlock.key"
Set-Content -Encoding ascii -LiteralPath $unlock ([Convert]::ToBase64String($bytes))
$unlockToml = $unlock.Replace([char]92, [char]47)
Set-Content -Encoding ascii -LiteralPath (Join-Path $meshbay "node.toml") @"
[hub]
url = "http://127.0.0.1:1"
username = "smoke"
[node]
quic_enabled = false
ui_port = $port
[keystore]
unlock_file = "$unlockToml"
"@
$oldLocal = $env:LOCALAPPDATA
$env:LOCALAPPDATA = $profileDir
$stderr = Join-Path $profileDir "stderr.txt"
$proc = $null
try {
$proc = Start-Process -FilePath $Exe -PassThru -WindowStyle Hidden `
-RedirectStandardError $stderr -RedirectStandardOutput (Join-Path $profileDir "stdout.txt")
$env:LOCALAPPDATA = $oldLocal
$tokenFile = Join-Path $meshbay "data\ui-token"
$status = $null
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
while ((Get-Date) -lt $deadline -and -not $proc.HasExited) {
if (Test-Path -LiteralPath $tokenFile) {
try {
$token = (Get-Content -LiteralPath $tokenFile -Raw).Trim()
$status = Invoke-RestMethod "http://127.0.0.1:$port/api/status?t=$token" -TimeoutSec 3
break
} catch { }
}
Start-Sleep -Milliseconds 500
}
$tail = if (Test-Path -LiteralPath $stderr) { (Get-Content -LiteralPath $stderr -Tail 30) -join "`n" } else { "" }
if ($proc.HasExited) {
throw "the frozen daemon exited (code $($proc.ExitCode)) before its control API answered:`n$tail"
}
if ($null -eq $status) {
throw "the frozen daemon's control API did not answer within ${TimeoutSeconds}s:`n$tail"
}
if ($status.version -ne $ExpectVersion) {
throw "the frozen daemon reports version '$($status.version)', expected '$ExpectVersion'"
}
$log = Join-Path $meshbay "state\node.log"
if (-not (Test-Path -LiteralPath $log) -or (Get-Item -LiteralPath $log).Length -eq 0) {
throw "the frozen daemon wrote no log file at $log"
}
Write-Host "OK daemon answered: version $($status.version), status $($status.status), log $log" -ForegroundColor Green
}
finally {
$env:LOCALAPPDATA = $oldLocal
if ($proc -and -not $proc.HasExited) { Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue }
if ($proc) { $proc.WaitForExit(10000) | Out-Null }
Remove-Item -LiteralPath $profileDir -Recurse -Force -ErrorAction SilentlyContinue
}
|