#!/usr/bin/env nu
use common.nu *
# curl over the unix socket, returning stdout. curl exits non-zero on the websocket check
# because it times out holding the upgraded connection open, so the exit code is ignored.
def --wrapped curl-unix [socket: string, ...args: string] {
^curl --silent --unix-socket $socket ...$args | complete | get stdout
}
def main [] {
let port = resolve-test-port 3030
let db_path = (mktemp -d -t hydrant_api_unix_socket_test.XXXXXX)
let socket = $"($db_path)/api.sock"
print "testing the api over a unix socket..."
print $"database path: ($db_path)"
let binary = build-hydrant
let instance = with-env { HYDRANT_API_BIND: $"unix:($socket)" } {
start-hydrant $binary $db_path $port
}
mut ready = false
for i in 1..30 {
if ((curl-unix $socket "http://localhost/stats") | str contains "{") {
$ready = true
break
}
sleep 1sec
}
mut failures = []
if not $ready {
$failures = ($failures | append "api never answered on the socket")
} else {
let mode = (ls -l $socket | get 0.mode)
if $mode != "rw-------" {
$failures = ($failures | append $"socket mode is ($mode), want rw-------")
}
let head = (curl-unix $socket "http://localhost/stream/head" | from json)
if not ("id" in $head) {
$failures = ($failures | append $"/stream/head returned ($head | to nuon)")
}
let upgrade = (curl-unix $socket --include --max-time 2
-H "Connection: Upgrade" -H "Upgrade: websocket"
-H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=="
"http://localhost/stream")
if not ($upgrade | str contains "101") {
$failures = ($failures | append $"/stream did not upgrade: ($upgrade | lines | first 1)")
}
let tcp = (do { ^curl --silent --max-time 2 $"http://127.0.0.1:($port)/stats" } | complete)
if $tcp.exit_code == 0 {
$failures = ($failures | append "api answered on tcp although only the socket was bound")
}
}
print $"stopping hydrant - pid: ($instance.pid)..."
try { kill $instance.pid }
# with both kinds of bind, management only answers on the socket
let split_db = (mktemp -d -t hydrant_api_split_test.XXXXXX)
let split_socket = $"($split_db)/api.sock"
let split = with-env {
HYDRANT_API_BIND: $"127.0.0.1:($port),unix:($split_socket)"
HYDRANT_API_TCP_MANAGEMENT: "false"
} {
start-hydrant $binary $split_db $port
}
let tcp_url = $"http://127.0.0.1:($port)"
if not (wait-for-api $tcp_url) {
$failures = ($failures | append "split api never answered on tcp")
} else {
let status = {|args| ^curl --silent --output /dev/null --write-out "%{http_code}" ...$args }
let checks = [
[what args want];
["tcp /stats" [$"($tcp_url)/stats"] "200"]
["tcp /filter" [$"($tcp_url)/filter"] "404"]
["socket /filter" [--unix-socket $split_socket "http://localhost/filter"] "200"]
]
for c in $checks {
let got = (do $status $c.args)
if $got != $c.want {
$failures = ($failures | append $"($c.what) answered ($got), want ($c.want)")
}
}
}
print $"stopping hydrant - pid: ($split.pid)..."
try { kill $split.pid }
# `none` turns the api off but hydrant itself keeps running
let none_db = (mktemp -d -t hydrant_api_none_test.XXXXXX)
let headless = with-env { HYDRANT_API_BIND: "none" } {
start-hydrant $binary $none_db $port
}
sleep 3sec
if (ps | where pid == $headless.pid | is-empty) {
$failures = ($failures | append "hydrant exited with HYDRANT_API_BIND=none")
}
let tcp = (do { ^curl --silent --max-time 2 $"http://127.0.0.1:($port)/stats" } | complete)
if $tcp.exit_code == 0 {
$failures = ($failures | append "api answered on tcp with HYDRANT_API_BIND=none")
}
print $"stopping hydrant - pid: ($headless.pid)..."
try { kill $headless.pid }
if ($failures | is-empty) {
print "=== TEST PASSED ==="
} else {
for f in $failures { print $" ($f)" }
try { open $instance.log | lines | last 30 | str join "\n" | print }
print "=== TEST FAILED ==="
exit 1
}
}