Skip to content

Commit 08a6842

Browse files
committed
annotations and simple tests
1 parent 6067ad8 commit 08a6842

7 files changed

Lines changed: 362 additions & 3 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Setup Tarantool Test Environment
2+
description: 'Sets up Tarantool and tt'
3+
4+
inputs:
5+
tarantool-version:
6+
description: 'Tarantool version to install'
7+
required: true
8+
default: '2.11'
9+
10+
runs:
11+
using: "composite"
12+
steps:
13+
- name: setup tarantool
14+
uses: tarantool/setup-tarantool@v3
15+
with:
16+
tarantool-version: ${{ inputs.tarantool-version }}
17+
- name: add tarantool/modules repo
18+
shell: bash
19+
run: |
20+
os=$(. /etc/os-release && echo $ID)
21+
dist=$(. /etc/os-release && echo $VERSION_CODENAME)
22+
curl -L "https://download.tarantool.org/tarantool/modules/gpgkey" | sudo apt-key add -
23+
apt_source_path="/etc/apt/sources.list.d/tarantool.list"
24+
echo "deb https://download.tarantool.org/tarantool/modules/${os}/ ${dist} main" | sudo tee ${apt_source_path}
25+
- name: install tt
26+
shell: bash
27+
run: sudo apt-get update && sudo apt-get install -y tt
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Setup Tarantool Test Environment
2+
description: 'Sets up Tarantool and dependencies for testing'
3+
4+
inputs:
5+
tarantool-version:
6+
description: 'Tarantool version to install'
7+
required: true
8+
9+
runs:
10+
using: "composite"
11+
steps:
12+
- name: setup tarantool
13+
uses: ./.github/actions/setup-tarantool
14+
with:
15+
tarantool-version: ${{ inputs.tarantool-version }}
16+
- name: install luacov-coveralls 0.2.3
17+
shell: bash
18+
run: tt rocks install --server https://luarocks.org luacov-coveralls 0.2.3
19+
- name: install luacov-console 1.2.0
20+
shell: bash
21+
run: tt rocks --server http://moonlibs.github.io/rocks install luacov-console 1.2.0
22+
- name: install luatest scm-1
23+
shell: bash
24+
run: tt rocks install luatest 1.1.0

.github/workflows/lint.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: Linting with luacheck
2+
3+
on:
4+
- push
5+
- pull_request
6+
7+
jobs:
8+
run-luacheck-linter:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
- uses: ./.github/actions/setup-tarantool
13+
with:
14+
tarantool-version: '2.11'
15+
- name: install tarantool/luacheck and execute it
16+
run: tt rocks install luacheck && .rocks/bin/luacheck .
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: Create and push rockspec for moonlibs/connection
2+
3+
on:
4+
workflow_run:
5+
workflows:
6+
- "Linting with luacheck"
7+
- "Testing with unit tests"
8+
types:
9+
- completed
10+
push:
11+
tags:
12+
- '*'
13+
14+
env:
15+
ROCK_NAME: connection
16+
17+
jobs:
18+
pack-and-push-tagged-rockspec:
19+
runs-on: ubuntu-latest
20+
if: ${{ github.event.workflow_run.conclusion == 'success' }} && startsWith(github.ref, 'refs/tags/') }}
21+
steps:
22+
- uses: actions/checkout@v4
23+
- uses: ./.github/actions/setup-tarantool
24+
25+
# https://stackoverflow.com/questions/58177786/get-the-current-pushed-tag-in-github-actions
26+
- name: Set env
27+
run: echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
28+
29+
- run: tt rocks new_version --tag=${{ env.TAG }} ${{ env.ROCK_NAME }}-dev-1.rockspec ${{ env.TAG }} "git+https://github.com/${{ github.repository }}.git"
30+
- run: tt rocks install ${{ env.ROCK_NAME }}-${{ env.TAG }}-1.rockspec
31+
- run: tt rocks pack ${{ env.ROCK_NAME }}-${{ env.TAG }}-1.rockspec
32+
33+
- uses: unfor19/install-aws-cli-action@v1.0.3
34+
- run:
35+
|
36+
mkdir .build
37+
cp ${{ env.ROCK_NAME }}-dev-1.rockspec ${{ env.ROCK_NAME }}-${{ env.TAG }}-1.rockspec \
38+
.build/
39+
cp *.src.rock .build/
40+
- name: rebuild and publish s3 luarocks server
41+
env:
42+
AWS_ACCESS_KEY_ID: ${{ secrets.MOONLIBS_S3_ACCESS_KEY_ID }}
43+
AWS_SECRET_ACCESS_KEY: ${{ secrets.MOONLIBS_S3_SECRET_KEY}}
44+
AWS_EC2_METADATA_DISABLED: true
45+
run: |
46+
cd .build && \
47+
aws s3 sync s3://moonlibs/ ./ && \
48+
tt rocks admin make_manifest . && \
49+
aws s3 sync --acl public-read ./ s3://moonlibs/;
50+
- uses: "marvinpinto/action-automatic-releases@latest"
51+
with:
52+
repo_token: "${{ secrets.GITHUB_TOKEN }}"
53+
prerelease: false
54+
files: |
55+
README.md
56+
${{env.ROCK_NAME}}-dev-1.rockspec
57+
${{env.ROCK_NAME}}-${{env.TAG}}-1.rockspec
58+
${{env.ROCK_NAME}}-${{env.TAG}}-1.src.rock

