1# This Source Code Form is subject to the terms of the Mozilla Public 2# License, v. 2.0. If a copy of the MPL was not distributed with this 3# file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5import json 6 7import attr 8 9import mozunit 10import mozpack.path as mozpath 11import pytest 12 13from mozlint.result import Issue, ResultSummary 14from mozlint import formatters 15 16NORMALISED_PATHS = { 17 "abc": mozpath.normpath("a/b/c.txt"), 18 "def": mozpath.normpath("d/e/f.txt"), 19 "root": mozpath.abspath("/fake/root"), 20} 21 22EXPECTED = { 23 "compact": { 24 "kwargs": {}, 25 "format": """ 26/fake/root/a/b/c.txt: line 1, Error - oh no foo (foo) 27/fake/root/a/b/c.txt: line 4, col 10, Error - oh no baz (baz) 28/fake/root/a/b/c.txt: line 5, Error - oh no foo-diff (foo-diff) 29/fake/root/d/e/f.txt: line 4, col 2, Warning - oh no bar (bar-not-allowed) 30 314 problems 32""".strip(), 33 }, 34 "stylish": { 35 "kwargs": {"disable_colors": True}, 36 "format": """ 37/fake/root/a/b/c.txt 38 1 error oh no foo (foo) 39 4:10 error oh no baz (baz) 40 5 error oh no foo-diff (foo-diff) 41 diff 1 42 - hello 43 + hello2 44 45/fake/root/d/e/f.txt 46 4:2 warning oh no bar bar-not-allowed (bar) 47 48\u2716 4 problems (3 errors, 1 warning, 0 fixed) 49""".strip(), 50 }, 51 "treeherder": { 52 "kwargs": {}, 53 "format": """ 54TEST-UNEXPECTED-ERROR | /fake/root/a/b/c.txt:1 | oh no foo (foo) 55TEST-UNEXPECTED-ERROR | /fake/root/a/b/c.txt:4:10 | oh no baz (baz) 56TEST-UNEXPECTED-ERROR | /fake/root/a/b/c.txt:5 | oh no foo-diff (foo-diff) 57TEST-UNEXPECTED-WARNING | /fake/root/d/e/f.txt:4:2 | oh no bar (bar-not-allowed) 58""".strip(), 59 }, 60 "unix": { 61 "kwargs": {}, 62 "format": """ 63{abc}:1: foo error: oh no foo 64{abc}:4:10: baz error: oh no baz 65{abc}:5: foo-diff error: oh no foo-diff 66{def}:4:2: bar-not-allowed warning: oh no bar 67""".format( 68 **NORMALISED_PATHS 69 ).strip(), 70 }, 71 "summary": { 72 "kwargs": {}, 73 "format": """ 74{root}/a: 3 errors 75{root}/d: 0 errors, 1 warning 76""".format( 77 **NORMALISED_PATHS 78 ).strip(), 79 }, 80} 81 82 83@pytest.fixture 84def result(scope="module"): 85 result = ResultSummary("/fake/root") 86 containers = ( 87 Issue(linter="foo", path="a/b/c.txt", message="oh no foo", lineno=1), 88 Issue( 89 linter="bar", 90 path="d/e/f.txt", 91 message="oh no bar", 92 hint="try baz instead", 93 level="warning", 94 lineno="4", 95 column="2", 96 rule="bar-not-allowed", 97 ), 98 Issue( 99 linter="baz", 100 path="a/b/c.txt", 101 message="oh no baz", 102 lineno=4, 103 column=10, 104 source="if baz:", 105 ), 106 Issue( 107 linter="foo-diff", 108 path="a/b/c.txt", 109 message="oh no foo-diff", 110 lineno=5, 111 source="if baz:", 112 diff="diff 1\n- hello\n+ hello2", 113 ), 114 ) 115 result = ResultSummary("/fake/root") 116 for c in containers: 117 result.issues[c.path].append(c) 118 return result 119 120 121@pytest.mark.parametrize("name", EXPECTED.keys()) 122def test_formatters(result, name): 123 opts = EXPECTED[name] 124 fmt = formatters.get(name, **opts["kwargs"]) 125 # encoding to str bypasses a UnicodeEncodeError in pytest 126 assert fmt(result) == opts["format"] 127 128 129def test_json_formatter(result): 130 fmt = formatters.get("json") 131 formatted = json.loads(fmt(result)) 132 133 assert set(formatted.keys()) == set(result.issues.keys()) 134 135 attrs = attr.fields(Issue) 136 for errors in formatted.values(): 137 for err in errors: 138 assert all(a.name in err for a in attrs) 139 140 141if __name__ == "__main__": 142 mozunit.main() 143