359 lines
11 KiB
Nim
359 lines
11 KiB
Nim
## Test suite for UTCP Protocol implementation
|
|
|
|
import unittest
|
|
import std/[tables, json, options]
|
|
import ../src/nimpak/utcp_protocol
|
|
|
|
suite "UTCP Address Assignment":
|
|
test "Assign UTCP address to Nippel":
|
|
let res = assignUTCPAddress(Nippel, "dev-env", "localhost")
|
|
|
|
check res.isOk
|
|
if res.isOk:
|
|
let address = res.okValue
|
|
check address.scheme == UtcpPlain
|
|
check address.host == "localhost"
|
|
check address.resourceType == Nippel
|
|
check address.resourceName == "dev-env"
|
|
|
|
test "Assign UTCP address with default host":
|
|
let res = assignUTCPAddress(Nexter, "web-server")
|
|
|
|
check res.isOk
|
|
let address = res.okValue
|
|
check address.host.len > 0 # Should use hostname
|
|
check address.resourceType == Nexter
|
|
check address.resourceName == "web-server"
|
|
|
|
test "Create agent endpoint":
|
|
let res = createAgentEndpoint("n8n-workflow", "localhost")
|
|
|
|
check res.isOk
|
|
let address = res.okValue
|
|
check address.resourceType == Agent
|
|
check address.resourceName == "n8n-workflow"
|
|
|
|
test "Create tool endpoint":
|
|
let res = createToolEndpoint("nexus", "localhost")
|
|
|
|
check res.isOk
|
|
let address = res.okValue
|
|
check address.resourceType == Tool
|
|
check address.resourceName == "nexus"
|
|
|
|
test "Create LLM endpoint":
|
|
let res = createLLMEndpoint("llama2", "localhost")
|
|
|
|
check res.isOk
|
|
let address = res.okValue
|
|
check address.resourceType == LLM
|
|
check address.resourceName == "llama2"
|
|
|
|
|
|
suite "UTCP Address Parsing":
|
|
test "Parse simple UTCP address":
|
|
let res = parseUTCPAddress("utcp://localhost/nippel/dev-env")
|
|
|
|
check res.isOk
|
|
let address = res.okValue
|
|
check address.scheme == UtcpPlain
|
|
check address.host == "localhost"
|
|
check address.resourceType == Nippel
|
|
check address.resourceName == "dev-env"
|
|
|
|
test "Parse UTCP address with port":
|
|
let res = parseUTCPAddress("utcp://localhost:8080/nexter/web-server")
|
|
|
|
check res.isOk
|
|
let address = res.okValue
|
|
check address.port.isSome
|
|
check address.port.get() == 8080
|
|
|
|
test "Parse UTCP address with path":
|
|
let res = parseUTCPAddress("utcp://localhost/nippel/dev-env/state")
|
|
|
|
check res.isOk
|
|
let address = res.okValue
|
|
check address.path == "/state"
|
|
|
|
test "Parse UTCP address with query":
|
|
let res = parseUTCPAddress("utcp://localhost/nippel/dev-env?cmd=vim")
|
|
|
|
check res.isOk
|
|
let address = res.okValue
|
|
check address.query.hasKey("cmd")
|
|
check address.query["cmd"] == "vim"
|
|
|
|
test "Parse secure UTCP address":
|
|
let res = parseUTCPAddress("utcps://localhost/agent/n8n")
|
|
|
|
check res.isOk
|
|
let address = res.okValue
|
|
check address.scheme == UtcpSecure
|
|
|
|
test "Parse invalid scheme":
|
|
let res = parseUTCPAddress("http://localhost/nippel/dev-env")
|
|
|
|
check not res.isOk
|
|
|
|
test "Parse invalid path":
|
|
let res = parseUTCPAddress("utcp://localhost/invalid")
|
|
|
|
check not res.isOk
|
|
|
|
|
|
suite "UTCP Address Formatting":
|
|
test "Format simple address":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env")
|
|
let formatted = formatUTCPAddress(address)
|
|
|
|
check formatted == "utcp://localhost/nippel/dev-env"
|
|
|
|
test "Format address with port":
|
|
let address = newUTCPAddress("localhost", Nexter, "web-server", port = some(8080))
|
|
let formatted = formatUTCPAddress(address)
|
|
|
|
check formatted == "utcp://localhost:8080/nexter/web-server"
|
|
|
|
test "Format address with path":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env", path = "/state")
|
|
let formatted = formatUTCPAddress(address)
|
|
|
|
check formatted == "utcp://localhost/nippel/dev-env/state"
|
|
|
|
test "Format address with query":
|
|
var query = initTable[string, string]()
|
|
query["cmd"] = "vim"
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env", query = query)
|
|
let formatted = formatUTCPAddress(address)
|
|
|
|
check formatted.contains("?cmd=vim")
|
|
|
|
test "Format secure address":
|
|
let address = newUTCPAddress("localhost", Agent, "n8n", scheme = UtcpSecure)
|
|
let formatted = formatUTCPAddress(address)
|
|
|
|
check formatted.startsWith("utcps://")
|
|
|
|
suite "UTCP Request Creation":
|
|
test "Create GET request":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env")
|
|
let request = newUTCPRequest(address, GET)
|
|
|
|
check request.meth == GET
|
|
check request.address.resourceName == "dev-env"
|
|
check request.headers.hasKey("User-Agent")
|
|
check request.headers.hasKey("UTCP-Version")
|
|
|
|
test "Create POST request with payload":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env")
|
|
let payload = %*{"command": "vim"}
|
|
let request = newUTCPRequest(address, POST, payload)
|
|
|
|
check request.meth == POST
|
|
check request.payload.hasKey("command")
|
|
check request.payload["command"].getStr() == "vim"
|
|
|
|
|
|
suite "UTCP Response Creation":
|
|
test "Create success response":
|
|
let response = newUTCPResponse(Ok, %*{"status": "active"}, "req-123")
|
|
|
|
check response.status == Ok
|
|
check response.requestId == "req-123"
|
|
check response.data.hasKey("status")
|
|
|
|
test "Create error response":
|
|
let response = newUTCPResponse(NotFound, %*{"error": "Not found"})
|
|
|
|
check response.status == NotFound
|
|
check response.data.hasKey("error")
|
|
|
|
suite "UTCP Method Handlers":
|
|
test "Handle GET state":
|
|
let res = handleGetState(Nippel, "dev-env")
|
|
|
|
check res.isOk
|
|
let state = res.okValue
|
|
check state.hasKey("resourceType")
|
|
check state.hasKey("resourceName")
|
|
check state.hasKey("status")
|
|
|
|
test "Handle activate":
|
|
let res = handleActivate(Nippel, "dev-env")
|
|
|
|
check res.isOk
|
|
let response = res.okValue
|
|
check response.hasKey("action")
|
|
check response["action"].getStr() == "activate"
|
|
|
|
test "Handle deactivate":
|
|
let res = handleDeactivate(Nippel, "dev-env")
|
|
|
|
check res.isOk
|
|
let response = res.okValue
|
|
check response.hasKey("action")
|
|
check response["action"].getStr() == "deactivate"
|
|
|
|
test "Handle get merkle":
|
|
let res = handleGetMerkle(Nippel, "dev-env")
|
|
|
|
check res.isOk
|
|
let merkle = res.okValue
|
|
check merkle.hasKey("merkleRoot")
|
|
|
|
test "Handle exec":
|
|
let res = handleExec(Nippel, "dev-env", "vim")
|
|
|
|
check res.isOk
|
|
let execResult = res.okValue
|
|
check execResult.hasKey("command")
|
|
check execResult["command"].getStr() == "vim"
|
|
|
|
|
|
suite "UTCP Request Routing":
|
|
test "Route GET state request":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env", path = "/state")
|
|
let request = newUTCPRequest(address, GET)
|
|
let res = routeUTCPRequest(request)
|
|
|
|
check res.isOk
|
|
let response = res.okValue
|
|
check response.status == Ok
|
|
check response.data.hasKey("resourceType")
|
|
|
|
test "Route POST activate request":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env", path = "/activate")
|
|
let request = newUTCPRequest(address, POST)
|
|
let res = routeUTCPRequest(request)
|
|
|
|
check res.isOk
|
|
let response = res.okValue
|
|
check response.status == Ok
|
|
check response.data["action"].getStr() == "activate"
|
|
|
|
test "Route POST deactivate request":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env", path = "/deactivate")
|
|
let request = newUTCPRequest(address, POST)
|
|
let res = routeUTCPRequest(request)
|
|
|
|
check res.isOk
|
|
let response = res.okValue
|
|
check response.status == Ok
|
|
check response.data["action"].getStr() == "deactivate"
|
|
|
|
test "Route GET merkle request":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env", path = "/merkle")
|
|
let request = newUTCPRequest(address, GET)
|
|
let res = routeUTCPRequest(request)
|
|
|
|
check res.isOk
|
|
let response = res.okValue
|
|
check response.status == Ok
|
|
check response.data.hasKey("merkleRoot")
|
|
|
|
test "Route POST exec request":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env", path = "/exec")
|
|
let payload = %*{"command": "vim"}
|
|
let request = newUTCPRequest(address, POST, payload)
|
|
let res = routeUTCPRequest(request)
|
|
|
|
check res.isOk
|
|
let response = res.okValue
|
|
check response.status == Ok
|
|
check response.data["command"].getStr() == "vim"
|
|
|
|
test "Route invalid path":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env", path = "/invalid")
|
|
let request = newUTCPRequest(address, GET)
|
|
let res = routeUTCPRequest(request)
|
|
|
|
check res.isOk
|
|
let response = res.okValue
|
|
check response.status == NotFound
|
|
|
|
test "Route unsupported method":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env")
|
|
let request = newUTCPRequest(address, DELETE)
|
|
let res = routeUTCPRequest(request)
|
|
|
|
check res.isOk
|
|
let response = res.okValue
|
|
check response.status == MethodNotAllowed
|
|
|
|
|
|
suite "UTCP Utility Functions":
|
|
test "Check local address - localhost":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env")
|
|
check isLocalAddress(address)
|
|
|
|
test "Check local address - 127.0.0.1":
|
|
let address = newUTCPAddress("127.0.0.1", Nippel, "dev-env")
|
|
check isLocalAddress(address)
|
|
|
|
test "Check remote address":
|
|
let address = newUTCPAddress("remote.example.com", Nippel, "dev-env")
|
|
check not isLocalAddress(address)
|
|
|
|
test "Get default port for plain UTCP":
|
|
let port = getDefaultPort(UtcpPlain)
|
|
check port == UTCP_DEFAULT_PORT
|
|
|
|
test "Get default port for secure UTCP":
|
|
let port = getDefaultPort(UtcpSecure)
|
|
check port == UTCP_DEFAULT_PORT + 1
|
|
|
|
test "Validate valid address":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env")
|
|
let res = validateAddress(address)
|
|
check res.isOk
|
|
|
|
test "Validate address with empty host":
|
|
let address = UTCPAddress(
|
|
scheme: UtcpPlain,
|
|
host: "",
|
|
resourceType: Nippel,
|
|
resourceName: "dev-env"
|
|
)
|
|
let res = validateAddress(address)
|
|
check not res.isOk
|
|
|
|
test "Validate address with empty resource name":
|
|
let address = UTCPAddress(
|
|
scheme: UtcpPlain,
|
|
host: "localhost",
|
|
resourceType: Nippel,
|
|
resourceName: ""
|
|
)
|
|
let res = validateAddress(address)
|
|
check not res.isOk
|
|
|
|
suite "UTCP Resource Types":
|
|
test "Create Nippel address":
|
|
let address = newUTCPAddress("localhost", Nippel, "dev-env")
|
|
check address.resourceType == Nippel
|
|
|
|
test "Create Nexter address":
|
|
let address = newUTCPAddress("localhost", Nexter, "web-server")
|
|
check address.resourceType == Nexter
|
|
|
|
test "Create Package address":
|
|
let address = newUTCPAddress("localhost", Package, "nginx")
|
|
check address.resourceType == Package
|
|
|
|
test "Create System address":
|
|
let address = newUTCPAddress("localhost", System, "config")
|
|
check address.resourceType == System
|
|
|
|
test "Create Tool address":
|
|
let address = newUTCPAddress("localhost", Tool, "nexus")
|
|
check address.resourceType == Tool
|
|
|
|
test "Create Agent address":
|
|
let address = newUTCPAddress("localhost", Agent, "n8n-workflow")
|
|
check address.resourceType == Agent
|
|
|
|
test "Create LLM address":
|
|
let address = newUTCPAddress("localhost", LLM, "llama2")
|
|
check address.resourceType == LLM
|