Browse Source

[Test] Test for TCP library

tags/1.8.0
Mikhail Galanin 5 years ago
parent
commit
b4d4cff669

+ 1
- 2
test/functional/cases/220_http.robot View File

@@ -11,8 +11,7 @@ Variables ${TESTDIR}/lib/vars.py
${URL_TLD} ${TESTDIR}/../lua/unit/test_tld.dat
${CONFIG} ${TESTDIR}/configs/lua_test.conf
${MESSAGE} ${TESTDIR}/messages/spam_message.eml
${REDIS_SCOPE} Suite
${RSPAMD_SCOPE} Suite
${RSPAMD_SCOPE} Test

*** Test Cases ***
Simple HTTP request

+ 63
- 0
test/functional/cases/230_tcp.robot View File

@@ -0,0 +1,63 @@
*** Settings ***
Test Setup Http Setup
Test Teardown Http Teardown
Library Process
Library ${TESTDIR}/lib/rspamd.py
Resource ${TESTDIR}/lib/rspamd.robot
Variables ${TESTDIR}/lib/vars.py

*** Variables ***
# ${CONFIG} ${TESTDIR}/configs/http.conf
${URL_TLD} ${TESTDIR}/../lua/unit/test_tld.dat
${CONFIG} ${TESTDIR}/configs/lua_test.conf
${MESSAGE} ${TESTDIR}/messages/spam_message.eml
${RSPAMD_SCOPE} Test

*** Test Cases ***
Simple TCP request
${result} = Scan Message With Rspamc ${MESSAGE}
Check Rspamc ${result} HTTP_ASYNC_RESPONSE
Check Rspamc ${result} HTTP_ASYNC_RESPONSE_2


Sync API TCP request
${result} = Scan Message With Rspamc ${MESSAGE}
Check Rspamc ${result} HTTP_SYNC_RESPONSE
Check Rspamc ${result} HTTP_SYNC_RESPONSE_2
Check Rspamc ${result} hello world
Check Rspamc ${result} hello post

Sync API TCP get request
Check url /request get HTTP_SYNC_EOF_get (0.00)[hello world]
Check url /content-length get HTTP_SYNC_CONTENT_get (0.00)[hello world]

Sync API TCP post request
Check url /request post HTTP_SYNC_EOF_post (0.00)[hello post]
Check url /content-length post HTTP_SYNC_CONTENT_post (0.00)[hello post]

*** Keywords ***
Lua Setup
[Arguments] ${LUA_SCRIPT}
Set Global Variable ${LUA_SCRIPT}
Generic Setup

Http Setup
Run Dummy Http
Lua Setup ${TESTDIR}/lua/tcp.lua

Http Teardown
${http_pid} = Get File /tmp/dummy_http.pid
Shutdown Process With Children ${http_pid}
Normal Teardown

Run Dummy Http
[Arguments]
${result} = Start Process ${TESTDIR}/util/dummy_http.py
Wait Until Created /tmp/dummy_http.pid


Check url
[Arguments] ${url} ${method} @{expect_results}
${result} = Scan Message With Rspamc --header=url:${url} --header=method:${method} ${MESSAGE}
: FOR ${expect} IN @{expect_results}
\ Check Rspamc ${result} ${expect}

+ 3
- 0
test/functional/lua/http.lua View File

@@ -43,12 +43,15 @@ local function http_symbol(task)
timeout = 1,
})

rspamd_logger.errx(task, 'rspamd_http.request[before]')

local err, response = rspamd_http.request({
url = 'http://127.0.0.1:18080' .. url,
task = task,
method = method,
timeout = 1,
})
rspamd_logger.errx(task, 'rspamd_http.request[done] err: %1 response:%2', err, response)

if not err then
task:insert_result('HTTP_CORO_' .. response.code, 1.0, response.content)

+ 170
- 0
test/functional/lua/tcp.lua View File

