Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.gd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
- name: Run tests
run: cd trimsock.gd && sh/test.sh
perf:
needs:
- test
strategy:
fail-fast: false
matrix:
Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/ci.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,14 @@ jobs:
run: cd trimsock.js && bun install
- name: Test
run: cd trimsock.js && bun test

perf:
runs-on: ubuntu-latest
needs:
- test
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- name: Install
run: cd trimsock.js && bun install
- name: Test
run: cd trimsock.js && bun perf
22 changes: 11 additions & 11 deletions trimsock.gd/addons/trimsock.gd/command.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class_name TrimsockCommand
class Chunk:
var text: String
var is_quoted: bool

static func quoted(p_text: String) -> Chunk:
var chunk := Chunk.new()
chunk.is_quoted = true
Expand All @@ -16,7 +16,7 @@ class Chunk:
chunk.is_quoted = false
chunk.text = p_text
return chunk

static func of_text(p_text: String) -> Chunk:
var chunk := Chunk.new()
chunk.is_quoted = p_text.contains(" ")
Expand Down Expand Up @@ -65,7 +65,7 @@ static func simple(name: String, text: String = "") -> TrimsockCommand:
command.name = name
if text:
command.chunks.append(Chunk.of_text(text))

return command

static func request(name: String, exchange_id: String = "") -> TrimsockCommand:
Expand Down Expand Up @@ -105,20 +105,20 @@ static func stream_finish(name: String, exchange_id: String = "") -> TrimsockCom

static func error_from(command: TrimsockCommand, name: String, data) -> TrimsockCommand:
var result := TrimsockCommand.new()

if not result.is_simple():
result.name = ""
result.type = Type.ERROR_RESPONSE
result.exchange_id = command.exchange_id
else:
result.name = name

if typeof(data) == TYPE_ARRAY:
for param in data:
result.params.append(str(param))
else:
result.chunks.append(Chunk.of_text(str(data)))

return result

static func unescape(what: String) -> String:
Expand Down Expand Up @@ -285,7 +285,7 @@ func serialize_to_stream(out: StreamPeer) -> void:
if is_empty() and not is_raw:
out.put_u8(_ord("\n"))
return

# Space after name
out.put_u8(_ord(" "))

Expand All @@ -308,11 +308,11 @@ func serialize_to_stream(out: StreamPeer) -> void:
elif not kv_pairs.is_empty() or not kv_map.is_empty() or not params.is_empty():
# Fall back to params if no chunks
var tokens := PackedStringArray()

# Print params first
for param in params:
tokens.append(_autoquoted_chunk(param))

# Print kv-params, either from `kv_pairs`, or `kv_map`
if not kv_pairs.is_empty():
for pair in kv_pairs:
Expand Down Expand Up @@ -340,10 +340,10 @@ func equals(what) -> bool:
if not command.name == name or \
not command.type == type:
return false

if not is_simple() and exchange_id != command.exchange_id:
return false

if not is_raw:
return text == command.text
else:
Expand Down
2 changes: 1 addition & 1 deletion trimsock.gd/addons/trimsock.gd/plugin.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
name="trimsock.gd"
description="Godot implementation of the trimsock protocol"
author="Tamás Gálffy"
version="0.13.0"
version="0.13.1"
script="trimsock.gd"
8 changes: 4 additions & 4 deletions trimsock.gd/addons/trimsock.gd/reader.gd
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ func _pop() -> TrimsockCommand:
var data_size := int(_queued_raw.text)
if not _line_reader.has_data(data_size):
return null

_queued_raw.raw = _line_reader.read_data(data_size)
_queued_raw.text = ""
_queued_raw.chunks.clear()

var result := _queued_raw
_queued_raw = null
return result
Expand All @@ -36,13 +36,13 @@ func _pop() -> TrimsockCommand:
var line := _line_reader.read_text()
if not line:
return null

var command := _line_parser.parse(line)
if command.is_raw:
# Command is raw, we'll keep it in the queue until we read the binary
# data for it
_queued_raw = command

# Try getting it immediately, in case we already have the data in buffer
return _pop()

Expand Down
27 changes: 27 additions & 0 deletions trimsock.gd/tests/command.perf.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
extends VestTest

