~bigbes/tarantool

tarantool-protobuf

ref: fde45f1ef7af07069489ba49087d926d76511721 tarantool-protobuf/cmd/conformance-runner.lua -rw-r--r-- 2.9 KiB
fde45f1e — Eugene Blikh docs: track protobuf editions support as a deferred non-goal 3 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env tarantool
--
-- protoc-gen-tarantool / pb runtime conformance test runner.
--
-- Speaks the Google protobuf conformance protocol on stdin/stdout: each
-- request and response is a little-endian uint32 length followed by a
-- `conformance.ConformanceRequest` / `conformance.ConformanceResponse`
-- serialized as protobuf. Loops until EOF.
--
-- Run against the canonical Google conformance binary like so:
--
--     conformance_test_runner --enforce_recommended \
--         tarantool cmd/conformance-runner.lua
--
-- LUA_PATH must let this script find `pb`, the generated modules, and
-- the conformance core module under `cmd/`:
--
--     LUA_PATH="./runtime/?/init.lua;./runtime/?.lua;\
--               ./examples/expected/?.lua;./examples/expected/?/init.lua;\
--               ./cmd/?.lua;;"

-- Make the script self-contained: derive package.path from this script's
-- own location instead of trusting LUA_PATH. `conformance_test_runner`
-- spawns the child with a stripped (or otherwise unhelpful) environment;
-- if we crash on the first require() the parent reads no reply and
-- reports the test as a timeout. Setting paths here avoids that.
local function script_dir()
    local src = debug.getinfo(1, 'S').source
    if src:sub(1, 1) == '@' then src = src:sub(2) end
    return src:match('^(.*/)[^/]+$') or './'
end
local SCRIPT_DIR = script_dir()
local REPO_ROOT  = SCRIPT_DIR .. '..'
package.path = table.concat({
    REPO_ROOT .. '/runtime/?/init.lua',
    REPO_ROOT .. '/runtime/?.lua',
    REPO_ROOT .. '/examples/expected/?.lua',
    REPO_ROOT .. '/examples/expected/?/init.lua',
    REPO_ROOT .. '/cmd/?.lua',
    REPO_ROOT .. '/cmd/?/init.lua',
    package.path,
}, ';')

local core = require('cmd.conformance.core')

-- When invoked by conformance_test_runner the child's stdin is a pipe.
-- Default C-stdio buffering can hold the request bytes inside libc until
-- BUFSIZ-aligned data arrives, which never happens because the parent is
-- waiting for our reply first. Disable input buffering so io.stdin:read(n)
-- returns as soon as `n` bytes are available; pair with unbuffered stdout
-- so we don't rely solely on per-write :flush().
io.stdin:setvbuf('no')
io.stdout:setvbuf('no')

local function read_n(n)
    local got = io.stdin:read(n)
    if got == nil or #got < n then return nil end
    return got
end

local function read_request_bytes()
    local hdr = read_n(4)
    if hdr == nil then return nil end
    local b1, b2, b3, b4 = hdr:byte(1, 4)
    return read_n(b1 + b2 * 256 + b3 * 65536 + b4 * 16777216)
end

local function write_response_bytes(payload)
    local n = #payload
    io.stdout:write(string.char(
        n % 256,
        math.floor(n / 256) % 256,
        math.floor(n / 65536) % 256,
        math.floor(n / 16777216) % 256))
    io.stdout:write(payload)
    io.stdout:flush()
end

while true do
    local req_bytes = read_request_bytes()
    if req_bytes == nil then break end
    write_response_bytes(core.handle_request(req_bytes))
end

os.exit(0)