@@ -0,0 +1,170 @@
--[[[
-- Just a test for TCP API
--]]

local rspamd_tcp = require "rspamd_tcp"
local logger = require "rspamd_logger"
local tcp_sync = require "lua_tcp_sync"

-- [[ old fashioned callback api ]]
local function http_simple_tcp_async_symbol(task)
logger.errx(task, 'http_tcp_symbol: begin')
local function http_get_cb(err, data, conn)
logger.errx(task, 'http_get_cb: got reply: %s, error: %s, conn: %s', data, err, conn)
task:insert_result('HTTP_ASYNC_RESPONSE_2', 1.0, data)
end
local function http_read_post_cb(err, conn)
logger.errx(task, 'http_read_post_cb: write done: error: %s, conn: %s', err, conn)
conn:add_read(http_get_cb)
end
local function http_read_cb(err, data, conn)
logger.errx(task, 'http_read_cb: got reply: %s, error: %s, conn: %s', data, err, conn)
conn:add_write(http_read_post_cb, "POST /request2 HTTP/1.1\r\n\r\n")
task:insert_result('HTTP_ASYNC_RESPONSE', 1.0, data)
end
rspamd_tcp:request({
task = task,
callback = http_read_cb,
host = '127.0.0.1',
data = {'GET /request HTTP/1.1\r\nConnection: keep-alive\r\n\r\n'},
read = true,
port = 18080,
})
end

local function http_simple_tcp_symbol(task)
logger.errx(task, 'connect_sync, before')

local err
local is_ok, connection = tcp_sync.connect {
task = task,
host = '127.0.0.1',
timeout = 20,
port = 18080,
}

logger.errx(task, 'connect_sync %1, %2', is_ok, tostring(connection))

is_ok, err = connection:write('GET /request_sync HTTP/1.1\r\nConnection: keep-alive\r\n\r\n')

logger.errx(task, 'write %1, %2', is_ok, err)
if not is_ok then
task:insert_result('HTTP_SYNC_WRITE_ERROR', 1.0, err)
logger.errx(task, 'write error: %1', err)
end

local data
is_ok, data = connection:read_once();

logger.errx(task, 'read_once: is_ok: %1, data: %2', is_ok, data)
if not is_ok then
task:insert_result('HTTP_SYNC_ERROR', 1.0, data)
else
task:insert_result('HTTP_SYNC_RESPONSE', 1.0, data)
end

is_ok, err = connection:write("POST /request2 HTTP/1.1\r\n\r\n")
logger.errx(task, 'write[2] %1, %2', is_ok, err)

is_ok, data = connection:read_once();
logger.errx(task, 'read_once[2]: is_ok %1, data: %2', is_ok, data)
if not is_ok then
task:insert_result('HTTP_SYNC_ERROR_2', 1.0, data)
else
task:insert_result('HTTP_SYNC_RESPONSE_2', 1.0, data)
end

connection:close()
end

local function http_tcp_symbol(task)
local url = tostring(task:get_request_header('url'))
local method = tostring(task:get_request_header('method'))

if url == 'nil' then
return
end

local err
local is_ok, connection = tcp_sync.connect {
task = task,
host = '127.0.0.1',
timeout = 20,
port = 18080,
}

logger.errx(task, 'connect_sync %1, %2', is_ok, tostring(connection))
if not is_ok then
logger.errx(task, 'connect error: %1', connection)
return
end

is_ok, err = connection:write(string.format('%s %s HTTP/1.1\r\nConnection: close\r\n\r\n', method:upper(), url))

logger.errx(task, 'write %1, %2', is_ok, err)
if not is_ok then
logger.errx(task, 'write error: %1', err)
return
end

local content_length, content

while true do
local header_line
is_ok, header_line = connection:read_until("\r\n")
if not is_ok then
logger.errx(task, 'failed to get header: %1', header_line)
return
end

if header_line == "" then
logger.errx(task, 'headers done')
break
end

local value
local header = header_line:gsub("([%w-]+): (.*)",
function (h, v) value = v; return h:lower() end)

logger.errx(task, 'parsed header: %1 -> "%2"', header, value)

if header == "content-length" then
content_length = tonumber(value)
end

end

if content_length then
is_ok, content = connection:read_bytes(content_length)
if is_ok then
task:insert_result('HTTP_SYNC_CONTENT_' .. method, 1.0, content)
end
else
is_ok, content = connection:read_until_eof()
if is_ok then
task:insert_result('HTTP_SYNC_EOF_' .. method, 1.0, content)
end
end
logger.errx(task, '(is_ok: %1) content [%2 bytes] %3', is_ok, content_length, content)
end

rspamd_config:register_symbol({
name = 'SIMPLE_TCP_ASYNC_TEST',
score = 1.0,
callback = http_simple_tcp_async_symbol,
no_squeeze = true
})
rspamd_config:register_symbol({
name = 'SIMPLE_TCP_TEST',
score = 1.0,
callback = http_simple_tcp_symbol,
no_squeeze = true
})

rspamd_config:register_symbol({
name = 'HTTP_TCP_TEST',
score = 1.0,
callback = http_tcp_symbol,
no_squeeze = true
})
-- ]]

