1import pytest
2import checkpackagelib.test_util as util
3import checkpackagelib.lib_config as m
4
5
6AttributesOrder = [
7    ('good example',
8     'any',
9     'config BR2_PACKAGE_FOO\n'
10     'bool "foo"\n'
11     'default y\n'
12     'depends on BR2_USE_BAR # runtime\n'
13     'select BR2_PACKAGE_BAZ\n'
14     'help\n'
15     '\t  help text\n',
16     []),
17    ('depends before default',
18     'any',
19     'config BR2_PACKAGE_FOO\n'
20     'bool "foo"\n'
21     'depends on BR2_USE_BAR\n'
22     'default y\n',
23     [['any:4: attributes order: type, default, depends on, select, help (url#_config_files)',
24       'default y\n']]),
25    ('select after help',
26     'any',
27     'config BR2_PACKAGE_FOO\n'
28     'bool "foo"\n'
29     'help\n'
30     '\t  help text\n'
31     'select BR2_PACKAGE_BAZ\n',
32     [['any:5: attributes order: type, default, depends on, select, help (url#_config_files)',
33       'select BR2_PACKAGE_BAZ\n']]),
34    ('string',
35     'any',
36     'config BR2_PACKAGE_FOO_PLUGINS\n'
37     'string "foo plugins"\n'
38     'default "all"\n',
39     []),
40    ('ignore tabs',
41     'any',
42     'config\tBR2_PACKAGE_FOO_PLUGINS\n'
43     'default\t"all"\n'
44     'string\t"foo plugins"\n',
45     [['any:3: attributes order: type, default, depends on, select, help (url#_config_files)',
46       'string\t"foo plugins"\n']]),
47    ('choice',
48     'any',
49     'config BR2_PACKAGE_FOO\n'
50     'bool "foo"\n'
51     'if BR2_PACKAGE_FOO\n'
52     '\n'
53     'choice\n'
54     'prompt "type of foo"\n'
55     'default BR2_PACKAGE_FOO_STRING\n'
56     '\n'
57     'config BR2_PACKAGE_FOO_NONE\n'
58     'bool "none"\n'
59     '\n'
60     'config BR2_PACKAGE_FOO_STRING\n'
61     'bool "string"\n'
62     '\n'
63     'endchoice\n'
64     '\n'
65     'endif\n'
66     '\n',
67     []),
68    ('type after default',
69     'any',
70     'config BR2_PACKAGE_FOO\n'
71     'bool "foo"\n'
72     'if BR2_PACKAGE_FOO\n'
73     '\n'
74     'choice\n'
75     'default BR2_PACKAGE_FOO_STRING\n'
76     'prompt "type of foo"\n',
77     [['any:7: attributes order: type, default, depends on, select, help (url#_config_files)',
78       'prompt "type of foo"\n']]),
79    ('menu',
80     'any',
81     'menuconfig BR2_PACKAGE_FOO\n'
82     'bool "foo"\n'
83     'help\n'
84     '\t  help text\n'
85     '\t  help text\n'
86     '\n'
87     'if BR2_PACKAGE_FOO\n'
88     '\n'
89     'menu "foo plugins"\n'
90     'config BR2_PACKAGE_FOO_COUNTER\n'
91     'bool "counter"\n'
92     '\n'
93     'endmenu\n'
94     '\n'
95     'endif\n',
96     []),
97    ]
98
99
100@pytest.mark.parametrize('testname,filename,string,expected', AttributesOrder)
101def test_AttributesOrder(testname, filename, string, expected):
102    warnings = util.check_file(m.AttributesOrder, filename, string)
103    assert warnings == expected
104
105
106CommentsMenusPackagesOrder = [
107    ('top menu (good)',
108     'package/Config.in',
109     'menu "Target packages"\n'
110     'source "package/busybox/Config.in"\n'
111     'source "package/skeleton/Config.in"\n',
112     []),
113    ('top menu (bad)',
114     'package/Config.in',
115     'source "package/skeleton/Config.in"\n'
116     'source "package/busybox/Config.in"\n',
117     [['package/Config.in:2: Packages in: The top level menu,\n'
118       '                     are not alphabetically ordered;\n'
119       "                     correct order: '-', '_', digits, capitals, lowercase;\n"
120       '                     first incorrect package: busybox',
121       'source "package/busybox/Config.in"\n']]),
122    ('menu (bad)',
123     'package/Config.in',
124     'menu "Target packages"\n'
125     'source "package/skeleton/Config.in"\n'
126     'source "package/busybox/Config.in"\n',
127     [['package/Config.in:3: Packages in: menu "Target packages",\n'
128       '                     are not alphabetically ordered;\n'
129       "                     correct order: '-', '_', digits, capitals, lowercase;\n"
130       '                     first incorrect package: busybox',
131       'source "package/busybox/Config.in"\n']]),
132    ('underscore (good)',
133     'package/Config.in.host',
134     'menu "Hardware handling"\n'
135     'menu "Firmware"\n'
136     'endmenu\n'
137     'source "package/usb_modeswitch/Config.in"\n'
138     'source "package/usbmount/Config.in"\n',
139     []),
140    ('underscore (bad)',
141     'package/Config.in.host',
142     'menu "Hardware handling"\n'
143     'menu "Firmware"\n'
144     'endmenu\n'
145     'source "package/usbmount/Config.in"\n'
146     'source "package/usb_modeswitch/Config.in"\n',
147     [['package/Config.in.host:5: Packages in: menu "Hardware handling",\n'
148       '                          are not alphabetically ordered;\n'
149       "                          correct order: '-', '_', digits, capitals, lowercase;\n"
150       '                          first incorrect package: usb_modeswitch',
151       'source "package/usb_modeswitch/Config.in"\n']]),
152    ('ignore other files',
153     'any other file',
154     'menu "Hardware handling"\n'
155     'source "package/bbb/Config.in"\n'
156     'source "package/aaa/Config.in"\n',
157     []),
158    ('dash (bad)',
159     'package/Config.in',
160     'menu "packages"\n'
161     'source "package/a_a/Config.in"\n'
162     'source "package/a-a/Config.in"\n'
163     'source "package/a1a/Config.in"\n'
164     'source "package/aAa/Config.in"\n'
165     'source "package/aaa/Config.in"\n',
166     [['package/Config.in:3: Packages in: menu "packages",\n'
167       '                     are not alphabetically ordered;\n'
168       "                     correct order: '-', '_', digits, capitals, lowercase;\n"
169       '                     first incorrect package: a-a',
170       'source "package/a-a/Config.in"\n']]),
171    ('underscore (bad)',
172     'package/Config.in',
173     'menu "packages"\n'
174     'source "package/a-a/Config.in"\n'
175     'source "package/a1a/Config.in"\n'
176     'source "package/a_a/Config.in"\n'
177     'source "package/aAa/Config.in"\n'
178     'source "package/aaa/Config.in"\n',
179     [['package/Config.in:4: Packages in: menu "packages",\n'
180       '                     are not alphabetically ordered;\n'
181       "                     correct order: '-', '_', digits, capitals, lowercase;\n"
182       '                     first incorrect package: a_a',
183       'source "package/a_a/Config.in"\n']]),
184    ('digit (bad)',
185     'package/Config.in',
186     'menu "packages"\n'
187     'source "package/a-a/Config.in"\n'
188     'source "package/a_a/Config.in"\n'
189     'source "package/aAa/Config.in"\n'
190     'source "package/a1a/Config.in"\n'
191     'source "package/aaa/Config.in"\n',
192     [['package/Config.in:5: Packages in: menu "packages",\n'
193       '                     are not alphabetically ordered;\n'
194       "                     correct order: '-', '_', digits, capitals, lowercase;\n"
195       '                     first incorrect package: a1a',
196       'source "package/a1a/Config.in"\n']]),
197    ('capitals (bad)',
198     'package/Config.in',
199     'menu "packages"\n'
200     'source "package/a-a/Config.in"\n'
201     'source "package/a_a/Config.in"\n'
202     'source "package/a1a/Config.in"\n'
203     'source "package/aaa/Config.in"\n'
204     'source "package/aAa/Config.in"\n',
205     [['package/Config.in:6: Packages in: menu "packages",\n'
206       '                     are not alphabetically ordered;\n'
207       "                     correct order: '-', '_', digits, capitals, lowercase;\n"
208       '                     first incorrect package: aAa',
209       'source "package/aAa/Config.in"\n']]),
210    ('digits, capitals, underscore (good)',
211     'package/Config.in',
212     'menu "packages"\n'
213     'source "package/a-a/Config.in"\n'
214     'source "package/a_a/Config.in"\n'
215     'source "package/a1a/Config.in"\n'
216     'source "package/aAa/Config.in"\n'
217     'source "package/aaa/Config.in"\n',
218     []),
219    ('conditional menu (good)',
220     'package/Config.in',
221     'menu "Other"\n'
222     'source "package/linux-pam/Config.in"\n'
223     'if BR2_PACKAGE_LINUX_PAM\n'
224     'comment "linux-pam plugins"\n'
225     'source "package/libpam-radius-auth/Config.in"\n'
226     'source "package/libpam-tacplus/Config.in"\n'
227     'endif\n'
228     'source "package/liquid-dsp/Config.in"\n',
229     []),
230    ('conditional menu (bad)',
231     'package/Config.in',
232     'menu "Other"\n'
233     'source "package/linux-pam/Config.in"\n'
234     'if BR2_PACKAGE_LINUX_PAM\n'
235     'comment "linux-pam plugins"\n'
236     'source "package/libpam-tacplus/Config.in"\n'
237     'source "package/libpam-radius-auth/Config.in"\n'
238     'endif\n'
239     'source "package/liquid-dsp/Config.in"\n',
240     [['package/Config.in:6: Packages in: comment "linux-pam plugins",\n'
241       '                     are not alphabetically ordered;\n'
242       "                     correct order: '-', '_', digits, capitals, lowercase;\n"
243       '                     first incorrect package: libpam-radius-auth',
244       'source "package/libpam-radius-auth/Config.in"\n']]),
245    ('no conditional (bad)',
246     'package/Config.in',
247     'menu "Other"\n'
248     'source "package/linux-pam/Config.in"\n'
249     'source "package/libpam-radius-auth/Config.in"\n'
250     'source "package/libpam-tacplus/Config.in"\n'
251     'source "package/liquid-dsp/Config.in"\n',
252     [['package/Config.in:3: Packages in: menu "Other",\n'
253       '                     are not alphabetically ordered;\n'
254       "                     correct order: '-', '_', digits, capitals, lowercase;\n"
255       '                     first incorrect package: libpam-radius-auth',
256       'source "package/libpam-radius-auth/Config.in"\n']]),
257    ]
258
259
260@pytest.mark.parametrize('testname,filename,string,expected', CommentsMenusPackagesOrder)
261def test_CommentsMenusPackagesOrder(testname, filename, string, expected):
262    warnings = util.check_file(m.CommentsMenusPackagesOrder, filename, string)
263    assert warnings == expected
264
265
266HelpText = [
267    ('single line',
268     'any',
269     'config BR2_PACKAGE_FOO\n'
270     'bool "foo"\n'
271     'default y\n'
272     'depends on BR2_USE_BAR # runtime\n'
273     'select BR2_PACKAGE_BAZ\n'
274     'help\n'
275     '\t  help text\n',
276     []),
277    ('larger than 72',
278     'any',
279     'help\n'
280     '\t  123456789 123456789 123456789 123456789 123456789 123456789 12\n'
281     '\t  123456789 123456789 123456789 123456789 123456789 123456789 123\n'
282     '\t  help text\n',
283     [['any:3: help text: <tab><2 spaces><62 chars> (url#writing-rules-config-in)',
284       '\t  123456789 123456789 123456789 123456789 123456789 123456789 123\n',
285       '\t  123456789 123456789 123456789 123456789 123456789 123456789 12']]),
286    ('long url at beginning of line',
287     'any',
288     'help\n'
289     '\t  123456789 123456789 123456789 123456789 123456789 123456789 12\n'
290     '\t  http://url.that.is.longer.than.seventy.two.characthers/folder_name\n'
291     '\t  https://url.that.is.longer.than.seventy.two.characthers/folder_name\n'
292     '\t  git://url.that.is.longer.than.seventy.two.characthers/folder_name\n',
293     []),
294    ('long url not at beginning of line',
295     'any',
296     'help\n'
297     '\t  123456789 123456789 123456789 123456789 123456789 123456789 12\n'
298     '\t  refer to http://url.that.is.longer.than.seventy.two.characthers/folder_name\n'
299     '\n'
300     '\t  http://url.that.is.longer.than.seventy.two.characthers/folder_name\n',
301     [['any:3: help text: <tab><2 spaces><62 chars> (url#writing-rules-config-in)',
302       '\t  refer to http://url.that.is.longer.than.seventy.two.characthers/folder_name\n',
303       '\t  123456789 123456789 123456789 123456789 123456789 123456789 12']]),
304    ('allow beautified items',
305     'any',
306     'help\n'
307     '\t  123456789 123456789 123456789 123456789 123456789 123456789 12\n'
308     '\t  summary:\n'
309     '\t    - enable that config\n'
310     '\t    - built it\n',
311     []),
312    ]
313
314
315@pytest.mark.parametrize('testname,filename,string,expected', HelpText)
316def test_HelpText(testname, filename, string, expected):
317    warnings = util.check_file(m.HelpText, filename, string)
318    assert warnings == expected
319
320
321Indent = [
322    ('good example',
323     'any',
324     'config BR2_PACKAGE_FOO\n'
325     '\tbool "foo"\n'
326     '\tdefault y\n'
327     '\tdepends on BR2_TOOLCHAIN_HAS_THREADS\n'
328     '\tdepends on BR2_INSTALL_LIBSTDCPP\n'
329     '# very useful comment\n'
330     '\tselect BR2_PACKAGE_BAZ\n'
331     '\thelp\n'
332     '\t  help text\n'
333     '\n'
334     'comment "foo needs toolchain w/ C++, threads"\n'
335     '\tdepends on !BR2_INSTALL_LIBSTDCPP || \\\n'
336     '\t\t!BR2_TOOLCHAIN_HAS_THREADS\n'
337     '\n'
338     'source "package/foo/bar/Config.in"\n',
339     []),
340    ('spaces',
341     'any',
342     'config BR2_PACKAGE_FOO\n'
343     '        bool "foo"\n',
344     [['any:2: should be indented with one tab (url#_config_files)',
345       '        bool "foo"\n']]),
346    ('without indent',
347     'any',
348     'config BR2_PACKAGE_FOO\n'
349     'default y\n',
350     [['any:2: should be indented with one tab (url#_config_files)',
351       'default y\n']]),
352    ('too much tabs',
353     'any',
354     'config BR2_PACKAGE_FOO\n'
355     '\t\tdepends on BR2_TOOLCHAIN_HAS_THREADS\n',
356     [['any:2: should be indented with one tab (url#_config_files)',
357       '\t\tdepends on BR2_TOOLCHAIN_HAS_THREADS\n']]),
358    ('help',
359     'any',
360     'config BR2_PACKAGE_FOO\n'
361     '     help\n',
362     [['any:2: should be indented with one tab (url#_config_files)',
363       '     help\n']]),
364    ('continuation line',
365     'any',
366     'comment "foo needs toolchain w/ C++, threads"\n'
367     '\tdepends on !BR2_INSTALL_LIBSTDCPP || \\\n'
368     '                !BR2_TOOLCHAIN_HAS_THREADS\n',
369     [['any:3: continuation line should be indented using tabs',
370       '                !BR2_TOOLCHAIN_HAS_THREADS\n']]),
371    ('comment with tabs',
372     'any',
373     '\tcomment "foo needs toolchain w/ C++, threads"\n',
374     [['any:1: should not be indented',
375       '\tcomment "foo needs toolchain w/ C++, threads"\n']]),
376    ('comment with spaces',
377     'any',
378     '  comment "foo needs toolchain w/ C++, threads"\n',
379     [['any:1: should not be indented',
380       '  comment "foo needs toolchain w/ C++, threads"\n']]),
381    ]
382
383
384@pytest.mark.parametrize('testname,filename,string,expected', Indent)
385def test_Indent(testname, filename, string, expected):
386    warnings = util.check_file(m.Indent, filename, string)
387    assert warnings == expected
388
389
390RedefinedConfig = [
391    ('no redefinition',
392     'any',
393     'config BR2_PACKAGE_FOO\n'
394     'bool "foo"\n'
395     'config BR2_PACKAGE_FOO_BAR\n'
396     'bool "foo"\n',
397     []),
398    ('no conditional',
399     'any',
400     'config BR2_PACKAGE_FOO\n'
401     'bool "foo"\n'
402     'config BR2_PACKAGE_BAR\n'
403     'bool "bar"\n'
404     'config BR2_PACKAGE_FOO\n'
405     'bool "foo"\n',
406     [['any:5: config BR2_PACKAGE_FOO redeclared (previous line: 1)',
407       'config BR2_PACKAGE_FOO\n']]),
408    ('three times',
409     'any',
410     'config BR2_PACKAGE_FOO\n'
411     'bool "foo"\n'
412     'config BR2_PACKAGE_FOO\n'
413     'bool "foo"\n'
414     'config BR2_PACKAGE_FOO\n'
415     'bool "foo"\n',
416     [['any:3: config BR2_PACKAGE_FOO redeclared (previous line: 1)',
417       'config BR2_PACKAGE_FOO\n'],
418      ['any:5: config BR2_PACKAGE_FOO redeclared (previous line: 1)',
419       'config BR2_PACKAGE_FOO\n']]),
420    ('same conditional',
421     'any',
422     'if BR2_PACKAGE_BAZ\n'
423     'config BR2_PACKAGE_FOO\n'
424     'bool "foo"\n'
425     'config BR2_PACKAGE_BAR\n'
426     'bool "bar"\n'
427     'config BR2_PACKAGE_FOO\n'
428     'bool "foo"\n'
429     'endif\n',
430     [['any:6: config BR2_PACKAGE_FOO redeclared (previous line: 2)',
431       'config BR2_PACKAGE_FOO\n']]),
432    ('equivalent conditional',
433     'any',
434     'if BR2_PACKAGE_BAZ\n'
435     'config BR2_PACKAGE_FOO\n'
436     'bool "foo"\n'
437     'endif\n'
438     'config BR2_PACKAGE_FOO\n'
439     'bool "foo"\n'
440     'if BR2_PACKAGE_BAZ\n'
441     'config BR2_PACKAGE_FOO\n'
442     'bool "foo"\n'
443     'endif\n',
444     [['any:8: config BR2_PACKAGE_FOO redeclared (previous line: 2)',
445       'config BR2_PACKAGE_FOO\n']]),
446    ('not equivalent conditional',
447     'any',
448     'if BR2_PACKAGE_BAZ\n'
449     'config BR2_PACKAGE_FOO\n'
450     'bool "foo"\n'
451     'endif\n'
452     'config BR2_PACKAGE_FOO\n'
453     'bool "foo"\n'
454     'if !BR2_PACKAGE_BAZ\n'
455     'config BR2_PACKAGE_FOO\n'
456     'bool "foo"\n'
457     'endif\n',
458     []),
459    ]
460
461
462@pytest.mark.parametrize('testname,filename,string,expected', RedefinedConfig)
463def test_RedefinedConfig(testname, filename, string, expected):
464    warnings = util.check_file(m.RedefinedConfig, filename, string)
465    assert warnings == expected
466