Test Failed
Pull Request — master (#7075)
by Alexander
02:16
created

ssg.build_sce   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 155
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 104
dl 0
loc 155
ccs 0
cts 96
cp 0
rs 10
c 0
b 0
f 0
wmc 24

4 Functions

Rating   Name   Duplication   Size   Complexity  
A _check_is_loaded() 0 5 1
A _check_is_applicable_for_product() 0 15 3
B load_sce_and_metadata() 0 23 6
F checks() 0 89 14
1
from __future__ import absolute_import
2
from __future__ import print_function
3
4
import os
5
import os.path
6
import json
7
8
9
from .build_yaml import Rule, DocumentationNotComplete
10
from .constants import MULTI_PLATFORM_LIST
11
from .jinja import process_file_with_macros
12
from .rule_yaml import parse_prodtype
13
from .rules import get_rule_dir_id, get_rule_dir_sces, find_rule_dirs_in_paths
14
from . import utils
15
16
17
def load_sce_and_metadata(file_path, local_env_yaml):
18
    raw_content = process_file_with_macros(file_path, local_env_yaml)
19
20
    metadata = dict()
21
    sce_content = []
22
23
    for line in raw_content.split("\n"):
24
        found_metadata = False
25
        keywords = ['platform', 'check-import', 'check-export', 'complex-check']
26
        for keyword in keywords:
27
            if line.startswith('# ' + keyword + ' = '):
28
                # Strip off the initial comment marker
29
                _, value = line[2:].split('=', maxsplit=1)
30
                values = value.strip()
31
                if ',' in values:
32
                    values.split(',')
33
                metadata[keyword] = values
34
                found_metadata = True
35
                break
36
        if not found_metadata:
37
            sce_content.append(line)
38
39
    return "\n".join(sce_content), metadata
40
41
42
def _check_is_applicable_for_product(metadata, product):
43
    if 'platform' not in metadata:
44
        return True
45
46
    product, product_version = utils.parse_name(product)
47
48
    multi_product = 'multi_platform_{0}'.format(product)
49
    if product in ['macos', 'ubuntu']:
50
        product_version = product_version[:2] + "." + product_version[2:]
51
52
    return ('multi_platform_all' in metadata['platform'] or
53
            (multi_product in metadata['platform'] and
54
             product in MULTI_PLATFORM_LIST) or
55
            (product in metadata['platform'] and
56
             product_version in metadata['platform']))
57
58
59
def _check_is_loaded(already_loaded, filename):
60
    # Right now this check doesn't look at metadata or anything
61
    # else. Eventually we might add versions to the entry or
62
    # something.
63
    return filename in already_loaded
64
65
66
def checks(env_yaml, yaml_path, sce_dirs, output):
67
    product = utils.required_key(env_yaml, "product")
68
    included_checks_count = 0
69
    reversed_dirs = sce_dirs[::-1]
70
    already_loaded = dict()
71
    local_env_yaml = dict()
72
    local_env_yaml.update(env_yaml)
73
74
    product_dir = os.path.dirname(yaml_path)
75
    relative_guide_dir = utils.required_key(env_yaml, "benchmark_root")
76
    guide_dir = os.path.abspath(os.path.join(product_dir, relative_guide_dir))
77
    additional_content_directories = env_yaml.get("additional_content_directories", [])
78
    add_content_dirs = [
79
        os.path.abspath(os.path.join(product_dir, rd))
80
        for rd in additional_content_directories
81
    ]
82
83
    for _dir_path in find_rule_dirs_in_paths([guide_dir] + add_content_dirs):
84
        rule_id = get_rule_dir_id(_dir_path)
85
86
        rule_path = os.path.join(_dir_path, "rule.yml")
87
        try:
88
            rule = Rule.from_yaml(rule_path, env_yaml)
89
        except DocumentationNotComplete:
90
            # Happens on non-debug builds when a rule isn't yet completed. We
91
            # don't want to build the SCE check for this rule yet so skip it
92
            # and move on.
93
            continue
94
95
        prodtypes = parse_prodtype(rule.prodtype)
96
        if prodtypes and 'all' not in prodtypes and product not in prodtypes:
97
            # The prodtype exists, isn't all and doesn't contain this current
98
            # product, so we're best to skip this rule altogether.
99
            continue
100
101
        local_env_yaml['rule_id'] = rule.id_
102
        local_env_yaml['rule_title'] = rule.title
103
        local_env_yaml['products'] = prodtypes  # default is all
104
105
        for _path in get_rule_dir_sces(_dir_path, product):
106
            # To be compatible with later checks, use the rule_id (i.e., the
107
            # value of _dir) to recreate the expected filename if this OVAL
108
            # was in a rule directory. However, note that unlike
109
            # build_oval.checks(...), we have to get this script's extension
110
            # first.
111
            _, ext = os.path.splitext(_path)
112
            filename = "{0}{1}".format(rule_id, ext)
113
114
            sce_content, metadata = load_sce_and_metadata(_path, local_env_yaml)
115
            metadata['filename'] = filename
116
117
            if not _check_is_applicable_for_product(metadata, product):
118
                continue
119
            if _check_is_loaded(already_loaded, filename):
120
                continue
121
122
            output_file = open(os.path.join(output, filename), 'w')
123
            print(sce_content, file=output_file)
124
125
            included_checks_count += 1
126
            already_loaded[rule_id] = metadata
127
128
    for sce_dir in reversed_dirs:
129
        if not os.path.isdir(sce_dir):
130
            continue
131
132
        for filename in sorted(os.listdir(sce_dir)):
133
            rule_id, _ = os.path.splitext(filename)
134
135
            sce_content, metadata = load_sce_and_metadata(filename, env_yaml)
136
            metadata['filename'] = filename
137
138
            if not _check_is_applicable_for_product(metadata, product):
139
                continue
140
            if _check_is_loaded(already_loaded, filename):
141
                continue
142
143
            output_file = open(os.path.join(output, filename), 'w')
144
            print(sce_content, file=output_file)
145
146
            included_checks_count += 1
147
            already_loaded[rule_id] = metadata
148
149
    # Finally, write out our metadata to disk so that we can reference it in
150
    # later build stages (such as during building shorthand content).
151
    metadata_path = os.path.join(output, 'metadata.json')
152
    json.dump(already_loaded, open(metadata_path, 'w'))
153
154
    return already_loaded
155