defmodule GitGudWeb.Protos.RunnerWireTest do
@moduledoc """
The runner messages, checked against bytes laid out the way
forgejo-runner lays them out (code.forgejo.org/forgejo/actions-proto-def,
runner/v1/messages.proto) rather than round-tripped through our own
module — which is how mismatched field numbers went unnoticed: a runner
read our `version` as its labels and our `token` as its name.
"""
use ExUnit.Case, async: true
import Bitwise
alias Runner.V1.DeclareResponse
alias Runner.V1.RegisterRequest
alias Runner.V1.Runner, as: RunnerMsg
alias Runner.V1.TaskNeed
# One length-delimited field: key = field number << 3 | wire type 2.
defp str(field, value), do: <<field <<< 3 ||| 2>> <> varint(byte_size(value)) <> value
defp varint(n) when n < 128, do: <<n>>
defp varint(n), do: <<(n &&& 0x7F) ||| 0x80>> <> varint(n >>> 7)
test "RegisterRequest decodes what a runner sends" do
# name=1 token=2 agent_labels=3 custom_labels=4 version=5 labels=6
bytes =
str(1, "win-ltsc") <>
str(2, "reg-token") <>
str(3, "old-agent") <>
str(4, "old-custom") <>
str(5, "v13.2.0") <> str(6, "windows:host") <> str(6, "windows-latest:host")
req = RegisterRequest.decode(bytes)
assert req.name == "win-ltsc"
assert req.token == "reg-token"
assert req.version == "v13.2.0"
assert req.labels == ["windows:host", "windows-latest:host"]
assert req.agent_labels == ["old-agent"]
assert req.custom_labels == ["old-custom"]
end
test "Runner encodes where a runner looks" do
bytes =
RunnerMsg.encode(%RunnerMsg{
id: 7,
uuid: "u",
token: "secret",
name: "win-ltsc",
version: "v13.2.0",
labels: ["windows:host"]
})
# token=3 name=4 version=8 labels=9
assert :binary.match(bytes, str(3, "secret")) != :nomatch
assert :binary.match(bytes, str(4, "win-ltsc")) != :nomatch
assert :binary.match(bytes, str(8, "v13.2.0")) != :nomatch
assert :binary.match(bytes, str(9, "windows:host")) != :nomatch
end
test "a DeclareResponse reads back with the runner's own numbering" do
bytes =
DeclareResponse.encode(%DeclareResponse{
runner: %RunnerMsg{name: "win-ltsc", version: "v13.2.0", labels: ["windows:host"]}
})
# Field 1 is the embedded Runner; decode it by upstream numbers.
<<0x0A, rest::binary>> = bytes
{len, runner_bytes} = decode_varint(rest)
runner = binary_part(runner_bytes, 0, len)
assert :binary.match(runner, str(4, "win-ltsc")) != :nomatch
assert :binary.match(runner, str(8, "v13.2.0")) != :nomatch
assert :binary.match(runner, str(9, "windows:host")) != :nomatch
end
test "TaskNeed: outputs=1, result=2" do
bytes = TaskNeed.encode(%TaskNeed{result: :RESULT_SUCCESS, outputs: %{}})
# result is a varint (wire type 0) on field 2: key 0x10, value 1.
assert bytes == <<0x10, 0x01>>
end
test "TaskNeed: outputs ride on field 1 as map entries, result on field 2" do
bytes =
%TaskNeed{result: :RESULT_FAILURE, outputs: %{"x" => "1"}}
|> TaskNeed.encode()
|> IO.iodata_to_binary()
entry = str(1, "x") <> str(2, "1")
assert bytes == str(1, entry) <> <<0x10, 0x02>>
assert %TaskNeed{result: :RESULT_FAILURE, outputs: %{"x" => "1"}} = TaskNeed.decode(bytes)
end
defp decode_varint(<<0::1, n::7, rest::binary>>), do: {n, rest}
defp decode_varint(<<1::1, n::7, rest::binary>>) do
{high, rest} = decode_varint(rest)
{n + (high <<< 7), rest}
end
end
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
3.5 KiB · text
History
b868907