blob: 85fde1f07a78187ca32c6c961f0c8d731c4e5f9b [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
Dave Houlton729c7822018-11-19 11:52:23 -070031import time
Dave Houltoncacef472018-05-29 13:00:42 -060032from collections import defaultdict
Tobin Ehlis35308dd2016-10-31 13:27:36 -060033
Dave Houltoncacef472018-05-29 13:00:42 -060034verbose_mode = False
35txt_db = False
36csv_db = False
37html_db = False
38txt_filename = "validation_error_database.txt"
39csv_filename = "validation_error_database.csv"
40html_filename = "validation_error_database.html"
Dave Houlton407df732018-08-06 17:58:24 -060041header_filename = "../layers/vk_validation_error_messages.h"
Dave Houltoncacef472018-05-29 13:00:42 -060042test_file = '../tests/layer_validation_tests.cpp'
43vuid_prefixes = ['VUID-', 'UNASSIGNED-']
Tobin Ehlis35308dd2016-10-31 13:27:36 -060044
Dave Houltoncacef472018-05-29 13:00:42 -060045# Hard-coded flags that could be command line args, if we decide that's useful
46# replace KHR vuids with non-KHR during consistency checking
47dealias_khr = True
48ignore_unassigned = True # These are not found in layer code unless they appear explicitly (most don't), so produce false positives
49
Mark Lobodzinski05849f02017-06-21 14:44:14 -060050generated_layer_source_directories = [
51'build',
52'dbuild',
53'release',
54]
55generated_layer_source_files = [
Mark Lobodzinskid4950072017-08-01 13:02:20 -060056'parameter_validation.cpp',
Mark Lobodzinski09fa2d42017-07-21 10:16:53 -060057'object_tracker.cpp',
Mark Lobodzinski05849f02017-06-21 14:44:14 -060058]
Tobin Ehlis35308dd2016-10-31 13:27:36 -060059layer_source_files = [
Mark Lobodzinskie3787b42017-06-21 13:41:00 -060060'../layers/core_validation.cpp',
61'../layers/descriptor_sets.cpp',
Mark Lobodzinskid4950072017-08-01 13:02:20 -060062'../layers/parameter_validation_utils.cpp',
Mark Lobodzinskib2de97f2017-07-06 15:28:11 -060063'../layers/object_tracker_utils.cpp',
Mark Lobodzinskie3787b42017-06-21 13:41:00 -060064'../layers/shader_validation.cpp',
65'../layers/buffer_validation.cpp',
Tobin Ehlis35308dd2016-10-31 13:27:36 -060066]
Tobin Ehlis35308dd2016-10-31 13:27:36 -060067
Dave Houlton407df732018-08-06 17:58:24 -060068# This needs to be updated as new extensions roll in
Dave Houltoncacef472018-05-29 13:00:42 -060069khr_aliases = {
70 'VUID-vkBindBufferMemory2KHR-device-parameter' : 'VUID-vkBindBufferMemory2-device-parameter',
71 'VUID-vkBindBufferMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindBufferMemory2-pBindInfos-parameter',
72 'VUID-vkBindImageMemory2KHR-device-parameter' : 'VUID-vkBindImageMemory2-device-parameter',
73 'VUID-vkBindImageMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindImageMemory2-pBindInfos-parameter',
74 'VUID-vkCmdDispatchBaseKHR-commandBuffer-parameter' : 'VUID-vkCmdDispatchBase-commandBuffer-parameter',
75 'VUID-vkCmdSetDeviceMaskKHR-commandBuffer-parameter' : 'VUID-vkCmdSetDeviceMask-commandBuffer-parameter',
76 'VUID-vkCreateDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-device-parameter',
77 'VUID-vkCreateDescriptorUpdateTemplateKHR-pDescriptorUpdateTemplate-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pDescriptorUpdateTemplate-parameter',
78 'VUID-vkCreateSamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-device-parameter',
79 'VUID-vkCreateSamplerYcbcrConversionKHR-pYcbcrConversion-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pYcbcrConversion-parameter',
80 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parameter',
81 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parent',
82 'VUID-vkDestroyDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-device-parameter',
83 'VUID-vkDestroySamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-device-parameter',
84 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parameter',
85 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parent' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parent',
86 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-instance-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-instance-parameter',
87 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-pPhysicalDeviceGroupProperties-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-pPhysicalDeviceGroupProperties-parameter',
88 'VUID-vkGetBufferMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetBufferMemoryRequirements2-device-parameter',
89 'VUID-vkGetDescriptorSetLayoutSupportKHR-device-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-device-parameter',
90 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-device-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-device-parameter',
91 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-pPeerMemoryFeatures-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-pPeerMemoryFeatures-parameter',
92 'VUID-vkGetImageMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageMemoryRequirements2-device-parameter',
93 'VUID-vkGetImageSparseMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-device-parameter',
94 'VUID-vkGetImageSparseMemoryRequirements2KHR-pSparseMemoryRequirements-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pSparseMemoryRequirements-parameter',
95 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-physicalDevice-parameter',
96 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-physicalDevice-parameter',
97 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-physicalDevice-parameter',
98 'VUID-vkGetPhysicalDeviceFeatures2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-physicalDevice-parameter',
99 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-format-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-format-parameter',
100 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-physicalDevice-parameter',
101 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-physicalDevice-parameter',
102 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-physicalDevice-parameter',
103 'VUID-vkGetPhysicalDeviceProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-physicalDevice-parameter',
104 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2KHR-pQueueFamilyProperties-parameter' : 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2-pQueueFamilyProperties-parameter',
105 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pProperties-parameter',
106 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-physicalDevice-parameter',
107 'VUID-vkTrimCommandPoolKHR-commandPool-parameter' : 'VUID-vkTrimCommandPool-commandPool-parameter',
108 'VUID-vkTrimCommandPoolKHR-commandPool-parent' : 'VUID-vkTrimCommandPool-commandPool-parent',
109 'VUID-vkTrimCommandPoolKHR-device-parameter' : 'VUID-vkTrimCommandPool-device-parameter',
110 'VUID-vkTrimCommandPoolKHR-flags-zerobitmask' : 'VUID-vkTrimCommandPool-flags-zerobitmask',
111 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorSet-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorSet-parameter',
112 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parameter',
113 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parent',
114 'VUID-vkUpdateDescriptorSetWithTemplateKHR-device-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-device-parameter',
115 'VUID-vkCreateDescriptorUpdateTemplateKHR-pCreateInfo-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pCreateInfo-parameter',
116 'VUID-vkCreateSamplerYcbcrConversionKHR-pCreateInfo-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pCreateInfo-parameter',
117 'VUID-vkGetBufferMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pInfo-parameter',
118 'VUID-vkGetBufferMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pMemoryRequirements-parameter',
119 'VUID-vkGetDescriptorSetLayoutSupportKHR-pCreateInfo-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pCreateInfo-parameter',
120 'VUID-vkGetDescriptorSetLayoutSupportKHR-pSupport-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pSupport-parameter',
121 'VUID-vkGetImageMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageMemoryRequirements2-pInfo-parameter',
122 'VUID-vkGetImageMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetImageMemoryRequirements2-pMemoryRequirements-parameter',
123 'VUID-vkGetImageSparseMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pInfo-parameter',
124 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferInfo-parameter',
125 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferProperties-parameter',
126 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceInfo-parameter',
127 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceProperties-parameter',
128 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreInfo-parameter',
129 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreProperties-parameter',
130 'VUID-vkGetPhysicalDeviceFeatures2KHR-pFeatures-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-pFeatures-parameter',
131 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-pFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-pFormatProperties-parameter',
132 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatInfo-parameter',
133 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatProperties-parameter',
134 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-pMemoryProperties-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-pMemoryProperties-parameter',
135 'VUID-vkGetPhysicalDeviceProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-pProperties-parameter',
136 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pFormatInfo-parameter' }
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600137
Dave Houltoncacef472018-05-29 13:00:42 -0600138def printHelp():
139 print ("Usage:")
140 print (" python vk_validation_stats.py <json_file>")
141 print (" [ -c ]")
142 print (" [ -todo ]")
143 print (" [ -vuid <vuid_name> ]")
144 print (" [ -text [ <text_out_filename>] ]")
145 print (" [ -csv [ <csv_out_filename>] ]")
146 print (" [ -html [ <html_out_filename>] ]")
Dave Houlton407df732018-08-06 17:58:24 -0600147 print (" [ -export_header ]")
Dave Houltoncacef472018-05-29 13:00:42 -0600148 print (" [ -verbose ]")
149 print (" [ -help ]")
150 print ("\n The vk_validation_stats script parses validation layer source files to")
151 print (" determine the set of valid usage checks and tests currently implemented,")
152 print (" and generates coverage values by comparing against the full set of valid")
153 print (" usage identifiers in the Vulkan-Headers registry file 'validusage.json'")
154 print ("\nArguments: ")
155 print (" <json-file> (required) registry file 'validusage.json'")
156 print (" -c report consistency warnings")
157 print (" -todo report unimplemented VUIDs")
158 print (" -vuid <vuid_name> report status of individual VUID <vuid_name>")
159 print (" -text [filename] output the error database text to <text_database_filename>,")
160 print (" defaults to 'validation_error_database.txt'")
161 print (" -csv [filename] output the error database in csv to <csv_database_filename>,")
162 print (" defaults to 'validation_error_database.csv'")
163 print (" -html [filename] output the error database in html to <html_database_filename>,")
164 print (" defaults to 'validation_error_database.html'")
Dave Houlton407df732018-08-06 17:58:24 -0600165 print (" -export_header export a new VUID error text header file to <%s>" % header_filename)
Dave Houltoncacef472018-05-29 13:00:42 -0600166 print (" -verbose show your work (to stdout)")
167
168class ValidationJSON:
169 def __init__(self, filename):
170 self.filename = filename
171 self.explicit_vuids = set()
172 self.implicit_vuids = set()
173 self.all_vuids = set()
174 self.vuid_db = defaultdict(list) # Maps VUID string to list of json-data dicts
175 self.apiversion = ""
Dave Houltoncacef472018-05-29 13:00:42 -0600176 self.duplicate_vuids = set()
Dave Houlton407df732018-08-06 17:58:24 -0600177
178 # A set of specific regular expression substitutions needed to clean up VUID text
179 self.regex_dict = {}
180 self.regex_dict[re.compile('<.*?>|&(amp;)+lt;|&(amp;)+gt;')] = ""
181 self.regex_dict[re.compile(r'\\\(codeSize \\over 4\\\)')] = "(codeSize/4)"
182 self.regex_dict[re.compile(r'\\\(\\lceil\{\\mathit\{rasterizationSamples} \\over 32}\\rceil\\\)')] = "(rasterizationSamples/32)"
Shannon McPhersonb40f1a22018-10-30 16:45:07 -0600183 self.regex_dict[re.compile(r'\\\(\\textrm\{codeSize} \\over 4\\\)')] = "(codeSize/4)"
Dave Houlton407df732018-08-06 17:58:24 -0600184 # Some fancy punctuation chars that break the Android build...
185 self.regex_dict[re.compile('&#8594;')] = "->" # Arrow char
186 self.regex_dict[re.compile('&#8217;')] = "'" # Left-slanting apostrophe to apostrophe
187 self.regex_dict[re.compile('&#822(0|1);')] = "'" # L/R-slanting quotes to apostrophe
Dave Houltoncacef472018-05-29 13:00:42 -0600188
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600189 def read(self):
Dave Houltoncacef472018-05-29 13:00:42 -0600190 self.json_dict = {}
191 if os.path.isfile(self.filename):
Dave Houlton407df732018-08-06 17:58:24 -0600192 json_file = open(self.filename, 'r', encoding='utf-8')
Dave Houltoncacef472018-05-29 13:00:42 -0600193 self.json_dict = json.load(json_file)
194 json_file.close()
195 if len(self.json_dict) == 0:
196 print("Error: Error loading validusage.json file <%s>" % self.filename)
197 sys.exit(-1)
198 try:
199 version = self.json_dict['version info']
200 validation = self.json_dict['validation']
201 self.apiversion = version['api version']
202 except:
203 print("Error: Failure parsing validusage.json object")
204 sys.exit(-1)
205
206 # Parse vuid from json into local databases
207 for apiname in validation.keys():
208 # print("entrypoint:%s"%apiname)
209 apidict = validation[apiname]
210 for ext in apidict.keys():
211 vlist = apidict[ext]
212 for ventry in vlist:
213 vuid_string = ventry['vuid']
214 if (vuid_string[-5:-1].isdecimal()):
215 self.explicit_vuids.add(vuid_string) # explicit end in 5 numeric chars
216 vtype = 'explicit'
217 else:
218 self.implicit_vuids.add(vuid_string) # otherwise, implicit
219 vtype = 'implicit'
220 vuid_text = ventry['text']
Dave Houlton407df732018-08-06 17:58:24 -0600221 for regex, replacement in self.regex_dict.items():
222 vuid_text = re.sub(regex, replacement, vuid_text) # do regex substitution
223 vuid_text = html.unescape(vuid_text) # anything missed by the regex
224 self.vuid_db[vuid_string].append({'api':apiname, 'ext':ext, 'type':vtype, 'text':vuid_text})
Dave Houltoncacef472018-05-29 13:00:42 -0600225 self.all_vuids = self.explicit_vuids | self.implicit_vuids
226 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 -0600227 if len(self.duplicate_vuids) > 0:
228 print("Warning: duplicate VUIDs found in validusage.json")
229
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600230
231class ValidationSource:
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600232 def __init__(self, source_file_list, generated_source_file_list, generated_source_directories):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600233 self.source_files = source_file_list
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600234 self.generated_source_files = generated_source_file_list
235 self.generated_source_dirs = generated_source_directories
Dave Houltoncacef472018-05-29 13:00:42 -0600236 self.vuid_count_dict = {} # dict of vuid values to the count of how much they're used, and location of where they're used
237 self.duplicated_checks = 0
238 self.explicit_vuids = set()
239 self.implicit_vuids = set()
240 self.unassigned_vuids = set()
241 self.all_vuids = set()
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600242
243 if len(self.generated_source_files) > 0:
244 qualified_paths = []
245 for source in self.generated_source_files:
246 for build_dir in self.generated_source_dirs:
247 filepath = '../%s/layers/%s' % (build_dir, source)
248 if os.path.isfile(filepath):
249 qualified_paths.append(filepath)
John Zulaufdde04c42018-01-16 15:32:45 -0700250 break
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600251 if len(self.generated_source_files) != len(qualified_paths):
Mark Lobodzinski2d193ac2017-06-27 09:38:15 -0600252 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 -0600253 print(self.generated_source_files)
Dave Houltoncacef472018-05-29 13:00:42 -0600254 print("Failed to locate one or more codegen files in layer source code - cannot proceed.")
John Zulaufdde04c42018-01-16 15:32:45 -0700255 exit(1)
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600256 else:
257 self.source_files.extend(qualified_paths)
258
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600259 def parse(self):
Dave Houltoncacef472018-05-29 13:00:42 -0600260 prepend = None
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600261 for sf in self.source_files:
Tobin Ehlis3d1f2bd2016-12-22 11:19:15 -0700262 line_num = 0
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600263 with open(sf) as f:
264 for line in f:
Tobin Ehlis3d1f2bd2016-12-22 11:19:15 -0700265 line_num = line_num + 1
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600266 if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
267 continue
Dave Houltoncacef472018-05-29 13:00:42 -0600268 # Find vuid strings
Michał Janiszewski3c3ce9e2018-10-30 23:25:21 +0100269 if prepend is not None:
Dave Houltoncacef472018-05-29 13:00:42 -0600270 line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char
271 prepend = None
272 if any(prefix in line for prefix in vuid_prefixes):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600273 line_list = line.split()
Dave Houltoncacef472018-05-29 13:00:42 -0600274
275 # 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
276 broken_vuid = line_list[-1].strip('"')
277 if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'):
278 prepend = line
279 continue
280
281 vuid_list = []
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600282 for str in line_list:
Dave Houltoncacef472018-05-29 13:00:42 -0600283 if any(prefix in str for prefix in vuid_prefixes):
284 vuid_list.append(str.strip(',);{}"'))
285 for vuid in vuid_list:
286 if vuid not in self.vuid_count_dict:
287 self.vuid_count_dict[vuid] = {}
288 self.vuid_count_dict[vuid]['count'] = 1
289 self.vuid_count_dict[vuid]['file_line'] = []
290 else:
291 if self.vuid_count_dict[vuid]['count'] == 1: # only count first time duplicated
292 self.duplicated_checks = self.duplicated_checks + 1
293 self.vuid_count_dict[vuid]['count'] = self.vuid_count_dict[vuid]['count'] + 1
294 self.vuid_count_dict[vuid]['file_line'].append('%s,%d' % (sf, line_num))
295 # Sort vuids by type
296 for vuid in self.vuid_count_dict.keys():
297 if (vuid.startswith('VUID-')):
298 if (vuid[-5:-1].isdecimal()):
299 self.explicit_vuids.add(vuid) # explicit end in 5 numeric chars
300 else:
301 self.implicit_vuids.add(vuid)
302 elif (vuid.startswith('UNASSIGNED-')):
303 self.unassigned_vuids.add(vuid)
304 else:
305 print("Unable to categorize VUID: %s" % vuid)
306 print("Confused while parsing VUIDs in layer source code - cannot proceed. (FIXME)")
307 exit(-1)
308 self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600309
310# Class to parse the validation layer test source and store testnames
Dave Houltoncacef472018-05-29 13:00:42 -0600311class ValidationTests:
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600312 def __init__(self, test_file_list, test_group_name=['VkLayerTest', 'VkPositiveLayerTest', 'VkWsiEnabledLayerTest']):
313 self.test_files = test_file_list
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600314 self.test_trigger_txt_list = []
315 for tg in test_group_name:
316 self.test_trigger_txt_list.append('TEST_F(%s' % tg)
Dave Houltoncacef472018-05-29 13:00:42 -0600317 self.explicit_vuids = set()
318 self.implicit_vuids = set()
319 self.unassigned_vuids = set()
320 self.all_vuids = set()
321 #self.test_to_vuids = {} # Map test name to VUIDs tested
322 self.vuid_to_tests = defaultdict(set) # Map VUIDs to set of test names where implemented
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600323
324 # Parse test files into internal data struct
325 def parse(self):
326 # For each test file, parse test names into set
327 grab_next_line = False # handle testname on separate line than wildcard
Tobin Ehlis9a68c982016-12-29 14:51:17 -0700328 testname = ''
Dave Houltoncacef472018-05-29 13:00:42 -0600329 prepend = None
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600330 for test_file in self.test_files:
331 with open(test_file) as tf:
332 for line in tf:
333 if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
334 continue
335
Dave Houltoncacef472018-05-29 13:00:42 -0600336 # if line ends in a broken VUID string, fix that before proceeding
Michał Janiszewski3c3ce9e2018-10-30 23:25:21 +0100337 if prepend is not None:
Dave Houltoncacef472018-05-29 13:00:42 -0600338 line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char
339 prepend = None
340 if any(prefix in line for prefix in vuid_prefixes):
341 line_list = line.split()
342
343 # 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
344 broken_vuid = line_list[-1].strip('"')
345 if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'):
346 prepend = line
347 continue
348
349 if any(ttt in line for ttt in self.test_trigger_txt_list):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600350 testname = line.split(',')[-1]
351 testname = testname.strip().strip(' {)')
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600352 if ('' == testname):
353 grab_next_line = True
354 continue
Dave Houltoncacef472018-05-29 13:00:42 -0600355 #self.test_to_vuids[testname] = []
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600356 if grab_next_line: # test name on its own line
357 grab_next_line = False
358 testname = testname.strip().strip(' {)')
Dave Houltoncacef472018-05-29 13:00:42 -0600359 #self.test_to_vuids[testname] = []
360 if any(prefix in line for prefix in vuid_prefixes):
361 line_list = re.split('[\s{}[\]()"]+',line)
Tobin Ehlis71f38c12017-01-12 14:26:56 -0700362 for sub_str in line_list:
Dave Houltoncacef472018-05-29 13:00:42 -0600363 if any(prefix in sub_str for prefix in vuid_prefixes):
364 vuid_str = sub_str.strip(',);:"')
365 self.vuid_to_tests[vuid_str].add(testname)
366 #self.test_to_vuids[testname].append(vuid_str)
367 if (vuid_str.startswith('VUID-')):
368 if (vuid_str[-5:-1].isdecimal()):
369 self.explicit_vuids.add(vuid_str) # explicit end in 5 numeric chars
370 else:
371 self.implicit_vuids.add(vuid_str)
372 elif (vuid_str.startswith('UNASSIGNED-')):
373 self.unassigned_vuids.add(vuid_str)
374 else:
375 print("Unable to categorize VUID: %s" % vuid_str)
376 print("Confused while parsing VUIDs in test code - cannot proceed. (FIXME)")
377 exit(-1)
378 self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600379
Dave Houltoncacef472018-05-29 13:00:42 -0600380# Class to do consistency checking
381#
382class Consistency:
383 def __init__(self, all_json, all_checks, all_tests):
384 self.valid = all_json
385 self.checks = all_checks
386 self.tests = all_tests
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600387
Dave Houltoncacef472018-05-29 13:00:42 -0600388 if (dealias_khr):
389 dk = set()
390 for vuid in self.checks:
391 if vuid in khr_aliases:
392 dk.add(khr_aliases[vuid])
393 else:
394 dk.add(vuid)
395 self.checks = dk
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600396
Dave Houltoncacef472018-05-29 13:00:42 -0600397 dk = set()
398 for vuid in self.tests:
399 if vuid in khr_aliases:
400 dk.add(khr_aliases[vuid])
401 else:
402 dk.add(vuid)
403 self.tests = dk
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600404
Dave Houltoncacef472018-05-29 13:00:42 -0600405 # Report undefined VUIDs in source code
406 def undef_vuids_in_layer_code(self):
407 undef_set = self.checks - self.valid
408 undef_set.discard('VUID-Undefined') # don't report Undefined
409 if ignore_unassigned:
410 unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')})
411 undef_set = undef_set - unassigned
412 if (len(undef_set) > 0):
413 print("\nFollowing VUIDs found in layer code are not defined in validusage.json (%d):" % len(undef_set))
414 undef = list(undef_set)
415 undef.sort()
416 for vuid in undef:
417 print(" %s" % vuid)
418 return False
419 return True
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600420
Dave Houltoncacef472018-05-29 13:00:42 -0600421 # Report undefined VUIDs in tests
422 def undef_vuids_in_tests(self):
423 undef_set = self.tests - self.valid
424 undef_set.discard('VUID-Undefined') # don't report Undefined
425 if ignore_unassigned:
426 unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')})
427 undef_set = undef_set - unassigned
428 if (len(undef_set) > 0):
429 ok = False
430 print("\nFollowing VUIDs found in layer tests are not defined in validusage.json (%d):" % len(undef_set))
431 undef = list(undef_set)
432 undef.sort()
433 for vuid in undef:
434 print(" %s" % vuid)
435 return False
436 return True
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600437
Dave Houltoncacef472018-05-29 13:00:42 -0600438 # Report vuids in tests that are not in source
439 def vuids_tested_not_checked(self):
440 undef_set = self.tests - self.checks
441 undef_set.discard('VUID-Undefined') # don't report Undefined
442 if ignore_unassigned:
443 unassigned = set()
444 for vuid in undef_set:
445 if vuid.startswith('UNASSIGNED-'):
446 unassigned.add(vuid)
447 undef_set = undef_set - unassigned
448 if (len(undef_set) > 0):
449 ok = False
450 print("\nFollowing VUIDs found in tests but are not checked in layer code (%d):" % len(undef_set))
451 undef = list(undef_set)
452 undef.sort()
453 for vuid in undef:
454 print(" %s" % vuid)
455 return False
456 return True
457
458 # TODO: Explicit checked VUIDs which have no test
459 # def explicit_vuids_checked_not_tested(self):
460
461
462# Class to output database in various flavors
463#
464class OutputDatabase:
465 def __init__(self, val_json, val_source, val_tests):
466 self.vj = val_json
467 self.vs = val_source
468 self.vt = val_tests
Dave Houlton729c7822018-11-19 11:52:23 -0700469 self.header_version = "/* THIS FILE IS GENERATED - DO NOT EDIT (scripts/vk_validation_stats.py) */"
470 self.header_version += "\n/* Vulkan specification version: %s */" % val_json.apiversion
471 self.header_version += "\n/* Header generated: %s */\n" % time.strftime('%Y-%m-%d %H:%M:%S')
472 self.header_preamble = """
Dave Houlton407df732018-08-06 17:58:24 -0600473/*
474 * Vulkan
475 *
476 * Copyright (c) 2016-2018 Google Inc.
477 * Copyright (c) 2016-2018 LunarG, Inc.
478 *
479 * Licensed under the Apache License, Version 2.0 (the "License");
480 * you may not use this file except in compliance with the License.
481 * You may obtain a copy of the License at
482 *
483 * http://www.apache.org/licenses/LICENSE-2.0
484 *
485 * Unless required by applicable law or agreed to in writing, software
486 * distributed under the License is distributed on an "AS IS" BASIS,
487 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
488 * See the License for the specific language governing permissions and
489 * limitations under the License.
490 *
491 * Author: Tobin Ehlis <tobine@google.com>
492 * Author: Dave Houlton <daveh@lunarg.com>
493 */
494
495#pragma once
496
497// Disable auto-formatting for generated file
498// clang-format off
499
Dave Houlton407df732018-08-06 17:58:24 -0600500// Mapping from VUID string to the corresponding spec text
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600501typedef struct _vuid_spec_text_pair {
502 const char * vuid;
503 const char * spec_text;
504} vuid_spec_text_pair;
505
506static const vuid_spec_text_pair vuid_spec_text[] = {
Dave Houlton407df732018-08-06 17:58:24 -0600507"""
508 self.header_postamble = """};
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600509"""
Dave Houlton407df732018-08-06 17:58:24 -0600510 self.spec_url = "https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html"
Dave Houltoncacef472018-05-29 13:00:42 -0600511
512 def dump_txt(self):
513 print("\n Dumping database to text file: %s" % txt_filename)
514 with open (txt_filename, 'w') as txt:
515 txt.write("## VUID Database\n")
516 txt.write("## Format: VUID_NAME | CHECKED | TEST | TYPE | API/STRUCT | EXTENSION | VUID_TEXT\n##\n")
517 vuid_list = list(self.vj.all_vuids)
518 vuid_list.sort()
519 for vuid in vuid_list:
520 db_list = self.vj.vuid_db[vuid]
521 db_list.sort(key=operator.itemgetter('ext')) # sort list to ease diffs of output file
522 for db_entry in db_list:
523 checked = 'N'
524 if vuid in self.vs.all_vuids:
525 checked = 'Y'
526 test = 'None'
527 if vuid in self.vt.vuid_to_tests:
528 test_list = list(self.vt.vuid_to_tests[vuid])
529 test_list.sort() # sort tests, for diff-ability
530 sep = ', '
531 test = sep.join(test_list)
532
533 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']))
534
535 def dump_csv(self):
536 print("\n Dumping database to csv file: %s" % csv_filename)
537 with open (csv_filename, 'w', newline='') as csvfile:
538 cw = csv.writer(csvfile)
539 cw.writerow(['VUID_NAME','CHECKED','TEST','TYPE','API/STRUCT','EXTENSION','VUID_TEXT'])
540 vuid_list = list(self.vj.all_vuids)
541 vuid_list.sort()
542 for vuid in vuid_list:
543 for db_entry in self.vj.vuid_db[vuid]:
544 row = [vuid]
545 if vuid in self.vs.all_vuids:
546 row.append('Y')
547 else:
548 row.append('N')
549 test = 'None'
550 if vuid in self.vt.vuid_to_tests:
551 sep = ', '
552 test = sep.join(self.vt.vuid_to_tests[vuid])
553 row.append(test)
554 row.append(db_entry['type'])
555 row.append(db_entry['api'])
556 row.append(db_entry['ext'])
557 row.append(db_entry['text'])
558 cw.writerow(row)
559
560 def dump_html(self):
561 print("\n Dumping database to html file: %s" % html_filename)
562 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'
563 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'
564 with open (html_filename, 'w') as hfile:
565 hfile.write(preamble)
566 hfile.write(headers)
567 vuid_list = list(self.vj.all_vuids)
568 vuid_list.sort()
569 for vuid in vuid_list:
570 for db_entry in self.vj.vuid_db[vuid]:
571 hfile.write('<tr><th>%s</th>' % vuid)
572 checked = '<span style="color:red;">N</span>'
573 if vuid in self.vs.all_vuids:
574 checked = '<span style="color:limegreen;">Y</span>'
575 hfile.write('<th>%s</th>' % checked)
576 test = 'None'
577 if vuid in self.vt.vuid_to_tests:
578 sep = ', '
579 test = sep.join(self.vt.vuid_to_tests[vuid])
580 hfile.write('<th>%s</th>' % test)
581 hfile.write('<th>%s</th>' % db_entry['type'])
582 hfile.write('<th>%s</th>' % db_entry['api'])
583 hfile.write('<th>%s</th>' % db_entry['ext'])
584 hfile.write('<th>%s</th></tr>\n' % db_entry['text'])
585 hfile.write('</table>\n</body>\n</html>\n')
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600586
Dave Houlton407df732018-08-06 17:58:24 -0600587 def export_header(self):
588 print("\n Exporting header file to: %s" % header_filename)
589 with open (header_filename, 'w') as hfile:
Dave Houlton729c7822018-11-19 11:52:23 -0700590 hfile.write(self.header_version)
Dave Houlton407df732018-08-06 17:58:24 -0600591 hfile.write(self.header_preamble)
592 vuid_list = list(self.vj.all_vuids)
593 vuid_list.sort()
594 for vuid in vuid_list:
595 db_entry = self.vj.vuid_db[vuid][0]
596 hfile.write(' {"%s", "%s (%s#%s)"},\n' % (vuid, db_entry['text'].strip(' '), self.spec_url, vuid))
597 # For multiply-defined VUIDs, include versions with extension appended
598 if len(self.vj.vuid_db[vuid]) > 1:
599 for db_entry in self.vj.vuid_db[vuid]:
600 hfile.write(' {"%s[%s]", "%s (%s#%s)"},\n' % (vuid, db_entry['ext'].strip(' '), db_entry['text'].strip(' '), self.spec_url, vuid))
601 hfile.write(self.header_postamble)
602
Mark Lobodzinskib44c54a2017-06-12 12:02:38 -0600603def main(argv):
Dave Houltoncacef472018-05-29 13:00:42 -0600604 global verbose_mode
605 global txt_filename
606 global csv_filename
607 global html_filename
608
609 run_consistency = False
610 report_unimplemented = False
611 get_vuid_status = ''
612 txt_out = False
613 csv_out = False
614 html_out = False
Dave Houlton407df732018-08-06 17:58:24 -0600615 header_out = False
Dave Houltoncacef472018-05-29 13:00:42 -0600616
617 if (1 > len(argv)):
618 printHelp()
619 sys.exit()
620
621 # Parse script args
622 json_filename = argv[0]
623 i = 1
624 while (i < len(argv)):
625 arg = argv[i]
626 i = i + 1
627 if (arg == '-c'):
628 run_consistency = True
629 elif (arg == '-vuid'):
630 get_vuid_status = argv[i]
631 i = i + 1
632 elif (arg == '-todo'):
633 report_unimplemented = True
Karl Schultz49d66bb2018-07-09 16:24:46 -0600634 elif (arg == '-text'):
Dave Houltoncacef472018-05-29 13:00:42 -0600635 txt_out = True
636 # Set filename if supplied, else use default
637 if i < len(argv) and not argv[i].startswith('-'):
638 txt_filename = argv[i]
639 i = i + 1
640 elif (arg == '-csv'):
641 csv_out = True
642 # Set filename if supplied, else use default
643 if i < len(argv) and not argv[i].startswith('-'):
644 csv_filename = argv[i]
645 i = i + 1
646 elif (arg == '-html'):
647 html_out = True
648 # Set filename if supplied, else use default
649 if i < len(argv) and not argv[i].startswith('-'):
650 html_filename = argv[i]
651 i = i + 1
Dave Houlton407df732018-08-06 17:58:24 -0600652 elif (arg == '-export_header'):
653 header_out = True
Dave Houltoncacef472018-05-29 13:00:42 -0600654 elif (arg in ['-verbose']):
655 verbose_mode = True
656 elif (arg in ['-help', '-h']):
657 printHelp()
658 sys.exit()
659 else:
660 print("Unrecognized argument: %s\n" % arg)
661 printHelp()
662 sys.exit()
663
Tobin Ehlis20e32582016-12-05 14:50:03 -0700664 result = 0 # Non-zero result indicates an error case
Dave Houltoncacef472018-05-29 13:00:42 -0600665
666 # Parse validusage json
667 val_json = ValidationJSON(json_filename)
668 val_json.read()
669 exp_json = len(val_json.explicit_vuids)
670 imp_json = len(val_json.implicit_vuids)
671 all_json = len(val_json.all_vuids)
672 if verbose_mode:
673 print("Found %d unique error vuids in validusage.json file." % all_json)
674 print(" %d explicit" % exp_json)
675 print(" %d implicit" % imp_json)
676 if len(val_json.duplicate_vuids) > 0:
677 print("%d VUIDs appear in validusage.json more than once." % len(val_json.duplicate_vuids))
678 for vuid in val_json.duplicate_vuids:
679 print(" %s" % vuid)
680 for ext in val_json.vuid_db[vuid]:
681 print(" with extension: %s" % ext['ext'])
682
683 # Parse layer source files
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600684 val_source = ValidationSource(layer_source_files, generated_layer_source_files, generated_layer_source_directories)
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600685 val_source.parse()
Dave Houltoncacef472018-05-29 13:00:42 -0600686 exp_checks = len(val_source.explicit_vuids)
687 imp_checks = len(val_source.implicit_vuids)
688 all_checks = len(val_source.vuid_count_dict.keys())
689 if verbose_mode:
690 print("Found %d unique vuid checks in layer source code." % all_checks)
691 print(" %d explicit" % exp_checks)
692 print(" %d implicit" % imp_checks)
693 print(" %d unassigned" % len(val_source.unassigned_vuids))
694 print(" %d checks are implemented more that once" % val_source.duplicated_checks)
695
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600696 # Parse test files
Dave Houltoncacef472018-05-29 13:00:42 -0600697 val_tests = ValidationTests([test_file, ])
698 val_tests.parse()
699 exp_tests = len(val_tests.explicit_vuids)
700 imp_tests = len(val_tests.implicit_vuids)
701 all_tests = len(val_tests.all_vuids)
Mark Lobodzinski060a8e32018-01-08 09:08:06 -0700702 if verbose_mode:
Dave Houltoncacef472018-05-29 13:00:42 -0600703 print("Found %d unique error vuids in test file %s." % (all_tests, test_file))
704 print(" %d explicit" % exp_tests)
705 print(" %d implicit" % imp_tests)
706 print(" %d unassigned" % len(val_tests.unassigned_vuids))
Mike Weiblenfe186122017-02-03 12:44:53 -0700707
Dave Houltoncacef472018-05-29 13:00:42 -0600708 # Process stats
709 print("\nValidation Statistics (using validusage.json version %s)" % val_json.apiversion)
710 print(" VUIDs defined in JSON file: %04d explicit, %04d implicit, %04d total." % (exp_json, imp_json, all_json))
711 print(" VUIDs checked in layer code: %04d explicit, %04d implicit, %04d total." % (exp_checks, imp_checks, all_checks))
712 print(" VUIDs tested in layer tests: %04d explicit, %04d implicit, %04d total." % (exp_tests, imp_tests, all_tests))
713
714 print("\nVUID check coverage")
715 print(" Explicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * exp_checks / exp_json), exp_checks, exp_json))
716 print(" Implicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * imp_checks / imp_json), imp_checks, imp_json))
717 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 -0700718
Dave Houltoncacef472018-05-29 13:00:42 -0600719 print("\nVUID test coverage")
720 print(" Explicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * exp_tests / exp_checks), exp_tests, exp_checks))
721 print(" Implicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * imp_tests / imp_checks), imp_tests, imp_checks))
722 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 -0700723
Dave Houltoncacef472018-05-29 13:00:42 -0600724 # Report status of a single VUID
725 if len(get_vuid_status) > 1:
726 print("\n\nChecking status of <%s>" % get_vuid_status);
727 if get_vuid_status not in val_json.all_vuids:
728 print(' Not a valid VUID string.')
729 else:
730 if get_vuid_status in val_source.explicit_vuids:
731 print(' Implemented!')
732 line_list = val_source.vuid_count_dict[get_vuid_status]['file_line']
733 for line in line_list:
734 print(' => %s' % line)
Dave Houltonf93bbab2018-06-26 17:21:12 -0600735 elif get_vuid_status in val_source.implicit_vuids:
736 print(' Implemented! (Implicit)')
737 line_list = val_source.vuid_count_dict[get_vuid_status]['file_line']
738 for line in line_list:
739 print(' => %s' % line)
Tobin Ehlis9a68c982016-12-29 14:51:17 -0700740 else:
Dave Houltoncacef472018-05-29 13:00:42 -0600741 print(' Not implemented.')
Dave Houltonf93bbab2018-06-26 17:21:12 -0600742 if get_vuid_status in val_tests.all_vuids:
Dave Houltoncacef472018-05-29 13:00:42 -0600743 print(' Has a test!')
744 test_list = val_tests.vuid_to_tests[get_vuid_status]
745 for test in test_list:
746 print(' => %s' % test)
747 else:
748 print(' Not tested.')
Mike Weiblenfe186122017-02-03 12:44:53 -0700749
Dave Houltoncacef472018-05-29 13:00:42 -0600750 # Report unimplemented explicit VUIDs
751 if report_unimplemented:
752 unim_explicit = val_json.explicit_vuids - val_source.explicit_vuids
753 print("\n\n%d explicit VUID checks remain unimplemented:" % len(unim_explicit))
754 ulist = list(unim_explicit)
755 ulist.sort()
756 for vuid in ulist:
757 print(" => %s" % vuid)
758
759 # Consistency tests
760 if run_consistency:
761 print("\n\nRunning consistency tests...")
762 con = Consistency(val_json.all_vuids, val_source.all_vuids, val_tests.all_vuids)
763 ok = con.undef_vuids_in_layer_code()
764 ok &= con.undef_vuids_in_tests()
765 ok &= con.vuids_tested_not_checked()
766
767 if ok:
768 print(" OK! No inconsistencies found.")
769
770 # Output database in requested format(s)
771 db_out = OutputDatabase(val_json, val_source, val_tests)
772 if txt_out:
773 db_out.dump_txt()
774 if csv_out:
775 db_out.dump_csv()
776 if html_out:
777 db_out.dump_html()
Dave Houlton407df732018-08-06 17:58:24 -0600778 if header_out:
779 db_out.export_header()
Tobin Ehlis20e32582016-12-05 14:50:03 -0700780 return result
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600781
782if __name__ == "__main__":
Mark Lobodzinskib44c54a2017-06-12 12:02:38 -0600783 sys.exit(main(sys.argv[1:]))
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600784