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