summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/dist/test_tag.py
blob: f36fa6613e13acd82e2eaa26366744246beb3ca2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
import os
import sys
from dist import compare_srcfile

##### LOCAL VARIABLES AND CONSTANTS #####
show_info = False
show_missing_files = False

nb_ignored_files = 0
nb_missing_files = 0
nb_valid_files = 0

sorted_tags = []
test_files = []

tagged_files = {}
valid_tags = []
test_type_tags = ['data_correctness', 'functional_correctness']

C_FILE_TYPE = 0
PY_FILE_TYPE = 1
END_TAG = "[END_TAGS]"
IGNORE_FILE = "ignored_file"
START_TAG = "[TEST_TAGS]"
#####

##### FUNCTIONS #####
def validate_tag(tag, filename):
    split_tag = tag.split(":")
    # Ensure the array isn't too long.
    if (len(split_tag) > 3):
        print("Tag contains too many sub tags: " + tag + " filename: " + filename);
        exit(1)

    # Walk the pieces of the tag and ensure they exist in test_tags.ok.
    for sub_tag in split_tag:
        if not sub_tag in valid_tags:
            print(
                "Invalid sub tag found: " + sub_tag + " in tag: " + tag + " filename: " + filename)
            exit(1)

def format_tag(tag):
    return tag.replace("_", " ").title()
#####

##### PROCESS ARGS #####
for arg in sys.argv:
    if arg == "-h":
        print("Usage: python test_tag.py [options]")
        print("Options:")
        print("\t-i\tShow info")
        print("\t-p\tShow files with no test tags")
        exit(1)
    elif arg == "-i":
        show_info = True
    elif arg == "-p":
        show_missing_files = True
#####

##### GET ALL TEST FILES #####
for root, dirs, files in os.walk("../test/"):
    path = root.split(os.sep)
    for file in files:
        filename = os.path.join('/'.join(path), file)
        if filename.endswith("main.c") or filename.endswith(".py"):
            test_files.append(filename)
#####

##### RETRIEVE VALID TAGS #####
validation_file = open("test_tags.ok", "r")

# The validation file contains an alphabetized list of valid tag words, with one word per line.
tags = validation_file.readlines()
tags = [tag.replace('\n', '') for tag in tags]

for tag in tags:
    valid_tags.append(tag)

# Check that the validation file is ordered.
if not all(tags[i] <= tags[i+1] for i in range(len(tags)-1)):
    print("Error: test_tags.ok is not alphabetically ordered!")
    exit(1)

validation_file.close()
#####

##### PARSE TEST FILES #####
for filename in test_files:
    input_file = open(filename, "r")
    lines = input_file.readlines()

    in_tag_block = False
    is_file_ignored = False
    is_file_tagged = False

    # Read line by line
    for line in lines:
        # Format line
        line = line.replace('\n', '').replace('\r', '') \
                   .replace(' ', '').replace('#', '') \
                   .replace('*', '')

        # Check if line is valid
        if not line:
            # Check if invalid line after START_TAG
            if in_tag_block == True:
                print("Syntax error in file: " + filename)
                exit(1)
            else:
                continue

        # Check if end of test tag
        if END_TAG in line:
            # END_TAG should not be before START_TAG
            if in_tag_block == False:
                print("Syntax error in file: " + filename + ". Unexpected tag: " + END_TAG)
                exit(1)
            # END_TAG should not be met before a test tag
            if is_file_ignored == False and is_file_tagged == False:
                print("Syntax error in file: " + filename + ". Missing test tag.")
                exit(1)
            nb_valid_files = nb_valid_files + 1
            # Go to next file
            break

        # Check if start of test tag
        if START_TAG in line:
            # Only one START_TAG is allowed
            if in_tag_block == True:
                print("Syntax error in file: " + filename + ". Unexpected tag: " + START_TAG)
                exit(1)
            in_tag_block = True
            continue

        if in_tag_block == True:
            tag = line
            # Check if file is ignored
            if is_file_ignored == True:
                print("Unexpected value in ignored file: " + filename)
                exit(1)
            if tag == IGNORE_FILE:
                nb_ignored_files = nb_ignored_files + 1
                is_file_ignored = True
                continue

            # Validate the tag's correctness.
            validate_tag(tag, filename)
            is_file_tagged = True

            skip_adding_test_type = False
            # Add the test type to the tag if it wasn't already.
            for test_type_tag in test_type_tags:
                if (tag.startswith(test_type_tag)):
                    skip_adding_test_type = True
                    break

            if not skip_adding_test_type:
                if filename.endswith(".c"):
                    tag = test_type_tags[C_FILE_TYPE] + ":" + tag
                if filename.endswith(".py"):
                    tag = test_type_tags[PY_FILE_TYPE] + ":" + tag

            # Check if current tag has already matched test files
            if tag in tagged_files:
                tagged_files[tag].append(filename)
            else:
                tagged_files[tag] = [filename]

    if is_file_ignored == False and is_file_tagged == False:
        nb_missing_files = nb_missing_files + 1
        if show_missing_files == True:
            print("Missing test tag in file: " + filename)

    input_file.close()
#####

##### GENERATE TEST COVERAGE MD #####
tmp_filename = '__tmp'
tfile = open('__tmp', 'w')

# Sort tags
sorted_tags = list(tagged_files.keys())
sorted_tags.sort()

for test_type_tag in test_type_tags:
    tfile.write("## " + format_tag(test_type_tag) + " tests:\n\n")
    tfile.write("|Component|Sub-component|Existing tests|\n")
    tfile.write("|---|---|---|\n")

    for tag in sorted_tags:
        # Split the tag.
        current_tag = tag.split(":")
        if (current_tag[0] != test_type_tag):
            continue

        # Parse and format tag.
        component = format_tag(current_tag[1])
        functionality = ""

        # The end tag is optional.
        if (len(current_tag) == 3):
            functionality = format_tag(current_tag[2])

        # Relative path to test files
        link = ""
        # Sort the filenames associated to the current tag
        tagged_files[tag].sort()
        for name in tagged_files[tag]:
            link += "[" + os.path.basename(name) + "](" + name + "), "
        # Remove the extra ", " at the end
        link = link[:-2]

        # Write to output
        tfile.write('|' + component + '|' + \
                        functionality + '|' + link + '\n')
tfile.close()
compare_srcfile(tmp_filename, "../test/test_coverage.md")
#####

##### STATS #####
if show_info == True:
    print("Tagged files:\t" + str(nb_valid_files - nb_ignored_files))
    print("Missing files:\t" + str(nb_missing_files))
    print("Ignored files:\t" + str(nb_ignored_files))
    print("Total files:\t" + str(nb_valid_files + nb_missing_files))
#####

# Enforce tagging
#if nb_missing_files > 0:
#    print("Files missing a tag: " + str(nb_missing_files))
#    if show_missing_files == False:
#        print("Call \'python test_tag.py -p\' to list all files with no tags")