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