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

ConfigurationTestLinter   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 5
Duplicated Lines 0 %
Metric Value
dl 0
loc 5
rs 10
wmc 1
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", use_stdout=False, use_stderr=False)
81
        self.assertEqual(str(cm.exception),
82
                         "No output streams provided at all.")
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
            @staticmethod
210
            def process_output(output, filename, file):
211
                process_output_mock(output, filename, file)
212
213
            @staticmethod
214
            def create_arguments(filename, file, config_file):
215
                code = "\n".join(["import sys",
216
                                  "print('hello stdout')",
217
                                  "print('hello stderr', file=sys.stderr)"])
218
                return "-c", code
219
220
        uut = (Linter(sys.executable, use_stdout=True)
221
               (TestLinter)
222
               (self.section, None))
223
        uut.run("", [])
224
225
        process_output_mock.assert_called_once_with("hello stdout\n", "", [])
226
        process_output_mock.reset_mock()
227
228
        uut = (Linter(sys.executable, use_stdout=False, use_stderr=True)
229
               (TestLinter)
230
               (self.section, None))
231
        uut.run("", [])
232
233
        process_output_mock.assert_called_once_with("hello stderr\n", "", [])
234
        process_output_mock.reset_mock()
235
236
        uut = (Linter(sys.executable, use_stdout=True, use_stderr=True)
237
               (TestLinter)
238
               (self.section, None))
239
240
        uut.run("", [])
241
242
        process_output_mock.assert_called_once_with(("hello stdout\n",
243
                                                     "hello stderr\n"), "", [])
244
245
    def test_execute_command(self):
246
        test_program_path = get_testfile_name("stdout_stderr.py")
247
        uut = Linter(sys.executable)(self.ManualProcessingTestLinter)
248
249
        # The test program puts out the stdin content (only the first line) to
250
        # stdout and the arguments passed to stderr.
251
        stdout, stderr = uut._execute_command(
252
            [test_program_path, "some_argument"],
253
            stdin="display content")
254
255
        self.assertEqual(stdout, "display content\n")
256
        self.assertEqual(stderr, "['some_argument']\n")
257
258
    def test_process_output_corrected(self):
259
        uut = (Linter(sys.executable, output_format="corrected")
260
               (self.EmptyTestLinter)
261
               (self.section, None))
262
263
        original = [s + "\n" for s in ["void main()  {", "return 09;", "}"]]
264
        fixed = [s + "\n" for s in ["void main()", "{", "return 9;", "}"]]
265
        fixed_string = "".join(fixed)
266
267
        results = list(uut.process_output(fixed_string,
268
                                          "some-file.c",
269
                                          original))
270
271
        diffs = list(Diff.from_string_arrays(original, fixed).split_diff())
272
        expected = [Result.from_values(uut,
273
                                       "Inconsistency found.",
274
                                       "some-file.c",
275
                                       1, None, 2, None,
276
                                       RESULT_SEVERITY.NORMAL,
277
                                       diffs={"some-file.c": diffs[0]})]
278
279
        self.assertEqual(results, expected)
280
281
        # Test when providing a sequence as output.
282
283
        results = list(uut.process_output([fixed_string, fixed_string],
284
                                          "some-file.c",
285
                                          original))
286
        self.assertEqual(results, 2 * expected)
287
288
    def test_process_output_regex(self):
289
        # Also test the case when an unknown severity is matched.
290
        test_output = ("12:4-14:0-Serious issue (error) -> ORIGIN=X\n"
291
                       "0:0-0:1-This is a warning (warning) -> ORIGIN=Y\n"
292
                       "813:77-1024:32-Just a note (info) -> ORIGIN=Z\n"
293
                       "0:0-0:0-Some unknown sev (???) -> ORIGIN=W\n")
294
        regex = (r"(?P<line>\d+):(?P<column>\d+)-"
295
                 r"(?P<end_line>\d+):(?P<end_column>\d+)-"
296
                 r"(?P<message>.*) \((?P<severity>.*)\) -> "
297
                 r"ORIGIN=(?P<origin>.*)")
298
299
        uut = (Linter(sys.executable,
300
                      output_format="regex",
301
                      output_regex=regex)
302
               (self.EmptyTestLinter)
303
               (self.section, None))
304
        uut.warn = Mock()
305
306
        sample_file = "some-file.xtx"
