# 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_lin
es):
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()