Failed Conditions
Pull Request — master (#1990)
by Mischa
01:31
created

ManualProcessingTestLinter.process_output()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
dl 0
loc 2
rs 10
1
import os
2
import sys
3
import unittest
4
from unittest.mock import ANY, Mock
5
6
from coalib.bearlib.abstractions.Linter import Linter
7
from coalib.results.Diff import Diff
8
from coalib.results.Result import Result
9
from coalib.results.RESULT_SEVERITY import RESULT_SEVERITY
10
from coalib.settings.Section import Section
11
12
13
def get_testfile_name(name):
14
    """
15
    Gets the full path to a testfile inside ``linter_test_files`` directory.
16
17
    :param name: The filename of the testfile to get the full path for.
18
    :return:     The full path to given testfile name.
19
    """
20
    return os.path.join(os.path.dirname(os.path.realpath(__file__)),
21
                        "linter_test_files",
22
                        name)
23
24
25
class LinterComponentTest(unittest.TestCase):
26
27
    # Using `object` instead of an empty class results in inheritance problems
28
    # inside the linter decorator.
29
    class EmptyTestLinter:
30
        pass
31
32
    class ManualProcessingTestLinter:
33
34
        def process_output(self, *args, **kwargs):
35
            pass
36
37
    def setUp(self):
38
        self.section = Section("TEST_SECTION")
39
40 View Code Duplication
    def test_decorator_invalid_parameters(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
41
        with self.assertRaises(ValueError) as cm:
42
            Linter("some-executable", invalid_arg=88, ABC=2000)
43
        self.assertEqual(
44
            str(cm.exception),
45
            "Invalid keyword arguments provided: 'ABC', 'invalid_arg'")
46
47
        with self.assertRaises(ValueError) as cm:
48
            Linter("some-executable", diff_severity=RESULT_SEVERITY.MAJOR)
49
        self.assertEqual(str(cm.exception),
50
                         "Invalid keyword arguments provided: 'diff_severity'")
51
52
        with self.assertRaises(ValueError) as cm:
53
            Linter("some-executable", diff_message="Custom message")
54
        self.assertEqual(str(cm.exception),
55
                         "Invalid keyword arguments provided: 'diff_message'")
56
57
        with self.assertRaises(ValueError) as cm:
58
            Linter("some-executable",
59
                   output_format="corrected",
60
                   output_regex=".*")
61
        self.assertEqual(str(cm.exception),
62
                         "Invalid keyword arguments provided: 'output_regex'")
63
64
        with self.assertRaises(ValueError) as cm:
65
            Linter("some-executable",
66
                   output_format="corrected",
67
                   severity_map={})
68
        self.assertEqual(str(cm.exception),
69
                         "Invalid keyword arguments provided: 'severity_map'")
70
71
        with self.assertRaises(ValueError) as cm:
72
            Linter("some-executable",
73
                   prerequisite_check_fail_message="some_message")
74
        self.assertEqual(str(cm.exception),
75
                         "Invalid keyword arguments provided: "
76
                         "'prerequisite_check_fail_message'")
77
78 View Code Duplication
    def test_decorator_invalid_states(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
79
        with self.assertRaises(ValueError) as cm:
80
            Linter("some-executable", output_stream="invalid+outputstream")
81
        self.assertEqual(str(cm.exception),
82
                         "Invalid output stream: 'invalid'")
83
84
        with self.assertRaises(ValueError) as cm:
85
            Linter("some-executable", output_format="INVALID")
86
        self.assertEqual(str(cm.exception),
87
                         "Invalid `output_format` specified.")
88
89
        with self.assertRaises(ValueError) as cm:
90
            Linter("some-executable", output_format="regex")
91
        self.assertEqual(str(cm.exception), "No `output_regex` specified.")
92
93
        with self.assertRaises(ValueError) as cm:
94
            Linter("some-executable",
95
                   output_format="regex",
96
                   output_regex="",
97
                   severity_map={})
98
        self.assertEqual(
99
            str(cm.exception),
100
            "Provided `severity_map` but named group `severity` is not used "
101
            "in `output_regex`.")
102
103
        with self.assertRaises(ValueError) as cm:
104
            Linter("some-executable")(object)
105
        self.assertEqual(str(cm.exception),
106
                         "`process_output` not provided by given class.")
107
108
        with self.assertRaises(ValueError) as cm:
109
            (Linter("some-executable", output_format="regex", output_regex="")
110
             (self.ManualProcessingTestLinter))
111
        self.assertEqual(
112
            str(cm.exception),
113
            "`process_output` is used by given class, but 'regex' output "
114
            "format was specified.")
115
116
    def test_decorator_generated_default_interface(self):
117
        uut = Linter("some-executable")(self.ManualProcessingTestLinter)
118
        with self.assertRaises(NotImplementedError):
119
            uut.create_arguments("filename", "content", None)
120
121
    def test_decorator_invalid_parameter_types(self):
122
        # Provide some invalid severity maps.
123
        with self.assertRaises(TypeError):
124
            Linter("some-executable",
125
                   output_format="regex",
126
                   output_regex="(?P<severity>)",
127
                   severity_map=list())
128
129
        with self.assertRaises(TypeError) as cm:
130
            Linter("some-executable",
131
                   output_format="regex",
132
                   output_regex="(?P<severity>)",
133
                   severity_map={3: 0})
134
        self.assertEqual(str(cm.exception),
135
                         "The key 3 inside given severity-map is no string.")
136
137
        with self.assertRaises(TypeError) as cm:
138
            Linter("some-executable",
139
                   output_format="regex",
140
                   output_regex="(?P<severity>)",
141
                   severity_map={"critical": "invalid"})
142
        self.assertEqual(str(cm.exception),
143
                         "The value 'invalid' for key 'critical' inside given "
144
                         "severity-map is no valid severity value.")
145
146
        with self.assertRaises(TypeError) as cm:
147
            Linter("some-executable",
148
                   output_format="regex",
149
                   output_regex="(?P<severity>)",
150
                   severity_map={"critical-error": 389274234})
151
        self.assertEqual(str(cm.exception),
152
                         "Invalid severity value 389274234 for key "
153
                         "'critical-error' inside given severity-map.")
154
155
        # Other type-error test cases.
156
157
        with self.assertRaises(TypeError):
158
            Linter("some-executable",
159
                   output_format="corrected",
160
                   diff_message=list())
161
162
        with self.assertRaises(TypeError) as cm:
163
            Linter("some-executable",
164
                   output_format="corrected",
165
                   diff_severity=999888777)
166
        self.assertEqual(str(cm.exception),
167
                         "Invalid value for `diff_severity`: 999888777")
168
169
        with self.assertRaises(TypeError):
170
            Linter("some-executable",
171
                   prerequisite_check_command=("command",),
172
                   prerequisite_check_fail_message=382983)
173
174
    def test_get_executable(self):
175
        uut = Linter("some-executable")(self.ManualProcessingTestLinter)
176
        self.assertEqual(uut.get_executable(), "some-executable")
177
178
    def test_check_prerequisites(self):
179
        uut = Linter(sys.executable)(self.ManualProcessingTestLinter)
180
        self.assertTrue(uut.check_prerequisites())
181
182
        uut = (Linter("invalid_nonexisting_programv412")
183
               (self.ManualProcessingTestLinter))
184
        self.assertEqual(uut.check_prerequisites(),
185
                         "'invalid_nonexisting_programv412' is not installed.")
186
187
        uut = (Linter(sys.executable,
188
                      prerequisite_check_command=(sys.executable, "--version"))
189
               (self.ManualProcessingTestLinter))
190
        self.assertTrue(uut.check_prerequisites())
191
192
        uut = (Linter(sys.executable,
193
                      prerequisite_check_command=("invalid_programv413",))
194
               (self.ManualProcessingTestLinter))
195
        self.assertEqual(uut.check_prerequisites(),
196
                         "Prerequisite check failed.")
197
198
        uut = (Linter(sys.executable,
199
                      prerequisite_check_command=("invalid_programv413",),
200
                      prerequisite_check_fail_message="NOPE")
201
               (self.ManualProcessingTestLinter))
202
        self.assertEqual(uut.check_prerequisites(), "NOPE")
203
204
    def test_output_stream(self):
205
        process_output_mock = Mock()
206
207
        class TestLinter:
208
209
            def process_output(self, output, filename, file):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
210
                process_output_mock(output, filename, file)
211
212
            @staticmethod
213
            def create_arguments(filename, file, config_file):
214
                code = "\n".join(["import sys",
215
                                  "print('hello stdout')",
216
                                  "print('hello stderr', file=sys.stderr)"])
217
                return "-c", code
218
219
        uut = (Linter(sys.executable, output_stream="stdout")
220
               (TestLinter)
221
               (self.section, None))
222
        uut.run("", [])
223
224
        process_output_mock.assert_called_once_with("hello stdout\n", "", [])
225
        process_output_mock.reset_mock()
226
227
        uut = (Linter(sys.executable, output_stream="stderr")
228
               (TestLinter)
229
               (self.section, None))
230
        uut.run("", [])
231
232
        process_output_mock.assert_called_once_with("hello stderr\n", "", [])
233
        process_output_mock.reset_mock()
234
235
        uut = (Linter(sys.executable, output_stream="stderr+stdout")
236
               (TestLinter)
237
               (self.section, None))
238
239
        uut.run("", [])
240
241
        process_output_mock.assert_called_once_with(("hello stderr\n",
242
                                                     "hello stdout\n"), "", [])
243
244
    def test_execute_command(self):
245
        test_program_path = get_testfile_name("stdout_stderr.py")
246
        uut = Linter(sys.executable)(self.ManualProcessingTestLinter)
247
248
        # The test program puts out the stdin content (only the first line) to
249
        # stdout and the arguments passed to stderr.
250
        stdout, stderr = uut._execute_command(
251
            [test_program_path, "some_argument"],
252
            stdin="display content")
253
254
        self.assertEqual(stdout, "display content\n")
255
        self.assertEqual(stderr, "['some_argument']\n")
256
257
    def test_process_output_corrected(self):
258
        uut = (Linter(sys.executable, output_format="corrected")
259
               (self.EmptyTestLinter)
260
               (self.section, None))
261
262
        original = [s + "\n" for s in ["void main()  {", "return 09;", "}"]]
263
        fixed = [s + "\n" for s in ["void main()", "{", "return 9;", "}"]]
264
        fixed_string = "".join(fixed)
265
266
        results = list(uut.process_output(fixed_string,
267
                                          "some-file.c",
268
                                          original))
269
270
        diffs = list(Diff.from_string_arrays(original, fixed).split_diff())
271
        expected = [Result.from_values(uut,
272
                                       "Inconsistency found.",
273
                                       "some-file.c",
274
                                       1, None, 2, None,
275
                                       RESULT_SEVERITY.NORMAL,
276
                                       diffs={"some-file.c": diffs[0]})]
277
278
        self.assertEqual(results, expected)
279
280
        # Test when providing a sequence as output.
281
282
        results = list(uut.process_output([fixed_string, fixed_string],
283
                                          "some-file.c",
284
                                          original))
285
        self.assertEqual(results, 2 * expected)
286
287
    def test_process_output_regex(self):
288
        # Also test the case when an unknown severity is matched.
289
        test_output = ("12:4-14:0-Serious issue (error) -> ORIGIN=X\n"
290
                       "0:0-0:1-This is a warning (warning) -> ORIGIN=Y\n"
291
                       "813:77-1024:32-Just a note (info) -> ORIGIN=Z\n"
292
                       "0:0-0:0-Some unknown sev (???) -> ORIGIN=W\n")
293
        regex = (r"(?P<line>\d+):(?P<column>\d+)-"
294
                 r"(?P<end_line>\d+):(?P<end_column>\d+)-"
295
                 r"(?P<message>.*) \((?P<severity>.*)\) -> "
296
                 r"ORIGIN=(?P<origin>.*)")
297
298
        uut = (Linter(sys.executable,
299
                      output_format="regex",
300
                      output_regex=regex)
301
               (self.EmptyTestLinter)
302
               (self.section, None))
303
        uut.warn = Mock()
304
305
        sample_file = "some-file.xtx"
306
        results = list(uut.process_output(test_output, sample_file, [""]))
307
        expected = [Result.from_values("EmptyTestLinter (X)",
308
                                       "Serious issue",
309
                                       sample_file,
310
                                       12, 4, 14, 0,
311
                                       RESULT_SEVERITY.MAJOR),
312
                    Result.from_values("EmptyTestLinter (Y)",
313
                                       "This is a warning",
314
                                       sample_file,
315
                                       0, 0, 0, 1,
316
                                       RESULT_SEVERITY.NORMAL),
317
                    Result.from_values("EmptyTestLinter (Z)",
318
                                       "Just a note",
319
                                       sample_file,
320
                                       813, 77, 1024, 32,
321
                                       RESULT_SEVERITY.INFO),
322
                    Result.from_values("EmptyTestLinter (W)",
323
                                       "Some unknown sev",
324
                                       sample_file,
325
                                       0, 0, 0, 0,
326
                                       RESULT_SEVERITY.NORMAL)]
327
328
        self.assertEqual(results, expected)
329
        uut.warn.assert_called_once_with(
330
            "No correspondence for '???' found in given severity map. "
331
            "Assuming `RESULT_SEVERITY.NORMAL`.")
332
333
        # Test when providing a sequence as output.
334
        test_output = ["", "12:4-14:0-Serious issue (error) -> ORIGIN=X\n"]
335
        results = list(uut.process_output(test_output, sample_file, [""]))
336
        expected = [Result.from_values("EmptyTestLinter (X)",
337
                                       "Serious issue",
338
                                       sample_file,
339
                                       12, 4, 14, 0,
340
                                       RESULT_SEVERITY.MAJOR)]
341
342
        self.assertEqual(results, expected)
343
344
    def test_get_non_optional_settings(self):
345
        class Handler(self.ManualProcessingTestLinter):
346
347
            @staticmethod
348
            def create_arguments(filename, file, config_file, param_x: int):
349
                pass
350
351
            @staticmethod
352
            def generate_config(filename, file, superparam):
353
                """
354
                :param superparam: A superparam!
355
                """
356
                return None
357
358
        uut = Linter(sys.executable)(Handler)
359
360
        self.assertEqual(uut.get_non_optional_settings(),
361
                         {"param_x": ("No description given.", int),
362
                          "superparam": ("A superparam!", None)})
363
364
    def test_section_settings_forwarding(self):
365
        create_arguments_mock = Mock()
366
        generate_config_mock = Mock()
367
        process_output_mock = Mock()
368
369
        class Handler(self.ManualProcessingTestLinter):
370
371
            @staticmethod
372
            def create_arguments(filename, file, config_file, my_param: int):
373
                create_arguments_mock(filename, file, config_file, my_param)
374
                # Execute python and do nothing.
375
                return "-c", "print('coala!')"
376
377
            @staticmethod
378
            def generate_config(filename, file, my_config_param: int):
379
                generate_config_mock(filename, file, my_config_param)
380
                return None
381
382
            def process_output(self, output, filename, file, makman2: str):
383
                process_output_mock(output, filename, file, makman2)
384
385
        self.section["my_param"] = "109"
386
        self.section["my_config_param"] = "88"
387
        self.section["makman2"] = "is cool"
388
389
        uut = Linter(sys.executable)(Handler)(self.section, None)
390
391
        self.assertIsNotNone(list(uut.execute(filename="some_file.cs",
392
                                              file=[])))
393
        create_arguments_mock.assert_called_once_with(
394
            "some_file.cs", [], None, 109)
395
        generate_config_mock.assert_called_once_with("some_file.cs", [], 88)
396
        process_output_mock.assert_called_once_with(
397
            "coala!\n", "some_file.cs", [], "is cool")
398
399
    def test_section_settings_defaults_forwarding(self):
400
        create_arguments_mock = Mock()
401
        generate_config_mock = Mock()
402
        process_output_mock = Mock()
403
404
        class Handler:
405
406
            @staticmethod
407
            def generate_config(filename, file, some_default: str="x"):
408
                generate_config_mock(filename, file, some_default)
409
                return None
410
411
            @staticmethod
412
            def create_arguments(filename, file, config_file, default: int=3):
413
                create_arguments_mock(
414
                    filename, file, config_file, default)
415
                return "-c", "print('hello')"
416
417
            def process_output(self, output, filename, file, xxx: int=64):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
418
                process_output_mock(output, filename, file, xxx)
419
420
        uut = Linter(sys.executable)(Handler)(self.section, None)
421
422
        self.assertIsNotNone(list(uut.execute(filename="abc.py", file=[])))
423
        create_arguments_mock.assert_called_once_with("abc.py", [], None, 3)
424
        generate_config_mock.assert_called_once_with("abc.py", [], "x")
425
        process_output_mock.assert_called_once_with(
426
            "hello\n", "abc.py", [], 64)
427
428
        create_arguments_mock.reset_mock()
429
        generate_config_mock.reset_mock()
430
        process_output_mock.reset_mock()
431
432
        self.section["default"] = "1000"
433
        self.section["some_default"] = "xyz"
434
        self.section["xxx"] = "-50"
435
        self.assertIsNotNone(list(uut.execute(filename="def.py", file=[])))
436
        create_arguments_mock.assert_called_once_with("def.py", [], None, 1000)
437
        generate_config_mock.assert_called_once_with("def.py", [], "xyz")
438
        process_output_mock.assert_called_once_with(
439
            "hello\n", "def.py", [], -50)
440
441
    def test_generate_config(self):
442
        uut = Linter("")(self.ManualProcessingTestLinter)
443
        with uut._create_config("filename", []) as config_file:
444
            self.assertIsNone(config_file)
445
446
        class ConfigurationTestLinter(self.ManualProcessingTestLinter):
447
448
            @staticmethod
449
            def generate_config(filename, file, val):
450
                return "config_value = " + str(val)
451
452
        uut = Linter("", config_suffix=".xml")(ConfigurationTestLinter)
453
        with uut._create_config("filename", [], val=88) as config_file:
454
            self.assertTrue(os.path.isfile(config_file))
455
            self.assertEqual(config_file[-4:], ".xml")
456
            with open(config_file, mode="r") as fl:
457
                self.assertEqual(fl.read(), "config_value = 88")
458
        self.assertFalse(os.path.isfile(config_file))
459
460
461
class LinterReallifeTest(unittest.TestCase):
462
463
    def setUp(self):
464
        self.section = Section("REALLIFE_TEST_SECTION")
465
466
        self.test_program_path = get_testfile_name("test_linter.py")
467
        self.test_program_regex = (
468
            r"L(?P<line>\d+)C(?P<column>\d+)-"
469
            r"L(?P<end_line>\d+)C(?P<end_column>\d+):"
470
            r" (?P<message>.*) \| (?P<severity>.+) SEVERITY")
471
        self.test_program_severity_map = {"MAJOR": RESULT_SEVERITY.MAJOR}
472
473
        self.testfile_path = get_testfile_name("test_file.txt")
474
        with open(self.testfile_path, mode="r") as fl:
475
            self.testfile_content = fl.read().splitlines(keepends=True)
476
477
        self.testfile2_path = get_testfile_name("test_file2.txt")
478
        with open(self.testfile2_path, mode="r") as fl:
479
            self.testfile2_content = fl.read().splitlines(keepends=True)
480
481 View Code Duplication
    def test_nostdin_nostderr_noconfig_nocorrection(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
482
        create_arguments_mock = Mock()
483
484
        class Handler:
485
486
            @staticmethod
487
            def create_arguments(filename, file, config_file):
488
                create_arguments_mock(filename, file, config_file)
489
                return self.test_program_path, filename
490
491
        uut = (Linter(sys.executable,
492
                      output_format="regex",
493
                      output_regex=self.test_program_regex,
494
                      severity_map=self.test_program_severity_map)
495
               (Handler)
496
               (self.section, None))
497
498
        results = list(uut.run(self.testfile_path, self.testfile_content))
499
        expected = [Result.from_values(uut,
500
                                       "Invalid char ('0')",
501
                                       self.testfile_path,
502
                                       3, 0, 3, 1,
503
                                       RESULT_SEVERITY.MAJOR),
504
                    Result.from_values(uut,
505
                                       "Invalid char ('.')",
506
                                       self.testfile_path,
507
                                       5, 0, 5, 1,
508
                                       RESULT_SEVERITY.MAJOR),
509
                    Result.from_values(uut,
510
                                       "Invalid char ('p')",
511
                                       self.testfile_path,
512
                                       9, 0, 9, 1,
513
                                       RESULT_SEVERITY.MAJOR)]
514
515
        self.assertEqual(results, expected)
516
        create_arguments_mock.assert_called_once_with(
517
            self.testfile_path, self.testfile_content, None)
518
519 View Code Duplication
    def test_stdin_stderr_noconfig_nocorrection(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
520
        create_arguments_mock = Mock()
521
522
        class Handler:
523
524
            @staticmethod
525
            def create_arguments(filename, file, config_file):
526
                create_arguments_mock(filename, file, config_file)
527
                return (self.test_program_path,
528
                        "--use_stderr",
529
                        "--use_stdin",
530
                        filename)
531
532
        uut = (Linter(sys.executable,
533
                      use_stdin=True,
534
                      output_stream="stderr",
535
                      output_format="regex",
536
                      output_regex=self.test_program_regex,
537
                      severity_map=self.test_program_severity_map)
538
               (Handler)
539
               (self.section, None))
540
541
        results = list(uut.run(self.testfile2_path, self.testfile2_content))
542
        expected = [Result.from_values(uut,
543
                                       "Invalid char ('X')",
544
                                       self.testfile2_path,
545
                                       0, 0, 0, 1,
546
                                       RESULT_SEVERITY.MAJOR),
547
                    Result.from_values(uut,
548
                                       "Invalid char ('i')",
549
                                       self.testfile2_path,
550
                                       4, 0, 4, 1,
551
                                       RESULT_SEVERITY.MAJOR)]
552
553
        self.assertEqual(results, expected)
554
        create_arguments_mock.assert_called_once_with(
555
            self.testfile2_path, self.testfile2_content, None)
556
557
    def test_nostdin_nostderr_noconfig_correction(self):
558
        create_arguments_mock = Mock()
559
560
        class Handler:
561
562
            @staticmethod
563
            def create_arguments(filename, file, config_file):
564
                create_arguments_mock(filename, file, config_file)
565
                return self.test_program_path, "--correct", filename
566
567
        uut = (Linter(sys.executable,
568
                      output_format="corrected",
569
                      diff_severity=RESULT_SEVERITY.INFO,
570
                      diff_message="Custom message")
571
               (Handler)
572
               (self.section, None))
573
574
        results = list(uut.run(self.testfile_path, self.testfile_content))
575
576
        expected_correction = [s + "\n"
577
                               for s in ["+", "-", "*", "++", "-", "-", "+"]]
578
579
        diffs = list(Diff.from_string_arrays(
580
            self.testfile_content,
581
            expected_correction).split_diff())
582
583
        expected = [Result.from_values(uut,
584
                                       "Custom message",
585
                                       self.testfile_path,
586
                                       4, None, 4, None,
587
                                       RESULT_SEVERITY.INFO,
588
                                       diffs={self.testfile_path: diffs[0]}),
589
                    Result.from_values(uut,
590
                                       "Custom message",
591
                                       self.testfile_path,
592
                                       6, None, 6, None,
593
                                       RESULT_SEVERITY.INFO,
594
                                       diffs={self.testfile_path: diffs[1]}),
595
                    Result.from_values(uut,
596
                                       "Custom message",
597
                                       self.testfile_path,
598
                                       10, None, 10, None,
599
                                       RESULT_SEVERITY.INFO,
600
                                       diffs={self.testfile_path: diffs[2]})]
601
602
        self.assertEqual(results, expected)
603
        create_arguments_mock.assert_called_once_with(
604
            self.testfile_path, self.testfile_content, None)
605
606
    def test_stdin_stdout_stderr_config_nocorrection(self):
607
        create_arguments_mock = Mock()
608
        generate_config_mock = Mock()
609
610
        class Handler:
611
612
            @staticmethod
613
            def generate_config(filename, file, some_val):
614
                # some_val shall only test the argument delegation from run().
615
                generate_config_mock(filename, file, some_val)
616
                return "\n".join(["use_stdin", "use_stderr"])
617
618
            @staticmethod
619
            def create_arguments(filename, file, config_file, some_val):
620
                create_arguments_mock(filename, file, config_file, some_val)
621
                return self.test_program_path, "--config", config_file
622
623
        uut = (Linter(sys.executable,
624
                      use_stdin=True,
625
                      output_stream="stderr+stdout",
626
                      output_format="regex",
627
                      output_regex=self.test_program_regex,
628
                      severity_map=self.test_program_severity_map)
629
               (Handler)
630
               (self.section, None))
631
632
        results = list(uut.run(self.testfile_path,
633
                               self.testfile_content,
634
                               some_val=33))
635
        expected = [Result.from_values(uut,
636
                                       "Invalid char ('0')",
637
                                       self.testfile_path,
638
                                       3, 0, 3, 1,
639
                                       RESULT_SEVERITY.MAJOR),
640
                    Result.from_values(uut,
641
                                       "Invalid char ('.')",
642
                                       self.testfile_path,
643
                                       5, 0, 5, 1,
644
                                       RESULT_SEVERITY.MAJOR),
645
                    Result.from_values(uut,
646
                                       "Invalid char ('p')",
647
                                       self.testfile_path,
648
                                       9, 0, 9, 1,
649
                                       RESULT_SEVERITY.MAJOR)]
650
651
        self.assertEqual(results, expected)
652
        create_arguments_mock.assert_called_once_with(
653
            self.testfile_path, self.testfile_content, ANY, 33)
654
        self.assertIsNotNone(create_arguments_mock.call_args[0][2])
655
        generate_config_mock.assert_called_once_with(
656
            self.testfile_path, self.testfile_content, 33)
657
658
    def test_stdin_stderr_config_correction(self):
659
        create_arguments_mock = Mock()
660
        generate_config_mock = Mock()
661
662
        # `some_value_A` and `some_value_B` are used to test the different
663
        # delegation to `generate_config()` and `create_arguments()`
664
        # accordingly.
665
        class Handler:
666
667
            @staticmethod
668
            def generate_config(filename, file, some_value_A):
669
                generate_config_mock(filename, file, some_value_A)
670
                return "\n".join(["use_stdin", "use_stderr", "correct"])
671
672
            @staticmethod
673
            def create_arguments(filename, file, config_file, some_value_B):
674
                create_arguments_mock(filename, file, config_file,
675
                                      some_value_B)
676
                return self.test_program_path, "--config", config_file
677
678
        uut = (Linter(sys.executable,
679
                      use_stdin=True,
680
                      output_stream="stderr",
681
                      output_format="corrected",
682
                      config_suffix=".conf")
683
               (Handler)
684
               (self.section, None))
685
686
        results = list(uut.run(self.testfile2_path,
687
                               self.testfile2_content,
688
                               some_value_A=124,
689
                               some_value_B=-78))
690
691
        expected_correction = ["+", "/", "/", "-"]
692
        expected_correction = [s + "\n" for s in expected_correction]
693
694
        diffs = list(Diff.from_string_arrays(
695
            self.testfile2_content,
696
            expected_correction).split_diff())
697
698
        expected = [Result.from_values(uut,
699
                                       "Inconsistency found.",
700
                                       self.testfile2_path,
701
                                       1, None, 1, None,
702
                                       RESULT_SEVERITY.NORMAL,
703
                                       diffs={self.testfile2_path: diffs[0]}),
704
                    Result.from_values(uut,
705
                                       "Inconsistency found.",
706
                                       self.testfile2_path,
707
                                       5, None, 5, None,
708
                                       RESULT_SEVERITY.NORMAL,
709
                                       diffs={self.testfile2_path: diffs[1]})]
710
711
        self.assertEqual(results, expected)
712
        create_arguments_mock.assert_called_once_with(
713
            self.testfile2_path, self.testfile2_content, ANY, -78)
714
        self.assertEqual(create_arguments_mock.call_args[0][2][-5:], ".conf")
715
        generate_config_mock.assert_called_once_with(
716
            self.testfile2_path, self.testfile2_content, 124)
717