+ 48
- 27
test/functional/util/dummy_http.py View File

@@ -1,10 +1,14 @@
#!/usr/bin/env python

import BaseHTTPServer
import SocketServer
import SimpleHTTPServer

import time
import os
import sys
import signal
import socket

PORT = 18080
HOST_NAME = '127.0.0.1'
@@ -14,12 +18,19 @@ PID = "/tmp/dummy_http.pid"

class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):

def setup(self):
BaseHTTPServer.BaseHTTPRequestHandler.setup(self)
self.protocol_version = "HTTP/1.1" # allow connection: keep-alive

def do_HEAD(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.log_message("to be closed: " + self.close_connection)

def do_GET(self):
response = "hello world"
"""Respond to a GET request."""
if self.path == "/empty":
self.finish()
@@ -33,11 +44,23 @@ class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
else:
self.send_response(200)

if self.path == "/content-length":
self.send_header("Content-Length", str(len(response)))

self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write("hello world")
self.wfile.write(response)
self.log_message("to be closed: %d, headers: %s, conn:'%s'" % (self.close_connection, str(self.headers), self.headers.get('Connection', "").lower()))

conntype = self.headers.get('Connection', "").lower()
if conntype != 'keep-alive':
self.close_connection = True
self.log_message("ka:'%s', pv:%s[%s]" % (str(conntype == 'keep-alive'), str(self.protocol_version >= "HTTP/1.1"), self.protocol_version))


def do_POST(self):
response = "hello post"
"""Respond to a GET request."""
if self.path == "/empty":
self.finish()
@@ -50,30 +73,35 @@ class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.send_response(403)
else:
self.send_response(200)
if self.path == "/content-length":
self.send_header("Content-Length", str(len(response)))

self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write("hello post")

self.wfile.write(response)

class MyHttp(BaseHTTPServer.HTTPServer):
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=False):
BaseHTTPServer.HTTPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate)
self.keep_running = True

class ThreadingSimpleServer(SocketServer.ThreadingMixIn,
BaseHTTPServer.HTTPServer):
def __init__(self):
BaseHTTPServer.HTTPServer.__init__(self, (HOST_NAME, PORT), MyHandler)
self.allow_reuse_address = True
self.timeout = 1
def run(self):
self.server_bind()
self.server_activate()

with open(PID, 'w+') as f:
f.write(str(os.getpid()))
f.close()

while self.keep_running:
try:
self.handle_request()
except Exception:
pass
try:
while 1:
sys.stdout.flush()
server.handle_request()
except KeyboardInterrupt:
print "Interrupt"
except socket.error:
print "Socket closed"
pass

def stop(self):
self.keep_running = False
@@ -81,20 +109,13 @@ class MyHttp(BaseHTTPServer.HTTPServer):


if __name__ == '__main__':
server_class = BaseHTTPServer.HTTPServer
httpd = MyHttp((HOST_NAME, PORT), MyHandler)
httpd.allow_reuse_address = True
httpd.timeout = 1
server = ThreadingSimpleServer()

def alarm_handler(signum, frame):
httpd.stop()
server.stop()

signal.signal(signal.SIGALRM, alarm_handler)
signal.signal(signal.SIGTERM, alarm_handler)
signal.alarm(10)
signal.alarm(1000)

try:
httpd.run()
except KeyboardInterrupt:
pass
httpd.server_close()
server.run()

Loading…
Cancel
Save