307
        results = list(uut.process_output(test_output, sample_file, [""]))
308
        expected = [Result.from_values("EmptyTestLinter (X)",
309
                                       "Serious issue",
310
                                       sample_file,
311
                                       12, 4, 14, 0,
312
                                       RESULT_SEVERITY.MAJOR),
313
                    Result.from_values("EmptyTestLinter (Y)",
314
                                       "This is a warning",
315
                                       sample_file,
316
                                       0, 0, 0, 1,
317
                                       RESULT_SEVERITY.NORMAL),
318
                    Result.from_values("EmptyTestLinter (Z)",
319
                                       "Just a note",
320
                                       sample_file,
321
                                       813, 77, 1024, 32,
322
                                       RESULT_SEVERITY.INFO),
323
                    Result.from_values("EmptyTestLinter (W)",
324
                                       "Some unknown sev",
325
                                       sample_file,
326
                                       0, 0, 0, 0,
327
                                       RESULT_SEVERITY.NORMAL)]
328
329
        self.assertEqual(results, expected)
330
        uut.warn.assert_called_once_with(
331
            "No correspondence for '???' found in given severity map. "
332
            "Assuming `RESULT_SEVERITY.NORMAL`.")
333
334
        # Test when providing a sequence as output.
335
        test_output = ["", "12:4-14:0-Serious issue (error) -> ORIGIN=X\n"]
336
        results = list(uut.process_output(test_output, sample_file, [""]))
337
        expected = [Result.from_values("EmptyTestLinter (X)",
338
                                       "Serious issue",
339
                                       sample_file,
340
                                       12, 4, 14, 0,
341
                                       RESULT_SEVERITY.MAJOR)]
342
343
        self.assertEqual(results, expected)
344
345
    def test_get_non_optional_settings(self):
346
        class Handler(self.ManualProcessingTestLinter):
347
348
            @staticmethod
349
            def create_arguments(filename, file, config_file, param_x: int):
350
                pass
351
352
            @staticmethod
353
            def generate_config(filename, file, superparam):
354
                """
355
                :param superparam: A superparam!
356
                """
357
                return None
358
359
        uut = Linter(sys.executable)(Handler)
360
361
        self.assertEqual(uut.get_non_optional_settings(),
362
                         {"param_x": ("No description given.", int),
363
                          "superparam": ("A superparam!", None)})
364
365
    def test_section_settings_forwarding(self):
366
        create_arguments_mock = Mock()
367
        generate_config_mock = Mock()
368
        process_output_mock = Mock()
369
370
        class Handler(self.ManualProcessingTestLinter):
371
372
            @staticmethod
373
            def create_arguments(filename, file, config_file, my_param: int):
374
                create_arguments_mock(filename, file, config_file, my_param)
375
                # Execute python and do nothing.
376
                return "-c", "print('coala!')"
377
378
            @staticmethod
379
            def generate_config(filename, file, my_config_param: int):
380
                generate_config_mock(filename, file, my_config_param)
381
                return None
382
383
            def process_output(self, output, filename, file, makman2: str):
384
                process_output_mock(output, filename, file, makman2)
385
386
        self.section["my_param"] = "109"
387
        self.section["my_config_param"] = "88"
388
        self.section["makman2"] = "is cool"
389
390
        uut = Linter(sys.executable)(Handler)(self.section, None)
391
392
        self.assertIsNotNone(list(uut.execute(filename="some_file.cs",
393
                                              file=[])))
394
        create_arguments_mock.assert_called_once_with(
395
            "some_file.cs", [], None, 109)
396
        generate_config_mock.assert_called_once_with("some_file.cs", [], 88)
397
        process_output_mock.assert_called_once_with(
398
            "coala!\n", "some_file.cs", [], "is cool")
399
400
    def test_section_settings_defaults_forwarding(self):
401
        create_arguments_mock = Mock()
402
        generate_config_mock = Mock()
403
        process_output_mock = Mock()
404
405
        class Handler:
406
407
            @staticmethod
408
            def generate_config(filename, file, some_default: str="x"):
409
                generate_config_mock(filename, file, some_default)
410
                return None
411
412
            @staticmethod
413
            def create_arguments(filename, file, config_file, default: int=3):
414
                create_arguments_mock(
415
                    filename, file, config_file, default)
416
                return "-c", "print('hello')"
417
418
            @staticmethod
