blob: f3688248f38b5eee9a6391263ab054c5942c6fb8 [file] [log] [blame]
Tobin Ehlis35308dd2016-10-31 13:27:36 -06001#!/usr/bin/env python3
Dave Houltoncacef472018-05-29 13:00:42 -06002# Copyright (c) 2015-2018 The Khronos Group Inc.
3# Copyright (c) 2015-2018 Valve Corporation
4# Copyright (c) 2015-2018 LunarG, Inc.
5# Copyright (c) 2015-2018 Google Inc.
Tobin Ehlis35308dd2016-10-31 13:27:36 -06006#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# Author: Tobin Ehlis <tobine@google.com>
Dave Houltoncacef472018-05-29 13:00:42 -060020# Author: Dave Houlton <daveh@lunarg.com>
Tobin Ehlis35308dd2016-10-31 13:27:36 -060021
22import argparse
23import os
24import sys
Dave Houltoncacef472018-05-29 13:00:42 -060025import operator
Tobin Ehlis35308dd2016-10-31 13:27:36 -060026import platform
Dave Houltoncacef472018-05-29 13:00:42 -060027import json
28import re
29import csv
30import html
31from collections import defaultdict
Tobin Ehlis35308dd2016-10-31 13:27:36 -060032
Dave Houltoncacef472018-05-29 13:00:42 -060033verbose_mode = False
34txt_db = False
35csv_db = False
36html_db = False
37txt_filename = "validation_error_database.txt"
38csv_filename = "validation_error_database.csv"
39html_filename = "validation_error_database.html"
Dave Houlton407df732018-08-06 17:58:24 -060040header_filename = "../layers/vk_validation_error_messages.h"
Dave Houltoncacef472018-05-29 13:00:42 -060041test_file = '../tests/layer_validation_tests.cpp'
42vuid_prefixes = ['VUID-', 'UNASSIGNED-']
Tobin Ehlis35308dd2016-10-31 13:27:36 -060043
Dave Houltoncacef472018-05-29 13:00:42 -060044# Hard-coded flags that could be command line args, if we decide that's useful
45# replace KHR vuids with non-KHR during consistency checking
46dealias_khr = True
47ignore_unassigned = True # These are not found in layer code unless they appear explicitly (most don't), so produce false positives
48
Mark Lobodzinski05849f02017-06-21 14:44:14 -060049generated_layer_source_directories = [
50'build',
51'dbuild',
52'release',
53]
54generated_layer_source_files = [
Mark Lobodzinskid4950072017-08-01 13:02:20 -060055'parameter_validation.cpp',
Mark Lobodzinski09fa2d42017-07-21 10:16:53 -060056'object_tracker.cpp',
Mark Lobodzinski05849f02017-06-21 14:44:14 -060057]
Tobin Ehlis35308dd2016-10-31 13:27:36 -060058layer_source_files = [
Mark Lobodzinskie3787b42017-06-21 13:41:00 -060059'../layers/core_validation.cpp',
60'../layers/descriptor_sets.cpp',
Mark Lobodzinskid4950072017-08-01 13:02:20 -060061'../layers/parameter_validation_utils.cpp',
Mark Lobodzinskib2de97f2017-07-06 15:28:11 -060062'../layers/object_tracker_utils.cpp',
Mark Lobodzinskie3787b42017-06-21 13:41:00 -060063'../layers/shader_validation.cpp',
64'../layers/buffer_validation.cpp',
Tobin Ehlis35308dd2016-10-31 13:27:36 -060065]
Tobin Ehlis35308dd2016-10-31 13:27:36 -060066
Dave Houlton407df732018-08-06 17:58:24 -060067# This needs to be updated as new extensions roll in
Dave Houltoncacef472018-05-29 13:00:42 -060068khr_aliases = {
69 'VUID-vkBindBufferMemory2KHR-device-parameter' : 'VUID-vkBindBufferMemory2-device-parameter',
70 'VUID-vkBindBufferMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindBufferMemory2-pBindInfos-parameter',
71 'VUID-vkBindImageMemory2KHR-device-parameter' : 'VUID-vkBindImageMemory2-device-parameter',
72 'VUID-vkBindImageMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindImageMemory2-pBindInfos-parameter',
73 'VUID-vkCmdDispatchBaseKHR-commandBuffer-parameter' : 'VUID-vkCmdDispatchBase-commandBuffer-parameter',
74 'VUID-vkCmdSetDeviceMaskKHR-commandBuffer-parameter' : 'VUID-vkCmdSetDeviceMask-commandBuffer-parameter',
75 'VUID-vkCreateDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-device-parameter',
76 'VUID-vkCreateDescriptorUpdateTemplateKHR-pDescriptorUpdateTemplate-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pDescriptorUpdateTemplate-parameter',
77 'VUID-vkCreateSamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-device-parameter',
78 'VUID-vkCreateSamplerYcbcrConversionKHR-pYcbcrConversion-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pYcbcrConversion-parameter',
79 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parameter',
80 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parent',
81 'VUID-vkDestroyDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-device-parameter',
82 'VUID-vkDestroySamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-device-parameter',
83 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parameter',
84 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parent' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parent',
85 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-instance-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-instance-parameter',
86 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-pPhysicalDeviceGroupProperties-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-pPhysicalDeviceGroupProperties-parameter',
87 'VUID-vkGetBufferMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetBufferMemoryRequirements2-device-parameter',
88 'VUID-vkGetDescriptorSetLayoutSupportKHR-device-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-device-parameter',
89 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-device-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-device-parameter',
90 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-pPeerMemoryFeatures-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-pPeerMemoryFeatures-parameter',
91 'VUID-vkGetImageMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageMemoryRequirements2-device-parameter',
92 'VUID-vkGetImageSparseMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-device-parameter',
93 'VUID-vkGetImageSparseMemoryRequirements2KHR-pSparseMemoryRequirements-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pSparseMemoryRequirements-parameter',
94 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-physicalDevice-parameter',
95 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-physicalDevice-parameter',
96 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-physicalDevice-parameter',
97 'VUID-vkGetPhysicalDeviceFeatures2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-physicalDevice-parameter',
98 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-format-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-format-parameter',
99 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-physicalDevice-parameter',
100 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-physicalDevice-parameter',
101 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-physicalDevice-parameter',
102 'VUID-vkGetPhysicalDeviceProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-physicalDevice-parameter',
103 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2KHR-pQueueFamilyProperties-parameter' : 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2-pQueueFamilyProperties-parameter',
104 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pProperties-parameter',
105 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-physicalDevice-parameter',
106 'VUID-vkTrimCommandPoolKHR-commandPool-parameter' : 'VUID-vkTrimCommandPool-commandPool-parameter',
107 'VUID-vkTrimCommandPoolKHR-commandPool-parent' : 'VUID-vkTrimCommandPool-commandPool-parent',
108 'VUID-vkTrimCommandPoolKHR-device-parameter' : 'VUID-vkTrimCommandPool-device-parameter',
109 'VUID-vkTrimCommandPoolKHR-flags-zerobitmask' : 'VUID-vkTrimCommandPool-flags-zerobitmask',
110 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorSet-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorSet-parameter',
111 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parameter',
112 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parent',
113 'VUID-vkUpdateDescriptorSetWithTemplateKHR-device-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-device-parameter',
114 'VUID-vkCreateDescriptorUpdateTemplateKHR-pCreateInfo-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pCreateInfo-parameter',
115 'VUID-vkCreateSamplerYcbcrConversionKHR-pCreateInfo-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pCreateInfo-parameter',
116 'VUID-vkGetBufferMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pInfo-parameter',
117 'VUID-vkGetBufferMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pMemoryRequirements-parameter',
118 'VUID-vkGetDescriptorSetLayoutSupportKHR-pCreateInfo-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pCreateInfo-parameter',
119 'VUID-vkGetDescriptorSetLayoutSupportKHR-pSupport-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pSupport-parameter',
120 'VUID-vkGetImageMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageMemoryRequirements2-pInfo-parameter',
121 'VUID-vkGetImageMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetImageMemoryRequirements2-pMemoryRequirements-parameter',
122 'VUID-vkGetImageSparseMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pInfo-parameter',
123 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferInfo-parameter',
124 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferProperties-parameter',
125 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceInfo-parameter',
126 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceProperties-parameter',
127 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreInfo-parameter',
128 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreProperties-parameter',
129 'VUID-vkGetPhysicalDeviceFeatures2KHR-pFeatures-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-pFeatures-parameter',
130 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-pFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-pFormatProperties-parameter',
131 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatInfo-parameter',
132 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatProperties-parameter',
133 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-pMemoryProperties-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-pMemoryProperties-parameter',
134 'VUID-vkGetPhysicalDeviceProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-pProperties-parameter',
135 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pFormatInfo-parameter' }
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600136
Dave Houltoncacef472018-05-29 13:00:42 -0600137def printHelp():
138 print ("Usage:")
139 print (" python vk_validation_stats.py <json_file>")
140 print (" [ -c ]")
141 print (" [ -todo ]")
142 print (" [ -vuid <vuid_name> ]")
143 print (" [ -text [ <text_out_filename>] ]")
144 print (" [ -csv [ <csv_out_filename>] ]")
145 print (" [ -html [ <html_out_filename>] ]")
Dave Houlton407df732018-08-06 17:58:24 -0600146 print (" [ -export_header ]")
Dave Houltoncacef472018-05-29 13:00:42 -0600147 print (" [ -verbose ]")
148 print (" [ -help ]")
149 print ("\n The vk_validation_stats script parses validation layer source files to")
150 print (" determine the set of valid usage checks and tests currently implemented,")
151 print (" and generates coverage values by comparing against the full set of valid")
152 print (" usage identifiers in the Vulkan-Headers registry file 'validusage.json'")
153 print ("\nArguments: ")
154 print (" <json-file> (required) registry file 'validusage.json'")
155 print (" -c report consistency warnings")
156 print (" -todo report unimplemented VUIDs")
157 print (" -vuid <vuid_name> report status of individual VUID <vuid_name>")
158 print (" -text [filename] output the error database text to <text_database_filename>,")
159 print (" defaults to 'validation_error_database.txt'")
160 print (" -csv [filename] output the error database in csv to <csv_database_filename>,")
161 print (" defaults to 'validation_error_database.csv'")
162 print (" -html [filename] output the error database in html to <html_database_filename>,")
163 print (" defaults to 'validation_error_database.html'")
Dave Houlton407df732018-08-06 17:58:24 -0600164 print (" -export_header export a new VUID error text header file to <%s>" % header_filename)
Dave Houltoncacef472018-05-29 13:00:42 -0600165 print (" -verbose show your work (to stdout)")
166
167class ValidationJSON:
168 def __init__(self, filename):
169 self.filename = filename
170 self.explicit_vuids = set()
171 self.implicit_vuids = set()
172 self.all_vuids = set()
173 self.vuid_db = defaultdict(list) # Maps VUID string to list of json-data dicts
174 self.apiversion = ""
Dave Houltoncacef472018-05-29 13:00:42 -0600175 self.duplicate_vuids = set()
Dave Houlton407df732018-08-06 17:58:24 -0600176
177 # A set of specific regular expression substitutions needed to clean up VUID text
178 self.regex_dict = {}
179 self.regex_dict[re.compile('<.*?>|&(amp;)+lt;|&(amp;)+gt;')] = ""
180 self.regex_dict[re.compile(r'\\\(codeSize \\over 4\\\)')] = "(codeSize/4)"
181 self.regex_dict[re.compile(r'\\\(\\lceil\{\\mathit\{rasterizationSamples} \\over 32}\\rceil\\\)')] = "(rasterizationSamples/32)"
Shannon McPhersonb40f1a22018-10-30 16:45:07 -0600182 self.regex_dict[re.compile(r'\\\(\\textrm\{codeSize} \\over 4\\\)')] = "(codeSize/4)"
Dave Houlton407df732018-08-06 17:58:24 -0600183 # Some fancy punctuation chars that break the Android build...
184 self.regex_dict[re.compile('&#8594;')] = "->" # Arrow char
185 self.regex_dict[re.compile('&#8217;')] = "'" # Left-slanting apostrophe to apostrophe
186 self.regex_dict[re.compile('&#822(0|1);')] = "'" # L/R-slanting quotes to apostrophe
Dave Houltoncacef472018-05-29 13:00:42 -0600187
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600188 def read(self):
Dave Houltoncacef472018-05-29 13:00:42 -0600189 self.json_dict = {}
190 if os.path.isfile(self.filename):
Dave Houlton407df732018-08-06 17:58:24 -0600191 json_file = open(self.filename, 'r', encoding='utf-8')
Dave Houltoncacef472018-05-29 13:00:42 -0600192 self.json_dict = json.load(json_file)
193 json_file.close()
194 if len(self.json_dict) == 0:
195 print("Error: Error loading validusage.json file <%s>" % self.filename)
196 sys.exit(-1)
197 try:
198 version = self.json_dict['version info']
199 validation = self.json_dict['validation']
200 self.apiversion = version['api version']
201 except:
202 print("Error: Failure parsing validusage.json object")
203 sys.exit(-1)
204
205 # Parse vuid from json into local databases
206 for apiname in validation.keys():
207 # print("entrypoint:%s"%apiname)
208 apidict = validation[apiname]
209 for ext in apidict.keys():
210 vlist = apidict[ext]
211 for ventry in vlist:
212 vuid_string = ventry['vuid']
213 if (vuid_string[-5:-1].isdecimal()):
214 self.explicit_vuids.add(vuid_string) # explicit end in 5 numeric chars
215 vtype = 'explicit'
216 else:
217 self.implicit_vuids.add(vuid_string) # otherwise, implicit
218 vtype = 'implicit'
219 vuid_text = ventry['text']
Dave Houlton407df732018-08-06 17:58:24 -0600220 for regex, replacement in self.regex_dict.items():
221 vuid_text = re.sub(regex, replacement, vuid_text) # do regex substitution
222 vuid_text = html.unescape(vuid_text) # anything missed by the regex
223 self.vuid_db[vuid_string].append({'api':apiname, 'ext':ext, 'type':vtype, 'text':vuid_text})
Dave Houltoncacef472018-05-29 13:00:42 -0600224 self.all_vuids = self.explicit_vuids | self.implicit_vuids
225 self.duplicate_vuids = set({v for v in self.vuid_db if len(self.vuid_db[v]) > 1})
Dave Houlton407df732018-08-06 17:58:24 -0600226 if len(self.duplicate_vuids) > 0:
227 print("Warning: duplicate VUIDs found in validusage.json")
228
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600229
230class ValidationSource:
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600231 def __init__(self, source_file_list, generated_source_file_list, generated_source_directories):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600232 self.source_files = source_file_list
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600233 self.generated_source_files = generated_source_file_list
234 self.generated_source_dirs = generated_source_directories
Dave Houltoncacef472018-05-29 13:00:42 -0600235 self.vuid_count_dict = {} # dict of vuid values to the count of how much they're used, and location of where they're used
236 self.duplicated_checks = 0
237 self.explicit_vuids = set()
238 self.implicit_vuids = set()
239 self.unassigned_vuids = set()
240 self.all_vuids = set()
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600241
242 if len(self.generated_source_files) > 0:
243 qualified_paths = []
244 for source in self.generated_source_files:
245 for build_dir in self.generated_source_dirs:
246 filepath = '../%s/layers/%s' % (build_dir, source)
247 if os.path.isfile(filepath):
248 qualified_paths.append(filepath)
John Zulaufdde04c42018-01-16 15:32:45 -0700249 break
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600250 if len(self.generated_source_files) != len(qualified_paths):
Mark Lobodzinski2d193ac2017-06-27 09:38:15 -0600251 print("Error: Unable to locate one or more of the following source files in the %s directories" % (", ".join(generated_source_directories)))
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600252 print(self.generated_source_files)
Dave Houltoncacef472018-05-29 13:00:42 -0600253 print("Failed to locate one or more codegen files in layer source code - cannot proceed.")
John Zulaufdde04c42018-01-16 15:32:45 -0700254 exit(1)
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600255 else:
256 self.source_files.extend(qualified_paths)
257
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600258 def parse(self):
Dave Houltoncacef472018-05-29 13:00:42 -0600259 prepend = None
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600260 for sf in self.source_files:
Tobin Ehlis3d1f2bd2016-12-22 11:19:15 -0700261 line_num = 0
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600262 with open(sf) as f:
263 for line in f:
Tobin Ehlis3d1f2bd2016-12-22 11:19:15 -0700264 line_num = line_num + 1
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600265 if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
266 continue
Dave Houltoncacef472018-05-29 13:00:42 -0600267 # Find vuid strings
268 if prepend != None:
269 line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char
270 prepend = None
271 if any(prefix in line for prefix in vuid_prefixes):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600272 line_list = line.split()
Dave Houltoncacef472018-05-29 13:00:42 -0600273
274 # A VUID string that has been broken by clang will start with a vuid prefix and end with -, and will be last in the list
275 broken_vuid = line_list[-1].strip('"')
276 if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'):
277 prepend = line
278 continue
279
280 vuid_list = []
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600281 for str in line_list:
Dave Houltoncacef472018-05-29 13:00:42 -0600282 if any(prefix in str for prefix in vuid_prefixes):
283 vuid_list.append(str.strip(',);{}"'))
284 for vuid in vuid_list:
285 if vuid not in self.vuid_count_dict:
286 self.vuid_count_dict[vuid] = {}
287 self.vuid_count_dict[vuid]['count'] = 1
288 self.vuid_count_dict[vuid]['file_line'] = []
289 else:
290 if self.vuid_count_dict[vuid]['count'] == 1: # only count first time duplicated
291 self.duplicated_checks = self.duplicated_checks + 1
292 self.vuid_count_dict[vuid]['count'] = self.vuid_count_dict[vuid]['count'] + 1
293 self.vuid_count_dict[vuid]['file_line'].append('%s,%d' % (sf, line_num))
294 # Sort vuids by type
295 for vuid in self.vuid_count_dict.keys():
296 if (vuid.startswith('VUID-')):
297 if (vuid[-5:-1].isdecimal()):
298 self.explicit_vuids.add(vuid) # explicit end in 5 numeric chars
299 else:
300 self.implicit_vuids.add(vuid)
301 elif (vuid.startswith('UNASSIGNED-')):
302 self.unassigned_vuids.add(vuid)
303 else:
304 print("Unable to categorize VUID: %s" % vuid)
305 print("Confused while parsing VUIDs in layer source code - cannot proceed. (FIXME)")
306 exit(-1)
307 self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600308
309# Class to parse the validation layer test source and store testnames
Dave Houltoncacef472018-05-29 13:00:42 -0600310class ValidationTests:
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600311 def __init__(self, test_file_list, test_group_name=['VkLayerTest', 'VkPositiveLayerTest', 'VkWsiEnabledLayerTest']):
312 self.test_files = test_file_list
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600313 self.test_trigger_txt_list = []
314 for tg in test_group_name:
315 self.test_trigger_txt_list.append('TEST_F(%s' % tg)
Dave Houltoncacef472018-05-29 13:00:42 -0600316 self.explicit_vuids = set()
317 self.implicit_vuids = set()
318 self.unassigned_vuids = set()
319 self.all_vuids = set()
320 #self.test_to_vuids = {} # Map test name to VUIDs tested
321 self.vuid_to_tests = defaultdict(set) # Map VUIDs to set of test names where implemented
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600322
323 # Parse test files into internal data struct
324 def parse(self):
325 # For each test file, parse test names into set
326 grab_next_line = False # handle testname on separate line than wildcard
Tobin Ehlis9a68c982016-12-29 14:51:17 -0700327 testname = ''
Dave Houltoncacef472018-05-29 13:00:42 -0600328 prepend = None
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600329 for test_file in self.test_files:
330 with open(test_file) as tf:
331 for line in tf:
332 if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
333 continue
334
Dave Houltoncacef472018-05-29 13:00:42 -0600335 # if line ends in a broken VUID string, fix that before proceeding
336 if prepend != None:
337 line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char
338 prepend = None
339 if any(prefix in line for prefix in vuid_prefixes):
340 line_list = line.split()
341
342 # A VUID string that has been broken by clang will start with a vuid prefix and end with -, and will be last in the list
343 broken_vuid = line_list[-1].strip('"')
344 if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'):
345 prepend = line
346 continue
347
348 if any(ttt in line for ttt in self.test_trigger_txt_list):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600349 testname = line.split(',')[-1]
350 testname = testname.strip().strip(' {)')
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600351 if ('' == testname):
352 grab_next_line = True
353 continue
Dave Houltoncacef472018-05-29 13:00:42 -0600354 #self.test_to_vuids[testname] = []
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600355 if grab_next_line: # test name on its own line
356 grab_next_line = False
357 testname = testname.strip().strip(' {)')
Dave Houltoncacef472018-05-29 13:00:42 -0600358 #self.test_to_vuids[testname] = []
359 if any(prefix in line for prefix in vuid_prefixes):
360 line_list = re.split('[\s{}[\]()"]+',line)
Tobin Ehlis71f38c12017-01-12 14:26:56 -0700361 for sub_str in line_list:
Dave Houltoncacef472018-05-29 13:00:42 -0600362 if any(prefix in sub_str for prefix in vuid_prefixes):
363 vuid_str = sub_str.strip(',);:"')
364 self.vuid_to_tests[vuid_str].add(testname)
365 #self.test_to_vuids[testname].append(vuid_str)
366 if (vuid_str.startswith('VUID-')):
367 if (vuid_str[-5:-1].isdecimal()):
368 self.explicit_vuids.add(vuid_str) # explicit end in 5 numeric chars
369 else:
370 self.implicit_vuids.add(vuid_str)
371 elif (vuid_str.startswith('UNASSIGNED-')):
372 self.unassigned_vuids.add(vuid_str)
373 else:
374 print("Unable to categorize VUID: %s" % vuid_str)
375 print("Confused while parsing VUIDs in test code - cannot proceed. (FIXME)")
376 exit(-1)
377 self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600378
Dave Houltoncacef472018-05-29 13:00:42 -0600379# Class to do consistency checking
380#
381class Consistency:
382 def __init__(self, all_json, all_checks, all_tests):
383 self.valid = all_json
384 self.checks = all_checks
385 self.tests = all_tests
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600386
Dave Houltoncacef472018-05-29 13:00:42 -0600387 if (dealias_khr):
388 dk = set()
389 for vuid in self.checks:
390 if vuid in khr_aliases:
391 dk.add(khr_aliases[vuid])
392 else:
393 dk.add(vuid)
394 self.checks = dk
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600395
Dave Houltoncacef472018-05-29 13:00:42 -0600396 dk = set()
397 for vuid in self.tests:
398 if vuid in khr_aliases:
399 dk.add(khr_aliases[vuid])
400 else:
401 dk.add(vuid)
402 self.tests = dk
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600403
Dave Houltoncacef472018-05-29 13:00:42 -0600404 # Report undefined VUIDs in source code
405 def undef_vuids_in_layer_code(self):
406 undef_set = self.checks - self.valid
407 undef_set.discard('VUID-Undefined') # don't report Undefined
408 if ignore_unassigned:
409 unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')})
410 undef_set = undef_set - unassigned
411 if (len(undef_set) > 0):
412 print("\nFollowing VUIDs found in layer code are not defined in validusage.json (%d):" % len(undef_set))
413 undef = list(undef_set)
414 undef.sort()
415 for vuid in undef:
416 print(" %s" % vuid)
417 return False
418 return True
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600419
Dave Houltoncacef472018-05-29 13:00:42 -0600420 # Report undefined VUIDs in tests
421 def undef_vuids_in_tests(self):
422 undef_set = self.tests - self.valid
423 undef_set.discard('VUID-Undefined') # don't report Undefined
424 if ignore_unassigned:
425 unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')})
426 undef_set = undef_set - unassigned
427 if (len(undef_set) > 0):
428 ok = False
429 print("\nFollowing VUIDs found in layer tests are not defined in validusage.json (%d):" % len(undef_set))
430 undef = list(undef_set)
431 undef.sort()
432 for vuid in undef:
433 print(" %s" % vuid)
434 return False
435 return True
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600436
Dave Houltoncacef472018-05-29 13:00:42 -0600437 # Report vuids in tests that are not in source
438 def vuids_tested_not_checked(self):
439 undef_set = self.tests - self.checks
440 undef_set.discard('VUID-Undefined') # don't report Undefined
441 if ignore_unassigned:
442 unassigned = set()
443 for vuid in undef_set:
444 if vuid.startswith('UNASSIGNED-'):
445 unassigned.add(vuid)
446 undef_set = undef_set - unassigned
447 if (len(undef_set) > 0):
448 ok = False
449 print("\nFollowing VUIDs found in tests but are not checked in layer code (%d):" % len(undef_set))
450 undef = list(undef_set)
451 undef.sort()
452 for vuid in undef:
453 print(" %s" % vuid)
454 return False
455 return True
456
457 # TODO: Explicit checked VUIDs which have no test
458 # def explicit_vuids_checked_not_tested(self):
459
460
461# Class to output database in various flavors
462#
463class OutputDatabase:
464 def __init__(self, val_json, val_source, val_tests):
465 self.vj = val_json
466 self.vs = val_source
467 self.vt = val_tests
Dave Houlton407df732018-08-06 17:58:24 -0600468 self.header_preamble = """/* THIS FILE IS GENERATED. DO NOT EDIT. */
469/* (scripts/vk_validation_stats.py) */
470/*
471 * Vulkan
472 *
473 * Copyright (c) 2016-2018 Google Inc.
474 * Copyright (c) 2016-2018 LunarG, Inc.
475 *
476 * Licensed under the Apache License, Version 2.0 (the "License");
477 * you may not use this file except in compliance with the License.
478 * You may obtain a copy of the License at
479 *
480 * http://www.apache.org/licenses/LICENSE-2.0
481 *
482 * Unless required by applicable law or agreed to in writing, software
483 * distributed under the License is distributed on an "AS IS" BASIS,
484 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
485 * See the License for the specific language governing permissions and
486 * limitations under the License.
487 *
488 * Author: Tobin Ehlis <tobine@google.com>
489 * Author: Dave Houlton <daveh@lunarg.com>
490 */
491
492#pragma once
493
494// Disable auto-formatting for generated file
495// clang-format off
496
Dave Houlton407df732018-08-06 17:58:24 -0600497// Mapping from VUID string to the corresponding spec text
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600498typedef struct _vuid_spec_text_pair {
499 const char * vuid;
500 const char * spec_text;
501} vuid_spec_text_pair;
502
503static const vuid_spec_text_pair vuid_spec_text[] = {
Dave Houlton407df732018-08-06 17:58:24 -0600504"""
505 self.header_postamble = """};
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600506"""
Dave Houlton407df732018-08-06 17:58:24 -0600507 self.spec_url = "https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html"
Dave Houltoncacef472018-05-29 13:00:42 -0600508
509 def dump_txt(self):
510 print("\n Dumping database to text file: %s" % txt_filename)
511 with open (txt_filename, 'w') as txt:
512 txt.write("## VUID Database\n")
513 txt.write("## Format: VUID_NAME | CHECKED | TEST | TYPE | API/STRUCT | EXTENSION | VUID_TEXT\n##\n")
514 vuid_list = list(self.vj.all_vuids)
515 vuid_list.sort()
516 for vuid in vuid_list:
517 db_list = self.vj.vuid_db[vuid]
518 db_list.sort(key=operator.itemgetter('ext')) # sort list to ease diffs of output file
519 for db_entry in db_list:
520 checked = 'N'
521 if vuid in self.vs.all_vuids:
522 checked = 'Y'
523 test = 'None'
524 if vuid in self.vt.vuid_to_tests:
525 test_list = list(self.vt.vuid_to_tests[vuid])
526 test_list.sort() # sort tests, for diff-ability
527 sep = ', '
528 test = sep.join(test_list)
529
530 txt.write("%s | %s | %s | %s | %s | %s | %s\n" % (vuid, checked, test, db_entry['type'], db_entry['api'], db_entry['ext'], db_entry['text']))
531
532 def dump_csv(self):
533 print("\n Dumping database to csv file: %s" % csv_filename)
534 with open (csv_filename, 'w', newline='') as csvfile:
535 cw = csv.writer(csvfile)
536 cw.writerow(['VUID_NAME','CHECKED','TEST','TYPE','API/STRUCT','EXTENSION','VUID_TEXT'])
537 vuid_list = list(self.vj.all_vuids)
538 vuid_list.sort()
539 for vuid in vuid_list:
540 for db_entry in self.vj.vuid_db[vuid]:
541 row = [vuid]
542 if vuid in self.vs.all_vuids:
543 row.append('Y')
544 else:
545 row.append('N')
546 test = 'None'
547 if vuid in self.vt.vuid_to_tests:
548 sep = ', '
549 test = sep.join(self.vt.vuid_to_tests[vuid])
550 row.append(test)
551 row.append(db_entry['type'])
552 row.append(db_entry['api'])
553 row.append(db_entry['ext'])
554 row.append(db_entry['text'])
555 cw.writerow(row)
556
557 def dump_html(self):
558 print("\n Dumping database to html file: %s" % html_filename)
559 preamble = '<!DOCTYPE html>\n<html>\n<head>\n<style>\ntable, th, td {\n border: 1px solid black;\n border-collapse: collapse; \n}\n</style>\n<body>\n<h2>Valid Usage Database</h2>\n<font size="2" face="Arial">\n<table style="width:100%">\n'
560 headers = '<tr><th>VUID NAME</th><th>CHECKED</th><th>TEST</th><th>TYPE</th><th>API/STRUCT</th><th>EXTENSION</th><th>VUID TEXT</th></tr>\n'
561 with open (html_filename, 'w') as hfile:
562 hfile.write(preamble)
563 hfile.write(headers)
564 vuid_list = list(self.vj.all_vuids)
565 vuid_list.sort()
566 for vuid in vuid_list:
567 for db_entry in self.vj.vuid_db[vuid]:
568 hfile.write('<tr><th>%s</th>' % vuid)
569 checked = '<span style="color:red;">N</span>'
570 if vuid in self.vs.all_vuids:
571 checked = '<span style="color:limegreen;">Y</span>'
572 hfile.write('<th>%s</th>' % checked)
573 test = 'None'
574 if vuid in self.vt.vuid_to_tests:
575 sep = ', '
576 test = sep.join(self.vt.vuid_to_tests[vuid])
577 hfile.write('<th>%s</th>' % test)
578 hfile.write('<th>%s</th>' % db_entry['type'])
579 hfile.write('<th>%s</th>' % db_entry['api'])
580 hfile.write('<th>%s</th>' % db_entry['ext'])
581 hfile.write('<th>%s</th></tr>\n' % db_entry['text'])
582 hfile.write('</table>\n</body>\n</html>\n')
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600583
Dave Houlton407df732018-08-06 17:58:24 -0600584 def export_header(self):
585 print("\n Exporting header file to: %s" % header_filename)
586 with open (header_filename, 'w') as hfile:
587 hfile.write(self.header_preamble)
588 vuid_list = list(self.vj.all_vuids)
589 vuid_list.sort()
590 for vuid in vuid_list:
591 db_entry = self.vj.vuid_db[vuid][0]
592 hfile.write(' {"%s", "%s (%s#%s)"},\n' % (vuid, db_entry['text'].strip(' '), self.spec_url, vuid))
593 # For multiply-defined VUIDs, include versions with extension appended
594 if len(self.vj.vuid_db[vuid]) > 1:
595 for db_entry in self.vj.vuid_db[vuid]:
596 hfile.write(' {"%s[%s]", "%s (%s#%s)"},\n' % (vuid, db_entry['ext'].strip(' '), db_entry['text'].strip(' '), self.spec_url, vuid))
597 hfile.write(self.header_postamble)
598
Mark Lobodzinskib44c54a2017-06-12 12:02:38 -0600599def main(argv):
Dave Houltoncacef472018-05-29 13:00:42 -0600600 global verbose_mode
601 global txt_filename
602 global csv_filename
603 global html_filename
604
605 run_consistency = False
606 report_unimplemented = False
607 get_vuid_status = ''
608 txt_out = False
609 csv_out = False
610 html_out = False
Dave Houlton407df732018-08-06 17:58:24 -0600611 header_out = False
Dave Houltoncacef472018-05-29 13:00:42 -0600612
613 if (1 > len(argv)):
614 printHelp()
615 sys.exit()
616
617 # Parse script args
618 json_filename = argv[0]
619 i = 1
620 while (i < len(argv)):
621 arg = argv[i]
622 i = i + 1
623 if (arg == '-c'):
624 run_consistency = True
625 elif (arg == '-vuid'):
626 get_vuid_status = argv[i]
627 i = i + 1
628 elif (arg == '-todo'):
629 report_unimplemented = True
Karl Schultz49d66bb2018-07-09 16:24:46 -0600630 elif (arg == '-text'):
Dave Houltoncacef472018-05-29 13:00:42 -0600631 txt_out = True
632 # Set filename if supplied, else use default
633 if i < len(argv) and not argv[i].startswith('-'):
634 txt_filename = argv[i]
635 i = i + 1
636 elif (arg == '-csv'):
637 csv_out = True
638 # Set filename if supplied, else use default
639 if i < len(argv) and not argv[i].startswith('-'):
640 csv_filename = argv[i]
641 i = i + 1
642 elif (arg == '-html'):
643 html_out = True
644 # Set filename if supplied, else use default
645 if i < len(argv) and not argv[i].startswith('-'):
646 html_filename = argv[i]
647 i = i + 1
Dave Houlton407df732018-08-06 17:58:24 -0600648 elif (arg == '-export_header'):
649 header_out = True
Dave Houltoncacef472018-05-29 13:00:42 -0600650 elif (arg in ['-verbose']):
651 verbose_mode = True
652 elif (arg in ['-help', '-h']):
653 printHelp()
654 sys.exit()
655 else:
656 print("Unrecognized argument: %s\n" % arg)
657 printHelp()
658 sys.exit()
659
Tobin Ehlis20e32582016-12-05 14:50:03 -0700660 result = 0 # Non-zero result indicates an error case
Dave Houltoncacef472018-05-29 13:00:42 -0600661
662 # Parse validusage json
663 val_json = ValidationJSON(json_filename)
664 val_json.read()
665 exp_json = len(val_json.explicit_vuids)
666 imp_json = len(val_json.implicit_vuids)
667 all_json = len(val_json.all_vuids)
668 if verbose_mode:
669 print("Found %d unique error vuids in validusage.json file." % all_json)
670 print(" %d explicit" % exp_json)
671 print(" %d implicit" % imp_json)
672 if len(val_json.duplicate_vuids) > 0:
673 print("%d VUIDs appear in validusage.json more than once." % len(val_json.duplicate_vuids))
674 for vuid in val_json.duplicate_vuids:
675 print(" %s" % vuid)
676 for ext in val_json.vuid_db[vuid]:
677 print(" with extension: %s" % ext['ext'])
678
679 # Parse layer source files
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600680 val_source = ValidationSource(layer_source_files, generated_layer_source_files, generated_layer_source_directories)
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600681 val_source.parse()
Dave Houltoncacef472018-05-29 13:00:42 -0600682 exp_checks = len(val_source.explicit_vuids)
683 imp_checks = len(val_source.implicit_vuids)
684 all_checks = len(val_source.vuid_count_dict.keys())
685 if verbose_mode:
686 print("Found %d unique vuid checks in layer source code." % all_checks)
687 print(" %d explicit" % exp_checks)
688 print(" %d implicit" % imp_checks)
689 print(" %d unassigned" % len(val_source.unassigned_vuids))
690 print(" %d checks are implemented more that once" % val_source.duplicated_checks)
691
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600692 # Parse test files
Dave Houltoncacef472018-05-29 13:00:42 -0600693 val_tests = ValidationTests([test_file, ])
694 val_tests.parse()
695 exp_tests = len(val_tests.explicit_vuids)
696 imp_tests = len(val_tests.implicit_vuids)
697 all_tests = len(val_tests.all_vuids)
Mark Lobodzinski060a8e32018-01-08 09:08:06 -0700698 if verbose_mode:
Dave Houltoncacef472018-05-29 13:00:42 -0600699 print("Found %d unique error vuids in test file %s." % (all_tests, test_file))
700 print(" %d explicit" % exp_tests)
701 print(" %d implicit" % imp_tests)
702 print(" %d unassigned" % len(val_tests.unassigned_vuids))
Mike Weiblenfe186122017-02-03 12:44:53 -0700703
Dave Houltoncacef472018-05-29 13:00:42 -0600704 # Process stats
705 print("\nValidation Statistics (using validusage.json version %s)" % val_json.apiversion)
706 print(" VUIDs defined in JSON file: %04d explicit, %04d implicit, %04d total." % (exp_json, imp_json, all_json))
707 print(" VUIDs checked in layer code: %04d explicit, %04d implicit, %04d total." % (exp_checks, imp_checks, all_checks))
708 print(" VUIDs tested in layer tests: %04d explicit, %04d implicit, %04d total." % (exp_tests, imp_tests, all_tests))
709
710 print("\nVUID check coverage")
711 print(" Explicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * exp_checks / exp_json), exp_checks, exp_json))
712 print(" Implicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * imp_checks / imp_json), imp_checks, imp_json))
713 print(" Overall VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * all_checks / all_json), all_checks, all_json))
Mike Weiblenfe186122017-02-03 12:44:53 -0700714
Dave Houltoncacef472018-05-29 13:00:42 -0600715 print("\nVUID test coverage")
716 print(" Explicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * exp_tests / exp_checks), exp_tests, exp_checks))
717 print(" Implicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * imp_tests / imp_checks), imp_tests, imp_checks))
718 print(" Overall VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * all_tests / all_checks), all_tests, all_checks))
Mike Weiblenfe186122017-02-03 12:44:53 -0700719
Dave Houltoncacef472018-05-29 13:00:42 -0600720 # Report status of a single VUID
721 if len(get_vuid_status) > 1:
722 print("\n\nChecking status of <%s>" % get_vuid_status);
723 if get_vuid_status not in val_json.all_vuids:
724 print(' Not a valid VUID string.')
725 else:
726 if get_vuid_status in val_source.explicit_vuids:
727 print(' Implemented!')
728 line_list = val_source.vuid_count_dict[get_vuid_status]['file_line']
729 for line in line_list:
730 print(' => %s' % line)
Dave Houltonf93bbab2018-06-26 17:21:12 -0600731 elif get_vuid_status in val_source.implicit_vuids:
732 print(' Implemented! (Implicit)')
733 line_list = val_source.vuid_count_dict[get_vuid_status]['file_line']
734 for line in line_list:
735 print(' => %s' % line)
Tobin Ehlis9a68c982016-12-29 14:51:17 -0700736 else:
Dave Houltoncacef472018-05-29 13:00:42 -0600737 print(' Not implemented.')
Dave Houltonf93bbab2018-06-26 17:21:12 -0600738 if get_vuid_status in val_tests.all_vuids:
Dave Houltoncacef472018-05-29 13:00:42 -0600739 print(' Has a test!')
740 test_list = val_tests.vuid_to_tests[get_vuid_status]
741 for test in test_list:
742 print(' => %s' % test)
743 else:
744 print(' Not tested.')
Mike Weiblenfe186122017-02-03 12:44:53 -0700745
Dave Houltoncacef472018-05-29 13:00:42 -0600746 # Report unimplemented explicit VUIDs
747 if report_unimplemented:
748 unim_explicit = val_json.explicit_vuids - val_source.explicit_vuids
749 print("\n\n%d explicit VUID checks remain unimplemented:" % len(unim_explicit))
750 ulist = list(unim_explicit)
751 ulist.sort()
752 for vuid in ulist:
753 print(" => %s" % vuid)
754
755 # Consistency tests
756 if run_consistency:
757 print("\n\nRunning consistency tests...")
758 con = Consistency(val_json.all_vuids, val_source.all_vuids, val_tests.all_vuids)
759 ok = con.undef_vuids_in_layer_code()
760 ok &= con.undef_vuids_in_tests()
761 ok &= con.vuids_tested_not_checked()
762
763 if ok:
764 print(" OK! No inconsistencies found.")
765
766 # Output database in requested format(s)
767 db_out = OutputDatabase(val_json, val_source, val_tests)
768 if txt_out:
769 db_out.dump_txt()
770 if csv_out:
771 db_out.dump_csv()
772 if html_out:
773 db_out.dump_html()
Dave Houlton407df732018-08-06 17:58:24 -0600774 if header_out:
775 db_out.export_header()
Tobin Ehlis20e32582016-12-05 14:50:03 -0700776 return result
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600777
778if __name__ == "__main__":
Mark Lobodzinskib44c54a2017-06-12 12:02:38 -0600779 sys.exit(main(sys.argv[1:]))
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600780