Browse Source

Kinda blind patched to support Python 3.6 + 3.7. Drop support for python 2 as it is near EOL anyway

master
Johann Schmitz 5 months ago
parent
commit
1f077a33ab
Signed by: ercpe <johann@j-schmitz.net> GPG Key ID: A084064277C501ED
6 changed files with 38 additions and 52 deletions
  1. +2
    -2
      .travis.yml
  2. +2
    -11
      Makefile
  3. +3
    -2
      amavisvt/amavisvtc.py
  4. +11
    -7
      amavisvt/daemon.py
  5. +0
    -10
      tests/test_client.py
  6. +20
    -20
      tests/test_daemon.py

+ 2
- 2
.travis.yml View File

@@ -1,10 +1,10 @@
language: python
python:
- 2.7
- 3.4
- 3.5
- 3.6
- 3.7
- pypy
# - nightly # 3.6

install:
- pip install -r requirements.txt


+ 2
- 11
Makefile View File

@@ -1,20 +1,11 @@
TARGET?=tests
TARGET?=test

VERSION := $(shell grep -Po '"(.*)"' amavisvt/__init__.py | sed -e 's/"//g')

test_default_python:
PYTHONPATH="." python -m pytest tests/ --junit-xml testresults.xml -rxsw -v

test_py2:
@echo Executing test with python2
PYTHONPATH="." python2 -m pytest tests/ --junit-xml testresults.xml -rxsw -v

test_py3:
test:
@echo Executing test with python3
PYTHONPATH="." python3 -m pytest tests/ --junit-xml testresults.xml -rxsw -v

test: test_py2 test_py3

compile:
@echo Compiling python code
python -m compileall amavisvt/


+ 3
- 2
amavisvt/amavisvtc.py View File

@@ -35,10 +35,11 @@ class AmavisVTClient(object):
absolute_args = [os.path.abspath(p) for p in arguments]
s = "%s %s" % (translate.get(command, command.upper()), ' '.join(absolute_args))

sock.sendall(s.strip() + "\n")
payload = s.strip() + "\n"
sock.sendall(payload.encode('utf-8'))

data = sock.recv(BUFFER_SIZE)
return data
return data.decode('utf-8')
finally:
if sock:
sock.close()


+ 11
- 7
amavisvt/daemon.py View File

@@ -26,7 +26,7 @@ class ThreadedRequestHandler(socketserver.BaseRequestHandler):

def handle(self):
temp = self.request.recv(BUFFER_SIZE)
data = temp
data = temp.decode('utf-8')

if '\n' not in data:
logger.error("Invalid data received: '%s'" % data)
@@ -68,7 +68,7 @@ class ThreadedRequestHandler(socketserver.BaseRequestHandler):
return None, None

def send_response(self, msg):
self.request.sendall(msg)
self.request.sendall(msg.encode('utf-8'))

def do_ping(self):
self.send_response('PONG')
@@ -93,7 +93,8 @@ class ThreadedRequestHandler(socketserver.BaseRequestHandler):
responses.append("%s: Detected as %s (%s of %s)" % (resource, ', '.join(set(matches)), scan_result.positives, scan_result.total))
else:
responses.append("%s: Clean" % resource)
self.request.sendall('\n'.join(responses))
payload = '\n'.join(responses)
self.request.sendall(payload.encode('utf-8'))

def do_report(self, filename_argument):
filename = os.path.abspath(filename_argument)
@@ -144,14 +145,17 @@ class AmavisVTDaemon(object):
try:
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(socket_path)
sock.sendall("PING")
sock.sendall("PING".encode('utf-8'))
data = sock.recv(BUFFER_SIZE)

if data and data.strip() == "PONG":
if not data or not isinstance(data, bytes):
logger.info("Received garbage from socket %s: '%s'", socket_path, data)
return False
data = data.decode('utf-8')
if data.strip() == "PONG":
return True

logger.info("Received garbage from socket %s: '%s'", socket_path, data)
return False
except Exception as ex:
logger.error("Socket %s isn't working: %s", socket_path, ex)
return False


+ 0
- 10
tests/test_client.py View File

@@ -103,16 +103,6 @@ class TestClientBasic(object):
assert avt.is_infected(VTResponse(RAW_DUMMY_RESPONSE))


class TestClientDatabase(object):
def test_database_fallback(self):
c = AmavisVTConfigurationParser({
'database-path': '/dev/null',
}, path='/dev/null')
avt = AmavisVT(c)
assert isinstance(avt.database, NoopDatabase)


class TestClientCache(object):
@mock.patch('amavisvt.client.memcache.Client.set')
def test_cache_set(self, memcached_client_set, avt):


+ 20
- 20
tests/test_daemon.py View File