419
            def process_output(output, filename, file, xxx: int=64):
420
                process_output_mock(output, filename, file, xxx)
421
422
        uut = Linter(sys.executable)(Handler)(self.section, None)
423
424
        self.assertIsNotNone(list(uut.execute(filename="abc.py", file=[])))
425
        create_arguments_mock.assert_called_once_with("abc.py", [], None, 3)
426
        generate_config_mock.assert_called_once_with("abc.py", [], "x")
427
        process_output_mock.assert_called_once_with(
428
            "hello\n", "abc.py", [], 64)
429
430
        create_arguments_mock.reset_mock()
431
        generate_config_mock.reset_mock()
432
        process_output_mock.reset_mock()
433
434
        self.section["default"] = "1000"
435
        self.section["some_default"] = "xyz"
436
        self.section["xxx"] = "-50"
437
        self.assertIsNotNone(list(uut.execute(filename="def.py", file=[])))
438
        create_arguments_mock.assert_called_once_with("def.py", [], None, 1000)
439
        generate_config_mock.assert_called_once_with("def.py", [], "xyz")
440
        process_output_mock.assert_called_once_with(
441
            "hello\n", "def.py", [], -50)
442
443
    def test_generate_config(self):
444
        uut = Linter("")(self.ManualProcessingTestLinter)
445
        with uut._create_config("filename", []) as config_file:
446
            self.assertIsNone(config_file)
447
448
        class ConfigurationTestLinter(self.ManualProcessingTestLinter):
449
450
            @staticmethod
451
            def generate_config(filename, file, val):
452
                return "config_value = " + str(val)
453
454
        uut = Linter("", config_suffix=".xml")(ConfigurationTestLinter)
455
        with uut._create_config("filename", [], val=88) as config_file:
456
            self.assertTrue(os.path.isfile(config_file))
457
            self.assertEqual(config_file[-4:], ".xml")
458
            with open(config_file, mode="r") as fl:
459
                self.assertEqual(fl.read(), "config_value = 88")
460
        self.assertFalse(os.path.isfile(config_file))
461
462
    def test_metaclass_repr(self):
463
        uut = Linter("my-tool")(self.ManualProcessingTestLinter)
464
        self.assertRegex(repr(uut),
465
                         r"<ManualProcessingTestLinter class \(wrapping "
466
                         r"'my-tool'\) at 0x[0-9a-f]+>")
467
468
        # Test also whether derivatives change the class name accordingly.
469
        class DerivedLinter(uut):
470
            pass
471
        self.assertRegex(repr(DerivedLinter),
472
                         r"<DerivedLinter class \(wrapping 'my-tool'\) at "
473
                         r"0x[0-9a-f]+>")
474
475
476
class LinterReallifeTest(unittest.TestCase):
477
478
    def setUp(self):
479
        self.section = Section("REALLIFE_TEST_SECTION")
480
481
        self.test_program_path = get_testfile_name("test_linter.py")
482
        self.test_program_regex = (
483
            r"L(?P<line>\d+)C(?P<column>\d+)-"
484
            r"L(?P<end_line>\d+)C(?P<end_column>\d+):"
485
            r" (?P<message>.*) \| (?P<severity>.+) SEVERITY")
486
        self.test_program_severity_map = {"MAJOR": RESULT_SEVERITY.MAJOR}
487
488
        self.testfile_path = get_testfile_name("test_file.txt")
489
        with open(self.testfile_path, mode="r") as fl:
490
            self.testfile_content = fl.read().splitlines(keepends=True)
491
492
        self.testfile2_path = get_testfile_name("test_file2.txt")
493
        with open(self.testfile2_path, mode="r") as fl:
494
            self.testfile2_content = fl.read().splitlines(keepends=True)
495
496
    def test_nostdin_nostderr_noconfig_nocorrection(self):
497
        create_arguments_mock = Mock()
498
499
        class Handler:
500
501
            @staticmethod
502
            def create_arguments(filename, file, config_file):
503
                create_arguments_mock(filename, file, config_file)
504
                return self.test_program_path, filename
505
506
        uut = (Linter(sys.executable,
507
                      output_format="regex",
508
                      output_regex=self.test_program_regex,
509
                      severity_map=self.test_program_severity_map)
510
               (Handler)
511
               (self.section, None))
512
513
        results = list(uut.run(self.testfile_path, self.testfile_content))
