[VVP] Updating error reporting for helpers
[vvp/validation-scripts.git] / ice_validator / tests / parametrizers.py
1 # -*- coding: utf8 -*-
2 # ============LICENSE_START=======================================================
3 # org.onap.vvp/validation-scripts
4 # ===================================================================
5 # Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6 # ===================================================================
7 #
8 # Unless otherwise specified, all software contained herein is licensed
9 # under the Apache License, Version 2.0 (the “License”);
10 # you may not use this software except in compliance with the License.
11 # You may obtain a copy of the License at
12 #
13 #             http://www.apache.org/licenses/LICENSE-2.0
14 #
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
20 #
21 #
22 #
23 # Unless otherwise specified, all documentation contained herein is licensed
24 # under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
25 # you may not use this documentation except in compliance with the License.
26 # You may obtain a copy of the License at
27 #
28 #             https://creativecommons.org/licenses/by/4.0/
29 #
30 # Unless required by applicable law or agreed to in writing, documentation
31 # distributed under the License is distributed on an "AS IS" BASIS,
32 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33 # See the License for the specific language governing permissions and
34 # limitations under the License.
35 #
36 # ============LICENSE_END============================================
37 #
38 # ECOMP is a trademark and service mark of AT&T Intellectual Property.
39 #
40 from os import path, listdir
41 import re
42 import yaml
43 import pytest
44 from .helpers import get_parsed_yml_for_yaml_files, check_basename_ending
45 from .utils.nested_files import get_list_of_nested_files
46
47 VERSION = '1.0.0'
48
49 # pylint: disable=invalid-name
50
51
52 def get_template_dir(metafunc):
53     '''
54     returns template_dir, either as its passed in on CLI
55     or, during --self-test, the directory whos name matches
56     the current tests module name
57     '''
58     if metafunc.config.getoption('template_dir') is None:
59         return path.join(
60             path.dirname(path.realpath(__file__)),
61             'fixtures',
62             metafunc.function.__module__.split('.')[-1])
63     else:
64         return metafunc.config.getoption('template_dir')[0]
65
66
67 def get_nested_files(filenames):
68     '''
69     returns all the nested files for a set of filenames
70     '''
71     nested_files = []
72     for filename in filenames:
73         try:
74             with open(filename) as fh:
75                 yml = yaml.load(fh)
76             if "resources" not in yml:
77                 continue
78             nested_files.extend(get_list_of_nested_files(
79                     yml["resources"],
80                     path.dirname(filename)))
81         except yaml.YAMLError as e:
82             print(e)  # pylint: disable=superfluous-parens
83             continue
84     return nested_files
85
86
87 def list_filenames_in_template_dir(
88             metafunc,
89             extensions,
90             template_type='',
91             sub_dirs=None):
92     '''
93     returns the filenames in a template_dir, either as its passed in
94     on CLI or, during --self-test, the directory whos name matches
95     the current tests module name
96     '''
97     sub_dirs = [] if sub_dirs is None else sub_dirs
98     template_dir = get_template_dir(metafunc)
99     filenames = []
100     if metafunc.config.getoption('self_test'):
101         filenames = [path.join(template_dir, s, f)
102                      for s in sub_dirs
103                      for f in listdir(path.join(template_dir, s))
104                      if path.isfile(path.join(template_dir, s, f))
105                      and path.splitext(f)[-1] in extensions
106                      and check_basename_ending(
107                             template_type,
108                             path.splitext(f)[0])]
109     else:
110         filenames = [path.join(template_dir, f)
111                      for f in listdir(template_dir)
112                      if path.isfile(path.join(template_dir, f))
113                      and path.splitext(f)[-1] in extensions
114                      and check_basename_ending(
115                                 template_type,
116                                 path.splitext(f)[0])]
117     return filenames
118
119
120 def list_template_dir(
121             metafunc,
122             extensions,
123             exclude_nested=True,
124             template_type='',
125             sub_dirs=None):
126     '''
127     returns the filenames excluding the nested files for a template_dir,
128     either as its passed in on CLI or, during --self-test, the
129     directory whos name matches the current tests module name
130     '''
131     sub_dirs = [] if sub_dirs is None else sub_dirs
132     filenames = []
133     nested_files = []
134     filenames = list_filenames_in_template_dir(
135             metafunc,
136             extensions,
137             template_type,
138             sub_dirs)
139     if exclude_nested:
140         nested_files = get_nested_files(filenames)
141     return list(set(filenames) - set(nested_files))
142
143
144 def get_filenames_list(
145             metafunc,
146             extensions=None,
147             exclude_nested=False,
148             template_type=''):
149     '''
150     returns the filename fixtures for the template dir, either as by how its
151     passed in on CLI or, during --self-test, the directory whos name
152     matches the current tests module name
153     '''
154     extensions = [
155             ".yaml",
156             ".yml",
157             ".env"
158             ] if extensions is None else extensions
159     if metafunc.config.getoption('self_test'):
160         filenames_list = list_template_dir(metafunc,
161                                            extensions,
162                                            exclude_nested,
163                                            template_type,
164                                            ['pass'])
165         filenames_list += [pytest.mark.xfail(f, strict=True)
166                            for f in list_template_dir(metafunc,
167                                                       extensions,
168                                                       exclude_nested,
169                                                       template_type,
170                                                       ['fail'])]
171     else:
172         filenames_list = list_template_dir(metafunc,
173                                            extensions,
174                                            exclude_nested,
175                                            template_type)
176
177     return filenames_list
178
179
180 def get_filenames_lists(
181             metafunc,
182             extensions=None,
183             exclude_nested=False,
184             template_type=''):
185     '''
186     returns the list of files in the template dir, either as by how its
187     passed in on CLI or, during --self-test, the directory whos name
188     matches the current tests module name
189     '''
190     extensions = [
191             ".yaml",
192             ".yml",
193             ".env"
194             ] if extensions is None else extensions
195     filenames_lists = []
196     if metafunc.config.getoption('self_test'):
197         filenames_lists.append(list_template_dir(metafunc,
198                                                  extensions,
199                                                  exclude_nested,
200                                                  template_type,
201                                                  ['pass']))
202         filenames_lists.append(pytest.mark.xfail(
203                             list_template_dir(metafunc,
204                                               extensions,
205                                               exclude_nested,
206                                               template_type,
207                                               ['fail']),
208                             strict=True))
209     else:
210         filenames_lists.append(list_template_dir(metafunc,
211                                                  extensions,
212                                                  exclude_nested,
213                                                  template_type))
214     return filenames_lists
215
216
217 def get_parsed_yaml_files(
218             metafunc,
219             extensions,
220             exclude_nested=True,
221             template_type='',
222             sections=None):
223     '''
224     returns the list of parsed yaml files in the specified template dir,
225     either as by how its passed in on CLI or, during --self-test, the
226     directory whos name matches the current tests module name
227     '''
228     sections = [] if sections is None else sections
229     extensions = [".yaml", ".yml"]
230
231     if metafunc.config.getoption('self_test'):
232         yaml_files = list_template_dir(metafunc, extensions, exclude_nested,
233                                        template_type, ['pass'])
234         parsed_yml_list = get_parsed_yml_for_yaml_files(yaml_files,
235                                                         sections)
236
237         yaml_files = list_template_dir(metafunc, extensions, exclude_nested,
238                                        template_type, ['fail'])
239         parsed_yml_list = get_parsed_yml_for_yaml_files(yaml_files,
240                                                         sections)
241         parsed_yml_list += [pytest.mark.xfail(parsed_yml, strict=True)
242                             for parsed_yml in parsed_yml_list]
243     else:
244         yaml_files = list_template_dir(metafunc, extensions)
245         parsed_yml_list = get_parsed_yml_for_yaml_files(yaml_files,
246                                                         sections)
247     return parsed_yml_list
248
249
250 def parametrize_filenames(metafunc):
251     '''
252     This param runs tests all files in the template dir
253     '''
254     filenames = get_filenames_lists(metafunc)
255     metafunc.parametrize('filenames', filenames)
256
257
258 def parametrize_filename(metafunc):
259     '''
260     This param runs tests once for every file in the template dir
261     '''
262     filenames = get_filenames_list(metafunc)
263     metafunc.parametrize('filename', filenames)
264
265
266 def parametrize_yaml_files(metafunc):
267     '''
268     This param runs tests for the yaml files in the template dir
269     '''
270     yaml_files = get_filenames_lists(metafunc, ['.yaml', '.yml'], False)
271     metafunc.parametrize("yaml_files", yaml_files)
272
273
274 def parametrize_yaml_file(metafunc):
275     '''
276     This param runs tests for every yaml file in the template dir
277     '''
278     yaml_files = get_filenames_list(metafunc, ['.yaml', '.yml'], False)
279     metafunc.parametrize('yaml_file', yaml_files)
280
281
282 def parametrize_templates(metafunc):
283     '''
284     This param runs tests for the template in the template dir
285     '''
286     templates = get_filenames_lists(metafunc, ['.yaml', '.yml'], True)
287     metafunc.parametrize("templates", templates)
288
289
290 def parametrize_template(metafunc):
291     '''
292     This param runs tests for every template in the template dir
293     '''
294     templates = get_filenames_list(metafunc, ['.yaml', '.yml'], True)
295     metafunc.parametrize('template', templates)
296
297
298 def parametrize_parsed_yaml_file(metafunc):
299     '''
300     This param runs tests for a parsed version of each yaml file
301     in the template dir
302     '''
303     parsed_yaml_files = get_parsed_yaml_files(metafunc, ['.yaml', '.yml'],
304                                               False)
305     metafunc.parametrize('parsed_yaml_file', parsed_yaml_files)
306
307
308 def parametrize_heat_templates(metafunc):
309     '''
310     This param runs tests for all heat templates in the template dir
311     '''
312     heat_templates = get_filenames_lists(metafunc, ['.yaml', '.yml'],
313                                          True, 'heat')
314     metafunc.parametrize('heat_templates', heat_templates)
315
316
317 def parametrize_heat_template(metafunc):
318     '''
319     This param runs tests for every heat template in the template dir
320     '''
321     heat_templates = get_filenames_list(metafunc, ['.yaml', '.yml'],
322                                         True, 'heat')
323     metafunc.parametrize('heat_template', heat_templates)
324
325
326 def parametrize_volume_templates(metafunc):
327     '''
328     This param runs tests for all volume templates in the template dir
329     '''
330     volume_templates = get_filenames_lists(metafunc, ['.yaml', '.yml'],
331                                            True, 'volume')
332     metafunc.parametrize('volume_templates', volume_templates)
333
334
335 def parametrize_volume_template(metafunc):
336     '''
337
338     This param runs tests for every volume template in the template dir
339     '''
340     volume_templates = get_filenames_list(metafunc, ['.yaml', '.yml'],
341                                           True, 'volume')
342     metafunc.parametrize('volume_template', volume_templates)
343
344
345 def parametrize_environment_files(metafunc):
346     '''
347     This param runs tests for all environment files in the template dir
348     '''
349     env_files = get_filenames_lists(metafunc, ['.env'])
350     metafunc.parametrize('env_files', env_files)
351
352
353 def parametrize_environment_file(metafunc):
354     '''
355     This param runs tests for every environment file in the template dir
356     '''
357     env_files = get_filenames_list(metafunc, ['.env'])
358     metafunc.parametrize('env_file', env_files)
359
360
361 def parametrize_parsed_environment_file(metafunc):
362     '''
363     This param runs tests for every parsed environment file
364     in the template dir
365     '''
366     parsed_env_files = get_parsed_yaml_files(metafunc, ['.env'])
367     metafunc.parametrize('parsed_env_file', parsed_env_files)
368
369
370 def parametrize_template_dir(metafunc):
371     '''
372     This param passes a  the template_dir as passed in on CLI
373     or, during --self-test, passes in the sub directories of
374     template_dir/pass/ and template_dir/fail
375     template_dir = get_template_dir(metafunc)
376     '''
377     template_dir = get_template_dir(metafunc)
378
379     if metafunc.config.getoption('self_test'):
380         dirs = [path.join(template_dir, s, t)
381                 for s in ['pass']
382                 for t in listdir(path.join(template_dir, s))
383                 if path.isdir(path.join(template_dir, s, t))]
384
385         dirs += [pytest.mark.xfail(path.join(template_dir, s, t))
386                  for s in ['fail']
387                  for t in listdir(path.join(template_dir, s))
388                  if path.isdir(path.join(template_dir, s, t))]
389     else:
390         dirs = [template_dir]
391
392     metafunc.parametrize('template_dir', dirs)
393
394
395 def parametrize_environment_pair(metafunc, template_type=''):
396     '''
397     Define a list of pairs of parsed yaml from the heat templates and
398     environment files
399     '''
400     pairs = []
401     if metafunc.config.getoption('self_test'):
402         sub_dirs = ['pass', 'fail']
403         env_files = list_template_dir(metafunc, ['.env'], True,
404                                       template_type, sub_dirs)
405         yaml_files = list_template_dir(metafunc, ['.yaml', '.yml'], True,
406                                        template_type, sub_dirs)
407     else:
408         env_files = list_template_dir(metafunc, ['.env'], True,
409                                       template_type)
410         yaml_files = list_template_dir(metafunc, ['.yaml', '.yml'],
411                                        True, template_type)
412
413     for filename in env_files:
414         basename = path.splitext(filename)[0]
415         if basename + '.yml' in yaml_files:
416             yfilename = basename + '.yml'
417         else:
418             yfilename = basename + '.yaml'
419
420         try:
421             with open(filename) as fh:
422                 eyml = yaml.load(fh)
423             with open(yfilename) as fh:
424                 yyml = yaml.load(fh)
425
426             if 'fail' in filename:
427                 pairs.append(pytest.mark.xfail({"name": basename,
428                                                 "yyml": yyml,
429                                                 "eyml": eyml},
430                              strict=True))
431             else:
432                 pairs.append({"name": basename, "yyml": yyml, "eyml": eyml})
433
434         except yaml.YAMLError as e:
435             print(e)  # pylint: disable=superfluous-parens
436
437     metafunc.parametrize('environment_pair', pairs)
438
439
440 def parametrize_heat_volume_pair(metafunc):
441     '''
442     Define a list of pairs of parsed yaml from the a heat and volume
443     template
444     '''
445     pairs = []
446     if metafunc.config.getoption('self_test'):
447         sub_dirs = ['pass', 'fail']
448         volume_files = list_template_dir(metafunc, ['.yaml', '.yml'],
449                                          True, 'volume', sub_dirs)
450         yaml_files = list_template_dir(metafunc, ['.yaml', '.yml'],
451                                        True, '', sub_dirs)
452     else:
453         volume_files = list_template_dir(metafunc, ['.yaml', '.yml'],
454                                          True, 'volume')
455         yaml_files = list_template_dir(metafunc, ['.yaml', '.yml'], True)
456
457     pattern = re.compile(r'\_volume$')
458     for vfilename in volume_files:
459         basename = pattern.sub('', path.splitext(vfilename)[0])
460         if basename + '.yml' in yaml_files:
461             yfilename = basename + '.yml'
462         else:
463             yfilename = basename + '.yaml'
464
465         try:
466             with open(vfilename) as fh:
467                 vyml = yaml.load(fh)
468             with open(yfilename) as fh:
469                 yyml = yaml.load(fh)
470
471             if 'fail' in vfilename:
472                 pairs.append(pytest.mark.xfail({"name": basename,
473                                                 "yyml": yyml,
474                                                 "vyml": vyml},
475                              strict=True))
476             else:
477                 pairs.append({"name": basename, "yyml": yyml, "vyml": vyml})
478
479         except yaml.YAMLError as e:
480             print(e)  # pylint: disable=superfluous-parens
481
482     metafunc.parametrize('heat_volume_pair', pairs)