Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pytests: Ignore log errors/warnings per function. #371

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,25 @@ def pytest_generate_tests(metafunc):
metafunc.fixturenames.append('tmp_ct')
metafunc.parametrize('repeat', range(count))


@pytest.fixture(autouse=True, scope="function")
def _function_scope(env, request):
env.set_current_test_name(request.node.name)
yield
env.check_error_log()
env.set_current_test_name(None)


@pytest.fixture(autouse=True, scope="module")
def _module_scope(env):
yield
env.check_error_log()


@pytest.fixture(autouse=True, scope="package")
def _package_scope(env):
env.httpd_error_log.clear_ignored_matches()
env.httpd_error_log.clear_ignored_lognos()
yield
assert env.apache_stop() == 0
env.check_error_log()
15 changes: 0 additions & 15 deletions test/modules/core/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,3 @@ def env(pytestconfig) -> CoreTestEnv:
env.apache_access_log_clear()
env.httpd_error_log.clear_log()
return env


@pytest.fixture(autouse=True, scope="package")
def _session_scope(env):
env.httpd_error_log.set_ignored_lognos([
'AH10244', # core: invalid URI path
'AH01264', # mod_cgid script not found
])
yield
assert env.apache_stop() == 0
errors, warnings = env.httpd_error_log.get_missed()
assert (len(errors), len(warnings)) == (0, 0),\
f"apache logged {len(errors)} errors and {len(warnings)} warnings: \n"\
"{0}\n{1}\n".format("\n".join(errors), "\n".join(warnings))

41 changes: 20 additions & 21 deletions test/modules/core/test_001_encoding.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import pytest
from typing import List, Optional

from pyhttpd.conf import HttpdConf


class TestEncoding:

EXP_AH10244_ERRS = 0

