#!/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" }