var commands := [
TrimsockCommand.request("whereami"),
TrimsockCommand.request("session/set-game-id").with_params(["RghrnyJK0mUA7cW05fCKo"]),
TrimsockCommand.request("lobby/create").with_params([ "noray://example.com:8890/Q9VKjXiAlwVK" ]).with_kv_map({ "name": "Cool Lobby" }),
TrimsockCommand.request("lobby/lock").with_text("YuDqpQovXvpc"),
TrimsockCommand.request("lobby/delete").with_text("YuDqpQovXvpc")
] as Array[TrimsockCommand]

func get_suite_name():
return "TrimsockCommand"

func suite():
test("Serialization", func():
var idx := 0
var peer := StreamPeerBuffer.new()

benchmark("Predefined commands", func(__):
commands[idx].serialize_to_stream(peer)
peer.data_array.clear()
idx = (idx + 1) % commands.size()
)\
.with_duration(4.0)\
.with_batch_size(512)\
.run()
)
1 change: 1 addition & 0 deletions trimsock.gd/tests/command.perf.gd.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://dskylbpiwu1nd
12 changes: 6 additions & 6 deletions trimsock.gd/tests/command.test.gd
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extends VestTest

func get_suite_name():
return "Command"
return "TrimsockCommand"

func suite():
define("serialize", func():
Expand All @@ -11,31 +11,31 @@ func suite():
check_serialized("raw", TrimsockCommand.simple("command").as_raw(), "\rcommand 0\n\n")
check_serialized("raw quoted", TrimsockCommand.simple("command name").as_raw(), "\r\"command name\" 0\n\n")
)

define("request-response", func():
check_serialized("request", TrimsockCommand.request("command", "1234"), "command?1234\n")
check_serialized("success", TrimsockCommand.success_response("command", "1234"), "command.1234\n")
check_serialized("error", TrimsockCommand.error_response("command", "1234"), "command!1234\n")
check_serialized("stream", TrimsockCommand.stream_chunk("command", "1234"), "command|1234\n")

check_serialized("success without name", TrimsockCommand.success_response("", "1234"), ".1234\n")
check_serialized("error without name", TrimsockCommand.error_response("", "1234"), "!1234\n")
check_serialized("stream without name", TrimsockCommand.stream_chunk("", "1234"), "|1234\n")
)

define("multiparam", func():
check_serialized("simple params", TrimsockCommand.simple("command").with_params(["foo", "bar"]), "command foo bar\n")
check_serialized("quote params", TrimsockCommand.simple("command").with_params(["foo bar", "quix"]), "command \"foo bar\" quix\n")
)

define("kv-params", func():
check_serialized("simple", TrimsockCommand.simple("command").with_kv_pairs([TrimsockCommand.pair_of("foo", "bar")]), "command foo=bar\n")
check_serialized("quoted", TrimsockCommand.simple("command").with_kv_pairs([TrimsockCommand.pair_of("foo bar", "quix baz")]), "command \"foo bar\"=\"quix baz\"\n")
check_serialized("key-quoted", TrimsockCommand.simple("command").with_kv_pairs([TrimsockCommand.pair_of("foo bar", "quix")]), "command \"foo bar\"=quix\n")
check_serialized("value-quoted", TrimsockCommand.simple("command").with_kv_pairs([TrimsockCommand.pair_of("foo", "quix baz")]), "command foo=\"quix baz\"\n")
check_serialized("with params", TrimsockCommand.simple("command").with_kv_pairs([TrimsockCommand.pair_of("foo", "bar")]).with_params(["foo", "bar"]), "command foo bar foo=bar\n")
)

define("kv-map", func():
check_serialized("simple", TrimsockCommand.simple("command").with_kv_map({ "foo": "bar" }), "command foo=bar\n")
check_serialized("quoted", TrimsockCommand.simple("command").with_kv_map({ "foo bar": "quix baz"}), "command \"foo bar\"=\"quix baz\"\n")
Expand Down
38 changes: 19 additions & 19 deletions trimsock.gd/tests/reactor.test.gd
Original file line number Diff line number Diff line change
Expand Up @@ -20,62 +20,62 @@ func suite():
var handler := func(cmd, xchg):
commands.append(cmd)
reactor.on("command", handler)

reactor.ingest_text(some_source, "command foo\n")
reactor.poll()

expect_not_empty(commands)
)

