190 lines
5.3 KiB
Python
190 lines
5.3 KiB
Python
# Any copyright is dedicated to the Public Domain.
|
|
# http://creativecommons.org/publicdomain/zero/1.0/
|
|
|
|
import io
|
|
import json
|
|
import time
|
|
import types
|
|
|
|
import mozunit
|
|
import pytest
|
|
from conftest import setup_args
|
|
from mozlog.formatters import JSONFormatter
|
|
from mozlog.handlers.base import StreamHandler
|
|
from mozlog.structuredlog import StructuredLogger
|
|
|
|
|
|
@pytest.fixture
|
|
def logger():
|
|
logger = StructuredLogger("mochitest_message_logger")
|
|
|
|
buf = io.StringIO()
|
|
handler = StreamHandler(buf, JSONFormatter())
|
|
logger.add_handler(handler)
|
|
return logger
|
|
|
|
|
|
@pytest.fixture
|
|
def get_message_logger(setup_test_harness, logger):
|
|
setup_test_harness(*setup_args)
|
|
runtests = pytest.importorskip("runtests")
|
|
|
|
def fake_message(self, action, **extra):
|
|
message = {
|
|
"action": action,
|
|
"time": time.time(),
|
|
}
|
|
if action in ("test_start", "test_end", "test_status"):
|
|
message["test"] = "test_foo.html"
|
|
|
|
if action == "test_end":
|
|
message["status"] = "PASS"
|
|
message["expected"] = "PASS"
|
|
|
|
elif action == "test_status":
|
|
message["subtest"] = "bar"
|
|
message["status"] = "PASS"
|
|
|
|
elif action == "log":
|
|
message["level"] = "INFO"
|
|
message["message"] = "foobar"
|
|
|
|
message.update(**extra)
|
|
return self.write(json.dumps(message))
|
|
|
|
def inner(**kwargs):
|
|
ml = runtests.MessageLogger(logger, **kwargs)
|
|
|
|
# Create a convenience function for faking incoming log messages.
|
|
ml.fake_message = types.MethodType(fake_message, ml)
|
|
return ml
|
|
|
|
return inner
|
|
|
|
|
|
@pytest.fixture
|
|
def get_lines(logger):
|
|
buf = logger.handlers[0].stream
|
|
|
|
def inner():
|
|
lines = buf.getvalue().splitlines()
|
|
buf.truncate(0)
|
|
# Python3 will not reposition the buffer position after
|
|
# truncate and will extend the buffer with null bytes.
|
|
# Force the buffer position to the start of the buffer
|
|
# to prevent null bytes from creeping in.
|
|
buf.seek(0)
|
|
return lines
|
|
|
|
return inner
|
|
|
|
|
|
@pytest.fixture
|
|
def assert_actions(get_lines):
|
|
def inner(expected):
|
|
if isinstance(expected, str):
|
|
expected = [expected]
|
|
|
|
lines = get_lines()
|
|
actions = [json.loads(l)["action"] for l in lines]
|
|
assert actions == expected
|
|
|
|
return inner
|
|
|
|
|
|
def test_buffering_on(get_message_logger, assert_actions):
|
|
ml = get_message_logger(buffering=True)
|
|
|
|
# no buffering initially (outside of test)
|
|
ml.fake_message("log")
|
|
assert_actions(["log"])
|
|
|
|
# inside a test buffering is enabled, only 'test_start' logged
|
|
ml.fake_message("test_start")
|
|
ml.fake_message("test_status")
|
|
ml.fake_message("log")
|
|
assert_actions(["test_start"])
|
|
|
|
# buffering turned off manually within a test
|
|
ml.fake_message("buffering_off")
|
|
ml.fake_message("test_status")
|
|
ml.fake_message("log")
|
|
assert_actions(["test_status", "log"])
|
|
|
|
# buffering turned back on again
|
|
ml.fake_message("buffering_on")
|
|
ml.fake_message("test_status")
|
|
ml.fake_message("log")
|
|
assert_actions([])
|
|
|
|
# test end, it failed! All previsouly buffered messages are now logged.
|
|
ml.fake_message("test_end", status="FAIL")
|
|
assert_actions(
|
|
[
|
|
"log", # "Buffered messages logged"
|
|
"test_status",
|
|
"log",
|
|
"test_status",
|
|
"log",
|
|
"log", # "Buffered messages finished"
|
|
"test_end",
|
|
]
|
|
)
|
|
|
|
# enabling buffering outside of a test has no affect
|
|
ml.fake_message("buffering_on")
|
|
ml.fake_message("log")
|
|
ml.fake_message("test_status")
|
|
assert_actions(["log", "test_status"])
|
|
|
|
|
|
def test_buffering_off(get_message_logger, assert_actions):
|
|
ml = get_message_logger(buffering=False)
|
|
|
|
ml.fake_message("test_start")
|
|
assert_actions(["test_start"])
|
|
|
|
# messages logged no matter what the state
|
|
ml.fake_message("test_status")
|
|
ml.fake_message("buffering_off")
|
|
ml.fake_message("log")
|
|
assert_actions(["test_status", "log"])
|
|
|
|
# even after a 'buffering_on' action
|
|
ml.fake_message("buffering_on")
|
|
ml.fake_message("test_status")
|
|
ml.fake_message("log")
|
|
assert_actions(["test_status", "log"])
|
|
|
|
# no buffer to empty on test fail
|
|
ml.fake_message("test_end", status="FAIL")
|
|
assert_actions(["test_end"])
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"name,expected",
|
|
(
|
|
("/tests/test_foo.html", "test_foo.html"),
|
|
("chrome://mochitests/content/a11y/test_foo.html", "test_foo.html"),
|
|
("chrome://mochitests/content/browser/test_foo.html", "test_foo.html"),
|
|
("chrome://mochitests/content/chrome/test_foo.html", "test_foo.html"),
|
|
(
|
|
"https://example.org:443/tests/netwerk/test_foo.html",
|
|
"netwerk/test_foo.html",
|
|
),
|
|
("http://mochi.test:8888/tests/test_foo.html", "test_foo.html"),
|
|
("http://mochi.test:8888/content/dom/browser/test_foo.html", None),
|
|
),
|
|
)
|
|
def test_test_names_fixed_to_be_relative(name, expected, get_message_logger, get_lines):
|
|
ml = get_message_logger(buffering=False)
|
|
ml.fake_message("test_start", test=name)
|
|
lines = get_lines()
|
|
|
|
if expected is None:
|
|
expected = name
|
|
assert json.loads(lines[0])["test"] == expected
|
|
|
|
|
|
if __name__ == "__main__":
|
|
mozunit.main()
|