summaryrefslogtreecommitdiff
path: root/_selfcheck.lua
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-08-03 10:44:48 -0600
committert <t@tjp.lol>2026-08-03 10:59:28 -0600
commite22b335db9bdc1e24e9ddb61a38720bd7b796a41 (patch)
tree80f5565cfedd987b574675fc9f3378dadc695004 /_selfcheck.lua
Initial commit: web.{fetch,search} tools
external `curl` for fetching, `exa` public service for search
Diffstat (limited to '_selfcheck.lua')
-rw-r--r--_selfcheck.lua59
1 files changed, 59 insertions, 0 deletions
diff --git a/_selfcheck.lua b/_selfcheck.lua
new file mode 100644
index 0000000..b7f35be
--- /dev/null
+++ b/_selfcheck.lua
@@ -0,0 +1,59 @@
+-- Self-check for panto-web. Run with:
+--
+-- panto lua panto-web/_selfcheck.lua
+
+local registered = {}
+package.loaded["panto"] = {
+ ext = {
+ register_tool = function(tool) registered[#registered + 1] = tool end,
+ json = {
+ decode = function() return {} end,
+ encode = function() return "{}" end,
+ },
+ },
+}
+
+local here = debug.getinfo(1, "S").source:match("^@(.*)/[^/]+$") or "."
+package.path = here .. "/panto-web/?.lua;" .. here .. "/panto-web/?/init.lua;" .. package.path
+
+local web = require("init")
+assert(web.name == "web", "entry name")
+
+local parsed = assert(web.parse_url("https://example.com:8443/docs?q=1"))
+assert(parsed.host == "example.com" and parsed.port == 8443, "URL host and port")
+local _, local_err = web.parse_url("http://user:pass@example.com/")
+assert(local_err:find("credentials", 1, true), "URL credentials rejected")
+assert(web.is_public_address("8.8.8.8"), "public IPv4 allowed")
+assert(not web.is_public_address("127.0.0.1"), "loopback IPv4 blocked")
+assert(not web.is_public_address("::1"), "loopback IPv6 blocked")
+assert(not web.is_public_address("::127.0.0.1"), "IPv4-compatible loopback blocked")
+
+local page, title = web.html_to_text([[<html><head><title>A &amp; B</title>
+<style>hidden</style></head><body><h1>Heading</h1><p>Hello &lt;world&gt;.</p>
+<script>also hidden</script><a href="https://example.com/x">Read</a></body></html>]])
+assert(title == "A & B", "HTML title decoded")
+assert(page:find("Heading", 1, true) and page:find("Hello <world>.", 1, true), "HTML text retained")
+assert(page:find("Read (https://example.com/x)", 1, true), "link destination retained")
+assert(not page:find("hidden", 1, true), "non-content HTML removed")
+
+local search_text = web.format_search([[Title: First result
+URL: https://example.com/one
+Highlights:
+Useful first excerpt.
+...
+---
+
+Title: Second result
+URL: https://example.com/two
+Highlights:
+Useful second excerpt.]], "example query")
+assert(search_text:find("1. First result", 1, true), "first search result")
+assert(search_text:find("URL: https://example.com/two", 1, true), "second search URL")
+
+web.activate()
+assert(registered[1].name == "web.fetch", "fetch tool registered")
+assert(registered[2].name == "web.search", "search tool registered")
+assert(web.on_fetch({ url = "file:///etc/passwd" }):find("only http", 1, true), "fetch rejects file URLs")
+assert(web.on_search({ query = "" }):find("non-empty", 1, true), "search rejects empty query")
+
+print("panto-web selfcheck: OK")