@@ -27,80 +27,80 @@ class NoHandleRequestHandler(PyTestableThreadedRequestHandler):
class TestRequestHandler(object):
def test_handle_no_data(self):
request_mock = mock.MagicMock()
request_mock.recv.return_value = ''
request_mock.recv.return_value = b''
server_mock = mock.MagicMock()
handler = PyTestableThreadedRequestHandler(request_mock, 'foo', server_mock)
handler.parse_command = mock.MagicMock()
request_mock.sendall.assert_called_with("ERROR: Invalid data: ''")
request_mock.sendall.assert_called_with(b"ERROR: Invalid data: ''")
assert not handler.parse_command.called
def test_handle_empty_data(self):
request_mock = mock.MagicMock()
request_mock.recv.return_value = '\n'
request_mock.recv.return_value = b'\n'
server_mock = mock.MagicMock()
handler = PyTestableThreadedRequestHandler(request_mock, 'foo', server_mock)
handler.parse_command = mock.MagicMock()
request_mock.sendall.assert_called_with("ERROR: Unknown command 'None'")
request_mock.sendall.assert_called_with(b"ERROR: Unknown command 'None'")
def test_handle_too_much_data(self):
request_mock = mock.MagicMock()
server_mock = mock.MagicMock()
data = 'x' * 10000
data = b'x' * 10000
request_mock.recv.return_value = data
handler = PyTestableThreadedRequestHandler(request_mock, 'foo', server_mock)
handler.parse_command = mock.MagicMock()
request_mock.sendall.assert_called_with("ERROR: Invalid data: '%s'" % data)
request_mock.sendall.assert_called_with(b"ERROR: Invalid data: '%s'" % data)
assert not handler.parse_command.called
def test_ping_command(self):
request_mock = mock.MagicMock()
server_mock = mock.MagicMock()
request_mock.recv.return_value = 'PING\n'
request_mock.recv.return_value = b'PING\n'
handler = PyTestableThreadedRequestHandler(request_mock, 'foo', server_mock)
handler.request.sendall.assert_called_with('PONG')
handler.request.sendall.assert_called_with(b'PONG')
def test_contscan_command_no_argument(self):
request_mock = mock.MagicMock()
server_mock = mock.MagicMock()
request_mock.recv.return_value = 'CONTSCAN\n'
request_mock.recv.return_value = b'CONTSCAN\n'
handler = PyTestableThreadedRequestHandler(request_mock, 'foo', server_mock)
handler.request.sendall.assert_called_with("ERROR: Wrong argument ''")
handler.request.sendall.assert_called_with(b"ERROR: Wrong argument ''")
def test_contscan_command_directory_does_not_exist(self):
request_mock = mock.MagicMock()
server_mock = mock.MagicMock()
request_mock.recv.return_value = 'CONTSCAN /tmp/this-directory-does-not-exist\n'
request_mock.recv.return_value = b'CONTSCAN /tmp/this-directory-does-not-exist\n'
handler = PyTestableThreadedRequestHandler(request_mock, 'foo', server_mock)
handler.request.sendall.assert_called_with("ERROR: Wrong argument '/tmp/this-directory-does-not-exist'")
handler.request.sendall.assert_called_with(b"ERROR: Wrong argument '/tmp/this-directory-does-not-exist'")
def test_handle_report_command(self):
request_mock = mock.MagicMock()
server_mock = mock.MagicMock()
request_mock.recv.return_value = 'REPORT /tmp\n'
request_mock.recv.return_value = b'REPORT /tmp\n'
handler = PyTestableThreadedRequestHandler(request_mock, 'foo', server_mock)
handler.request.sendall.assert_called_with("ERROR: File does not exist or is inaccessible: '/tmp'")
handler.request.sendall.assert_called_with(b"ERROR: File does not exist or is inaccessible: '/tmp'")
@mock.patch('amavisvt.daemon.AmavisVT')
def test_handle_error_in_command(self, avt):
request_mock = mock.MagicMock()
server_mock = mock.MagicMock()
request_mock.recv.return_value = 'REPORT %s\n' % __file__
request_mock.recv.return_value = f'REPORT {__file__}\n'.encode('utf-8')
# return value of the mocked AmavisVT constructor
inner_mock = mock.MagicMock()
@@ -111,7 +111,7 @@ class TestRequestHandler(object):
inner_mock.report_to_vt = report_to_vt_mock
handler = PyTestableThreadedRequestHandler(request_mock, 'foo', server_mock)
handler.request.sendall.assert_called_with('ERROR: Command error')
handler.request.sendall.assert_called_with(b'ERROR: Command error')
@mock.patch('amavisvt.daemon.AmavisVT')
def test_contscan_command(self, avt):
@@ -130,7 +130,7 @@ class TestRequestHandler(object):
assert avt.called
run_mock.assert_called_with('/')
request_mock.sendall.assert_called_with('AmavisVTd scan results:')
request_mock.sendall.assert_called_with(b'AmavisVTd scan results:')
@mock.patch('amavisvt.daemon.AmavisVT')
def test_contscan_command_response(self, avt):
@@ -162,7 +162,7 @@ class TestRequestHandler(object):
assert request_mock.sendall.called
call_args, call_kwargs = request_mock.sendall.call_args
assert len(call_args) == 1
lines = call_args[0].split('\n')
lines = call_args[0].decode('utf-8').split('\n')
assert len(lines) == 5
assert lines[0] == "AmavisVTd scan results:"
assert lines[1] == 'test.zip: Clean'
@@ -208,7 +208,7 @@ class TestRequestHandler(object):
assert len(call_args) == 1
assert isinstance(call_args[0], Resource)
assert call_args[0].path == __file__
request_mock.sendall.assert_called_with('No response')
request_mock.sendall.assert_called_with(b'No response')
@mock.patch('amavisvt.daemon.AmavisVT')
def test_report_command_valid_argument_with_response(self, avt):
@@ -234,7 +234,7 @@ class TestRequestHandler(object):
assert isinstance(call_args[0], Resource)
assert call_args[0].path == __file__
request_mock.sendall.assert_called_with(
'99017f6eebbac24f351415dd410d522d: Scan finished, scan information embedded in this object')
b'99017f6eebbac24f351415dd410d522d: Scan finished, scan information embedded in this object')
def test_parse_command_invalid(self):
handler = NoHandleRequestHandler(None, None, None)


Loading…
Cancel
Save