summaryrefslogtreecommitdiff
path: root/tests/test_self.py
diff options
context:
space:
mode:
authorAshley Whetter <ashley@awhetter.co.uk>2019-06-14 22:28:42 -0700
committerClaudiu Popa <pcmanticore@gmail.com>2019-06-20 10:02:14 +0200
commit33b8185a455c1686d038258697bb93005f2441c2 (patch)
tree4a50ccac775c009436e45803129e428ed694065f /tests/test_self.py
parent7081d91f30728653000bdfc59ea85a3395f96418 (diff)
downloadpylint-git-33b8185a455c1686d038258697bb93005f2441c2.tar.gz
Stopped installing tests with package
Diffstat (limited to 'tests/test_self.py')
-rw-r--r--tests/test_self.py669
1 files changed, 669 insertions, 0 deletions
diff --git a/tests/test_self.py b/tests/test_self.py
new file mode 100644
index 000000000..051eea87d
--- /dev/null
+++ b/tests/test_self.py
@@ -0,0 +1,669 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
+# Copyright (c) 2014-2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2014 Vlad Temian <vladtemian@gmail.com>
+# Copyright (c) 2014 Google, Inc.
+# Copyright (c) 2014 Arun Persaud <arun@nubati.net>
+# Copyright (c) 2015 Ionel Cristian Maries <contact@ionelmc.ro>
+# Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
+# Copyright (c) 2016 Moises Lopez <moylop260@vauxoo.com>
+# Copyright (c) 2017 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2017 Daniel Miller <millerdev@gmail.com>
+# Copyright (c) 2017 Bryce Guinta <bryce.paul.guinta@gmail.com>
+# Copyright (c) 2017 Thomas Hisch <t.hisch@gmail.com>
+# Copyright (c) 2017 Ville Skyttä <ville.skytta@iki.fi>
+# Copyright (c) 2018 Sushobhit <31987769+sushobhit27@users.noreply.github.com>
+# Copyright (c) 2018 Jason Owen <jason.a.owen@gmail.com>
+# Copyright (c) 2018 Jace Browning <jacebrowning@gmail.com>
+# Copyright (c) 2018 Reverb C <reverbc@users.noreply.github.com>
+
+# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
+
+import configparser
+import contextlib
+import json
+import platform
+import re
+import subprocess
+import tempfile
+import textwrap
+from io import StringIO
+from os.path import abspath, dirname, join
+from unittest import mock
+
+import pytest
+
+from pylint import utils
+from pylint.lint import Run
+from pylint.reporters import BaseReporter, JSONReporter
+from pylint.reporters.text import *
+
+HERE = abspath(dirname(__file__))
+
+
+@contextlib.contextmanager
+def _patch_streams(out):
+ sys.stderr = sys.stdout = out
+ try:
+ yield
+ finally:
+ sys.stderr = sys.__stderr__
+ sys.stdout = sys.__stdout__
+
+
+@contextlib.contextmanager
+def _configure_lc_ctype(lc_ctype):
+ lc_ctype_env = "LC_CTYPE"
+ original_lctype = os.environ.get(lc_ctype_env)
+ os.environ[lc_ctype_env] = lc_ctype
+ try:
+ yield
+ finally:
+ os.environ.pop(lc_ctype_env)
+ if original_lctype:
+ os.environ[lc_ctype_env] = original_lctype
+
+
+class MultiReporter(BaseReporter):
+ def __init__(self, reporters):
+ self._reporters = reporters
+ self.path_strip_prefix = os.getcwd() + os.sep
+
+ def on_set_current_module(self, *args, **kwargs):
+ for rep in self._reporters:
+ rep.on_set_current_module(*args, **kwargs)
+
+ def handle_message(self, msg):
+ for rep in self._reporters:
+ rep.handle_message(msg)
+
+ def display_reports(self, layout):
+ pass
+
+ @property
+ def out(self):
+ return self._reporters[0].out
+
+ @property
+ def linter(self):
+ return self._linter
+
+ @linter.setter
+ def linter(self, value):
+ self._linter = value
+ for rep in self._reporters:
+ rep.linter = value
+
+
+class TestRunTC(object):
+ def _runtest(self, args, reporter=None, out=None, code=None):
+ if out is None:
+ out = StringIO()
+ pylint_code = self._run_pylint(args, reporter=reporter, out=out)
+ if reporter:
+ output = reporter.out.getvalue()
+ elif hasattr(out, "getvalue"):
+ output = out.getvalue()
+ else:
+ output = None
+ msg = "expected output status %s, got %s" % (code, pylint_code)
+ if output is not None:
+ msg = "%s. Below pylint output: \n%s" % (msg, output)
+ assert pylint_code == code, msg
+
+ def _run_pylint(self, args, out, reporter=None):
+ args = args + ["--persistent=no"]
+ with _patch_streams(out):
+ with pytest.raises(SystemExit) as cm:
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ Run(args, reporter=reporter)
+ return cm.value.code
+
+ def _clean_paths(self, output):
+ """Remove version-specific tox parent directories from paths."""
+ return re.sub(
+ "^py.+/site-packages/", "", output.replace("\\", "/"), flags=re.MULTILINE
+ )
+
+ def _test_output(self, args, expected_output):
+ out = StringIO()
+ self._run_pylint(args, out=out)
+ actual_output = self._clean_paths(out.getvalue())
+ assert expected_output.strip() in actual_output.strip()
+
+ def test_pkginfo(self):
+ """Make pylint check itself."""
+ self._runtest(["pylint.__pkginfo__"], reporter=TextReporter(StringIO()), code=0)
+
+ def test_all(self):
+ """Make pylint check itself."""
+ reporters = [
+ TextReporter(StringIO()),
+ ColorizedTextReporter(StringIO()),
+ JSONReporter(StringIO()),
+ ]
+ self._runtest(
+ [join(HERE, "functional/arguments.py")],
+ reporter=MultiReporter(reporters),
+ code=2,
+ )
+
+ def test_no_ext_file(self):
+ self._runtest([join(HERE, "input", "noext")], code=0)
+
+ def test_w0704_ignored(self):
+ self._runtest([join(HERE, "input", "ignore_except_pass_by_default.py")], code=0)
+
+ def test_exit_zero(self):
+ self._runtest(
+ ["--exit-zero", join(HERE, "regrtest_data", "syntax_error.py")], code=0
+ )
+
+ def test_generate_config_option(self):
+ self._runtest(["--generate-rcfile"], code=0)
+
+ def test_generate_config_option_order(self):
+ out1 = StringIO()
+ out2 = StringIO()
+ self._runtest(["--generate-rcfile"], code=0, out=out1)
+ self._runtest(["--generate-rcfile"], code=0, out=out2)
+ output1 = out1.getvalue()
+ output2 = out2.getvalue()
+ assert output1 == output2
+
+ def test_generate_config_disable_symbolic_names(self):
+ # Test that --generate-rcfile puts symbolic names in the --disable
+ # option.
+
+ out = StringIO()
+ self._run_pylint(["--generate-rcfile", "--rcfile="], out=out)
+
+ output = out.getvalue()
+ # Get rid of the pesky messages that pylint emits if the
+ # configuration file is not found.
+ master = re.search(r"\[MASTER", output)
+ out = StringIO(output[master.start() :])
+ parser = configparser.RawConfigParser()
+ parser.read_file(out)
+ messages = utils._splitstrip(parser.get("MESSAGES CONTROL", "disable"))
+ assert "suppressed-message" in messages
+
+ def test_generate_rcfile_no_obsolete_methods(self):
+ out = StringIO()
+ self._run_pylint(["--generate-rcfile"], out=out)
+ output = out.getvalue()
+ assert "profile" not in output
+
+ def test_inexisting_rcfile(self):
+ out = StringIO()
+ with pytest.raises(IOError) as excinfo:
+ self._run_pylint(["--rcfile=/tmp/norcfile.txt"], out=out)
+ assert "The config file /tmp/norcfile.txt doesn't exist!" == str(excinfo.value)
+
+ def test_help_message_option(self):
+ self._runtest(["--help-msg", "W0101"], code=0)
+
+ def test_error_help_message_option(self):
+ self._runtest(["--help-msg", "WX101"], code=0)
+
+ def test_error_missing_arguments(self):
+ self._runtest([], code=32)
+
+ def test_no_out_encoding(self):
+ """test redirection of stdout with non ascii caracters
+ """
+ # This test reproduces bug #48066 ; it happens when stdout is redirected
+ # through '>' : the sys.stdout.encoding becomes then None, and if the
+ # output contains non ascii, pylint will crash
+ if sys.version_info < (3, 0):
+ strio = tempfile.TemporaryFile()
+ else:
+ strio = StringIO()
+ assert strio.encoding is None
+ self._runtest(
+ [join(HERE, "regrtest_data/no_stdout_encoding.py"), "--enable=all"],
+ out=strio,
+ code=28,
+ )
+
+ def test_parallel_execution(self):
+ self._runtest(
+ [
+ "-j 2",
+ join(HERE, "functional/arguments.py"),
+ join(HERE, "functional/arguments.py"),
+ ],
+ code=2,
+ )
+
+ def test_parallel_execution_missing_arguments(self):
+ self._runtest(["-j 2", "not_here", "not_here_too"], code=1)
+
+ def test_py3k_option(self):
+ # Test that --py3k flag works.
+ rc_code = 0
+ self._runtest(
+ [join(HERE, "functional", "unpacked_exceptions.py"), "--py3k"], code=rc_code
+ )
+
+ def test_py3k_jobs_option(self):
+ rc_code = 0
+ self._runtest(
+ [join(HERE, "functional", "unpacked_exceptions.py"), "--py3k", "-j 2"],
+ code=rc_code,
+ )
+
+ @pytest.mark.skipif(sys.version_info[0] > 2, reason="Requires the --py3k flag.")
+ def test_py3k_commutative_with_errors_only(self):
+
+ # Test what gets emitted with -E only
+ module = join(HERE, "regrtest_data", "py3k_error_flag.py")
+ expected = textwrap.dedent(
+ """
+ ************* Module py3k_error_flag
+ Explicit return in __init__
+ """
+ )
+ self._test_output(
+ [module, "-E", "--msg-template='{msg}'"], expected_output=expected
+ )
+
+ # Test what gets emitted with -E --py3k
+ expected = textwrap.dedent(
+ """
+ ************* Module py3k_error_flag
+ Use raise ErrorClass(args) instead of raise ErrorClass, args.
+ """
+ )
+ self._test_output(
+ [module, "-E", "--py3k", "--msg-template='{msg}'"], expected_output=expected
+ )
+
+ # Test what gets emitted with --py3k -E
+ self._test_output(
+ [module, "--py3k", "-E", "--msg-template='{msg}'"], expected_output=expected
+ )
+
+ @pytest.mark.skipif(sys.version_info[0] > 2, reason="Requires the --py3k flag.")
+ def test_py3k_commutative_with_config_disable(self):
+ module = join(HERE, "regrtest_data", "py3k_errors_and_warnings.py")
+ rcfile = join(HERE, "regrtest_data", "py3k-disabled.rc")
+ cmd = [module, "--msg-template='{msg}'", "--reports=n"]
+
+ expected = textwrap.dedent(
+ """
+ ************* Module py3k_errors_and_warnings
+ import missing `from __future__ import absolute_import`
+ Use raise ErrorClass(args) instead of raise ErrorClass, args.
+ Calling a dict.iter*() method
+ print statement used
+ """
+ )
+ self._test_output(cmd + ["--py3k"], expected_output=expected)
+
+ expected = textwrap.dedent(
+ """
+ ************* Module py3k_errors_and_warnings
+ Use raise ErrorClass(args) instead of raise ErrorClass, args.
+ Calling a dict.iter*() method
+ print statement used
+ """
+ )
+ self._test_output(
+ cmd + ["--py3k", "--rcfile", rcfile], expected_output=expected
+ )
+
+ expected = textwrap.dedent(
+ """
+ ************* Module py3k_errors_and_warnings
+ Use raise ErrorClass(args) instead of raise ErrorClass, args.
+ print statement used
+ """
+ )
+ self._test_output(
+ cmd + ["--py3k", "-E", "--rcfile", rcfile], expected_output=expected
+ )
+
+ self._test_output(
+ cmd + ["-E", "--py3k", "--rcfile", rcfile], expected_output=expected
+ )
+
+ def test_abbreviations_are_not_supported(self):
+ expected = "no such option: --load-plugin"
+ self._test_output([".", "--load-plugin"], expected_output=expected)
+
+ def test_enable_all_works(self):
+ module = join(HERE, "data", "clientmodule_test.py")
+ expected = textwrap.dedent(
+ """
+ ************* Module data.clientmodule_test
+ {0}:10:8: W0612: Unused variable 'local_variable' (unused-variable)
+ {0}:18:4: C0111: Missing method docstring (missing-docstring)
+ {0}:22:0: C0111: Missing class docstring (missing-docstring)
+ """.format(module)
+ )
+ self._test_output(
+ [module, "--disable=all", "--enable=all", "-rn"], expected_output=expected
+ )
+
+ def test_wrong_import_position_when_others_disabled(self):
+ module1 = join(HERE, "regrtest_data", "import_something.py")
+ module2 = join(HERE, "regrtest_data", "wrong_import_position.py")
+ expected_output = textwrap.dedent(
+ """
+ ************* Module wrong_import_position
+ {}:11:0: C0413: Import "import os" should be placed at the top of the module (wrong-import-position)
+ """.format(module2)
+ )
+ args = [
+ module2,
+ module1,
+ "--disable=all",
+ "--enable=wrong-import-position",
+ "-rn",
+ "-sn",
+ ]
+ out = StringIO()
+ self._run_pylint(args, out=out)
+ actual_output = self._clean_paths(out.getvalue().strip())
+
+ to_remove = "No config file found, using default configuration"
+ if to_remove in actual_output:
+ actual_output = actual_output[len(to_remove) :]
+ if actual_output.startswith("Using config file "):
+ # If ~/.pylintrc is present remove the
+ # Using config file... line
+ actual_output = actual_output[actual_output.find("\n") :]
+ assert expected_output.strip() == actual_output.strip()
+
+ def test_import_itself_not_accounted_for_relative_imports(self):
+ expected = "Your code has been rated at 10.00/10"
+ package = join(HERE, "regrtest_data", "dummy")
+ self._test_output(
+ [package, "--disable=locally-disabled", "-rn"], expected_output=expected
+ )
+
+ def test_reject_empty_indent_strings(self):
+ expected = "indent string can't be empty"
+ module = join(HERE, "data", "clientmodule_test.py")
+ self._test_output([module, "--indent-string="], expected_output=expected)
+
+ def test_json_report_when_file_has_syntax_error(self):
+ out = StringIO()
+ module = join(HERE, "regrtest_data", "syntax_error.py")
+ self._runtest([module], code=2, reporter=JSONReporter(out))
+ output = json.loads(out.getvalue())
+ assert isinstance(output, list)
+ assert len(output) == 1
+ assert isinstance(output[0], dict)
+ expected = {
+ "obj": "",
+ "column": 8 if platform.python_implementation() == "PyPy" else 15,
+ "line": 1,
+ "type": "error",
+ "symbol": "syntax-error",
+ "module": "syntax_error",
+ }
+ message = output[0]
+ for key, value in expected.items():
+ assert key in message
+ assert message[key] == value
+ assert "invalid syntax" in message["message"].lower()
+
+ def test_json_report_when_file_is_missing(self):
+ out = StringIO()
+ module = join(HERE, "regrtest_data", "totally_missing.py")
+ self._runtest([module], code=1, reporter=JSONReporter(out))
+ output = json.loads(out.getvalue())
+ assert isinstance(output, list)
+ assert len(output) == 1
+ assert isinstance(output[0], dict)
+ expected = {
+ "obj": "",
+ "column": 0,
+ "line": 1,
+ "type": "fatal",
+ "symbol": "fatal",
+ "module": module,
+ }
+ message = output[0]
+ for key, value in expected.items():
+ assert key in message
+ assert message[key] == value
+ assert message["message"].startswith("No module named")
+
+ def test_json_report_does_not_escape_quotes(self):
+ out = StringIO()
+ module = join(HERE, "regrtest_data", "unused_variable.py")
+ self._runtest([module], code=4, reporter=JSONReporter(out))
+ output = json.loads(out.getvalue())
+ assert isinstance(output, list)
+ assert len(output) == 1
+ assert isinstance(output[0], dict)
+ expected = {
+ "symbol": "unused-variable",
+ "module": "unused_variable",
+ "column": 4,
+ "message": "Unused variable 'variable'",
+ "message-id": "W0612",
+ "line": 4,
+ "type": "warning",
+ }
+ message = output[0]
+ for key, value in expected.items():
+ assert key in message
+ assert message[key] == value
+
+ def test_information_category_disabled_by_default(self):
+ expected = "Your code has been rated at 10.00/10"
+ path = join(HERE, "regrtest_data", "meta.py")
+ self._test_output([path], expected_output=expected)
+
+ def test_error_mode_shows_no_score(self):
+ module = join(HERE, "regrtest_data", "application_crash.py")
+ expected_output = textwrap.dedent(
+ """
+ ************* Module application_crash
+ {}:1:6: E0602: Undefined variable 'something_undefined' (undefined-variable)
+ """.format(module)
+ )
+ self._test_output([module, "-E"], expected_output=expected_output)
+
+ def test_evaluation_score_shown_by_default(self):
+ expected_output = "Your code has been rated at "
+ module = join(HERE, "regrtest_data", "application_crash.py")
+ self._test_output([module], expected_output=expected_output)
+
+ def test_confidence_levels(self):
+ expected = "Your code has been rated at"
+ path = join(HERE, "regrtest_data", "meta.py")
+ self._test_output(
+ [path, "--confidence=HIGH,INFERENCE"], expected_output=expected
+ )
+
+ def test_bom_marker(self):
+ path = join(HERE, "regrtest_data", "meta.py")
+ config_path = join(HERE, "regrtest_data", ".pylintrc")
+ expected = "Your code has been rated at 10.00/10"
+ self._test_output(
+ [path, "--rcfile=%s" % config_path, "-rn"], expected_output=expected
+ )
+
+ def test_pylintrc_plugin_duplicate_options(self):
+ dummy_plugin_path = join(HERE, "regrtest_data", "dummy_plugin")
+ # Enable --load-plugins=dummy_plugin
+ sys.path.append(dummy_plugin_path)
+ config_path = join(HERE, "regrtest_data", "dummy_plugin.rc")
+ expected = (
+ ":dummy-message-01 (I9061): *Dummy short desc 01*\n"
+ " Dummy long desc This message belongs to the dummy_plugin checker.\n\n"
+ ":dummy-message-02 (I9060): *Dummy short desc 02*\n"
+ " Dummy long desc This message belongs to the dummy_plugin checker."
+ )
+ self._test_output(
+ [
+ "--rcfile=%s" % config_path,
+ "--help-msg=dummy-message-01,dummy-message-02",
+ ],
+ expected_output=expected,
+ )
+ expected = (
+ "[DUMMY_PLUGIN]\n\n# Dummy option 1\ndummy_option_1=dummy value 1\n\n"
+ "# Dummy option 2\ndummy_option_2=dummy value 2"
+ )
+ self._test_output(
+ ["--rcfile=%s" % config_path, "--generate-rcfile"], expected_output=expected
+ )
+ sys.path.remove(dummy_plugin_path)
+
+ def test_pylintrc_comments_in_values(self):
+ path = join(HERE, "regrtest_data", "test_pylintrc_comments.py")
+ config_path = join(HERE, "regrtest_data", "comments_pylintrc")
+ expected = textwrap.dedent(
+ """
+ ************* Module test_pylintrc_comments
+ {0}:2:0: W0311: Bad indentation. Found 1 spaces, expected 4 (bad-indentation)
+ {0}:1:0: C0111: Missing module docstring (missing-docstring)
+ {0}:1:0: C0111: Missing function docstring (missing-docstring)
+ """.format(path)
+ )
+ self._test_output(
+ [path, "--rcfile=%s" % config_path, "-rn"], expected_output=expected
+ )
+
+ def test_no_crash_with_formatting_regex_defaults(self):
+ self._runtest(
+ ["--ignore-patterns=a"], reporter=TextReporter(StringIO()), code=32
+ )
+
+ def test_getdefaultencoding_crashes_with_lc_ctype_utf8(self):
+ module = join(HERE, "regrtest_data", "application_crash.py")
+ expected_output = textwrap.dedent(
+ """
+ ************* Module application_crash
+ {}:1:6: E0602: Undefined variable 'something_undefined' (undefined-variable)
+ """.format(module)
+ )
+ with _configure_lc_ctype("UTF-8"):
+ self._test_output([module, "-E"], expected_output=expected_output)
+
+ @pytest.mark.skipif(sys.platform == "win32", reason="only occurs on *nix")
+ def test_parseable_file_path(self):
+ file_name = "test_target.py"
+ fake_path = HERE + os.getcwd()
+ module = join(fake_path, file_name)
+
+ try:
+ # create module under directories which have the same name as reporter.path_strip_prefix
+ # e.g. /src/some/path/src/test_target.py when reporter.path_strip_prefix = /src/
+ os.makedirs(fake_path)
+ with open(module, "w") as test_target:
+ test_target.write("a,b = object()")
+
+ self._test_output(
+ [module, "--output-format=parseable"],
+ expected_output=file_name,
+ )
+ finally:
+ os.remove(module)
+ os.removedirs(fake_path)
+
+ @pytest.mark.parametrize(
+ "input_path,module,expected_path",
+ [
+ (join(HERE, "mymodule.py"), "mymodule", join(HERE, "mymodule.py")),
+ ("mymodule.py", "mymodule", "mymodule.py"),
+ ],
+ )
+ def test_stdin(self, input_path, module, expected_path):
+ expected_output = (
+ "************* Module {module}\n"
+ "{path}:1:0: W0611: Unused import os (unused-import)\n\n"
+ ).format(path=expected_path, module=module)
+
+ with mock.patch(
+ "pylint.lint._read_stdin", return_value="import os\n"
+ ) as mock_stdin:
+ self._test_output(
+ ["--from-stdin", input_path, "--disable=all", "--enable=unused-import"],
+ expected_output=expected_output,
+ )
+ assert mock_stdin.call_count == 1
+
+ def test_stdin_missing_modulename(self):
+ self._runtest(["--from-stdin"], code=32)
+
+ @pytest.mark.parametrize("write_bpy_to_disk", [False, True])
+ def test_relative_imports(self, write_bpy_to_disk, tmpdir):
+ a = tmpdir.join("a")
+
+ b_code = textwrap.dedent(
+ """
+ from .c import foobar
+ from .d import bla # module does not exist
+
+ foobar('hello')
+ bla()
+ """
+ )
+
+ c_code = textwrap.dedent(
+ """
+ def foobar(arg):
+ pass
+ """
+ )
+
+ a.mkdir()
+ a.join("__init__.py").write("")
+ if write_bpy_to_disk:
+ a.join("b.py").write(b_code)
+ a.join("c.py").write(c_code)
+
+ curdir = os.getcwd()
+ try:
+ # why don't we start pylint in a subprocess?
+ os.chdir(str(tmpdir))
+ expected = (
+ "************* Module a.b\n"
+ "a/b.py:3:0: E0401: Unable to import 'a.d' (import-error)\n\n"
+ )
+
+ if write_bpy_to_disk:
+ # --from-stdin is not used here
+ self._test_output(
+ ["a/b.py", "--disable=all", "--enable=import-error"],
+ expected_output=expected,
+ )
+
+ # this code needs to work w/ and w/o a file named a/b.py on the
+ # harddisk.
+ with mock.patch("pylint.lint._read_stdin", return_value=b_code):
+ self._test_output(
+ [
+ "--from-stdin",
+ join("a", "b.py"),
+ "--disable=all",
+ "--enable=import-error",
+ ],
+ expected_output=expected,
+ )
+
+ finally:
+ os.chdir(curdir)
+
+ def test_version(self):
+ def check(lines):
+ assert lines[0].startswith("pylint ")
+ assert lines[1].startswith("astroid ")
+ assert lines[2].startswith("Python ")
+
+ out = StringIO()
+ self._run_pylint(["--version"], out=out)
+ check(out.getvalue().splitlines())
+
+ result = subprocess.check_output([sys.executable, "-m", "pylint", "--version"])
+ result = result.decode("utf-8")
+ check(result.splitlines())