@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
conf = HttpdConf(env, extras={
Expand Down Expand Up @@ -57,29 +56,29 @@ def test_core_001_03(self, env, path):
assert r.response["status"] == 200

# check path traversals
@pytest.mark.parametrize(["path", "status"], [
["/../echo.py", 400],
["/nothing/../../echo.py", 400],
["/cgi-bin/../../echo.py", 400],
["/nothing/%2e%2e/%2e%2e/echo.py", 400],
["/cgi-bin/%2e%2e/%2e%2e/echo.py", 400],
["/nothing/%%32%65%%32%65/echo.py", 400],
["/cgi-bin/%%32%65%%32%65/echo.py", 400],
["/nothing/%%32%65%%32%65/%%32%65%%32%65/h2_env.py", 400],
["/cgi-bin/%%32%65%%32%65/%%32%65%%32%65/h2_env.py", 400],
["/nothing/%25%32%65%25%32%65/echo.py", 404],
["/cgi-bin/%25%32%65%25%32%65/echo.py", 404],
["/nothing/%25%32%65%25%32%65/%25%32%65%25%32%65/h2_env.py", 404],
["/cgi-bin/%25%32%65%25%32%65/%25%32%65%25%32%65/h2_env.py", 404],
@pytest.mark.parametrize(["path", "status", "lognos"], [
["/../echo.py", 400, ["AH10244"]],
["/nothing/../../echo.py", 400, ["AH10244"]],
["/cgi-bin/../../echo.py", 400, ["AH10244"]],
["/nothing/%2e%2e/%2e%2e/echo.py", 400, ["AH10244"]],
["/cgi-bin/%2e%2e/%2e%2e/echo.py", 400, ["AH10244"]],
["/nothing/%%32%65%%32%65/echo.py", 400, ["AH10244"]],
["/cgi-bin/%%32%65%%32%65/echo.py", 400, ["AH10244"]],
["/nothing/%%32%65%%32%65/%%32%65%%32%65/h2_env.py", 400, ["AH10244"]],
["/cgi-bin/%%32%65%%32%65/%%32%65%%32%65/h2_env.py", 400, ["AH10244"]],
["/nothing/%25%32%65%25%32%65/echo.py", 404, ["AH01264"]],
["/cgi-bin/%25%32%65%25%32%65/echo.py", 404, ["AH01264"]],
["/nothing/%25%32%65%25%32%65/%25%32%65%25%32%65/h2_env.py", 404, ["AH01264"]],
["/cgi-bin/%25%32%65%25%32%65/%25%32%65%25%32%65/h2_env.py", 404, ["AH01264"]],
])
def test_core_001_04(self, env, path, status):
def test_core_001_04(self, env, path, status, lognos: Optional[List[str]]):
url = env.mkurl("https", "test1", path)
r = env.curl_get(url)
assert r.response["status"] == status
if status == 400:
TestEncoding.EXP_AH10244_ERRS += 1
# the log will have a core:err about invalid URI path

#
if lognos is not None:
env.httpd_error_log.ignore_recent(lognos = lognos)
# check handling of %2f url encodings that are not decoded by default
@pytest.mark.parametrize(["host", "path", "status"], [
["test1", "/006%2f006.css", 404],
Expand Down
11 changes: 0 additions & 11 deletions test/modules/http1/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,3 @@ def env(pytestconfig) -> H1TestEnv:
env.apache_access_log_clear()
env.httpd_error_log.clear_log()
return env


@pytest.fixture(autouse=True, scope="package")
def _session_scope(env):
yield
assert env.apache_stop() == 0
errors, warnings = env.httpd_error_log.get_missed()
assert (len(errors), len(warnings)) == (0, 0),\
f"apache logged {len(errors)} errors and {len(warnings)} warnings: \n"\
"{0}\n{1}\n".format("\n".join(errors), "\n".join(warnings))

8 changes: 0 additions & 8 deletions test/modules/http1/env.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import inspect
import logging
import os
import re
import subprocess
from typing import Dict, Any

Expand Down Expand Up @@ -61,13 +60,6 @@ def __init__(self, pytestconfig=None):
super().__init__(pytestconfig=pytestconfig)
self.add_httpd_log_modules(["http", "core"])

self.httpd_error_log.set_ignored_lognos([
'AH00135', # unsafe/strict tests send invalid methods
'AH02430', # test of invalid chars in response headers
])
self.httpd_error_log.add_ignored_patterns([
])

def setup_httpd(self, setup: HttpdTestSetup = None):
super().setup_httpd(setup=H1TestSetup(env=self))

Expand Down
1 change: 0 additions & 1 deletion test/modules/http1/test_003_get.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import re
import socket

import pytest
Expand Down
1 change: 0 additions & 1 deletion test/modules/http1/test_004_post.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import inspect
import json
import os
import re
import sys

import pytest
Expand Down
172 changes: 87 additions & 85 deletions test/modules/http1/test_006_unsafe.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import re
import socket
from typing import Optional
from typing import List, Optional

import pytest

Expand All @@ -23,88 +23,88 @@ def _class_scope(self, env):
# 1: any HTTP success
# 200-500: specific HTTP status code
# None: HTTPD should drop connection without error message
@pytest.mark.parametrize(["intext", "status"], [
["GET / HTTP/1.0\r\n\r\n", 1],
["GET / HTTP/1.0\n\n", 1],
["get / HTTP/1.0\r\n\r\n", 501],
["G ET / HTTP/1.0\r\n\r\n", 400],
["G\0ET / HTTP/1.0\r\n\r\n", 400],
["G/T / HTTP/1.0\r\n\r\n", 501],
["GET /\0 HTTP/1.0\r\n\r\n", 400],
["GET / HTTP/1.0\0\r\n\r\n", 400],
["GET\f/ HTTP/1.0\r\n\r\n", 400],
["GET\r/ HTTP/1.0\r\n\r\n", 400],
["GET\t/ HTTP/1.0\r\n\r\n", 400],
["GET / HTT/1.0\r\n\r\n", 0],
["GET / HTTP/1.0\r\nHost: localhost\r\n\r\n", 1],
["GET / HTTP/2.0\r\nHost: localhost\r\n\r\n", 1],
["GET / HTTP/1.2\r\nHost: localhost\r\n\r\n", 1],
["GET / HTTP/1.11\r\nHost: localhost\r\n\r\n", 400],
["GET / HTTP/10.0\r\nHost: localhost\r\n\r\n", 400],
["GET / HTTP/1.0 \r\nHost: localhost\r\n\r\n", 200],
["GET / HTTP/1.0 x\r\nHost: localhost\r\n\r\n", 400],
["GET / HTTP/\r\nHost: localhost\r\n\r\n", 0],
["GET / HTTP/0.9\r\n\r\n", 0],
["GET / HTTP/0.8\r\n\r\n", 0],
["GET /\x01 HTTP/1.0\r\n\r\n", 400],
["GET / HTTP/1.0\r\nFoo: bar\r\n\r\n", 200],
["GET / HTTP/1.0\r\nFoo:bar\r\n\r\n", 200],
["GET / HTTP/1.0\r\nFoo: b\0ar\r\n\r\n", 400],
["GET / HTTP/1.0\r\nFoo: b\x01ar\r\n\r\n", 200],
["GET / HTTP/1.0\r\nFoo\r\n\r\n", 400],
["GET / HTTP/1.0\r\nFoo bar\r\n\r\n", 400],
["GET / HTTP/1.0\r\n: bar\r\n\r\n", 400],
["GET / HTTP/1.0\r\nX: bar\r\n\r\n", 200],
["GET / HTTP/1.0\r\nFoo bar:bash\r\n\r\n", 400],
["GET / HTTP/1.0\r\nFoo :bar\r\n\r\n", 400],
["GET / HTTP/1.0\r\n Foo:bar\r\n\r\n", 400],
["GET / HTTP/1.0\r\nF\x01o: bar\r\n\r\n", 200],
["GET / HTTP/1.0\r\nF\ro: bar\r\n\r\n", 400],
["GET / HTTP/1.0\r\nF\to: bar\r\n\r\n", 400],
["GET / HTTP/1.0\r\nFo: b\tar\r\n\r\n", 200],
["GET / HTTP/1.0\r\nFo: bar\r\r\n\r\n", 400],
["GET / HTTP/1.0\r\r", None],
["GET /\r\n", 90],
["GET /#frag HTTP/1.0\r\n", 400],
["GET / HTTP/1.0\r\nHost: localhost\r\nHost: localhost\r\n\r\n", 200],
["GET http://017700000001/ HTTP/1.0\r\n\r\n", 200],
["GET http://0x7f.1/ HTTP/1.0\r\n\r\n", 200],
["GET http://127.0.0.1/ HTTP/1.0\r\n\r\n", 200],
["GET http://127.01.0.1/ HTTP/1.0\r\n\r\n", 200],
["GET http://%3127.0.0.1/ HTTP/1.0\r\n\r\n", 200],
["GET / HTTP/1.0\r\nHost: localhost:80\r\nHost: localhost:80\r\n\r\n", 200],
["GET / HTTP/1.0\r\nHost: localhost:80 x\r\n\r", 400],
["GET http://localhost:80/ HTTP/1.0\r\n\r\n", 200],
["GET http://localhost:80x/ HTTP/1.0\r\n\r\n", 400],
["GET http://localhost:80:80/ HTTP/1.0\r\n\r\n", 400],
["GET http://localhost::80/ HTTP/1.0\r\n\r\n", 400],
["GET http://foo@localhost:80/ HTTP/1.0\r\n\r\n", 200],
["GET http://[::1]/ HTTP/1.0\r\n\r\n", 1],
["GET http://[::1:2]/ HTTP/1.0\r\n\r\n", 1],
["GET http://[4712::abcd]/ HTTP/1.0\r\n\r\n", 1],
["GET http://[4712::abcd:1]/ HTTP/1.0\r\n\r\n", 1],
["GET http://[4712::abcd::]/ HTTP/1.0\r\n\r\n", 400],
["GET http://[4712:abcd::]/ HTTP/1.0\r\n\r\n", 1],
["GET http://[4712::abcd]:8000/ HTTP/1.0\r\n\r\n", 1],
["GET http://4713::abcd:8001/ HTTP/1.0\r\n\r\n", 400],
["GET / HTTP/1.0\r\nHost: [::1]\r\n\r\n", 1],
["GET / HTTP/1.0\r\nHost: [::1:2]\r\n\r\n", 1],
["GET / HTTP/1.0\r\nHost: [4711::abcd]\r\n\r\n", 1],
["GET / HTTP/1.0\r\nHost: [4711::abcd:1]\r\n\r\n", 1],
["GET / HTTP/1.0\r\nHost: [4711:abcd::]\r\n\r\n", 1],
["GET / HTTP/1.0\r\nHost: [4711::abcd]:8000\r\n\r\n", 1],
["GET / HTTP/1.0\r\nHost: 4714::abcd:8001\r\n\r\n", 200],
["GET / HTTP/1.0\r\nHost: abc\xa0\r\n\r\n", 200],
["GET / HTTP/1.0\r\nHost: abc\\foo\r\n\r\n", 400],
["GET http://foo/ HTTP/1.0\r\nHost: bar\r\n\r\n", 200],
["GET http://foo:81/ HTTP/1.0\r\nHost: bar\r\n\r\n", 200],
["GET http://[::1]:81/ HTTP/1.0\r\nHost: bar\r\n\r\n", 200],
["GET http://10.0.0.1:81/ HTTP/1.0\r\nHost: bar\r\n\r\n", 200],
["GET / HTTP/1.0\r\nHost: foo-bar.example.com\r\n\r\n", 200],
["GET / HTTP/1.0\r\nHost: foo_bar.example.com\r\n\r\n", 200],
["GET http://foo_bar/ HTTP/1.0\r\n\r\n", 200],
@pytest.mark.parametrize(["intext", "status", "lognos"], [
["GET / HTTP/1.0\r\n\r\n", 1, None],
["GET / HTTP/1.0\n\n", 1, None],
["get / HTTP/1.0\r\n\r\n", 501, ["AH00135"]],
["G ET / HTTP/1.0\r\n\r\n", 400, None],
["G\0ET / HTTP/1.0\r\n\r\n", 400, None],
["G/T / HTTP/1.0\r\n\r\n", 501, ["AH00135"]],
["GET /\0 HTTP/1.0\r\n\r\n", 400, None],
["GET / HTTP/1.0\0\r\n\r\n", 400, None],
["GET\f/ HTTP/1.0\r\n\r\n", 400, None],
["GET\r/ HTTP/1.0\r\n\r\n", 400, None],
["GET\t/ HTTP/1.0\r\n\r\n", 400, None],
["GET / HTT/1.0\r\n\r\n", 0, None],
["GET / HTTP/1.0\r\nHost: localhost\r\n\r\n", 1, None],
["GET / HTTP/2.0\r\nHost: localhost\r\n\r\n", 1, None],
["GET / HTTP/1.2\r\nHost: localhost\r\n\r\n", 1, None],
["GET / HTTP/1.11\r\nHost: localhost\r\n\r\n", 400, None],
["GET / HTTP/10.0\r\nHost: localhost\r\n\r\n", 400, None],
["GET / HTTP/1.0 \r\nHost: localhost\r\n\r\n", 200, None],
["GET / HTTP/1.0 x\r\nHost: localhost\r\n\r\n", 400, None],
["GET / HTTP/\r\nHost: localhost\r\n\r\n", 0, None],
["GET / HTTP/0.9\r\n\r\n", 0, None],
["GET / HTTP/0.8\r\n\r\n", 0, None],
["GET /\x01 HTTP/1.0\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\nFoo: bar\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nFoo:bar\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nFoo: b\0ar\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\nFoo: b\x01ar\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nFoo\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\nFoo bar\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\n: bar\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\nX: bar\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nFoo bar:bash\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\nFoo :bar\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\n Foo:bar\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\nF\x01o: bar\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nF\ro: bar\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\nF\to: bar\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\nFo: b\tar\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nFo: bar\r\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\r", None, None],
["GET /\r\n", 0, None],
["GET /#frag HTTP/1.0\r\n", 400, None],
["GET / HTTP/1.0\r\nHost: localhost\r\nHost: localhost\r\n\r\n", 200, None],
["GET http://017700000001/ HTTP/1.0\r\n\r\n", 200, None],
["GET http://0x7f.1/ HTTP/1.0\r\n\r\n", 200, None],
["GET http://127.0.0.1/ HTTP/1.0\r\n\r\n", 200, None],
["GET http://127.01.0.1/ HTTP/1.0\r\n\r\n", 200, None],
["GET http://%3127.0.0.1/ HTTP/1.0\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nHost: localhost:80\r\nHost: localhost:80\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nHost: localhost:80 x\r\n\r", 400, None],
["GET http://localhost:80/ HTTP/1.0\r\n\r\n", 200, None],
["GET http://localhost:80x/ HTTP/1.0\r\n\r\n", 400, None],
["GET http://localhost:80:80/ HTTP/1.0\r\n\r\n", 400, None],
["GET http://localhost::80/ HTTP/1.0\r\n\r\n", 400, None],
["GET http://foo@localhost:80/ HTTP/1.0\r\n\r\n", 200, None],
["GET http://[::1]/ HTTP/1.0\r\n\r\n", 1, None],
["GET http://[::1:2]/ HTTP/1.0\r\n\r\n", 1, None],
["GET http://[4712::abcd]/ HTTP/1.0\r\n\r\n", 1, None],
["GET http://[4712::abcd:1]/ HTTP/1.0\r\n\r\n", 1, None],
["GET http://[4712::abcd::]/ HTTP/1.0\r\n\r\n", 400, None],
["GET http://[4712:abcd::,]/ HTTP/1.0\r\n\r\n", 1, None],
["GET http://[4712::abcd]:8000/ HTTP/1.0\r\n\r\n", 1, None],
["GET http://4713::abcd:8001/ HTTP/1.0\r\n\r\n", 400, None],
["GET / HTTP/1.0\r\nHost: [::1]\r\n\r\n", 1, None],
["GET / HTTP/1.0\r\nHost: [::1:2]\r\n\r\n", 1, None],
["GET / HTTP/1.0\r\nHost: [4711::abcd]\r\n\r\n", 1, None],
["GET / HTTP/1.0\r\nHost: [4711::abcd:1]\r\n\r\n", 1, None],
["GET / HTTP/1.0\r\nHost: [4711:abcd::]\r\n\r\n", 1, None],
["GET / HTTP/1.0\r\nHost: [4711::abcd]:8000\r\n\r\n", 1, None],
["GET / HTTP/1.0\r\nHost: 4714::abcd:8001\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nHost: abc\xa0\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nHost: abc\\foo\r\n\r\n", 400, None],
["GET http://foo/ HTTP/1.0\r\nHost: bar\r\n\r\n", 200, None],
["GET http://foo:81/ HTTP/1.0\r\nHost: bar\r\n\r\n", 200, None],
["GET http://[::1]:81/ HTTP/1.0\r\nHost: bar\r\n\r\n", 200, None],
["GET http://10.0.0.1:81/ HTTP/1.0\r\nHost: bar\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nHost: foo-bar.example.com\r\n\r\n", 200, None],
["GET / HTTP/1.0\r\nHost: foo_bar.example.com\r\n\r\n", 200, None],
["GET http://foo_bar/ HTTP/1.0\r\n\r\n", 200, None],
])
def test_h1_006_01(self, env, intext, status: Optional[int]):
def test_h1_006_01(self, env, intext, status: Optional[int], lognos: Optional[List[str]]):
with socket.create_connection(('localhost', int(env.http_port))) as sock:
# on some OS, the server does not see our connection until there is
# something incoming
Expand All @@ -119,14 +119,16 @@ def test_h1_006_01(self, env, intext, status: Optional[int]):
rlines = msg.splitlines()
response = rlines[0]
m = re.match(r'^HTTP/1.1 (\d+)\s+(\S+)', response)
assert m or status == 90, f"unrecognized response: {rlines}"
assert m or status == 0, f"unrecognized response: {rlines}"
if status == 1:
assert int(m.group(1)) >= 200
elif status == 90:
elif status == 0:
# headerless 0.9 response, yuk
assert len(rlines) >= 1, f"{rlines}"
elif status > 0:
assert int(m.group(1)) == status, f"{rlines}"
else:
assert int(m.group(1)) >= 400, f"{rlines}"

#
if lognos is not None:
env.httpd_error_log.ignore_recent(lognos = lognos)
Loading