blob: 36567319ded96ced0e505fb2fb537379992a22f6 [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',
55]
56generated_layer_source_files = [
Mark Lobodzinskid4950072017-08-01 13:02:20 -060057'parameter_validation.cpp',
Mark Lobodzinski09fa2d42017-07-21 10:16:53 -060058'object_tracker.cpp',
Mark Lobodzinski05849f02017-06-21 14:44:14 -060059]
Tobin Ehlis35308dd2016-10-31 13:27:36 -060060layer_source_files = [
Shannon McPherson9a4ae982019-01-07 16:05:25 -070061'../layers/buffer_validation.cpp',
Mark Lobodzinskie3787b42017-06-21 13:41:00 -060062'../layers/core_validation.cpp',
63'../layers/descriptor_sets.cpp',
Mark Lobodzinskid4950072017-08-01 13:02:20 -060064'../layers/parameter_validation_utils.cpp',
Mark Lobodzinskib2de97f2017-07-06 15:28:11 -060065'../layers/object_tracker_utils.cpp',
Mark Lobodzinskie3787b42017-06-21 13:41:00 -060066'../layers/shader_validation.cpp',
Shannon McPherson9a4ae982019-01-07 16:05:25 -070067'../layers/stateless_validation.h'
Tobin Ehlis35308dd2016-10-31 13:27:36 -060068]
Tobin Ehlis35308dd2016-10-31 13:27:36 -060069
Dave Houlton407df732018-08-06 17:58:24 -060070# This needs to be updated as new extensions roll in
Dave Houltoncacef472018-05-29 13:00:42 -060071khr_aliases = {
72 'VUID-vkBindBufferMemory2KHR-device-parameter' : 'VUID-vkBindBufferMemory2-device-parameter',
73 'VUID-vkBindBufferMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindBufferMemory2-pBindInfos-parameter',
74 'VUID-vkBindImageMemory2KHR-device-parameter' : 'VUID-vkBindImageMemory2-device-parameter',
75 'VUID-vkBindImageMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindImageMemory2-pBindInfos-parameter',
76 'VUID-vkCmdDispatchBaseKHR-commandBuffer-parameter' : 'VUID-vkCmdDispatchBase-commandBuffer-parameter',
77 'VUID-vkCmdSetDeviceMaskKHR-commandBuffer-parameter' : 'VUID-vkCmdSetDeviceMask-commandBuffer-parameter',
78 'VUID-vkCreateDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-device-parameter',
79 'VUID-vkCreateDescriptorUpdateTemplateKHR-pDescriptorUpdateTemplate-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pDescriptorUpdateTemplate-parameter',
80 'VUID-vkCreateSamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-device-parameter',
81 'VUID-vkCreateSamplerYcbcrConversionKHR-pYcbcrConversion-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pYcbcrConversion-parameter',
82 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parameter',
83 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parent',
84 'VUID-vkDestroyDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-device-parameter',
85 'VUID-vkDestroySamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-device-parameter',
86 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parameter',
87 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parent' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parent',
88 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-instance-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-instance-parameter',
89 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-pPhysicalDeviceGroupProperties-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-pPhysicalDeviceGroupProperties-parameter',
90 'VUID-vkGetBufferMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetBufferMemoryRequirements2-device-parameter',
91 'VUID-vkGetDescriptorSetLayoutSupportKHR-device-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-device-parameter',
92 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-device-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-device-parameter',
93 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-pPeerMemoryFeatures-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-pPeerMemoryFeatures-parameter',
94 'VUID-vkGetImageMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageMemoryRequirements2-device-parameter',
95 'VUID-vkGetImageSparseMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-device-parameter',
96 'VUID-vkGetImageSparseMemoryRequirements2KHR-pSparseMemoryRequirements-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pSparseMemoryRequirements-parameter',
97 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-physicalDevice-parameter',
98 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-physicalDevice-parameter',
99 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-physicalDevice-parameter',
100 'VUID-vkGetPhysicalDeviceFeatures2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-physicalDevice-parameter',
101 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-format-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-format-parameter',
102 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-physicalDevice-parameter',
103 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-physicalDevice-parameter',
104 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-physicalDevice-parameter',
105 'VUID-vkGetPhysicalDeviceProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-physicalDevice-parameter',
106 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2KHR-pQueueFamilyProperties-parameter' : 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2-pQueueFamilyProperties-parameter',
107 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pProperties-parameter',
108 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-physicalDevice-parameter',
109 'VUID-vkTrimCommandPoolKHR-commandPool-parameter' : 'VUID-vkTrimCommandPool-commandPool-parameter',
110 'VUID-vkTrimCommandPoolKHR-commandPool-parent' : 'VUID-vkTrimCommandPool-commandPool-parent',
111 'VUID-vkTrimCommandPoolKHR-device-parameter' : 'VUID-vkTrimCommandPool-device-parameter',
112 'VUID-vkTrimCommandPoolKHR-flags-zerobitmask' : 'VUID-vkTrimCommandPool-flags-zerobitmask',
113 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorSet-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorSet-parameter',
114 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parameter',
115 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parent',
116 'VUID-vkUpdateDescriptorSetWithTemplateKHR-device-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-device-parameter',
117 'VUID-vkCreateDescriptorUpdateTemplateKHR-pCreateInfo-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pCreateInfo-parameter',
118 'VUID-vkCreateSamplerYcbcrConversionKHR-pCreateInfo-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pCreateInfo-parameter',
119 'VUID-vkGetBufferMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pInfo-parameter',
120 'VUID-vkGetBufferMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pMemoryRequirements-parameter',
121 'VUID-vkGetDescriptorSetLayoutSupportKHR-pCreateInfo-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pCreateInfo-parameter',
122 'VUID-vkGetDescriptorSetLayoutSupportKHR-pSupport-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pSupport-parameter',
123 'VUID-vkGetImageMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageMemoryRequirements2-pInfo-parameter',
124 'VUID-vkGetImageMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetImageMemoryRequirements2-pMemoryRequirements-parameter',
125 'VUID-vkGetImageSparseMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pInfo-parameter',
126 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferInfo-parameter',
127 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferProperties-parameter',
128 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceInfo-parameter',
129 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceProperties-parameter',
130 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreInfo-parameter',
131 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreProperties-parameter',
132 'VUID-vkGetPhysicalDeviceFeatures2KHR-pFeatures-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-pFeatures-parameter',
133 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-pFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-pFormatProperties-parameter',
134 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatInfo-parameter',
135 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatProperties-parameter',
136 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-pMemoryProperties-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-pMemoryProperties-parameter',
137 'VUID-vkGetPhysicalDeviceProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-pProperties-parameter',
138 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pFormatInfo-parameter' }
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600139
Dave Houltoncacef472018-05-29 13:00:42 -0600140def printHelp():
141 print ("Usage:")
142 print (" python vk_validation_stats.py <json_file>")
143 print (" [ -c ]")
144 print (" [ -todo ]")
145 print (" [ -vuid <vuid_name> ]")
146 print (" [ -text [ <text_out_filename>] ]")
147 print (" [ -csv [ <csv_out_filename>] ]")
148 print (" [ -html [ <html_out_filename>] ]")
Dave Houlton407df732018-08-06 17:58:24 -0600149 print (" [ -export_header ]")
Dave Houltoncacef472018-05-29 13:00:42 -0600150 print (" [ -verbose ]")
151 print (" [ -help ]")
152 print ("\n The vk_validation_stats script parses validation layer source files to")
153 print (" determine the set of valid usage checks and tests currently implemented,")
154 print (" and generates coverage values by comparing against the full set of valid")
155 print (" usage identifiers in the Vulkan-Headers registry file 'validusage.json'")
156 print ("\nArguments: ")
157 print (" <json-file> (required) registry file 'validusage.json'")
158 print (" -c report consistency warnings")
159 print (" -todo report unimplemented VUIDs")
160 print (" -vuid <vuid_name> report status of individual VUID <vuid_name>")
161 print (" -text [filename] output the error database text to <text_database_filename>,")
162 print (" defaults to 'validation_error_database.txt'")
163 print (" -csv [filename] output the error database in csv to <csv_database_filename>,")
164 print (" defaults to 'validation_error_database.csv'")
165 print (" -html [filename] output the error database in html to <html_database_filename>,")
166 print (" defaults to 'validation_error_database.html'")
Dave Houlton407df732018-08-06 17:58:24 -0600167 print (" -export_header export a new VUID error text header file to <%s>" % header_filename)
Dave Houltoncacef472018-05-29 13:00:42 -0600168 print (" -verbose show your work (to stdout)")
169
170class ValidationJSON:
171 def __init__(self, filename):
172 self.filename = filename
173 self.explicit_vuids = set()
174 self.implicit_vuids = set()
175 self.all_vuids = set()
176 self.vuid_db = defaultdict(list) # Maps VUID string to list of json-data dicts
177 self.apiversion = ""
Dave Houltoncacef472018-05-29 13:00:42 -0600178 self.duplicate_vuids = set()
Dave Houlton407df732018-08-06 17:58:24 -0600179
180 # A set of specific regular expression substitutions needed to clean up VUID text
181 self.regex_dict = {}
182 self.regex_dict[re.compile('<.*?>|&(amp;)+lt;|&(amp;)+gt;')] = ""
183 self.regex_dict[re.compile(r'\\\(codeSize \\over 4\\\)')] = "(codeSize/4)"
Shannon McPherson3ea65132018-12-05 10:37:39 -0700184 self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{height}{maxFragmentDensityTexelSize_{height}}}\\rceil\\\)')] = "the ceiling of height/maxFragmentDensityTexelSize.height"
185 self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{width}{maxFragmentDensityTexelSize_{width}}}\\rceil\\\)')] = "the ceiling of width/maxFragmentDensityTexelSize.width"
186 self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{maxFramebufferHeight}{minFragmentDensityTexelSize_{height}}}\\rceil\\\)')] = "the ceiling of maxFramebufferHeight/minFragmentDensityTexelSize.height"
187 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 -0600188 self.regex_dict[re.compile(r'\\\(\\lceil\{\\mathit\{rasterizationSamples} \\over 32}\\rceil\\\)')] = "(rasterizationSamples/32)"
Shannon McPhersonb40f1a22018-10-30 16:45:07 -0600189 self.regex_dict[re.compile(r'\\\(\\textrm\{codeSize} \\over 4\\\)')] = "(codeSize/4)"
Dave Houlton407df732018-08-06 17:58:24 -0600190 # Some fancy punctuation chars that break the Android build...
191 self.regex_dict[re.compile('&#8594;')] = "->" # Arrow char
192 self.regex_dict[re.compile('&#8217;')] = "'" # Left-slanting apostrophe to apostrophe
193 self.regex_dict[re.compile('&#822(0|1);')] = "'" # L/R-slanting quotes to apostrophe
Dave Houltoncacef472018-05-29 13:00:42 -0600194
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600195 def read(self):
Dave Houltoncacef472018-05-29 13:00:42 -0600196 self.json_dict = {}
197 if os.path.isfile(self.filename):
Dave Houlton407df732018-08-06 17:58:24 -0600198 json_file = open(self.filename, 'r', encoding='utf-8')
Dave Houltoncacef472018-05-29 13:00:42 -0600199 self.json_dict = json.load(json_file)
200 json_file.close()
201 if len(self.json_dict) == 0:
202 print("Error: Error loading validusage.json file <%s>" % self.filename)
203 sys.exit(-1)
204 try:
205 version = self.json_dict['version info']
206 validation = self.json_dict['validation']
207 self.apiversion = version['api version']
208 except:
209 print("Error: Failure parsing validusage.json object")
210 sys.exit(-1)
211
212 # Parse vuid from json into local databases
213 for apiname in validation.keys():
214 # print("entrypoint:%s"%apiname)
215 apidict = validation[apiname]
216 for ext in apidict.keys():
217 vlist = apidict[ext]
218 for ventry in vlist:
219 vuid_string = ventry['vuid']
220 if (vuid_string[-5:-1].isdecimal()):
221 self.explicit_vuids.add(vuid_string) # explicit end in 5 numeric chars
222 vtype = 'explicit'
223 else:
224 self.implicit_vuids.add(vuid_string) # otherwise, implicit
225 vtype = 'implicit'
226 vuid_text = ventry['text']
Dave Houlton407df732018-08-06 17:58:24 -0600227 for regex, replacement in self.regex_dict.items():
228 vuid_text = re.sub(regex, replacement, vuid_text) # do regex substitution
229 vuid_text = html.unescape(vuid_text) # anything missed by the regex
230 self.vuid_db[vuid_string].append({'api':apiname, 'ext':ext, 'type':vtype, 'text':vuid_text})
Dave Houltoncacef472018-05-29 13:00:42 -0600231 self.all_vuids = self.explicit_vuids | self.implicit_vuids
232 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 -0600233 if len(self.duplicate_vuids) > 0:
234 print("Warning: duplicate VUIDs found in validusage.json")
235
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600236
237class ValidationSource:
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600238 def __init__(self, source_file_list, generated_source_file_list, generated_source_directories):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600239 self.source_files = source_file_list
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600240 self.generated_source_files = generated_source_file_list
241 self.generated_source_dirs = generated_source_directories
Dave Houltoncacef472018-05-29 13:00:42 -0600242 self.vuid_count_dict = {} # dict of vuid values to the count of how much they're used, and location of where they're used
243 self.duplicated_checks = 0
244 self.explicit_vuids = set()
245 self.implicit_vuids = set()
246 self.unassigned_vuids = set()
247 self.all_vuids = set()
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600248
249 if len(self.generated_source_files) > 0:
250 qualified_paths = []
251 for source in self.generated_source_files:
252 for build_dir in self.generated_source_dirs:
253 filepath = '../%s/layers/%s' % (build_dir, source)
254 if os.path.isfile(filepath):
255 qualified_paths.append(filepath)
John Zulaufdde04c42018-01-16 15:32:45 -0700256 break
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600257 if len(self.generated_source_files) != len(qualified_paths):
Mark Lobodzinski2d193ac2017-06-27 09:38:15 -0600258 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 -0600259 print(self.generated_source_files)
Dave Houltoncacef472018-05-29 13:00:42 -0600260 print("Failed to locate one or more codegen files in layer source code - cannot proceed.")
John Zulaufdde04c42018-01-16 15:32:45 -0700261 exit(1)
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600262 else:
263 self.source_files.extend(qualified_paths)
264
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600265 def parse(self):
Dave Houltoncacef472018-05-29 13:00:42 -0600266 prepend = None
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600267 for sf in self.source_files:
Tobin Ehlis3d1f2bd2016-12-22 11:19:15 -0700268 line_num = 0
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600269 with open(sf) as f:
270 for line in f:
Tobin Ehlis3d1f2bd2016-12-22 11:19:15 -0700271 line_num = line_num + 1
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600272 if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
273 continue
Dave Houltoncacef472018-05-29 13:00:42 -0600274 # Find vuid strings
Michał Janiszewski3c3ce9e2018-10-30 23:25:21 +0100275 if prepend is not None:
Dave Houltoncacef472018-05-29 13:00:42 -0600276 line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char
277 prepend = None
278 if any(prefix in line for prefix in vuid_prefixes):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600279 line_list = line.split()
Dave Houltoncacef472018-05-29 13:00:42 -0600280
281 # 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
282 broken_vuid = line_list[-1].strip('"')
283 if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'):
284 prepend = line
285 continue
286
287 vuid_list = []
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600288 for str in line_list:
Dave Houltoncacef472018-05-29 13:00:42 -0600289 if any(prefix in str for prefix in vuid_prefixes):
290 vuid_list.append(str.strip(',);{}"'))
291 for vuid in vuid_list:
292 if vuid not in self.vuid_count_dict:
293 self.vuid_count_dict[vuid] = {}
294 self.vuid_count_dict[vuid]['count'] = 1
295 self.vuid_count_dict[vuid]['file_line'] = []
296 else:
297 if self.vuid_count_dict[vuid]['count'] == 1: # only count first time duplicated
298 self.duplicated_checks = self.duplicated_checks + 1
299 self.vuid_count_dict[vuid]['count'] = self.vuid_count_dict[vuid]['count'] + 1
300 self.vuid_count_dict[vuid]['file_line'].append('%s,%d' % (sf, line_num))
301 # Sort vuids by type
302 for vuid in self.vuid_count_dict.keys():
303 if (vuid.startswith('VUID-')):
304 if (vuid[-5:-1].isdecimal()):
305 self.explicit_vuids.add(vuid) # explicit end in 5 numeric chars
306 else:
307 self.implicit_vuids.add(vuid)
308 elif (vuid.startswith('UNASSIGNED-')):
309 self.unassigned_vuids.add(vuid)
310 else:
311 print("Unable to categorize VUID: %s" % vuid)
312 print("Confused while parsing VUIDs in layer source code - cannot proceed. (FIXME)")
313 exit(-1)
314 self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600315
316# Class to parse the validation layer test source and store testnames
Dave Houltoncacef472018-05-29 13:00:42 -0600317class ValidationTests:
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600318 def __init__(self, test_file_list, test_group_name=['VkLayerTest', 'VkPositiveLayerTest', 'VkWsiEnabledLayerTest']):
319 self.test_files = test_file_list
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600320 self.test_trigger_txt_list = []
321 for tg in test_group_name:
322 self.test_trigger_txt_list.append('TEST_F(%s' % tg)
Dave Houltoncacef472018-05-29 13:00:42 -0600323 self.explicit_vuids = set()
324 self.implicit_vuids = set()
325 self.unassigned_vuids = set()
326 self.all_vuids = set()
327 #self.test_to_vuids = {} # Map test name to VUIDs tested
328 self.vuid_to_tests = defaultdict(set) # Map VUIDs to set of test names where implemented
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600329
330 # Parse test files into internal data struct
331 def parse(self):
332 # For each test file, parse test names into set
333 grab_next_line = False # handle testname on separate line than wildcard
Tobin Ehlis9a68c982016-12-29 14:51:17 -0700334 testname = ''
Dave Houltoncacef472018-05-29 13:00:42 -0600335 prepend = None
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600336 for test_file in self.test_files:
337 with open(test_file) as tf:
338 for line in tf:
339 if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
340 continue
341
Dave Houltoncacef472018-05-29 13:00:42 -0600342 # if line ends in a broken VUID string, fix that before proceeding
Michał Janiszewski3c3ce9e2018-10-30 23:25:21 +0100343 if prepend is not None:
Dave Houltoncacef472018-05-29 13:00:42 -0600344 line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char
345 prepend = None
346 if any(prefix in line for prefix in vuid_prefixes):
347 line_list = line.split()
348
349 # 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
350 broken_vuid = line_list[-1].strip('"')
351 if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'):
352 prepend = line
353 continue
354
355 if any(ttt in line for ttt in self.test_trigger_txt_list):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600356 testname = line.split(',')[-1]
357 testname = testname.strip().strip(' {)')
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600358 if ('' == testname):
359 grab_next_line = True
360 continue
Dave Houltoncacef472018-05-29 13:00:42 -0600361 #self.test_to_vuids[testname] = []
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600362 if grab_next_line: # test name on its own line
363 grab_next_line = False
364 testname = testname.strip().strip(' {)')
Dave Houltoncacef472018-05-29 13:00:42 -0600365 #self.test_to_vuids[testname] = []
366 if any(prefix in line for prefix in vuid_prefixes):
367 line_list = re.split('[\s{}[\]()"]+',line)
Tobin Ehlis71f38c12017-01-12 14:26:56 -0700368 for sub_str in line_list:
Dave Houltoncacef472018-05-29 13:00:42 -0600369 if any(prefix in sub_str for prefix in vuid_prefixes):
370 vuid_str = sub_str.strip(',);:"')
371 self.vuid_to_tests[vuid_str].add(testname)
372 #self.test_to_vuids[testname].append(vuid_str)
373 if (vuid_str.startswith('VUID-')):
374 if (vuid_str[-5:-1].isdecimal()):
375 self.explicit_vuids.add(vuid_str) # explicit end in 5 numeric chars
376 else:
377 self.implicit_vuids.add(vuid_str)
378 elif (vuid_str.startswith('UNASSIGNED-')):
379 self.unassigned_vuids.add(vuid_str)
380 else:
381 print("Unable to categorize VUID: %s" % vuid_str)
382 print("Confused while parsing VUIDs in test code - cannot proceed. (FIXME)")
383 exit(-1)
384 self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600385
Dave Houltoncacef472018-05-29 13:00:42 -0600386# Class to do consistency checking
387#
388class Consistency:
389 def __init__(self, all_json, all_checks, all_tests):
390 self.valid = all_json
391 self.checks = all_checks
392 self.tests = all_tests
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600393
Dave Houltoncacef472018-05-29 13:00:42 -0600394 if (dealias_khr):
395 dk = set()
396 for vuid in self.checks:
397 if vuid in khr_aliases:
398 dk.add(khr_aliases[vuid])
399 else:
400 dk.add(vuid)
401 self.checks = dk
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600402
Dave Houltoncacef472018-05-29 13:00:42 -0600403 dk = set()
404 for vuid in self.tests:
405 if vuid in khr_aliases:
406 dk.add(khr_aliases[vuid])
407 else:
408 dk.add(vuid)
409 self.tests = dk
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600410
Dave Houltoncacef472018-05-29 13:00:42 -0600411 # Report undefined VUIDs in source code
412 def undef_vuids_in_layer_code(self):
413 undef_set = self.checks - self.valid
414 undef_set.discard('VUID-Undefined') # don't report Undefined
415 if ignore_unassigned:
416 unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')})
417 undef_set = undef_set - unassigned
418 if (len(undef_set) > 0):
419 print("\nFollowing VUIDs found in layer code are not defined in validusage.json (%d):" % len(undef_set))
420 undef = list(undef_set)
421 undef.sort()
422 for vuid in undef:
423 print(" %s" % vuid)
424 return False
425 return True
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600426
Dave Houltoncacef472018-05-29 13:00:42 -0600427 # Report undefined VUIDs in tests
428 def undef_vuids_in_tests(self):
429 undef_set = self.tests - self.valid
430 undef_set.discard('VUID-Undefined') # don't report Undefined
431 if ignore_unassigned:
432 unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')})
433 undef_set = undef_set - unassigned
434 if (len(undef_set) > 0):
435 ok = False
436 print("\nFollowing VUIDs found in layer tests are not defined in validusage.json (%d):" % len(undef_set))
437 undef = list(undef_set)
438 undef.sort()
439 for vuid in undef:
440 print(" %s" % vuid)
441 return False
442 return True
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600443
Dave Houltoncacef472018-05-29 13:00:42 -0600444 # Report vuids in tests that are not in source
445 def vuids_tested_not_checked(self):
446 undef_set = self.tests - self.checks
447 undef_set.discard('VUID-Undefined') # don't report Undefined
448 if ignore_unassigned:
449 unassigned = set()
450 for vuid in undef_set:
451 if vuid.startswith('UNASSIGNED-'):
452 unassigned.add(vuid)
453 undef_set = undef_set - unassigned
454 if (len(undef_set) > 0):
455 ok = False
456 print("\nFollowing VUIDs found in tests but are not checked in layer code (%d):" % len(undef_set))
457 undef = list(undef_set)
458 undef.sort()
459 for vuid in undef:
460 print(" %s" % vuid)
461 return False
462 return True
463
464 # TODO: Explicit checked VUIDs which have no test
465 # def explicit_vuids_checked_not_tested(self):
466
467
468# Class to output database in various flavors
469#
470class OutputDatabase:
471 def __init__(self, val_json, val_source, val_tests):
472 self.vj = val_json
473 self.vs = val_source
474 self.vt = val_tests
Dave Houlton729c7822018-11-19 11:52:23 -0700475 self.header_version = "/* THIS FILE IS GENERATED - DO NOT EDIT (scripts/vk_validation_stats.py) */"
476 self.header_version += "\n/* Vulkan specification version: %s */" % val_json.apiversion
477 self.header_version += "\n/* Header generated: %s */\n" % time.strftime('%Y-%m-%d %H:%M:%S')
478 self.header_preamble = """
Dave Houlton407df732018-08-06 17:58:24 -0600479/*
480 * Vulkan
481 *
482 * Copyright (c) 2016-2018 Google Inc.
483 * Copyright (c) 2016-2018 LunarG, Inc.
484 *
485 * Licensed under the Apache License, Version 2.0 (the "License");
486 * you may not use this file except in compliance with the License.
487 * You may obtain a copy of the License at
488 *
489 * http://www.apache.org/licenses/LICENSE-2.0
490 *
491 * Unless required by applicable law or agreed to in writing, software
492 * distributed under the License is distributed on an "AS IS" BASIS,
493 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
494 * See the License for the specific language governing permissions and
495 * limitations under the License.
496 *
497 * Author: Tobin Ehlis <tobine@google.com>
498 * Author: Dave Houlton <daveh@lunarg.com>
499 */
500
501#pragma once
502
503// Disable auto-formatting for generated file
504// clang-format off
505
Dave Houlton407df732018-08-06 17:58:24 -0600506// Mapping from VUID string to the corresponding spec text
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600507typedef struct _vuid_spec_text_pair {
508 const char * vuid;
509 const char * spec_text;
510} vuid_spec_text_pair;
511
512static const vuid_spec_text_pair vuid_spec_text[] = {
Dave Houlton407df732018-08-06 17:58:24 -0600513"""
514 self.header_postamble = """};
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600515"""
Dave Houlton407df732018-08-06 17:58:24 -0600516 self.spec_url = "https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html"
Dave Houltoncacef472018-05-29 13:00:42 -0600517
518 def dump_txt(self):
519 print("\n Dumping database to text file: %s" % txt_filename)
520 with open (txt_filename, 'w') as txt:
521 txt.write("## VUID Database\n")
522 txt.write("## Format: VUID_NAME | CHECKED | TEST | TYPE | API/STRUCT | EXTENSION | VUID_TEXT\n##\n")
523 vuid_list = list(self.vj.all_vuids)
524 vuid_list.sort()
525 for vuid in vuid_list:
526 db_list = self.vj.vuid_db[vuid]
527 db_list.sort(key=operator.itemgetter('ext')) # sort list to ease diffs of output file
528 for db_entry in db_list:
529 checked = 'N'
530 if vuid in self.vs.all_vuids:
531 checked = 'Y'
532 test = 'None'
533 if vuid in self.vt.vuid_to_tests:
534 test_list = list(self.vt.vuid_to_tests[vuid])
535 test_list.sort() # sort tests, for diff-ability
536 sep = ', '
537 test = sep.join(test_list)
538
539 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']))
540
541 def dump_csv(self):
542 print("\n Dumping database to csv file: %s" % csv_filename)
543 with open (csv_filename, 'w', newline='') as csvfile:
544 cw = csv.writer(csvfile)
545 cw.writerow(['VUID_NAME','CHECKED','TEST','TYPE','API/STRUCT','EXTENSION','VUID_TEXT'])
546 vuid_list = list(self.vj.all_vuids)
547 vuid_list.sort()
548 for vuid in vuid_list:
549 for db_entry in self.vj.vuid_db[vuid]:
550 row = [vuid]
551 if vuid in self.vs.all_vuids:
552 row.append('Y')
553 else:
554 row.append('N')
555 test = 'None'
556 if vuid in self.vt.vuid_to_tests:
557 sep = ', '
558 test = sep.join(self.vt.vuid_to_tests[vuid])
559 row.append(test)
560 row.append(db_entry['type'])
561 row.append(db_entry['api'])
562 row.append(db_entry['ext'])
563 row.append(db_entry['text'])
564 cw.writerow(row)
565
566 def dump_html(self):
567 print("\n Dumping database to html file: %s" % html_filename)
568 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'
569 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'
570 with open (html_filename, 'w') as hfile:
571 hfile.write(preamble)
572 hfile.write(headers)
573 vuid_list = list(self.vj.all_vuids)
574 vuid_list.sort()
575 for vuid in vuid_list:
576 for db_entry in self.vj.vuid_db[vuid]:
577 hfile.write('<tr><th>%s</th>' % vuid)
578 checked = '<span style="color:red;">N</span>'
579 if vuid in self.vs.all_vuids:
580 checked = '<span style="color:limegreen;">Y</span>'
581 hfile.write('<th>%s</th>' % checked)
582 test = 'None'
583 if vuid in self.vt.vuid_to_tests:
584 sep = ', '
585 test = sep.join(self.vt.vuid_to_tests[vuid])
586 hfile.write('<th>%s</th>' % test)
587 hfile.write('<th>%s</th>' % db_entry['type'])
588 hfile.write('<th>%s</th>' % db_entry['api'])
589 hfile.write('<th>%s</th>' % db_entry['ext'])
590 hfile.write('<th>%s</th></tr>\n' % db_entry['text'])
591 hfile.write('</table>\n</body>\n</html>\n')
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600592
Dave Houlton407df732018-08-06 17:58:24 -0600593 def export_header(self):
594 print("\n Exporting header file to: %s" % header_filename)
595 with open (header_filename, 'w') as hfile:
Dave Houlton729c7822018-11-19 11:52:23 -0700596 hfile.write(self.header_version)
Dave Houlton407df732018-08-06 17:58:24 -0600597 hfile.write(self.header_preamble)
598 vuid_list = list(self.vj.all_vuids)
599 vuid_list.sort()
600 for vuid in vuid_list:
601 db_entry = self.vj.vuid_db[vuid][0]
602 hfile.write(' {"%s", "%s (%s#%s)"},\n' % (vuid, db_entry['text'].strip(' '), self.spec_url, vuid))
603 # For multiply-defined VUIDs, include versions with extension appended
604 if len(self.vj.vuid_db[vuid]) > 1:
605 for db_entry in self.vj.vuid_db[vuid]:
606 hfile.write(' {"%s[%s]", "%s (%s#%s)"},\n' % (vuid, db_entry['ext'].strip(' '), db_entry['text'].strip(' '), self.spec_url, vuid))
607 hfile.write(self.header_postamble)
608
Mark Lobodzinskib44c54a2017-06-12 12:02:38 -0600609def main(argv):
Dave Houltoncacef472018-05-29 13:00:42 -0600610 global verbose_mode
611 global txt_filename
612 global csv_filename
613 global html_filename
614
615 run_consistency = False
616 report_unimplemented = False
617 get_vuid_status = ''
618 txt_out = False
619 csv_out = False
620 html_out = False
Dave Houlton407df732018-08-06 17:58:24 -0600621 header_out = False
Dave Houltoncacef472018-05-29 13:00:42 -0600622
623 if (1 > len(argv)):
624 printHelp()
625 sys.exit()
626
627 # Parse script args
628 json_filename = argv[0]
629 i = 1
630 while (i < len(argv)):
631 arg = argv[i]
632 i = i + 1
633 if (arg == '-c'):
634 run_consistency = True
635 elif (arg == '-vuid'):
636 get_vuid_status = argv[i]
637 i = i + 1
638 elif (arg == '-todo'):
639 report_unimplemented = True
Karl Schultz49d66bb2018-07-09 16:24:46 -0600640 elif (arg == '-text'):
Dave Houltoncacef472018-05-29 13:00:42 -0600641 txt_out = True
642 # Set filename if supplied, else use default
643 if i < len(argv) and not argv[i].startswith('-'):
644 txt_filename = argv[i]
645 i = i + 1
646 elif (arg == '-csv'):
647 csv_out = True
648 # Set filename if supplied, else use default
649 if i < len(argv) and not argv[i].startswith('-'):
650 csv_filename = argv[i]
651 i = i + 1
652 elif (arg == '-html'):
653 html_out = True
654 # Set filename if supplied, else use default
655 if i < len(argv) and not argv[i].startswith('-'):
656 html_filename = argv[i]
657 i = i + 1
Dave Houlton407df732018-08-06 17:58:24 -0600658 elif (arg == '-export_header'):
659 header_out = True
Dave Houltoncacef472018-05-29 13:00:42 -0600660 elif (arg in ['-verbose']):
661 verbose_mode = True
662 elif (arg in ['-help', '-h']):
663 printHelp()
664 sys.exit()
665 else:
666 print("Unrecognized argument: %s\n" % arg)
667 printHelp()
668 sys.exit()
669
Tobin Ehlis20e32582016-12-05 14:50:03 -0700670 result = 0 # Non-zero result indicates an error case
Dave Houltoncacef472018-05-29 13:00:42 -0600671
672 # Parse validusage json
673 val_json = ValidationJSON(json_filename)
674 val_json.read()
675 exp_json = len(val_json.explicit_vuids)
676 imp_json = len(val_json.implicit_vuids)
677 all_json = len(val_json.all_vuids)
678 if verbose_mode:
679 print("Found %d unique error vuids in validusage.json file." % all_json)
680 print(" %d explicit" % exp_json)
681 print(" %d implicit" % imp_json)
682 if len(val_json.duplicate_vuids) > 0:
683 print("%d VUIDs appear in validusage.json more than once." % len(val_json.duplicate_vuids))
684 for vuid in val_json.duplicate_vuids:
685 print(" %s" % vuid)
686 for ext in val_json.vuid_db[vuid]:
687 print(" with extension: %s" % ext['ext'])
688
689 # Parse layer source files
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600690 val_source = ValidationSource(layer_source_files, generated_layer_source_files, generated_layer_source_directories)
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600691 val_source.parse()
Dave Houltoncacef472018-05-29 13:00:42 -0600692 exp_checks = len(val_source.explicit_vuids)
693 imp_checks = len(val_source.implicit_vuids)
694 all_checks = len(val_source.vuid_count_dict.keys())
695 if verbose_mode:
696 print("Found %d unique vuid checks in layer source code." % all_checks)
697 print(" %d explicit" % exp_checks)
698 print(" %d implicit" % imp_checks)
699 print(" %d unassigned" % len(val_source.unassigned_vuids))
700 print(" %d checks are implemented more that once" % val_source.duplicated_checks)
701
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600702 # Parse test files
Dave Houltoncacef472018-05-29 13:00:42 -0600703 val_tests = ValidationTests([test_file, ])
704 val_tests.parse()
705 exp_tests = len(val_tests.explicit_vuids)
706 imp_tests = len(val_tests.implicit_vuids)
707 all_tests = len(val_tests.all_vuids)
Mark Lobodzinski060a8e32018-01-08 09:08:06 -0700708 if verbose_mode:
Dave Houltoncacef472018-05-29 13:00:42 -0600709 print("Found %d unique error vuids in test file %s." % (all_tests, test_file))
710 print(" %d explicit" % exp_tests)
711 print(" %d implicit" % imp_tests)
712 print(" %d unassigned" % len(val_tests.unassigned_vuids))
Mike Weiblenfe186122017-02-03 12:44:53 -0700713
Dave Houltoncacef472018-05-29 13:00:42 -0600714 # Process stats
715 print("\nValidation Statistics (using validusage.json version %s)" % val_json.apiversion)
716 print(" VUIDs defined in JSON file: %04d explicit, %04d implicit, %04d total." % (exp_json, imp_json, all_json))
717 print(" VUIDs checked in layer code: %04d explicit, %04d implicit, %04d total." % (exp_checks, imp_checks, all_checks))
718 print(" VUIDs tested in layer tests: %04d explicit, %04d implicit, %04d total." % (exp_tests, imp_tests, all_tests))
719
720 print("\nVUID check coverage")
721 print(" Explicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * exp_checks / exp_json), exp_checks, exp_json))
722 print(" Implicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * imp_checks / imp_json), imp_checks, imp_json))
723 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 -0700724
Dave Houltoncacef472018-05-29 13:00:42 -0600725 print("\nVUID test coverage")
726 print(" Explicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * exp_tests / exp_checks), exp_tests, exp_checks))
727 print(" Implicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * imp_tests / imp_checks), imp_tests, imp_checks))
728 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 -0700729
Dave Houltoncacef472018-05-29 13:00:42 -0600730 # Report status of a single VUID
731 if len(get_vuid_status) > 1:
732 print("\n\nChecking status of <%s>" % get_vuid_status);
733 if get_vuid_status not in val_json.all_vuids:
734 print(' Not a valid VUID string.')
735 else:
736 if get_vuid_status in val_source.explicit_vuids:
737 print(' Implemented!')
738 line_list = val_source.vuid_count_dict[get_vuid_status]['file_line']
739 for line in line_list:
740 print(' => %s' % line)
Dave Houltonf93bbab2018-06-26 17:21:12 -0600741 elif get_vuid_status in val_source.implicit_vuids:
742 print(' Implemented! (Implicit)')
743 line_list = val_source.vuid_count_dict[get_vuid_status]['file_line']
744 for line in line_list:
745 print(' => %s' % line)
Tobin Ehlis9a68c982016-12-29 14:51:17 -0700746 else:
Dave Houltoncacef472018-05-29 13:00:42 -0600747 print(' Not implemented.')
Dave Houltonf93bbab2018-06-26 17:21:12 -0600748 if get_vuid_status in val_tests.all_vuids:
Dave Houltoncacef472018-05-29 13:00:42 -0600749 print(' Has a test!')
750 test_list = val_tests.vuid_to_tests[get_vuid_status]
751 for test in test_list:
752 print(' => %s' % test)
753 else:
754 print(' Not tested.')
Mike Weiblenfe186122017-02-03 12:44:53 -0700755
Dave Houltoncacef472018-05-29 13:00:42 -0600756 # Report unimplemented explicit VUIDs
757 if report_unimplemented:
758 unim_explicit = val_json.explicit_vuids - val_source.explicit_vuids
759 print("\n\n%d explicit VUID checks remain unimplemented:" % len(unim_explicit))
760 ulist = list(unim_explicit)
761 ulist.sort()
762 for vuid in ulist:
763 print(" => %s" % vuid)
764
765 # Consistency tests
766 if run_consistency:
767 print("\n\nRunning consistency tests...")
768 con = Consistency(val_json.all_vuids, val_source.all_vuids, val_tests.all_vuids)
769 ok = con.undef_vuids_in_layer_code()
770 ok &= con.undef_vuids_in_tests()
771 ok &= con.vuids_tested_not_checked()
772
773 if ok:
774 print(" OK! No inconsistencies found.")
775
776 # Output database in requested format(s)
777 db_out = OutputDatabase(val_json, val_source, val_tests)
778 if txt_out:
779 db_out.dump_txt()
780 if csv_out:
781 db_out.dump_csv()
782 if html_out:
783 db_out.dump_html()
Dave Houlton407df732018-08-06 17:58:24 -0600784 if header_out:
785 db_out.export_header()
Tobin Ehlis20e32582016-12-05 14:50:03 -0700786 return result
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600787
788if __name__ == "__main__":
Mark Lobodzinskib44c54a2017-06-12 12:02:38 -0600789 sys.exit(main(sys.argv[1:]))
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600790