.github/workflows/tests.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Testing with unit tests
2+
3+
on:
4+
- push
5+
- pull_request
6+
7+
jobs:
8+
run-unit-tests:
9+
runs-on: ubuntu-22.04
10+
strategy:
11+
matrix:
12+
version: ["1.10.15", "2.10.7", "2.11.2", "3.0.1"]
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: ./.github/actions/setup-test
16+
with:
17+
tarantool-version: ${{matrix.version}}
18+
- name: run tests
19+
run: luatest --no-capture --coverage -v
20+
- name: rename luacov.stats.out
21+
run: mv luacov.stats.out luacov.stats.out-${{matrix.version}}
22+
- uses: actions/upload-artifact@master
23+
with:
24+
name: luacov.stats.out-${{matrix.version}}
25+
path: luacov.stats.out-${{matrix.version}}
26+
27+
run-coverage-report:
28+
runs-on: ubuntu-latest
29+
needs: ["run-unit-tests"]
30+
steps:
31+
- uses: actions/checkout@v4
32+
- uses: ./.github/actions/setup-test
33+
with:
34+
tarantool-version: '2.11'
35+
- name: Download run artifacts
36+
uses: actions/download-artifact@v4
37+
with:
38+
pattern: luacov.stats.out-*
39+
merge-multiple: true
40+
- name: debug
41+
run: ls -la .
42+
- name: merge luacov.stats.out
43+
run: cat luacov.stats.out-* | >luacov.stats.out tarantool -e 'm={} for k in io.lines() do local vs=io.read():split(" ") vs[#vs]=nil local r = m[k] if r then for i, v in pairs(vs) do r[i]=r[i]+v end else m[k]=vs end end; for k, v in pairs(m) do print(k) print(table.concat(v, " ")) end'
44+
- name: prepare coverage report
45+
run: .rocks/bin/luacov-console . && .rocks/bin/luacov-console -s
46+
- name: publish coveralls report
47+
env:
48+
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
49+
run: .rocks/bin/luacov-coveralls -v

connection.lua

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ local S2S = {
6969
[CONNECTING] = 'CONNECTING',
7070
[CONNECTED] = 'CONNECTED',
7171
[RECONNECTING] = 'RECONNECTING',
72+
NOTCONNECTED = NOTCONNECTED,
73+
CONNECTED = CONNECTED,
74+
CONNECTING = CONNECTING,
75+
RECONNECTING = RECONNECTING,
7276
}
7377
M.S2S = S2S
7478

@@ -154,7 +158,6 @@ function M:_init(host, port, opt)
154158
self._gen = 0
155159

156160
self.wsize = 32
157-
local osz = self.wsize
158161
self.wbuf = ffi.new('struct iovec[?]', self.wsize)
159162

160163
self.wcur = 0
@@ -495,11 +498,10 @@ function M:connect()
495498
end, weak)
496499
end
497500

498-
function M:_wbuf_realloc( ... )
501+
function M:_wbuf_realloc()
499502
local old = self.wbuf
500503
local osz = self.wsize
501504
self.wsize = osz * 2
502-
local nsz = self.wsize
503505
self.wbuf = ffi.new('struct iovec[?]', self.wsize)
504506
C.memcpy(self.wbuf, old, self.wcur * ffi.sizeof(self.wbuf[0]))
505507
end