514
        expected = [Result.from_values(uut,
515
                                       "Invalid char ('0')",
516
                                       self.testfile_path,
517
                                       3, 0, 3, 1,
518
                                       RESULT_SEVERITY.MAJOR),
519
                    Result.from_values(uut,
520
                                       "Invalid char ('.')",
521
                                       self.testfile_path,
522
                                       5, 0, 5, 1,
523
                                       RESULT_SEVERITY.MAJOR),
524
                    Result.from_values(uut,
525
                                       "Invalid char ('p')",
526
                                       self.testfile_path,
527
                                       9, 0, 9, 1,
528
                                       RESULT_SEVERITY.MAJOR)]
529
530
        self.assertEqual(results, expected)
531
        create_arguments_mock.assert_called_once_with(
532
            self.testfile_path, self.testfile_content, None)
533
534
    def test_stdin_stderr_noconfig_nocorrection(self):
535
        create_arguments_mock = Mock()
536
537
        class Handler:
538
539
            @staticmethod
540
            def create_arguments(filename, file, config_file):
541
                create_arguments_mock(filename, file, config_file)
542
                return (self.test_program_path,
543
                        "--use_stderr",
544
                        "--use_stdin",
545
                        filename)
546
547
        uut = (Linter(sys.executable,
548
                      use_stdin=True,
549
                      use_stdout=False,
550
                      use_stderr=True,
551
                      output_format="regex",
552
                      output_regex=self.test_program_regex,
553
                      severity_map=self.test_program_severity_map)
554
               (Handler)
555
               (self.section, None))
556
557
        results = list(uut.run(self.testfile2_path, self.testfile2_content))
558
        expected = [Result.from_values(uut,
559
                                       "Invalid char ('X')",
560
                                       self.testfile2_path,
561
                                       0, 0, 0, 1,
562
                                       RESULT_SEVERITY.MAJOR),
563
                    Result.from_values(uut,
564
                                       "Invalid char ('i')",
565
                                       self.testfile2_path,
566
                                       4, 0, 4, 1,
567
                                       RESULT_SEVERITY.MAJOR)]
568
569
        self.assertEqual(results, expected)
570
        create_arguments_mock.assert_called_once_with(
571
            self.testfile2_path, self.testfile2_content, None)
572
573
    def test_nostdin_nostderr_noconfig_correction(self):
574
        create_arguments_mock = Mock()
575
576
        class Handler:
577
578
            @staticmethod
579
            def create_arguments(filename, file, config_file):
580
                create_arguments_mock(filename, file, config_file)
581
                return self.test_program_path, "--correct", filename
582
583
        uut = (Linter(sys.executable,
584
                      output_format="corrected",
585
                      diff_severity=RESULT_SEVERITY.INFO,
586
                      diff_message="Custom message")
587
               (Handler)
588
               (self.section, None))
589
590
        results = list(uut.run(self.testfile_path, self.testfile_content))
591
592
        expected_correction = [s + "\n"
593
                               for s in ["+", "-", "*", "++", "-", "-", "+"]]
594
595
        diffs = list(Diff.from_string_arrays(
596
            self.testfile_content,
597
            expected_correction).split_diff())
598
599
        expected = [Result.from_values(uut,
600
                                       "Custom message",
601
                                       self.testfile_path,
602
                                       4, None, 4, None,
603
                                       RESULT_SEVERITY.INFO,
604
                                       diffs={self.testfile_path: diffs[0]}),
605
                    Result.from_values(uut,
606
                                       "Custom message",
607
                                       self.testfile_path,
608
                                       6, None, 6, None,
609
                                       RESULT_SEVERITY.INFO,
610
                                       diffs={self.testfile_path: diffs[1]}),
611
                    Result.from_values(uut,
612
                                       "Custom message",
613
                                       self.testfile_path,
614
                                       10, None, 10, None,
615
                                       RESULT_SEVERITY.INFO,
616
                                       diffs={self.testfile_path: diffs[2]})]
617
618
        self.assertEqual(results, expected)
619
        create_arguments_mock.assert_called_once_with(
620
            self.testfile_path, self.testfile_content, None)
621
622
    def test_stdin_stdout_stderr_config_nocorrection(self):
623
        create_arguments_mock = Mock()
624
        generate_config_mock = Mock()
625
626
        class Handler:
