docs: Formatting the code
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
module openrpc
|
||||
|
||||
import freeflowuniverse.herolib.core.code { Attribute, Struct, StructField, Type }
|
||||
import freeflowuniverse.herolib.core.code { Attribute, Struct, StructField }
|
||||
|
||||
const example_txt = "
|
||||
Example: Get pet example.
|
||||
@@ -40,7 +40,7 @@ const test_struct = Struct{
|
||||
fields: [
|
||||
StructField{
|
||||
name: 'TestField'
|
||||
typ: code.type_i32
|
||||
typ: code.type_i32
|
||||
attrs: [Attribute{
|
||||
name: 'example'
|
||||
arg: '21'
|
||||
|
||||
@@ -23,7 +23,7 @@ pub mut:
|
||||
pub fn new_unix_client(params UNIXClientParams) &UNIXClient {
|
||||
return &UNIXClient{
|
||||
socket_path: params.socket_path
|
||||
timeout: params.timeout
|
||||
timeout: params.timeout
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,11 +46,9 @@ pub fn (mut client UNIXClient) call(method string, params string) !string {
|
||||
response := jsonrpc.decode_response(response_json) or {
|
||||
return error('Failed to decode response: ${err}')
|
||||
}
|
||||
|
||||
|
||||
// Validate response
|
||||
response.validate() or {
|
||||
return error('Invalid response: ${err}')
|
||||
}
|
||||
response.validate() or { return error('Invalid response: ${err}') }
|
||||
|
||||
// Check ID matches
|
||||
if response.id != request.id {
|
||||
@@ -73,46 +71,40 @@ fn (mut client UNIXClient) send_request(request string) !string {
|
||||
mut conn := unix.connect_stream(client.socket_path) or {
|
||||
return error('Failed to connect to Unix socket at ${client.socket_path}: ${err}')
|
||||
}
|
||||
|
||||
|
||||
defer {
|
||||
conn.close() or { console.print_stderr('Error closing connection: ${err}') }
|
||||
}
|
||||
|
||||
|
||||
// Set timeout
|
||||
if client.timeout > 0 {
|
||||
conn.set_read_timeout(client.timeout * time.second)
|
||||
conn.set_write_timeout(client.timeout * time.second)
|
||||
}
|
||||
|
||||
|
||||
// Send request
|
||||
console.print_debug('Sending request: ${request}')
|
||||
|
||||
conn.write_string(request) or {
|
||||
return error('Failed to send request: ${err}')
|
||||
}
|
||||
|
||||
|
||||
conn.write_string(request) or { return error('Failed to send request: ${err}') }
|
||||
|
||||
// Read response
|
||||
mut buffer := []u8{len: 4096}
|
||||
bytes_read := conn.read(mut buffer) or {
|
||||
return error('Failed to read response: ${err}')
|
||||
}
|
||||
|
||||
bytes_read := conn.read(mut buffer) or { return error('Failed to read response: ${err}') }
|
||||
|
||||
if bytes_read == 0 {
|
||||
return error('No response received from server')
|
||||
}
|
||||
|
||||
|
||||
response := buffer[..bytes_read].bytestr()
|
||||
console.print_debug('Received response: ${response}')
|
||||
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
// ping sends a simple ping to test connectivity
|
||||
pub fn (mut client UNIXClient) ping() !bool {
|
||||
// Try to discover the specification as a connectivity test
|
||||
client.discover() or {
|
||||
return error('Ping failed: ${err}')
|
||||
}
|
||||
client.discover() or { return error('Ping failed: ${err}') }
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -41,53 +41,53 @@ fn (mut h TestHandler) handle(req jsonrpc.Request) !jsonrpc.Response {
|
||||
fn test_unix_client_basic() {
|
||||
// This test requires a running server, so it's more of an integration test
|
||||
// In practice, you would start a server in a separate goroutine or process
|
||||
|
||||
|
||||
mut client := new_unix_client(
|
||||
socket_path: '/tmp/test_heromodels'
|
||||
timeout: 5
|
||||
timeout: 5
|
||||
)
|
||||
|
||||
|
||||
// Test string-based call
|
||||
result := client.call('test.echo', '{"message": "hello"}') or {
|
||||
println('Expected error since no server is running: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
println('Echo result: ${result}')
|
||||
}
|
||||
|
||||
fn test_unix_client_typed() {
|
||||
mut client := new_unix_client(
|
||||
socket_path: '/tmp/test_heromodels'
|
||||
timeout: 5
|
||||
timeout: 5
|
||||
)
|
||||
|
||||
|
||||
// Test typed call
|
||||
params := TestParams{
|
||||
name: 'test'
|
||||
name: 'test'
|
||||
value: 42
|
||||
}
|
||||
|
||||
|
||||
result := client.call_generic[TestParams, TestResult]('test.process', params) or {
|
||||
println('Expected error since no server is running: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
println('Typed result: ${result}')
|
||||
}
|
||||
|
||||
fn test_unix_client_discover() {
|
||||
mut client := new_unix_client(
|
||||
socket_path: '/tmp/test_heromodels'
|
||||
timeout: 5
|
||||
timeout: 5
|
||||
)
|
||||
|
||||
|
||||
// Test discovery
|
||||
spec := client.discover() or {
|
||||
println('Expected error since no server is running: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
println('OpenRPC spec version: ${spec.openrpc}')
|
||||
println('Info title: ${spec.info.title}')
|
||||
}
|
||||
@@ -95,81 +95,77 @@ fn test_unix_client_discover() {
|
||||
fn test_unix_client_ping() {
|
||||
mut client := new_unix_client(
|
||||
socket_path: '/tmp/test_heromodels'
|
||||
timeout: 5
|
||||
timeout: 5
|
||||
)
|
||||
|
||||
|
||||
// Test ping
|
||||
is_alive := client.ping() or {
|
||||
println('Expected error since no server is running: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
println('Server is alive: ${is_alive}')
|
||||
}
|
||||
|
||||
// Integration test that demonstrates full client-server interaction
|
||||
fn test_full_integration() {
|
||||
socket_path := '/tmp/test_heromodels_integration'
|
||||
|
||||
|
||||
// Create a test OpenRPC specification
|
||||
mut spec := OpenRPC{
|
||||
openrpc: '1.3.0'
|
||||
info: Info{
|
||||
title: 'Test API'
|
||||
info: Info{
|
||||
title: 'Test API'
|
||||
version: '1.0.0'
|
||||
}
|
||||
methods: [
|
||||
Method{
|
||||
name: 'test.echo'
|
||||
name: 'test.echo'
|
||||
params: []
|
||||
result: ContentDescriptor{
|
||||
name: 'result'
|
||||
name: 'result'
|
||||
schema: jsonschema.Schema{}
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
// Create handler
|
||||
mut test_handler := TestHandler{}
|
||||
handler := Handler{
|
||||
specification: spec
|
||||
handler: test_handler
|
||||
handler: test_handler
|
||||
}
|
||||
|
||||
|
||||
// Start server in background
|
||||
mut server := new_unix_server(handler, socket_path: socket_path) or {
|
||||
println('Failed to create server: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Start server in a separate thread
|
||||
spawn fn [mut server] () {
|
||||
server.start() or {
|
||||
println('Server error: ${err}')
|
||||
}
|
||||
server.start() or { println('Server error: ${err}') }
|
||||
}()
|
||||
|
||||
|
||||
// Give server time to start
|
||||
// time.sleep(100 * time.millisecond)
|
||||
|
||||
|
||||
// Create client and test
|
||||
mut client := new_unix_client(
|
||||
socket_path: socket_path
|
||||
timeout: 5
|
||||
timeout: 5
|
||||
)
|
||||
|
||||
|
||||
// Test the connection
|
||||
result := client.call('test.echo', '{"test": "data"}') or {
|
||||
println('Client call failed: ${err}')
|
||||
server.close() or {}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
println('Integration test result: ${result}')
|
||||
|
||||
|
||||
// Clean up
|
||||
server.close() or {
|
||||
println('Failed to close server: ${err}')
|
||||
}
|
||||
server.close() or { println('Failed to close server: ${err}') }
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ pub fn decode_json_any(data string) !Any {
|
||||
|
||||
pub fn decode_json_string(data string) !string {
|
||||
mut o := decode(data)!
|
||||
return json.encode(o)
|
||||
return json.encode(o)
|
||||
}
|
||||
|
||||
pub fn decode(data string) !OpenRPC {
|
||||
|
||||
@@ -13,5 +13,6 @@ fn test_decode() ! {
|
||||
content := doc_file.read()!
|
||||
object := json.decode(OpenRPC, content)!
|
||||
assert object.openrpc == '1.0.0-rc1'
|
||||
assert object.methods.map(it.name) == ['list_pets', 'create_pet', 'get_pet', 'update_pet', 'delete_pet']
|
||||
assert object.methods.map(it.name) == ['list_pets', 'create_pet', 'get_pet', 'update_pet',
|
||||
'delete_pet']
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module openrpc
|
||||
|
||||
import json
|
||||
import x.json2 { Any }
|
||||
import x.json2
|
||||
|
||||
// encode encodes an OpenRPC document struct into json string.
|
||||
// eliminates undefined variable by calling prune on the initial encoding.
|
||||
|
||||
@@ -8,7 +8,7 @@ const blank_openrpc = '{"openrpc": "1.0.0","info": {"version": "1.0.0"},"methods
|
||||
// test if encode can correctly encode a blank OpenRPC
|
||||
fn test_encode_blank() ! {
|
||||
doc := OpenRPC{
|
||||
info: Info{
|
||||
info: Info{
|
||||
title: ''
|
||||
version: '1.0.0'
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@ pub fn new(params Params) !OpenRPC {
|
||||
}
|
||||
|
||||
text := if params.path != '' {
|
||||
os.read_file(params.path) or { return error('Could not read openrpc spec file at ${params.path}: ${err}') }
|
||||
os.read_file(params.path) or {
|
||||
return error('Could not read openrpc spec file at ${params.path}: ${err}')
|
||||
}
|
||||
} else {
|
||||
params.text
|
||||
}
|
||||
|
||||
@@ -3,14 +3,11 @@ module openrpc
|
||||
import os
|
||||
import json
|
||||
|
||||
|
||||
//path to openrpc.json file
|
||||
// path to openrpc.json file
|
||||
pub fn new_handler(openrpc_path string) !Handler {
|
||||
|
||||
mut openrpc_handler := openrpc.Handler {
|
||||
mut openrpc_handler := Handler{
|
||||
specification: new(path: openrpc_path)!
|
||||
}
|
||||
|
||||
return openrpc_handler
|
||||
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ import freeflowuniverse.herolib.schemas.jsonrpc
|
||||
|
||||
pub struct UNIXServer {
|
||||
pub mut:
|
||||
listener &unix.StreamListener
|
||||
listener &unix.StreamListener
|
||||
socket_path string
|
||||
handler Handler @[required]
|
||||
handler Handler @[required]
|
||||
}
|
||||
|
||||
@[params]
|
||||
@@ -30,19 +30,19 @@ pub fn new_unix_server(handler Handler, params UNIXServerParams) !&UNIXServer {
|
||||
if os.exists(params.socket_path) {
|
||||
os.rm(params.socket_path)!
|
||||
}
|
||||
|
||||
|
||||
listener := unix.listen_stream(params.socket_path, unix.ListenOptions{})!
|
||||
|
||||
|
||||
return &UNIXServer{
|
||||
listener: listener
|
||||
handler: handler
|
||||
listener: listener
|
||||
handler: handler
|
||||
socket_path: params.socket_path
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut server UNIXServer) start() ! {
|
||||
console.print_header('Starting HeroModels OpenRPC Server on ${server.socket_path}')
|
||||
|
||||
|
||||
for {
|
||||
mut conn := server.listener.accept()!
|
||||
spawn server.handle_connection(mut conn)
|
||||
@@ -60,7 +60,7 @@ fn (mut server UNIXServer) handle_connection(mut conn unix.StreamConn) {
|
||||
defer {
|
||||
conn.close() or { console.print_stderr('Error closing connection: ${err}') }
|
||||
}
|
||||
|
||||
|
||||
for {
|
||||
// Read JSON-RPC request
|
||||
mut buffer := []u8{len: 4096}
|
||||
@@ -68,11 +68,11 @@ fn (mut server UNIXServer) handle_connection(mut conn unix.StreamConn) {
|
||||
console.print_debug('Connection closed or error reading: ${err}')
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
if bytes_read == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
request_data := buffer[..bytes_read].bytestr()
|
||||
console.print_debug('Received request: ${request_data}')
|
||||
|
||||
@@ -109,4 +109,4 @@ fn (mut server UNIXServer) process_request(request_data string) ?string {
|
||||
return jsonrpc.new_error(request.id, jsonrpc.internal_error).encode()
|
||||
}
|
||||
return response.encode()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ pub fn test_new_unix_server() ! {
|
||||
mut server := new_unix_server(handler)!
|
||||
|
||||
defer {
|
||||
server.close() or {panic(err)}
|
||||
server.close() or { panic(err) }
|
||||
}
|
||||
|
||||
spawn server.start()
|
||||
@@ -49,49 +49,48 @@ pub fn test_unix_server_handle_connection() ! {
|
||||
specification: new(path: openrpc_path)!
|
||||
}
|
||||
mut server := new_unix_server(handler)!
|
||||
|
||||
|
||||
// Start server in background
|
||||
spawn server.start()
|
||||
|
||||
|
||||
// Give server time to start
|
||||
time.sleep(50 * time.millisecond)
|
||||
|
||||
|
||||
// Connect to the server
|
||||
mut conn := unix.connect_stream(server.socket_path)!
|
||||
|
||||
defer {
|
||||
conn.close() or {panic(err)}
|
||||
server.close() or {panic(err)}
|
||||
conn.close() or { panic(err) }
|
||||
server.close() or { panic(err) }
|
||||
}
|
||||
println('Connected to server at ${server.socket_path}')
|
||||
|
||||
// Test 1: Send rpc.discover request
|
||||
discover_request := jsonrpc.new_request('rpc.discover', '')
|
||||
request_json := discover_request.encode()
|
||||
|
||||
|
||||
// Send the request
|
||||
conn.write_string(request_json)!
|
||||
|
||||
|
||||
// Read the response
|
||||
mut buffer := []u8{len: 4096}
|
||||
bytes_read := conn.read(mut buffer)!
|
||||
response_data := buffer[..bytes_read].bytestr()
|
||||
|
||||
|
||||
// Parse and validate response
|
||||
response := jsonrpc.decode_response(response_data)!
|
||||
assert response.id == discover_request.id
|
||||
assert response.is_result()
|
||||
assert !response.is_error()
|
||||
|
||||
|
||||
// Validate that the result contains OpenRPC specification
|
||||
result := response.result()!
|
||||
assert result.len > 0
|
||||
|
||||
|
||||
// Test 2: Send invalid JSON request
|
||||
invalid_request := '{"invalid": "json"}'
|
||||
conn.write_string(invalid_request)!
|
||||
|
||||
|
||||
// Set a short read timeout to test no response behavior
|
||||
conn.set_read_timeout(10 * time.millisecond)
|
||||
|
||||
@@ -107,17 +106,17 @@ pub fn test_unix_server_handle_connection() ! {
|
||||
// Test 3: Send request with non-existent method
|
||||
nonexistent_request := jsonrpc.new_request('nonexistent.method', '{}')
|
||||
nonexistent_json := nonexistent_request.encode()
|
||||
|
||||
|
||||
conn.write_string(nonexistent_json)!
|
||||
|
||||
|
||||
// Read method not found response
|
||||
bytes_read3 := conn.read(mut buffer)!
|
||||
method_error_data := buffer[..bytes_read3].bytestr()
|
||||
|
||||
|
||||
method_error_response := jsonrpc.decode_response(method_error_data)!
|
||||
assert method_error_response.is_error()
|
||||
assert method_error_response.id == nonexistent_request.id
|
||||
|
||||
|
||||
if error_obj := method_error_response.error() {
|
||||
assert error_obj.code == jsonrpc.method_not_found.code
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user