blob: 7c726533b80a6993521d87d5b7739dcc4c62b18e [file] [log] [blame]
Tobin Ehlis35308dd2016-10-31 13:27:36 -06001#!/usr/bin/env python3
Shannon McPherson9a4ae982019-01-07 16:05:25 -07002# Copyright (c) 2015-2019 The Khronos Group Inc.
3# Copyright (c) 2015-2019 Valve Corporation
4# Copyright (c) 2015-2019 LunarG, Inc.
5# Copyright (c) 2015-2019 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>
Shannon McPherson3ea65132018-12-05 10:37:39 -070021# Author: Shannon McPherson <shannon@lunarg.com>
Tobin Ehlis35308dd2016-10-31 13:27:36 -060022
23import argparse
24import os
25import sys
Dave Houltoncacef472018-05-29 13:00:42 -060026import operator
Tobin Ehlis35308dd2016-10-31 13:27:36 -060027import platform
Dave Houltoncacef472018-05-29 13:00:42 -060028import json
29import re
30import csv
31import html
Dave Houlton729c7822018-11-19 11:52:23 -070032import time
Dave Houltoncacef472018-05-29 13:00:42 -060033from collections import defaultdict
Tobin Ehlis35308dd2016-10-31 13:27:36 -060034
Dave Houltoncacef472018-05-29 13:00:42 -060035verbose_mode = False
36txt_db = False
37csv_db = False
38html_db = False
39txt_filename = "validation_error_database.txt"
40csv_filename = "validation_error_database.csv"
41html_filename = "validation_error_database.html"
Dave Houlton407df732018-08-06 17:58:24 -060042header_filename = "../layers/vk_validation_error_messages.h"
Dave Houltoncacef472018-05-29 13:00:42 -060043test_file = '../tests/layer_validation_tests.cpp'
44vuid_prefixes = ['VUID-', 'UNASSIGNED-']
Tobin Ehlis35308dd2016-10-31 13:27:36 -060045
Dave Houltoncacef472018-05-29 13:00:42 -060046# Hard-coded flags that could be command line args, if we decide that's useful
47# replace KHR vuids with non-KHR during consistency checking
48dealias_khr = True
49ignore_unassigned = True # These are not found in layer code unless they appear explicitly (most don't), so produce false positives
50
Mark Lobodzinski05849f02017-06-21 14:44:14 -060051generated_layer_source_directories = [
52'build',
53'dbuild',
54'release',
Jasper St. Pierref5addf32019-01-18 13:56:42 -080055'../build/Vulkan-ValidationLayers/'
Mark Lobodzinski05849f02017-06-21 14:44:14 -060056]
57generated_layer_source_files = [
Mark Lobodzinskid4950072017-08-01 13:02:20 -060058'parameter_validation.cpp',
Mark Lobodzinski09fa2d42017-07-21 10:16:53 -060059'object_tracker.cpp',
Mark Lobodzinski05849f02017-06-21 14:44:14 -060060]
Tobin Ehlis35308dd2016-10-31 13:27:36 -060061layer_source_files = [
Shannon McPherson9a4ae982019-01-07 16:05:25 -070062'../layers/buffer_validation.cpp',
Mark Lobodzinskie3787b42017-06-21 13:41:00 -060063'../layers/core_validation.cpp',
64'../layers/descriptor_sets.cpp',
Mark Lobodzinskid4950072017-08-01 13:02:20 -060065'../layers/parameter_validation_utils.cpp',
Mark Lobodzinskib2de97f2017-07-06 15:28:11 -060066'../layers/object_tracker_utils.cpp',
Mark Lobodzinskie3787b42017-06-21 13:41:00 -060067'../layers/shader_validation.cpp',
Shannon McPherson9a4ae982019-01-07 16:05:25 -070068'../layers/stateless_validation.h'
Tobin Ehlis35308dd2016-10-31 13:27:36 -060069]
Tobin Ehlis35308dd2016-10-31 13:27:36 -060070
Dave Houlton407df732018-08-06 17:58:24 -060071# This needs to be updated as new extensions roll in
Dave Houltoncacef472018-05-29 13:00:42 -060072khr_aliases = {
73 'VUID-vkBindBufferMemory2KHR-device-parameter' : 'VUID-vkBindBufferMemory2-device-parameter',
74 'VUID-vkBindBufferMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindBufferMemory2-pBindInfos-parameter',
75 'VUID-vkBindImageMemory2KHR-device-parameter' : 'VUID-vkBindImageMemory2-device-parameter',
76 'VUID-vkBindImageMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindImageMemory2-pBindInfos-parameter',
77 'VUID-vkCmdDispatchBaseKHR-commandBuffer-parameter' : 'VUID-vkCmdDispatchBase-commandBuffer-parameter',
78 'VUID-vkCmdSetDeviceMaskKHR-commandBuffer-parameter' : 'VUID-vkCmdSetDeviceMask-commandBuffer-parameter',
79 'VUID-vkCreateDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-device-parameter',
80 'VUID-vkCreateDescriptorUpdateTemplateKHR-pDescriptorUpdateTemplate-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pDescriptorUpdateTemplate-parameter',
81 'VUID-vkCreateSamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-device-parameter',
82 'VUID-vkCreateSamplerYcbcrConversionKHR-pYcbcrConversion-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pYcbcrConversion-parameter',
83 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parameter',
84 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parent',
85 'VUID-vkDestroyDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-device-parameter',
86 'VUID-vkDestroySamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-device-parameter',
87 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parameter',
88 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parent' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parent',
89 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-instance-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-instance-parameter',
90 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-pPhysicalDeviceGroupProperties-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-pPhysicalDeviceGroupProperties-parameter',
91 'VUID-vkGetBufferMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetBufferMemoryRequirements2-device-parameter',
92 'VUID-vkGetDescriptorSetLayoutSupportKHR-device-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-device-parameter',
93 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-device-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-device-parameter',
94 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-pPeerMemoryFeatures-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-pPeerMemoryFeatures-parameter',
95 'VUID-vkGetImageMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageMemoryRequirements2-device-parameter',
96 'VUID-vkGetImageSparseMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-device-parameter',
97 'VUID-vkGetImageSparseMemoryRequirements2KHR-pSparseMemoryRequirements-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pSparseMemoryRequirements-parameter',
98 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-physicalDevice-parameter',
99 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-physicalDevice-parameter',
100 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-physicalDevice-parameter',
101 'VUID-vkGetPhysicalDeviceFeatures2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-physicalDevice-parameter',
102 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-format-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-format-parameter',
103 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-physicalDevice-parameter',
104 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-physicalDevice-parameter',
105 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-physicalDevice-parameter',
106 'VUID-vkGetPhysicalDeviceProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-physicalDevice-parameter',
107 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2KHR-pQueueFamilyProperties-parameter' : 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2-pQueueFamilyProperties-parameter',
108 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pProperties-parameter',
109 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-physicalDevice-parameter',
110 'VUID-vkTrimCommandPoolKHR-commandPool-parameter' : 'VUID-vkTrimCommandPool-commandPool-parameter',
111 'VUID-vkTrimCommandPoolKHR-commandPool-parent' : 'VUID-vkTrimCommandPool-commandPool-parent',
112 'VUID-vkTrimCommandPoolKHR-device-parameter' : 'VUID-vkTrimCommandPool-device-parameter',
113 'VUID-vkTrimCommandPoolKHR-flags-zerobitmask' : 'VUID-vkTrimCommandPool-flags-zerobitmask',
114 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorSet-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorSet-parameter',
115 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parameter',
116 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parent',
117 'VUID-vkUpdateDescriptorSetWithTemplateKHR-device-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-device-parameter',
118 'VUID-vkCreateDescriptorUpdateTemplateKHR-pCreateInfo-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pCreateInfo-parameter',
119 'VUID-vkCreateSamplerYcbcrConversionKHR-pCreateInfo-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pCreateInfo-parameter',
120 'VUID-vkGetBufferMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pInfo-parameter',
121 'VUID-vkGetBufferMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pMemoryRequirements-parameter',
122 'VUID-vkGetDescriptorSetLayoutSupportKHR-pCreateInfo-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pCreateInfo-parameter',
123 'VUID-vkGetDescriptorSetLayoutSupportKHR-pSupport-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pSupport-parameter',
124 'VUID-vkGetImageMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageMemoryRequirements2-pInfo-parameter',
125 'VUID-vkGetImageMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetImageMemoryRequirements2-pMemoryRequirements-parameter',
126 'VUID-vkGetImageSparseMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pInfo-parameter',
127 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferInfo-parameter',
128 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferProperties-parameter',
129 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceInfo-parameter',
130 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceProperties-parameter',
131 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreInfo-parameter',
132 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreProperties-parameter',
133 'VUID-vkGetPhysicalDeviceFeatures2KHR-pFeatures-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-pFeatures-parameter',
134 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-pFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-pFormatProperties-parameter',
135 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatInfo-parameter',
136 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatProperties-parameter',
137 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-pMemoryProperties-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-pMemoryProperties-parameter',
138 'VUID-vkGetPhysicalDeviceProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-pProperties-parameter',
139 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pFormatInfo-parameter' }
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600140
Dave Houltoncacef472018-05-29 13:00:42 -0600141def printHelp():
142 print ("Usage:")
143 print (" python vk_validation_stats.py <json_file>")
144 print (" [ -c ]")
145 print (" [ -todo ]")
146 print (" [ -vuid <vuid_name> ]")
147 print (" [ -text [ <text_out_filename>] ]")
148 print (" [ -csv [ <csv_out_filename>] ]")
149 print (" [ -html [ <html_out_filename>] ]")
Dave Houlton407df732018-08-06 17:58:24 -0600150 print (" [ -export_header ]")
Dave Houltoncacef472018-05-29 13:00:42 -0600151 print (" [ -verbose ]")
152 print (" [ -help ]")
153 print ("\n The vk_validation_stats script parses validation layer source files to")
154 print (" determine the set of valid usage checks and tests currently implemented,")
155 print (" and generates coverage values by comparing against the full set of valid")
156 print (" usage identifiers in the Vulkan-Headers registry file 'validusage.json'")
157 print ("\nArguments: ")
158 print (" <json-file> (required) registry file 'validusage.json'")
159 print (" -c report consistency warnings")
160 print (" -todo report unimplemented VUIDs")
161 print (" -vuid <vuid_name> report status of individual VUID <vuid_name>")
162 print (" -text [filename] output the error database text to <text_database_filename>,")
163 print (" defaults to 'validation_error_database.txt'")
164 print (" -csv [filename] output the error database in csv to <csv_database_filename>,")
165 print (" defaults to 'validation_error_database.csv'")
166 print (" -html [filename] output the error database in html to <html_database_filename>,")
167 print (" defaults to 'validation_error_database.html'")
Dave Houlton407df732018-08-06 17:58:24 -0600168 print (" -export_header export a new VUID error text header file to <%s>" % header_filename)
Dave Houltoncacef472018-05-29 13:00:42 -0600169 print (" -verbose show your work (to stdout)")
170
171class ValidationJSON:
172 def __init__(self, filename):
173 self.filename = filename
174 self.explicit_vuids = set()
175 self.implicit_vuids = set()
176 self.all_vuids = set()
177 self.vuid_db = defaultdict(list) # Maps VUID string to list of json-data dicts
178 self.apiversion = ""
Dave Houltoncacef472018-05-29 13:00:42 -0600179 self.duplicate_vuids = set()
Dave Houlton407df732018-08-06 17:58:24 -0600180
181 # A set of specific regular expression substitutions needed to clean up VUID text
182 self.regex_dict = {}
183 self.regex_dict[re.compile('<.*?>|&(amp;)+lt;|&(amp;)+gt;')] = ""
184 self.regex_dict[re.compile(r'\\\(codeSize \\over 4\\\)')] = "(codeSize/4)"
Shannon McPherson3ea65132018-12-05 10:37:39 -0700185 self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{height}{maxFragmentDensityTexelSize_{height}}}\\rceil\\\)')] = "the ceiling of height/maxFragmentDensityTexelSize.height"
186 self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{width}{maxFragmentDensityTexelSize_{width}}}\\rceil\\\)')] = "the ceiling of width/maxFragmentDensityTexelSize.width"
187 self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{maxFramebufferHeight}{minFragmentDensityTexelSize_{height}}}\\rceil\\\)')] = "the ceiling of maxFramebufferHeight/minFragmentDensityTexelSize.height"
188 self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{maxFramebufferWidth}{minFragmentDensityTexelSize_{width}}}\\rceil\\\)')] = "the ceiling of maxFramebufferWidth/minFragmentDensityTexelSize.width"
Dave Houlton407df732018-08-06 17:58:24 -0600189 self.regex_dict[re.compile(r'\\\(\\lceil\{\\mathit\{rasterizationSamples} \\over 32}\\rceil\\\)')] = "(rasterizationSamples/32)"
Shannon McPhersonb40f1a22018-10-30 16:45:07 -0600190 self.regex_dict[re.compile(r'\\\(\\textrm\{codeSize} \\over 4\\\)')] = "(codeSize/4)"
Dave Houlton407df732018-08-06 17:58:24 -0600191 # Some fancy punctuation chars that break the Android build...
192 self.regex_dict[re.compile('&#8594;')] = "->" # Arrow char
193 self.regex_dict[re.compile('&#8217;')] = "'" # Left-slanting apostrophe to apostrophe
194 self.regex_dict[re.compile('&#822(0|1);')] = "'" # L/R-slanting quotes to apostrophe
Dave Houltoncacef472018-05-29 13:00:42 -0600195
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600196 def read(self):
Dave Houltoncacef472018-05-29 13:00:42 -0600197 self.json_dict = {}
198 if os.path.isfile(self.filename):
Dave Houlton407df732018-08-06 17:58:24 -0600199 json_file = open(self.filename, 'r', encoding='utf-8')
Dave Houltoncacef472018-05-29 13:00:42 -0600200 self.json_dict = json.load(json_file)
201 json_file.close()
202 if len(self.json_dict) == 0:
203 print("Error: Error loading validusage.json file <%s>" % self.filename)
204 sys.exit(-1)
205 try:
206 version = self.json_dict['version info']
207 validation = self.json_dict['validation']
208 self.apiversion = version['api version']
209 except:
210 print("Error: Failure parsing validusage.json object")
211 sys.exit(-1)
212
213 # Parse vuid from json into local databases
214 for apiname in validation.keys():
215 # print("entrypoint:%s"%apiname)
216 apidict = validation[apiname]
217 for ext in apidict.keys():
218 vlist = apidict[ext]
219 for ventry in vlist:
220 vuid_string = ventry['vuid']
221 if (vuid_string[-5:-1].isdecimal()):
222 self.explicit_vuids.add(vuid_string) # explicit end in 5 numeric chars
223 vtype = 'explicit'
224 else:
225 self.implicit_vuids.add(vuid_string) # otherwise, implicit
226 vtype = 'implicit'
227 vuid_text = ventry['text']
Dave Houlton407df732018-08-06 17:58:24 -0600228 for regex, replacement in self.regex_dict.items():
229 vuid_text = re.sub(regex, replacement, vuid_text) # do regex substitution
230 vuid_text = html.unescape(vuid_text) # anything missed by the regex
231 self.vuid_db[vuid_string].append({'api':apiname, 'ext':ext, 'type':vtype, 'text':vuid_text})
Dave Houltoncacef472018-05-29 13:00:42 -0600232 self.all_vuids = self.explicit_vuids | self.implicit_vuids
233 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 -0600234 if len(self.duplicate_vuids) > 0:
235 print("Warning: duplicate VUIDs found in validusage.json")
236
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600237
238class ValidationSource:
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600239 def __init__(self, source_file_list, generated_source_file_list, generated_source_directories):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600240 self.source_files = source_file_list
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600241 self.generated_source_files = generated_source_file_list
242 self.generated_source_dirs = generated_source_directories
Dave Houltoncacef472018-05-29 13:00:42 -0600243 self.vuid_count_dict = {} # dict of vuid values to the count of how much they're used, and location of where they're used
244 self.duplicated_checks = 0
245 self.explicit_vuids = set()
246 self.implicit_vuids = set()
247 self.unassigned_vuids = set()
248 self.all_vuids = set()
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600249
250 if len(self.generated_source_files) > 0:
251 qualified_paths = []
252 for source in self.generated_source_files:
253 for build_dir in self.generated_source_dirs:
254 filepath = '../%s/layers/%s' % (build_dir, source)
255 if os.path.isfile(filepath):
256 qualified_paths.append(filepath)
John Zulaufdde04c42018-01-16 15:32:45 -0700257 break
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600258 if len(self.generated_source_files) != len(qualified_paths):
Mark Lobodzinski2d193ac2017-06-27 09:38:15 -0600259 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 -0600260 print(self.generated_source_files)
Dave Houltoncacef472018-05-29 13:00:42 -0600261 print("Failed to locate one or more codegen files in layer source code - cannot proceed.")
John Zulaufdde04c42018-01-16 15:32:45 -0700262 exit(1)
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600263 else:
264 self.source_files.extend(qualified_paths)
265
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600266 def parse(self):
Dave Houltoncacef472018-05-29 13:00:42 -0600267 prepend = None
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600268 for sf in self.source_files:
Tobin Ehlis3d1f2bd2016-12-22 11:19:15 -0700269 line_num = 0
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600270 with open(sf) as f:
271 for line in f:
Tobin Ehlis3d1f2bd2016-12-22 11:19:15 -0700272 line_num = line_num + 1
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600273 if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
274 continue
Dave Houltoncacef472018-05-29 13:00:42 -0600275 # Find vuid strings
Michał Janiszewski3c3ce9e2018-10-30 23:25:21 +0100276 if prepend is not None:
Dave Houltoncacef472018-05-29 13:00:42 -0600277 line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char
278 prepend = None
279 if any(prefix in line for prefix in vuid_prefixes):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600280 line_list = line.split()
Dave Houltoncacef472018-05-29 13:00:42 -0600281
282 # 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
283 broken_vuid = line_list[-1].strip('"')
284 if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'):
285 prepend = line
286 continue
287
288 vuid_list = []
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600289 for str in line_list:
Dave Houltoncacef472018-05-29 13:00:42 -0600290 if any(prefix in str for prefix in vuid_prefixes):
291 vuid_list.append(str.strip(',);{}"'))
292 for vuid in vuid_list:
293 if vuid not in self.vuid_count_dict:
294 self.vuid_count_dict[vuid] = {}
295 self.vuid_count_dict[vuid]['count'] = 1
296 self.vuid_count_dict[vuid]['file_line'] = []
297 else:
298 if self.vuid_count_dict[vuid]['count'] == 1: # only count first time duplicated
299 self.duplicated_checks = self.duplicated_checks + 1
300 self.vuid_count_dict[vuid]['count'] = self.vuid_count_dict[vuid]['count'] + 1
301 self.vuid_count_dict[vuid]['file_line'].append('%s,%d' % (sf, line_num))
302 # Sort vuids by type
303 for vuid in self.vuid_count_dict.keys():
304 if (vuid.startswith('VUID-')):
305 if (vuid[-5:-1].isdecimal()):
306 self.explicit_vuids.add(vuid) # explicit end in 5 numeric chars
307 else:
308 self.implicit_vuids.add(vuid)
309 elif (vuid.startswith('UNASSIGNED-')):
310 self.unassigned_vuids.add(vuid)
311 else:
312 print("Unable to categorize VUID: %s" % vuid)
313 print("Confused while parsing VUIDs in layer source code - cannot proceed. (FIXME)")
314 exit(-1)
315 self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600316
317# Class to parse the validation layer test source and store testnames
Dave Houltoncacef472018-05-29 13:00:42 -0600318class ValidationTests:
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600319 def __init__(self, test_file_list, test_group_name=['VkLayerTest', 'VkPositiveLayerTest', 'VkWsiEnabledLayerTest']):
320 self.test_files = test_file_list
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600321 self.test_trigger_txt_list = []
322 for tg in test_group_name:
323 self.test_trigger_txt_list.append('TEST_F(%s' % tg)
Dave Houltoncacef472018-05-29 13:00:42 -0600324 self.explicit_vuids = set()
325 self.implicit_vuids = set()
326 self.unassigned_vuids = set()
327 self.all_vuids = set()
328 #self.test_to_vuids = {} # Map test name to VUIDs tested
329 self.vuid_to_tests = defaultdict(set) # Map VUIDs to set of test names where implemented
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600330
331 # Parse test files into internal data struct
332 def parse(self):
333 # For each test file, parse test names into set
334 grab_next_line = False # handle testname on separate line than wildcard
Tobin Ehlis9a68c982016-12-29 14:51:17 -0700335 testname = ''
Dave Houltoncacef472018-05-29 13:00:42 -0600336 prepend = None
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600337 for test_file in self.test_files:
338 with open(test_file) as tf:
339 for line in tf:
340 if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
341 continue
342
Dave Houltoncacef472018-05-29 13:00:42 -0600343 # if line ends in a broken VUID string, fix that before proceeding
Michał Janiszewski3c3ce9e2018-10-30 23:25:21 +0100344 if prepend is not None:
Dave Houltoncacef472018-05-29 13:00:42 -0600345 line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char
346 prepend = None
347 if any(prefix in line for prefix in vuid_prefixes):
348 line_list = line.split()
349
350 # 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
351 broken_vuid = line_list[-1].strip('"')
352 if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'):
353 prepend = line
354 continue
355
356 if any(ttt in line for ttt in self.test_trigger_txt_list):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600357 testname = line.split(',')[-1]
358 testname = testname.strip().strip(' {)')
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600359 if ('' == testname):
360 grab_next_line = True
361 continue
Dave Houltoncacef472018-05-29 13:00:42 -0600362 #self.test_to_vuids[testname] = []
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600363 if grab_next_line: # test name on its own line
364 grab_next_line = False
365 testname = testname.strip().strip(' {)')
Dave Houltoncacef472018-05-29 13:00:42 -0600366 #self.test_to_vuids[testname] = []
367 if any(prefix in line for prefix in vuid_prefixes):
368 line_list = re.split('[\s{}[\]()"]+',line)
Tobin Ehlis71f38c12017-01-12 14:26:56 -0700369 for sub_str in line_list:
Dave Houltoncacef472018-05-29 13:00:42 -0600370 if any(prefix in sub_str for prefix in vuid_prefixes):
371 vuid_str = sub_str.strip(',);:"')
372 self.vuid_to_tests[vuid_str].add(testname)
373 #self.test_to_vuids[testname].append(vuid_str)
374 if (vuid_str.startswith('VUID-')):
375 if (vuid_str[-5:-1].isdecimal()):
376 self.explicit_vuids.add(vuid_str) # explicit end in 5 numeric chars
377 else:
378 self.implicit_vuids.add(vuid_str)
379 elif (vuid_str.startswith('UNASSIGNED-')):
380 self.unassigned_vuids.add(vuid_str)
381 else:
382 print("Unable to categorize VUID: %s" % vuid_str)
383 print("Confused while parsing VUIDs in test code - cannot proceed. (FIXME)")
384 exit(-1)
385 self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600386
Dave Houltoncacef472018-05-29 13:00:42 -0600387# Class to do consistency checking
388#
389class Consistency:
390 def __init__(self, all_json, all_checks, all_tests):
391 self.valid = all_json
392 self.checks = all_checks
393 self.tests = all_tests
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600394
Dave Houltoncacef472018-05-29 13:00:42 -0600395 if (dealias_khr):
396 dk = set()
397 for vuid in self.checks:
398 if vuid in khr_aliases:
399 dk.add(khr_aliases[vuid])
400 else:
401 dk.add(vuid)
402 self.checks = dk
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600403
Dave Houltoncacef472018-05-29 13:00:42 -0600404 dk = set()
405 for vuid in self.tests:
406 if vuid in khr_aliases:
407 dk.add(khr_aliases[vuid])
408 else:
409 dk.add(vuid)
410 self.tests = dk
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600411
Dave Houltoncacef472018-05-29 13:00:42 -0600412 # Report undefined VUIDs in source code
413 def undef_vuids_in_layer_code(self):
414 undef_set = self.checks - self.valid
415 undef_set.discard('VUID-Undefined') # don't report Undefined
416 if ignore_unassigned:
417 unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')})
418 undef_set = undef_set - unassigned
419 if (len(undef_set) > 0):
420 print("\nFollowing VUIDs found in layer code are not defined in validusage.json (%d):" % len(undef_set))
421 undef = list(undef_set)
422 undef.sort()
423 for vuid in undef:
424 print(" %s" % vuid)
425 return False
426 return True
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600427
Dave Houltoncacef472018-05-29 13:00:42 -0600428 # Report undefined VUIDs in tests
429 def undef_vuids_in_tests(self):
430 undef_set = self.tests - self.valid
431 undef_set.discard('VUID-Undefined') # don't report Undefined
432 if ignore_unassigned:
433 unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')})
434 undef_set = undef_set - unassigned
435 if (len(undef_set) > 0):
436 ok = False
437 print("\nFollowing VUIDs found in layer tests are not defined in validusage.json (%d):" % len(undef_set))
438 undef = list(undef_set)
439 undef.sort()
440 for vuid in undef:
441 print(" %s" % vuid)
442 return False
443 return True
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600444
Dave Houltoncacef472018-05-29 13:00:42 -0600445 # Report vuids in tests that are not in source
446 def vuids_tested_not_checked(self):
447 undef_set = self.tests - self.checks
448 undef_set.discard('VUID-Undefined') # don't report Undefined
449 if ignore_unassigned:
450 unassigned = set()
451 for vuid in undef_set:
452 if vuid.startswith('UNASSIGNED-'):
453 unassigned.add(vuid)
454 undef_set = undef_set - unassigned
455 if (len(undef_set) > 0):
456 ok = False
457 print("\nFollowing VUIDs found in tests but are not checked in layer code (%d):" % len(undef_set))
458 undef = list(undef_set)
459 undef.sort()
460 for vuid in undef:
461 print(" %s" % vuid)
462 return False
463 return True
464
465 # TODO: Explicit checked VUIDs which have no test
466 # def explicit_vuids_checked_not_tested(self):
467
468
469# Class to output database in various flavors
470#
471class OutputDatabase:
472 def __init__(self, val_json, val_source, val_tests):
473 self.vj = val_json
474 self.vs = val_source
475 self.vt = val_tests
Dave Houlton729c7822018-11-19 11:52:23 -0700476 self.header_version = "/* THIS FILE IS GENERATED - DO NOT EDIT (scripts/vk_validation_stats.py) */"
477 self.header_version += "\n/* Vulkan specification version: %s */" % val_json.apiversion
478 self.header_version += "\n/* Header generated: %s */\n" % time.strftime('%Y-%m-%d %H:%M:%S')
479 self.header_preamble = """
Dave Houlton407df732018-08-06 17:58:24 -0600480/*
481 * Vulkan
482 *
Jasper St. Pierre1948bcc2019-01-18 13:55:20 -0800483 * Copyright (c) 2016-2019 Google Inc.
484 * Copyright (c) 2016-2019 LunarG, Inc.
Dave Houlton407df732018-08-06 17:58:24 -0600485 *
486 * Licensed under the Apache License, Version 2.0 (the "License");
487 * you may not use this file except in compliance with the License.
488 * You may obtain a copy of the License at
489 *
490 * http://www.apache.org/licenses/LICENSE-2.0
491 *
492 * Unless required by applicable law or agreed to in writing, software
493 * distributed under the License is distributed on an "AS IS" BASIS,
494 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
495 * See the License for the specific language governing permissions and
496 * limitations under the License.
497 *
498 * Author: Tobin Ehlis <tobine@google.com>
499 * Author: Dave Houlton <daveh@lunarg.com>
500 */
501
502#pragma once
503
504// Disable auto-formatting for generated file
505// clang-format off
506
Dave Houlton407df732018-08-06 17:58:24 -0600507// Mapping from VUID string to the corresponding spec text
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600508typedef struct _vuid_spec_text_pair {
509 const char * vuid;
510 const char * spec_text;
511} vuid_spec_text_pair;
512
513static const vuid_spec_text_pair vuid_spec_text[] = {
Dave Houlton407df732018-08-06 17:58:24 -0600514"""
515 self.header_postamble = """};
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600516"""
Dave Houlton407df732018-08-06 17:58:24 -0600517 self.spec_url = "https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html"
Dave Houltoncacef472018-05-29 13:00:42 -0600518
519 def dump_txt(self):
520 print("\n Dumping database to text file: %s" % txt_filename)
521 with open (txt_filename, 'w') as txt:
522 txt.write("## VUID Database\n")
523 txt.write("## Format: VUID_NAME | CHECKED | TEST | TYPE | API/STRUCT | EXTENSION | VUID_TEXT\n##\n")
524 vuid_list = list(self.vj.all_vuids)
525 vuid_list.sort()
526 for vuid in vuid_list:
527 db_list = self.vj.vuid_db[vuid]
528 db_list.sort(key=operator.itemgetter('ext')) # sort list to ease diffs of output file
529 for db_entry in db_list:
530 checked = 'N'
531 if vuid in self.vs.all_vuids:
532 checked = 'Y'
533 test = 'None'
534 if vuid in self.vt.vuid_to_tests:
535 test_list = list(self.vt.vuid_to_tests[vuid])
536 test_list.sort() # sort tests, for diff-ability
537 sep = ', '
538 test = sep.join(test_list)
539
540 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']))
541
542 def dump_csv(self):
543 print("\n Dumping database to csv file: %s" % csv_filename)
544 with open (csv_filename, 'w', newline='') as csvfile:
545 cw = csv.writer(csvfile)
546 cw.writerow(['VUID_NAME','CHECKED','TEST','TYPE','API/STRUCT','EXTENSION','VUID_TEXT'])
547 vuid_list = list(self.vj.all_vuids)
548 vuid_list.sort()
549 for vuid in vuid_list:
550 for db_entry in self.vj.vuid_db[vuid]:
551 row = [vuid]
552 if vuid in self.vs.all_vuids:
553 row.append('Y')
554 else:
555 row.append('N')
556 test = 'None'
557 if vuid in self.vt.vuid_to_tests:
558 sep = ', '
559 test = sep.join(self.vt.vuid_to_tests[vuid])
560 row.append(test)
561 row.append(db_entry['type'])
562 row.append(db_entry['api'])
563 row.append(db_entry['ext'])
564 row.append(db_entry['text'])
565 cw.writerow(row)
566
567 def dump_html(self):
568 print("\n Dumping database to html file: %s" % html_filename)
569 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'
570 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'
571 with open (html_filename, 'w') as hfile:
572 hfile.write(preamble)
573 hfile.write(headers)
574 vuid_list = list(self.vj.all_vuids)
575 vuid_list.sort()
576 for vuid in vuid_list:
577 for db_entry in self.vj.vuid_db[vuid]:
578 hfile.write('<tr><th>%s</th>' % vuid)
579 checked = '<span style="color:red;">N</span>'
580 if vuid in self.vs.all_vuids:
581 checked = '<span style="color:limegreen;">Y</span>'
582 hfile.write('<th>%s</th>' % checked)
583 test = 'None'
584 if vuid in self.vt.vuid_to_tests:
585 sep = ', '
586 test = sep.join(self.vt.vuid_to_tests[vuid])
587 hfile.write('<th>%s</th>' % test)
588 hfile.write('<th>%s</th>' % db_entry['type'])
589 hfile.write('<th>%s</th>' % db_entry['api'])
590 hfile.write('<th>%s</th>' % db_entry['ext'])
591 hfile.write('<th>%s</th></tr>\n' % db_entry['text'])
592 hfile.write('</table>\n</body>\n</html>\n')
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600593
Dave Houlton407df732018-08-06 17:58:24 -0600594 def export_header(self):
595 print("\n Exporting header file to: %s" % header_filename)
596 with open (header_filename, 'w') as hfile:
Dave Houlton729c7822018-11-19 11:52:23 -0700597 hfile.write(self.header_version)
Dave Houlton407df732018-08-06 17:58:24 -0600598 hfile.write(self.header_preamble)
599 vuid_list = list(self.vj.all_vuids)
600 vuid_list.sort()
601 for vuid in vuid_list:
602 db_entry = self.vj.vuid_db[vuid][0]
603 hfile.write(' {"%s", "%s (%s#%s)"},\n' % (vuid, db_entry['text'].strip(' '), self.spec_url, vuid))
604 # For multiply-defined VUIDs, include versions with extension appended
605 if len(self.vj.vuid_db[vuid]) > 1:
606 for db_entry in self.vj.vuid_db[vuid]:
607 hfile.write(' {"%s[%s]", "%s (%s#%s)"},\n' % (vuid, db_entry['ext'].strip(' '), db_entry['text'].strip(' '), self.spec_url, vuid))
608 hfile.write(self.header_postamble)
609
Mark Lobodzinskib44c54a2017-06-12 12:02:38 -0600610def main(argv):
Dave Houltoncacef472018-05-29 13:00:42 -0600611 global verbose_mode
612 global txt_filename
613 global csv_filename
614 global html_filename
615
616 run_consistency = False
617 report_unimplemented = False
618 get_vuid_status = ''
619 txt_out = False
620 csv_out = False
621 html_out = False
Dave Houlton407df732018-08-06 17:58:24 -0600622 header_out = False
Dave Houltoncacef472018-05-29 13:00:42 -0600623
624 if (1 > len(argv)):
625 printHelp()
626 sys.exit()
627
628 # Parse script args
629 json_filename = argv[0]
630 i = 1
631 while (i < len(argv)):
632 arg = argv[i]
633 i = i + 1
634 if (arg == '-c'):
635 run_consistency = True
636 elif (arg == '-vuid'):
637 get_vuid_status = argv[i]
638 i = i + 1
639 elif (arg == '-todo'):
640 report_unimplemented = True
Karl Schultz49d66bb2018-07-09 16:24:46 -0600641 elif (arg == '-text'):
Dave Houltoncacef472018-05-29 13:00:42 -0600642 txt_out = True
643 # Set filename if supplied, else use default
644 if i < len(argv) and not argv[i].startswith('-'):
645 txt_filename = argv[i]
646 i = i + 1
647 elif (arg == '-csv'):
648 csv_out = True
649 # Set filename if supplied, else use default
650 if i < len(argv) and not argv[i].startswith('-'):
651 csv_filename = argv[i]
652 i = i + 1
653 elif (arg == '-html'):
654 html_out = True
655 # Set filename if supplied, else use default
656 if i < len(argv) and not argv[i].startswith('-'):
657 html_filename = argv[i]
658 i = i + 1
Dave Houlton407df732018-08-06 17:58:24 -0600659 elif (arg == '-export_header'):
660 header_out = True
Dave Houltoncacef472018-05-29 13:00:42 -0600661 elif (arg in ['-verbose']):
662 verbose_mode = True
663 elif (arg in ['-help', '-h']):
664 printHelp()
665 sys.exit()
666 else:
667 print("Unrecognized argument: %s\n" % arg)
668 printHelp()
669 sys.exit()
670
Tobin Ehlis20e32582016-12-05 14:50:03 -0700671 result = 0 # Non-zero result indicates an error case
Dave Houltoncacef472018-05-29 13:00:42 -0600672
673 # Parse validusage json
674 val_json = ValidationJSON(json_filename)
675 val_json.read()
676 exp_json = len(val_json.explicit_vuids)
677 imp_json = len(val_json.implicit_vuids)
678 all_json = len(val_json.all_vuids)
679 if verbose_mode:
680 print("Found %d unique error vuids in validusage.json file." % all_json)
681 print(" %d explicit" % exp_json)
682 print(" %d implicit" % imp_json)
683 if len(val_json.duplicate_vuids) > 0:
684 print("%d VUIDs appear in validusage.json more than once." % len(val_json.duplicate_vuids))
685 for vuid in val_json.duplicate_vuids:
686 print(" %s" % vuid)
687 for ext in val_json.vuid_db[vuid]:
688 print(" with extension: %s" % ext['ext'])
689
690 # Parse layer source files
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600691 val_source = ValidationSource(layer_source_files, generated_layer_source_files, generated_layer_source_directories)
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600692 val_source.parse()
Dave Houltoncacef472018-05-29 13:00:42 -0600693 exp_checks = len(val_source.explicit_vuids)
694 imp_checks = len(val_source.implicit_vuids)
695 all_checks = len(val_source.vuid_count_dict.keys())
696 if verbose_mode:
697 print("Found %d unique vuid checks in layer source code." % all_checks)
698 print(" %d explicit" % exp_checks)
699 print(" %d implicit" % imp_checks)
700 print(" %d unassigned" % len(val_source.unassigned_vuids))
701 print(" %d checks are implemented more that once" % val_source.duplicated_checks)
702
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600703 # Parse test files
Dave Houltoncacef472018-05-29 13:00:42 -0600704 val_tests = ValidationTests([test_file, ])
705 val_tests.parse()
706 exp_tests = len(val_tests.explicit_vuids)
707 imp_tests = len(val_tests.implicit_vuids)
708 all_tests = len(val_tests.all_vuids)
Mark Lobodzinski060a8e32018-01-08 09:08:06 -0700709 if verbose_mode:
Dave Houltoncacef472018-05-29 13:00:42 -0600710 print("Found %d unique error vuids in test file %s." % (all_tests, test_file))
711 print(" %d explicit" % exp_tests)
712 print(" %d implicit" % imp_tests)
713 print(" %d unassigned" % len(val_tests.unassigned_vuids))
Mike Weiblenfe186122017-02-03 12:44:53 -0700714
Dave Houltoncacef472018-05-29 13:00:42 -0600715 # Process stats
716 print("\nValidation Statistics (using validusage.json version %s)" % val_json.apiversion)
717 print(" VUIDs defined in JSON file: %04d explicit, %04d implicit, %04d total." % (exp_json, imp_json, all_json))
718 print(" VUIDs checked in layer code: %04d explicit, %04d implicit, %04d total." % (exp_checks, imp_checks, all_checks))
719 print(" VUIDs tested in layer tests: %04d explicit, %04d implicit, %04d total." % (exp_tests, imp_tests, all_tests))
720
721 print("\nVUID check coverage")
722 print(" Explicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * exp_checks / exp_json), exp_checks, exp_json))
723 print(" Implicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * imp_checks / imp_json), imp_checks, imp_json))
724 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 -0700725
Dave Houltoncacef472018-05-29 13:00:42 -0600726 print("\nVUID test coverage")
727 print(" Explicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * exp_tests / exp_checks), exp_tests, exp_checks))
728 print(" Implicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * imp_tests / imp_checks), imp_tests, imp_checks))
729 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 -0700730
Dave Houltoncacef472018-05-29 13:00:42 -0600731 # Report status of a single VUID
732 if len(get_vuid_status) > 1:
733 print("\n\nChecking status of <%s>" % get_vuid_status);
734 if get_vuid_status not in val_json.all_vuids:
735 print(' Not a valid VUID string.')
736 else:
737 if get_vuid_status in val_source.explicit_vuids:
738 print(' Implemented!')
739 line_list = val_source.vuid_count_dict[get_vuid_status]['file_line']
740 for line in line_list:
741 print(' => %s' % line)
Dave Houltonf93bbab2018-06-26 17:21:12 -0600742 elif get_vuid_status in val_source.implicit_vuids:
743 print(' Implemented! (Implicit)')
744 line_list = val_source.vuid_count_dict[get_vuid_status]['file_line']
745 for line in line_list:
746 print(' => %s' % line)
Tobin Ehlis9a68c982016-12-29 14:51:17 -0700747 else:
Dave Houltoncacef472018-05-29 13:00:42 -0600748 print(' Not implemented.')
Dave Houltonf93bbab2018-06-26 17:21:12 -0600749 if get_vuid_status in val_tests.all_vuids:
Dave Houltoncacef472018-05-29 13:00:42 -0600750 print(' Has a test!')
751 test_list = val_tests.vuid_to_tests[get_vuid_status]
752 for test in test_list:
753 print(' => %s' % test)
754 else:
755 print(' Not tested.')
Mike Weiblenfe186122017-02-03 12:44:53 -0700756
Dave Houltoncacef472018-05-29 13:00:42 -0600757 # Report unimplemented explicit VUIDs
758 if report_unimplemented:
759 unim_explicit = val_json.explicit_vuids - val_source.explicit_vuids
760 print("\n\n%d explicit VUID checks remain unimplemented:" % len(unim_explicit))
761 ulist = list(unim_explicit)
762 ulist.sort()
763 for vuid in ulist:
764 print(" => %s" % vuid)
765
766 # Consistency tests
767 if run_consistency:
768 print("\n\nRunning consistency tests...")
769 con = Consistency(val_json.all_vuids, val_source.all_vuids, val_tests.all_vuids)
770 ok = con.undef_vuids_in_layer_code()
771 ok &= con.undef_vuids_in_tests()
772 ok &= con.vuids_tested_not_checked()
773
774 if ok:
775 print(" OK! No inconsistencies found.")
776
777 # Output database in requested format(s)
778 db_out = OutputDatabase(val_json, val_source, val_tests)
779 if txt_out:
780 db_out.dump_txt()
781 if csv_out:
782 db_out.dump_csv()
783 if html_out:
784 db_out.dump_html()
Dave Houlton407df732018-08-06 17:58:24 -0600785 if header_out:
786 db_out.export_header()
Tobin Ehlis20e32582016-12-05 14:50:03 -0700787 return result
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600788
789if __name__ == "__main__":
Mark Lobodzinskib44c54a2017-06-12 12:02:38 -0600790 sys.exit(main(sys.argv[1:]))
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600791