test("should handle unknown", func():
var commands := []
var handler := func(cmd, xchg):
commands.append(cmd)
reactor.send(some_source, TrimsockCommand.simple("error"))
reactor.on_unknown(handler)

reactor.ingest_text(some_source, "unknown foo\n")
reactor.poll()

expect_not_empty(commands, "No commands handled!")
expect_not_empty(reactor.outbox, "No commands sent!")
)

test("should handle unknown by default", func():
# Flimsy test: it should ensure that the default handler is not broken
# The test only breaks when ran in debug, but might catch an issue or
# two simply by being here

reactor.ingest_text(some_source, "unknown foo\n")
reactor.poll()

ok()
)

test("should route to exchange", func():
var commands := []
var handler := func(cmd: TrimsockCommand, xchg: TrimsockExchange):
commands.append(cmd)
while xchg.is_open():
commands.append(await xchg.read())
reactor.on("command", handler)

reactor.ingest_text(some_source, "command|1 foo\ncommand|1 bar\n")
reactor.poll()

expect_equal(commands.size(), 2)
)

test("should reply with handler return value", func():
var commands := []
var handler := func(cmd, xchg):
commands.append(cmd)
return TrimsockCommand.simple("response")
reactor.on("command", handler)

reactor.ingest_text(some_source, "command foo\n")
reactor.poll()

expect_equal(commands.size(), 1)
expect_equal(reactor.outbox[0].target, some_source)
expect_equal(reactor.outbox[0].command, TrimsockCommand.simple("response"))
Expand All @@ -84,18 +84,18 @@ func suite():
test("should fill ID on request", func():
var command := TrimsockCommand.simple("request")
command.exchange_id = ""

reactor.request(some_source, command)

expect(reactor.outbox[0].command.is_request(), "Command was not a request!")
expect_not_empty(reactor.outbox[0].command.exchange_id, "Request ID was empty!")
)
test("should fill ID on stream", func():
test("should fill ID on stream", func():
var command := TrimsockCommand.simple("stream", "foo")
command.exchange_id = ""

reactor.stream(some_source, command)

expect(reactor.outbox[0].command.is_stream(), "Command was not a stream!")
expect_not_empty(reactor.outbox[0].command.exchange_id, "Stream ID was empty!")
)
28 changes: 28 additions & 0 deletions trimsock.gd/tests/reader.perf.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
extends VestTest

const COMMANDS := [
"whereami?\n",
"session/set-game-id RghrnyJK0mUA7cW05fCKo\n",
"lobby/create? noray://example.com:8890/Q9VKjXiAlwVK name=\"Cool Lobby\"\n",
"lobby/lock? YuDqpQovXvpc",
"lobby/delete? YuDqpQovXvpc"
]

func get_suite_name():
return "TrimsockReader"

func suite():
var reader := TrimsockReader.new()
var idx := 0

test("Parsing", func():
benchmark("Predefined commands", func(__):
reader.ingest_text(COMMANDS[idx])
while reader.read() != null:
pass
idx = (idx + 1) % COMMANDS.size()
)\
.with_duration(4.)\
.with_batch_size(128)\
.run()
)
1 change: 1 addition & 0 deletions trimsock.gd/tests/reader.perf.gd.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://brvun1xvnsvqx
4 changes: 2 additions & 2 deletions trimsock.gd/tests/reader.test.gd
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
extends VestTest

func get_suite_name():
return "Reader"
return "TrimsockReader"

var reader: TrimsockReader

func suite():
on_case_begin.connect(func(__):
reader = TrimsockReader.new()
)

test("should read raw message", func():
ok()
reader.ingest_text("\rcommand 4\na\ncd\n")
Expand Down
Binary file modified trimsock.js/bun.lockb
Binary file not shown.
5 changes: 3 additions & 2 deletions trimsock.js/package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"name": "trimsock",
"private": true,
"version": "0.18.1",
"version": "0.18.2",
"type": "module",
"scripts": {
"docs": "typedoc",
"format": "bun --filter '*' check --write --unsafe",
"fmt": "bun format",
"build": "bun --filter '*' build"
"build": "bun --filter '*' build",
"perf": "bun --filter '*' perf"
},
"workspaces": [
"packages/*",
Expand Down
2 changes: 1 addition & 1 deletion trimsock.js/packages/trimsock-bun/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@foxssake/trimsock-bun",
"version": "0.18.1",
"version": "0.18.2",
"module": "dist/index.js",
"type": "module",
"author": "Tamás Gálffy",
Expand Down
Loading
Loading