627
628
            @staticmethod
629
            def generate_config(filename, file, some_val):
630
                # some_val shall only test the argument delegation from run().
631
                generate_config_mock(filename, file, some_val)
632
                return "\n".join(["use_stdin", "use_stderr"])
633
634
            @staticmethod
635
            def create_arguments(filename, file, config_file, some_val):
636
                create_arguments_mock(filename, file, config_file, some_val)
637
                return self.test_program_path, "--config", config_file
638
639
        uut = (Linter(sys.executable,
640
                      use_stdin=True,
641
                      use_stderr=True,
642
                      output_format="regex",
643
                      output_regex=self.test_program_regex,
644
                      severity_map=self.test_program_severity_map)
645
               (Handler)
646
               (self.section, None))
647
648
        results = list(uut.run(self.testfile_path,
649
                               self.testfile_content,
650
                               some_val=33))
651
        expected = [Result.from_values(uut,
652
                                       "Invalid char ('0')",
653
                                       self.testfile_path,
654
                                       3, 0, 3, 1,
655
                                       RESULT_SEVERITY.MAJOR),
656
                    Result.from_values(uut,
657
                                       "Invalid char ('.')",
658
                                       self.testfile_path,
659
                                       5, 0, 5, 1,
660
                                       RESULT_SEVERITY.MAJOR),
661
                    Result.from_values(uut,
662
                                       "Invalid char ('p')",
663
                                       self.testfile_path,
664
                                       9, 0, 9, 1,
665
                                       RESULT_SEVERITY.MAJOR)]
666
667
        self.assertEqual(results, expected)
668
        create_arguments_mock.assert_called_once_with(
669
            self.testfile_path, self.testfile_content, ANY, 33)
670
        self.assertIsNotNone(create_arguments_mock.call_args[0][2])
671
        generate_config_mock.assert_called_once_with(
672
            self.testfile_path, self.testfile_content, 33)
673
674
    def test_stdin_stderr_config_correction(self):
675
        create_arguments_mock = Mock()
676
        generate_config_mock = Mock()
677
678
        # `some_value_A` and `some_value_B` are used to test the different
679
        # delegation to `generate_config()` and `create_arguments()`
680
        # accordingly.
681
        class Handler:
682
683
            @staticmethod
684
            def generate_config(filename, file, some_value_A):
685
                generate_config_mock(filename, file, some_value_A)
686
                return "\n".join(["use_stdin", "use_stderr", "correct"])
687
688
            @staticmethod
689
            def create_arguments(filename, file, config_file, some_value_B):
690
                create_arguments_mock(filename, file, config_file,
691
                                      some_value_B)
692
                return self.test_program_path, "--config", config_file
693
694
        uut = (Linter(sys.executable,
695
                      use_stdin=True,
696
                      use_stdout=False,
697
                      use_stderr=True,
698
                      output_format="corrected",
699
                      config_suffix=".conf")
700
               (Handler)
701
               (self.section, None))
702
703
        results = list(uut.run(self.testfile2_path,
704
                               self.testfile2_content,
705
                               some_value_A=124,
706
                               some_value_B=-78))
707
708
        expected_correction = ["+", "/", "/", "-"]
709
        expected_correction = [s + "\n" for s in expected_correction]
710
711
        diffs = list(Diff.from_string_arrays(
712
            self.testfile2_content,
713
            expected_correction).split_diff())
714
715
        expected = [Result.from_values(uut,
716
                                       "Inconsistency found.",
717
                                       self.testfile2_path,
718
                                       1, None, 1, None,
719
                                       RESULT_SEVERITY.NORMAL,
720
                                       diffs={self.testfile2_path: diffs[0]}),
721
                    Result.from_values(uut,
722
                                       "Inconsistency found.",
723
                                       self.testfile2_path,
724
                                       5, None, 5, None,
725
                                       RESULT_SEVERITY.NORMAL,
726
                                       diffs={self.testfile2_path: diffs[1]})]
727
728
        self.assertEqual(results, expected)
729
        create_arguments_mock.assert_called_once_with(
730
            self.testfile2_path, self.testfile2_content, ANY, -78)
731
        self.assertEqual(create_arguments_mock.call_args[0][2][-5:], ".conf")
732
        generate_config_mock.assert_called_once_with(
733
            self.testfile2_path, self.testfile2_content, 124)
734