test/001_basic_test.lua

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
local t = require('luatest')
2+
local fiber = require('fiber')
3+
local json = require('json')
4+
local g = t.group('basic')
5+
6+
local username = 'guest'
7+
local password = ''
8+
9+
---@type luatest.server
10+
local server = t.Server:new({
11+
alias = 'server',
12+
box_cfg = {
13+
listen = '127.0.0.1:3301',
14+
},
15+
net_box_port = 3301,
16+
net_box_uri = '127.0.0.1:3301',
17+
})
18+
19+
g.before_all(function()
20+
server:start({wait_until_ready = true})
21+
end)
22+
23+
g.after_all(function()
24+
server:stop()
25+
end)
26+
27+
local connection = require 'connection'
28+
29+
function g.test_connect()
30+
---@type connection
31+
local cnn = connection:new(server.net_box.host, server.net_box.port)
32+
cnn.connwait:get(1)
33+
t.assert_equals(cnn.state, connection.S2S.CONNECTED, 'connection has been established')
34+
cnn:close()
35+
t.assert_equals(cnn.state, connection.S2S.NOTCONNECTED, 'connection has been closed')
36+
end
37+
38+
---@class connection.greeter: connection
39+
local greeter = require 'obj'.class({}, 'connection.greeter', connection)
40+
41+
function greeter:on_connect_io()
42+
self:super(greeter, 'on_connect_io')()
43+
self.stage = 'greeting'
44+
end
45+
46+
function greeter:on_greeting_read()
47+
local avail = self.avail
48+
local greeting_size = 128
49+
if avail < greeting_size then return end
50+
51+
local ffi = require 'ffi'
52+
local str = ffi.string(self.rbuf, greeting_size)
53+
self.avail = avail - greeting_size -- consume the greeting
54+
55+
local _, salt_b64 = unpack(string.split(str, '\n'))
56+
local digest = require 'digest'
57+
58+
local salt = digest.base64_decode(salt_b64):sub(1, 20)
59+
local step1 = digest.sha1(password)
60+
local step2 = digest.sha1(step1)
61+
local step3 = digest.sha1(salt .. step2)
62+
63+
local function xor(s1, s2, n)
64+
local r = table.new(n, 0)
65+
for i = 1, n do
66+
r[i] = string.char(bit.bxor(s1:byte(i), s2:byte(i)))
67+
end
68+
return table.concat(r, '')
69+
end
70+
71+
local scramble = xor(step1, step3, #salt)
72+
73+
-- now construct auth packet
74+
local msgpack = require('msgpack')
75+
local key = {
76+
REQUEST_TYPE = 0x00,
77+
SYNC = 0x01,
78+
TUPLE = 0x21,
79+
USER_NAME = 0x23,
80+
}
81+
local val = {
82+
AUTH = 0x07,
83+
}
84+
local hdr = {
85+
[key.REQUEST_TYPE] = val.AUTH,
86+
[key.SYNC] = 0x01,
87+
}
88+
local bdy = {
89+
[key.USER_NAME] = username,
90+
[key.TUPLE] = {'chap-sha1', scramble},
91+
}
92+
local buf = msgpack.encode(hdr) .. msgpack.encode(bdy)
93+
local size = msgpack.encode(#buf)
94+
local pkt = table.concat({
95+
string.char(0xce),
96+
-- prepend \0-bytes to buffer
97+
("\x00\x00\x00\x00"):sub(1, 4 - #size) .. size,
98+
buf
99+
},'')
100+
101+
self:push_write(pkt)
102+
self.stage = 'fetching_schema'
103+
self:flush()
104+
end
105+
106+
function greeter:on_fetching_schema_read(is_last)
107+
local msgpack = require('msgpack')
108+
109+
local ptr = self.rbuf
110+
local avail = tonumber(self.avail)
111+
local tail = ptr + avail
112+
113+
local sz
114+
sz, ptr = msgpack.decode(ptr, tonumber(tail-ptr))
115+
if sz == nil then
116+
-- not enough data
117+
return
118+
end
119+
self:log('D', 'size:%s', sz)
120+
121+
if avail < sz then
122+
-- not enough data
123+
self:log('D', 'not enough data, need %s, have %s', sz, avail)
124+
return
125+
end
126+
127+
local hdr
128+
hdr, ptr = msgpack.decode(ptr, tonumber(tail-ptr))
129+
if hdr == nil then
130+
-- not enough data
131+
return
132+
end
133+
self:log('D', 'hdr:%s', json.encode(hdr))
134+
135+
local bdy
136+
bdy, ptr = msgpack.decode(ptr, tonumber(tail-ptr))
137+
if bdy == nil then
138+
-- not enough data
139+
return
140+
end
141+
self:log('D', 'bdy:%s', json.encode(bdy))
142+
self.avail = tail - ptr
143+
144+
self.on_schema:put({
145+
header = hdr,
146+
body = bdy,
147+
})
148+
end
149+
150+
---Tarantool greeter
151+
function greeter:on_read(is_last)
152+
if self.stage == 'greeting' then
153+
return self:on_greeting_read(is_last)
154+
elseif self.stage == 'fetching_schema' then
155+
return self:on_fetching_schema_read(is_last)
156+
else
157+
self:log('E', 'unknown stage %s', self.stage)
158+
self.avail = 0
159+
end
160+
end
161+
162+
function g.test_greeting()
163+
local cnn = greeter:new(server.net_box.host, server.net_box.port)
164+
cnn.on_schema = fiber.channel()
165+
cnn.connwait:get(1)
166+
t.assert_equals(cnn.state, connection.S2S.CONNECTED, 'connection has been established')
167+
168+
local packet = cnn.on_schema:get(5)
169+
t.assert(packet, "packet with schema must be received")
170+
171+
local schema_version = server:exec(function()
172+
return box.info.schema_version or box.internal.schema_version()
173+
end)
174+
175+
t.assert_items_equals(packet.header, {
176+
[0x00] = 0x00, -- REQUEST_TYPE:OK
177+
[0x01] = 0x01, -- SYNC:1
178+
[0x05] = schema_version, -- SCHEMA_ID:83
179+
}, "packet.header is okay")
180+
181+
t.assert_items_equals(packet.body, {}, "packet body is empty")
182+
t.assert_equals(cnn.state, connection.S2S.CONNECTED, 'connection has been established')
183+
end

0 commit comments

Comments
 (0)