#!/usr/bin/env nu
# tests the blue.microcosm.links backlinks API with deterministic local fixtures
use common.nu *
def get-all-backlinks [url: string, subject: string, source: string, reverse: bool] {
mut all = []
mut cursor = ""
loop {
let reverse_param = if $reverse { "&reverse=true" } else { "" }
let params = if ($cursor | is-empty) {
$"subject=($subject | url encode)&source=($source | url encode)&limit=2($reverse_param)"
} else {
$"subject=($subject | url encode)&source=($source | url encode)&limit=2&cursor=($cursor | url encode)($reverse_param)"
}
let response = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinks?($params)")
$all = ($all | append $response.backlinks)
let next = ($response | get --optional cursor)
if ($next | is-empty) {
break
}
$cursor = $next
}
$all
}
def main [] {
let port = resolve-test-port 3020
let debug_port = resolve-test-debug-port ($port + 1)
let url = $"http://127.0.0.1:($port)"
let debug_url = $"http://127.0.0.1:($debug_port)"
let db_path = (mktemp -d -t hydrant_backlinks.XXXXXX)
print $"database path: ($db_path)"
let binary = (build-hydrant-features "backlinks")
let instance = (with-env {
HYDRANT_RELAY_HOSTS: "",
HYDRANT_CRAWLER_URLS: "",
HYDRANT_ENABLE_CRAWLER: "false",
HYDRANT_ENABLE_FIREHOSE: "false",
HYDRANT_ENABLE_BACKFILL: "false",
} {
start-hydrant $binary $db_path $port
})
if not (wait-for-api $url) {
fail "hydrant failed to start" $instance.pid
}
let seeded = (
http post -f -e -H [Content-Length 0]
$"($debug_url)/debug/seed_backlinks?like_count=5&post_count=2" ""
)
if $seeded.status != 200 {
fail $"backlink fixture seed returned ($seeded.status)" $instance.pid
}
let fixture = $seeded.body
let subject = $fixture.subject
let did = $fixture.did
let subject_param = ($subject | url encode)
print "checking unfiltered results and count..."
let all = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinks?subject=($subject_param)&limit=100")
let all_count = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinksCount?subject=($subject_param)")
let expected_total = ($fixture.like_count + $fixture.post_count)
if ($all.backlinks | length) != $expected_total or $all_count.count != $expected_total {
fail $"expected ($expected_total) backlinks, got results=($all.backlinks | length) count=($all_count.count)" $instance.pid
}
print "checking collection and path filters..."
let like_source = "app.bsky.feed.like"
let like_source_param = ($like_source | url encode)
let likes = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinks?subject=($subject_param)&source=($like_source_param)&limit=100")
let like_count = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinksCount?subject=($subject_param)&source=($like_source_param)")
if ($likes.backlinks | length) != $fixture.like_count or $like_count.count != $fixture.like_count {
fail "like source filter returned the wrong cardinality" $instance.pid
}
if ($likes.backlinks | any { |entry| not ($entry.uri | str contains "/app.bsky.feed.like/") }) {
fail "like source filter returned another collection" $instance.pid
}
if not ($likes.backlinks | any { |entry| $entry.uri | str ends-with "/stinkpot" }) {
fail "eight-byte rkey was not preserved through backlink projection" $instance.pid
}
if ($likes.backlinks | any { |entry| ($entry.cid | is-empty) }) {
fail "backlink result omitted a record CID" $instance.pid
}
let path_source = ("app.bsky.feed.like:subject.uri" | url encode)
let path_filtered = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinks?subject=($subject_param)&source=($path_source)&limit=100")
if ($path_filtered.backlinks | length) != $fixture.like_count {
fail "collection:path filter returned the wrong cardinality" $instance.pid
}
let post_source = ("app.bsky.feed.post" | url encode)
let posts = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinks?subject=($subject_param)&source=($post_source)&limit=100")
if ($posts.backlinks | length) != $fixture.post_count {
fail "post source filter returned the wrong cardinality" $instance.pid
}
print "checking cursor pagination..."
let paged = (get-all-backlinks $url $subject $like_source false)
let full_uris = ($likes.backlinks | get uri)
let paged_uris = ($paged | get uri)
if $paged_uris != $full_uris or ($paged_uris | uniq | length) != $fixture.like_count {
fail "cursor pagination skipped or duplicated backlinks" $instance.pid
}
print "checking reverse and DID filters..."
let reverse = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinks?subject=($subject_param)&source=($like_source_param)&limit=100&reverse=true")
if ($reverse.backlinks | get uri) != ($full_uris | reverse) {
fail "reverse scan did not invert result order" $instance.pid
}
let reverse_paged = (get-all-backlinks $url $subject $like_source true)
if ($reverse_paged | get uri) != ($full_uris | reverse) {
fail "reverse cursor pagination skipped or duplicated backlinks" $instance.pid
}
let matching_did = ($did | url encode)
let matching = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinks?subject=($subject_param)&did=($matching_did)&limit=100")
if ($matching.backlinks | length) != $expected_total {
fail "matching DID filter dropped backlinks" $instance.pid
}
let other_did = ("did:plc:ewvi7nxzyoun6zhxrhs64oiz" | url encode)
let excluded = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinks?subject=($subject_param)&did=($other_did)&limit=100")
if not ($excluded.backlinks | is-empty) {
fail "non-matching DID filter returned backlinks" $instance.pid
}
let repeated = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinks?subject=($subject_param)&did=($other_did)&did=($matching_did)&limit=100")
if ($repeated.backlinks | length) != $expected_total {
fail "repeated DID filters were not decoded as an array" $instance.pid
}
let repeated_count = (http get $"($url)/xrpc/blue.microcosm.links.getBacklinksCount?subject=($subject_param)&did=($other_did)&did=($matching_did)")
if $repeated_count.count != $expected_total {
fail "repeated DID count filters were not decoded as an array" $instance.pid
}
try { kill $instance.pid }
print "all backlinks tests PASSED"
}