blob: 5a5c329afe4ed326fc52d47637ead5cf78cd2178 [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',
Jasper St. Pierre512613a2019-04-08 16:25:23 -070064'../layers/core_validation_drawdispatch.cpp',
Mark Lobodzinskie3787b42017-06-21 13:41:00 -060065'../layers/descriptor_sets.cpp',
Mark Lobodzinskid4950072017-08-01 13:02:20 -060066'../layers/parameter_validation_utils.cpp',
Mark Lobodzinskib2de97f2017-07-06 15:28:11 -060067'../layers/object_tracker_utils.cpp',
Mark Lobodzinskie3787b42017-06-21 13:41:00 -060068'../layers/shader_validation.cpp',
Shannon McPherson9a4ae982019-01-07 16:05:25 -070069'../layers/stateless_validation.h'
Tobin Ehlis35308dd2016-10-31 13:27:36 -060070]
Tobin Ehlis35308dd2016-10-31 13:27:36 -060071
Dave Houlton407df732018-08-06 17:58:24 -060072# This needs to be updated as new extensions roll in
Mark Lobodzinski02e23172019-03-04 15:27:55 -070073khr_aliases = {
74 'VUID-vkBindBufferMemory2KHR-device-parameter' : 'VUID-vkBindBufferMemory2-device-parameter',
75 'VUID-vkBindBufferMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindBufferMemory2-pBindInfos-parameter',
76 'VUID-vkBindImageMemory2KHR-device-parameter' : 'VUID-vkBindImageMemory2-device-parameter',
77 'VUID-vkBindImageMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindImageMemory2-pBindInfos-parameter',
78 'VUID-vkCmdDispatchBaseKHR-commandBuffer-parameter' : 'VUID-vkCmdDispatchBase-commandBuffer-parameter',
79 'VUID-vkCmdSetDeviceMaskKHR-commandBuffer-parameter' : 'VUID-vkCmdSetDeviceMask-commandBuffer-parameter',
80 'VUID-vkCreateDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-device-parameter',
81 'VUID-vkCreateDescriptorUpdateTemplateKHR-pDescriptorUpdateTemplate-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pDescriptorUpdateTemplate-parameter',
82 'VUID-vkCreateSamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-device-parameter',
83 'VUID-vkCreateSamplerYcbcrConversionKHR-pYcbcrConversion-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pYcbcrConversion-parameter',
84 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parameter',
Dave Houltoncacef472018-05-29 13:00:42 -060085 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parent',
Mark Lobodzinski02e23172019-03-04 15:27:55 -070086 'VUID-vkDestroyDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-device-parameter',
87 'VUID-vkDestroySamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-device-parameter',
88 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parameter',
Dave Houltoncacef472018-05-29 13:00:42 -060089 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parent' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parent',
Mark Lobodzinski02e23172019-03-04 15:27:55 -070090 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-instance-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-instance-parameter',
91 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-pPhysicalDeviceGroupProperties-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-pPhysicalDeviceGroupProperties-parameter',
92 'VUID-vkGetBufferMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetBufferMemoryRequirements2-device-parameter',
93 'VUID-vkGetDescriptorSetLayoutSupportKHR-device-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-device-parameter',
94 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-device-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-device-parameter',
95 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-pPeerMemoryFeatures-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-pPeerMemoryFeatures-parameter',
96 'VUID-vkGetImageMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageMemoryRequirements2-device-parameter',
97 'VUID-vkGetImageSparseMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-device-parameter',
98 'VUID-vkGetImageSparseMemoryRequirements2KHR-pSparseMemoryRequirements-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pSparseMemoryRequirements-parameter',
99 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-physicalDevice-parameter',
100 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-physicalDevice-parameter',
101 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-physicalDevice-parameter',
102 'VUID-vkGetPhysicalDeviceFeatures2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-physicalDevice-parameter',
103 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-format-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-format-parameter',
104 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-physicalDevice-parameter',
105 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-physicalDevice-parameter',
106 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-physicalDevice-parameter',
107 'VUID-vkGetPhysicalDeviceProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-physicalDevice-parameter',
108 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2KHR-pQueueFamilyProperties-parameter' : 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2-pQueueFamilyProperties-parameter',
109 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pProperties-parameter',
110 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-physicalDevice-parameter',
111 'VUID-vkTrimCommandPoolKHR-commandPool-parameter' : 'VUID-vkTrimCommandPool-commandPool-parameter',
Dave Houltoncacef472018-05-29 13:00:42 -0600112 'VUID-vkTrimCommandPoolKHR-commandPool-parent' : 'VUID-vkTrimCommandPool-commandPool-parent',
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700113 'VUID-vkTrimCommandPoolKHR-device-parameter' : 'VUID-vkTrimCommandPool-device-parameter',
Dave Houltoncacef472018-05-29 13:00:42 -0600114 'VUID-vkTrimCommandPoolKHR-flags-zerobitmask' : 'VUID-vkTrimCommandPool-flags-zerobitmask',
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700115 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorSet-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorSet-parameter',
116 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parameter',
Dave Houltoncacef472018-05-29 13:00:42 -0600117 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parent',
118 'VUID-vkUpdateDescriptorSetWithTemplateKHR-device-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-device-parameter',
119 'VUID-vkCreateDescriptorUpdateTemplateKHR-pCreateInfo-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pCreateInfo-parameter',
120 'VUID-vkCreateSamplerYcbcrConversionKHR-pCreateInfo-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pCreateInfo-parameter',
121 'VUID-vkGetBufferMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pInfo-parameter',
122 'VUID-vkGetBufferMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pMemoryRequirements-parameter',
123 'VUID-vkGetDescriptorSetLayoutSupportKHR-pCreateInfo-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pCreateInfo-parameter',
124 'VUID-vkGetDescriptorSetLayoutSupportKHR-pSupport-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pSupport-parameter',
125 'VUID-vkGetImageMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageMemoryRequirements2-pInfo-parameter',
126 'VUID-vkGetImageMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetImageMemoryRequirements2-pMemoryRequirements-parameter',
127 'VUID-vkGetImageSparseMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pInfo-parameter',
128 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferInfo-parameter',
129 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferProperties-parameter',
130 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceInfo-parameter',
131 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceProperties-parameter',
132 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreInfo-parameter',
133 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreProperties-parameter',
134 'VUID-vkGetPhysicalDeviceFeatures2KHR-pFeatures-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-pFeatures-parameter',
135 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-pFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-pFormatProperties-parameter',
136 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatInfo-parameter',
137 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatProperties-parameter',
138 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-pMemoryProperties-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-pMemoryProperties-parameter',
139 'VUID-vkGetPhysicalDeviceProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-pProperties-parameter',
140 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pFormatInfo-parameter' }
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600141
Dave Houltoncacef472018-05-29 13:00:42 -0600142def printHelp():
143 print ("Usage:")
144 print (" python vk_validation_stats.py <json_file>")
145 print (" [ -c ]")
146 print (" [ -todo ]")
147 print (" [ -vuid <vuid_name> ]")
148 print (" [ -text [ <text_out_filename>] ]")
149 print (" [ -csv [ <csv_out_filename>] ]")
150 print (" [ -html [ <html_out_filename>] ]")
Dave Houlton407df732018-08-06 17:58:24 -0600151 print (" [ -export_header ]")
Dave Houltoncacef472018-05-29 13:00:42 -0600152 print (" [ -verbose ]")
153 print (" [ -help ]")
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700154 print ("\n The vk_validation_stats script parses validation layer source files to")
155 print (" determine the set of valid usage checks and tests currently implemented,")
Dave Houltoncacef472018-05-29 13:00:42 -0600156 print (" and generates coverage values by comparing against the full set of valid")
157 print (" usage identifiers in the Vulkan-Headers registry file 'validusage.json'")
158 print ("\nArguments: ")
159 print (" <json-file> (required) registry file 'validusage.json'")
160 print (" -c report consistency warnings")
161 print (" -todo report unimplemented VUIDs")
162 print (" -vuid <vuid_name> report status of individual VUID <vuid_name>")
163 print (" -text [filename] output the error database text to <text_database_filename>,")
164 print (" defaults to 'validation_error_database.txt'")
165 print (" -csv [filename] output the error database in csv to <csv_database_filename>,")
166 print (" defaults to 'validation_error_database.csv'")
167 print (" -html [filename] output the error database in html to <html_database_filename>,")
168 print (" defaults to 'validation_error_database.html'")
Dave Houlton407df732018-08-06 17:58:24 -0600169 print (" -export_header export a new VUID error text header file to <%s>" % header_filename)
Dave Houltoncacef472018-05-29 13:00:42 -0600170 print (" -verbose show your work (to stdout)")
171
172class ValidationJSON:
173 def __init__(self, filename):
174 self.filename = filename
175 self.explicit_vuids = set()
176 self.implicit_vuids = set()
177 self.all_vuids = set()
178 self.vuid_db = defaultdict(list) # Maps VUID string to list of json-data dicts
179 self.apiversion = ""
Dave Houltoncacef472018-05-29 13:00:42 -0600180 self.duplicate_vuids = set()
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700181
Dave Houlton407df732018-08-06 17:58:24 -0600182 # A set of specific regular expression substitutions needed to clean up VUID text
183 self.regex_dict = {}
184 self.regex_dict[re.compile('<.*?>|&(amp;)+lt;|&(amp;)+gt;')] = ""
185 self.regex_dict[re.compile(r'\\\(codeSize \\over 4\\\)')] = "(codeSize/4)"
Shannon McPherson3ea65132018-12-05 10:37:39 -0700186 self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{height}{maxFragmentDensityTexelSize_{height}}}\\rceil\\\)')] = "the ceiling of height/maxFragmentDensityTexelSize.height"
187 self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{width}{maxFragmentDensityTexelSize_{width}}}\\rceil\\\)')] = "the ceiling of width/maxFragmentDensityTexelSize.width"
188 self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{maxFramebufferHeight}{minFragmentDensityTexelSize_{height}}}\\rceil\\\)')] = "the ceiling of maxFramebufferHeight/minFragmentDensityTexelSize.height"
189 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 -0600190 self.regex_dict[re.compile(r'\\\(\\lceil\{\\mathit\{rasterizationSamples} \\over 32}\\rceil\\\)')] = "(rasterizationSamples/32)"
Shannon McPhersonb40f1a22018-10-30 16:45:07 -0600191 self.regex_dict[re.compile(r'\\\(\\textrm\{codeSize} \\over 4\\\)')] = "(codeSize/4)"
Dave Houlton407df732018-08-06 17:58:24 -0600192 # Some fancy punctuation chars that break the Android build...
193 self.regex_dict[re.compile('&#8594;')] = "->" # Arrow char
194 self.regex_dict[re.compile('&#8217;')] = "'" # Left-slanting apostrophe to apostrophe
195 self.regex_dict[re.compile('&#822(0|1);')] = "'" # L/R-slanting quotes to apostrophe
Dave Houltoncacef472018-05-29 13:00:42 -0600196
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600197 def read(self):
Dave Houltoncacef472018-05-29 13:00:42 -0600198 self.json_dict = {}
199 if os.path.isfile(self.filename):
Dave Houlton407df732018-08-06 17:58:24 -0600200 json_file = open(self.filename, 'r', encoding='utf-8')
Dave Houltoncacef472018-05-29 13:00:42 -0600201 self.json_dict = json.load(json_file)
202 json_file.close()
203 if len(self.json_dict) == 0:
204 print("Error: Error loading validusage.json file <%s>" % self.filename)
205 sys.exit(-1)
206 try:
207 version = self.json_dict['version info']
208 validation = self.json_dict['validation']
209 self.apiversion = version['api version']
210 except:
211 print("Error: Failure parsing validusage.json object")
212 sys.exit(-1)
213
214 # Parse vuid from json into local databases
215 for apiname in validation.keys():
216 # print("entrypoint:%s"%apiname)
217 apidict = validation[apiname]
218 for ext in apidict.keys():
219 vlist = apidict[ext]
220 for ventry in vlist:
221 vuid_string = ventry['vuid']
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700222 if (vuid_string[-5:-1].isdecimal()):
Dave Houltoncacef472018-05-29 13:00:42 -0600223 self.explicit_vuids.add(vuid_string) # explicit end in 5 numeric chars
224 vtype = 'explicit'
225 else:
226 self.implicit_vuids.add(vuid_string) # otherwise, implicit
227 vtype = 'implicit'
228 vuid_text = ventry['text']
Dave Houlton407df732018-08-06 17:58:24 -0600229 for regex, replacement in self.regex_dict.items():
230 vuid_text = re.sub(regex, replacement, vuid_text) # do regex substitution
231 vuid_text = html.unescape(vuid_text) # anything missed by the regex
232 self.vuid_db[vuid_string].append({'api':apiname, 'ext':ext, 'type':vtype, 'text':vuid_text})
Dave Houltoncacef472018-05-29 13:00:42 -0600233 self.all_vuids = self.explicit_vuids | self.implicit_vuids
234 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 -0600235 if len(self.duplicate_vuids) > 0:
236 print("Warning: duplicate VUIDs found in validusage.json")
237
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600238
239class ValidationSource:
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600240 def __init__(self, source_file_list, generated_source_file_list, generated_source_directories):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600241 self.source_files = source_file_list
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600242 self.generated_source_files = generated_source_file_list
243 self.generated_source_dirs = generated_source_directories
Dave Houltoncacef472018-05-29 13:00:42 -0600244 self.vuid_count_dict = {} # dict of vuid values to the count of how much they're used, and location of where they're used
245 self.duplicated_checks = 0
246 self.explicit_vuids = set()
247 self.implicit_vuids = set()
248 self.unassigned_vuids = set()
249 self.all_vuids = set()
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600250
251 if len(self.generated_source_files) > 0:
252 qualified_paths = []
253 for source in self.generated_source_files:
254 for build_dir in self.generated_source_dirs:
255 filepath = '../%s/layers/%s' % (build_dir, source)
256 if os.path.isfile(filepath):
257 qualified_paths.append(filepath)
John Zulaufdde04c42018-01-16 15:32:45 -0700258 break
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600259 if len(self.generated_source_files) != len(qualified_paths):
Mark Lobodzinski2d193ac2017-06-27 09:38:15 -0600260 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 -0600261 print(self.generated_source_files)
Dave Houltoncacef472018-05-29 13:00:42 -0600262 print("Failed to locate one or more codegen files in layer source code - cannot proceed.")
John Zulaufdde04c42018-01-16 15:32:45 -0700263 exit(1)
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600264 else:
265 self.source_files.extend(qualified_paths)
266
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600267 def parse(self):
Dave Houltoncacef472018-05-29 13:00:42 -0600268 prepend = None
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600269 for sf in self.source_files:
Tobin Ehlis3d1f2bd2016-12-22 11:19:15 -0700270 line_num = 0
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600271 with open(sf) as f:
272 for line in f:
Tobin Ehlis3d1f2bd2016-12-22 11:19:15 -0700273 line_num = line_num + 1
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600274 if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
275 continue
Dave Houltoncacef472018-05-29 13:00:42 -0600276 # Find vuid strings
Michał Janiszewski3c3ce9e2018-10-30 23:25:21 +0100277 if prepend is not None:
Dave Houltoncacef472018-05-29 13:00:42 -0600278 line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char
279 prepend = None
280 if any(prefix in line for prefix in vuid_prefixes):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600281 line_list = line.split()
Dave Houltoncacef472018-05-29 13:00:42 -0600282
283 # 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
284 broken_vuid = line_list[-1].strip('"')
285 if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'):
286 prepend = line
287 continue
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700288
Dave Houltoncacef472018-05-29 13:00:42 -0600289 vuid_list = []
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600290 for str in line_list:
Dave Houltoncacef472018-05-29 13:00:42 -0600291 if any(prefix in str for prefix in vuid_prefixes):
292 vuid_list.append(str.strip(',);{}"'))
293 for vuid in vuid_list:
294 if vuid not in self.vuid_count_dict:
295 self.vuid_count_dict[vuid] = {}
296 self.vuid_count_dict[vuid]['count'] = 1
297 self.vuid_count_dict[vuid]['file_line'] = []
298 else:
299 if self.vuid_count_dict[vuid]['count'] == 1: # only count first time duplicated
300 self.duplicated_checks = self.duplicated_checks + 1
301 self.vuid_count_dict[vuid]['count'] = self.vuid_count_dict[vuid]['count'] + 1
302 self.vuid_count_dict[vuid]['file_line'].append('%s,%d' % (sf, line_num))
303 # Sort vuids by type
304 for vuid in self.vuid_count_dict.keys():
305 if (vuid.startswith('VUID-')):
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700306 if (vuid[-5:-1].isdecimal()):
Dave Houltoncacef472018-05-29 13:00:42 -0600307 self.explicit_vuids.add(vuid) # explicit end in 5 numeric chars
308 else:
309 self.implicit_vuids.add(vuid)
310 elif (vuid.startswith('UNASSIGNED-')):
311 self.unassigned_vuids.add(vuid)
312 else:
313 print("Unable to categorize VUID: %s" % vuid)
314 print("Confused while parsing VUIDs in layer source code - cannot proceed. (FIXME)")
315 exit(-1)
316 self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600317
318# Class to parse the validation layer test source and store testnames
Dave Houltoncacef472018-05-29 13:00:42 -0600319class ValidationTests:
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600320 def __init__(self, test_file_list, test_group_name=['VkLayerTest', 'VkPositiveLayerTest', 'VkWsiEnabledLayerTest']):
321 self.test_files = test_file_list
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600322 self.test_trigger_txt_list = []
323 for tg in test_group_name:
324 self.test_trigger_txt_list.append('TEST_F(%s' % tg)
Dave Houltoncacef472018-05-29 13:00:42 -0600325 self.explicit_vuids = set()
326 self.implicit_vuids = set()
327 self.unassigned_vuids = set()
328 self.all_vuids = set()
329 #self.test_to_vuids = {} # Map test name to VUIDs tested
330 self.vuid_to_tests = defaultdict(set) # Map VUIDs to set of test names where implemented
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600331
332 # Parse test files into internal data struct
333 def parse(self):
334 # For each test file, parse test names into set
335 grab_next_line = False # handle testname on separate line than wildcard
Tobin Ehlis9a68c982016-12-29 14:51:17 -0700336 testname = ''
Dave Houltoncacef472018-05-29 13:00:42 -0600337 prepend = None
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600338 for test_file in self.test_files:
339 with open(test_file) as tf:
340 for line in tf:
341 if True in [line.strip().startswith(comment) for comment in ['//', '/*']]:
342 continue
343
Dave Houltoncacef472018-05-29 13:00:42 -0600344 # if line ends in a broken VUID string, fix that before proceeding
Michał Janiszewski3c3ce9e2018-10-30 23:25:21 +0100345 if prepend is not None:
Dave Houltoncacef472018-05-29 13:00:42 -0600346 line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char
347 prepend = None
348 if any(prefix in line for prefix in vuid_prefixes):
349 line_list = line.split()
350
351 # 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
352 broken_vuid = line_list[-1].strip('"')
353 if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'):
354 prepend = line
355 continue
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700356
Dave Houltoncacef472018-05-29 13:00:42 -0600357 if any(ttt in line for ttt in self.test_trigger_txt_list):
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600358 testname = line.split(',')[-1]
359 testname = testname.strip().strip(' {)')
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600360 if ('' == testname):
361 grab_next_line = True
362 continue
Dave Houltoncacef472018-05-29 13:00:42 -0600363 #self.test_to_vuids[testname] = []
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600364 if grab_next_line: # test name on its own line
365 grab_next_line = False
366 testname = testname.strip().strip(' {)')
Dave Houltoncacef472018-05-29 13:00:42 -0600367 #self.test_to_vuids[testname] = []
368 if any(prefix in line for prefix in vuid_prefixes):
369 line_list = re.split('[\s{}[\]()"]+',line)
Tobin Ehlis71f38c12017-01-12 14:26:56 -0700370 for sub_str in line_list:
Dave Houltoncacef472018-05-29 13:00:42 -0600371 if any(prefix in sub_str for prefix in vuid_prefixes):
372 vuid_str = sub_str.strip(',);:"')
373 self.vuid_to_tests[vuid_str].add(testname)
374 #self.test_to_vuids[testname].append(vuid_str)
375 if (vuid_str.startswith('VUID-')):
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700376 if (vuid_str[-5:-1].isdecimal()):
Dave Houltoncacef472018-05-29 13:00:42 -0600377 self.explicit_vuids.add(vuid_str) # explicit end in 5 numeric chars
378 else:
379 self.implicit_vuids.add(vuid_str)
380 elif (vuid_str.startswith('UNASSIGNED-')):
381 self.unassigned_vuids.add(vuid_str)
382 else:
383 print("Unable to categorize VUID: %s" % vuid_str)
384 print("Confused while parsing VUIDs in test code - cannot proceed. (FIXME)")
385 exit(-1)
386 self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600387
Dave Houltoncacef472018-05-29 13:00:42 -0600388# Class to do consistency checking
389#
390class Consistency:
391 def __init__(self, all_json, all_checks, all_tests):
392 self.valid = all_json
393 self.checks = all_checks
394 self.tests = all_tests
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600395
Dave Houltoncacef472018-05-29 13:00:42 -0600396 if (dealias_khr):
397 dk = set()
398 for vuid in self.checks:
399 if vuid in khr_aliases:
400 dk.add(khr_aliases[vuid])
401 else:
402 dk.add(vuid)
403 self.checks = dk
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600404
Dave Houltoncacef472018-05-29 13:00:42 -0600405 dk = set()
406 for vuid in self.tests:
407 if vuid in khr_aliases:
408 dk.add(khr_aliases[vuid])
409 else:
410 dk.add(vuid)
411 self.tests = dk
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600412
Dave Houltoncacef472018-05-29 13:00:42 -0600413 # Report undefined VUIDs in source code
414 def undef_vuids_in_layer_code(self):
415 undef_set = self.checks - self.valid
416 undef_set.discard('VUID-Undefined') # don't report Undefined
417 if ignore_unassigned:
418 unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')})
419 undef_set = undef_set - unassigned
420 if (len(undef_set) > 0):
421 print("\nFollowing VUIDs found in layer code are not defined in validusage.json (%d):" % len(undef_set))
422 undef = list(undef_set)
423 undef.sort()
424 for vuid in undef:
425 print(" %s" % vuid)
426 return False
427 return True
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600428
Dave Houltoncacef472018-05-29 13:00:42 -0600429 # Report undefined VUIDs in tests
430 def undef_vuids_in_tests(self):
431 undef_set = self.tests - self.valid
432 undef_set.discard('VUID-Undefined') # don't report Undefined
433 if ignore_unassigned:
434 unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')})
435 undef_set = undef_set - unassigned
436 if (len(undef_set) > 0):
437 ok = False
438 print("\nFollowing VUIDs found in layer tests are not defined in validusage.json (%d):" % len(undef_set))
439 undef = list(undef_set)
440 undef.sort()
441 for vuid in undef:
442 print(" %s" % vuid)
443 return False
444 return True
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600445
Dave Houltoncacef472018-05-29 13:00:42 -0600446 # Report vuids in tests that are not in source
447 def vuids_tested_not_checked(self):
448 undef_set = self.tests - self.checks
449 undef_set.discard('VUID-Undefined') # don't report Undefined
450 if ignore_unassigned:
451 unassigned = set()
452 for vuid in undef_set:
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700453 if vuid.startswith('UNASSIGNED-'):
Dave Houltoncacef472018-05-29 13:00:42 -0600454 unassigned.add(vuid)
455 undef_set = undef_set - unassigned
456 if (len(undef_set) > 0):
457 ok = False
458 print("\nFollowing VUIDs found in tests but are not checked in layer code (%d):" % len(undef_set))
459 undef = list(undef_set)
460 undef.sort()
461 for vuid in undef:
462 print(" %s" % vuid)
463 return False
464 return True
465
466 # TODO: Explicit checked VUIDs which have no test
467 # def explicit_vuids_checked_not_tested(self):
468
469
470# Class to output database in various flavors
471#
472class OutputDatabase:
473 def __init__(self, val_json, val_source, val_tests):
474 self.vj = val_json
475 self.vs = val_source
476 self.vt = val_tests
Dave Houlton729c7822018-11-19 11:52:23 -0700477 self.header_version = "/* THIS FILE IS GENERATED - DO NOT EDIT (scripts/vk_validation_stats.py) */"
478 self.header_version += "\n/* Vulkan specification version: %s */" % val_json.apiversion
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700479 self.header_version += "\n/* Header generated: %s */\n" % time.strftime('%Y-%m-%d %H:%M:%S')
Dave Houlton729c7822018-11-19 11:52:23 -0700480 self.header_preamble = """
Dave Houlton407df732018-08-06 17:58:24 -0600481/*
482 * Vulkan
483 *
Jasper St. Pierre1948bcc2019-01-18 13:55:20 -0800484 * Copyright (c) 2016-2019 Google Inc.
485 * Copyright (c) 2016-2019 LunarG, Inc.
Dave Houlton407df732018-08-06 17:58:24 -0600486 *
487 * Licensed under the Apache License, Version 2.0 (the "License");
488 * you may not use this file except in compliance with the License.
489 * You may obtain a copy of the License at
490 *
491 * http://www.apache.org/licenses/LICENSE-2.0
492 *
493 * Unless required by applicable law or agreed to in writing, software
494 * distributed under the License is distributed on an "AS IS" BASIS,
495 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
496 * See the License for the specific language governing permissions and
497 * limitations under the License.
498 *
499 * Author: Tobin Ehlis <tobine@google.com>
500 * Author: Dave Houlton <daveh@lunarg.com>
501 */
502
503#pragma once
504
505// Disable auto-formatting for generated file
506// clang-format off
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700507
Dave Houlton407df732018-08-06 17:58:24 -0600508// Mapping from VUID string to the corresponding spec text
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600509typedef struct _vuid_spec_text_pair {
510 const char * vuid;
511 const char * spec_text;
512} vuid_spec_text_pair;
513
514static const vuid_spec_text_pair vuid_spec_text[] = {
Dave Houlton407df732018-08-06 17:58:24 -0600515"""
516 self.header_postamble = """};
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600517"""
Dave Houlton407df732018-08-06 17:58:24 -0600518 self.spec_url = "https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html"
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700519
Dave Houltoncacef472018-05-29 13:00:42 -0600520 def dump_txt(self):
521 print("\n Dumping database to text file: %s" % txt_filename)
522 with open (txt_filename, 'w') as txt:
523 txt.write("## VUID Database\n")
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700524 txt.write("## Format: VUID_NAME | CHECKED | TEST | TYPE | API/STRUCT | EXTENSION | VUID_TEXT\n##\n")
Dave Houltoncacef472018-05-29 13:00:42 -0600525 vuid_list = list(self.vj.all_vuids)
526 vuid_list.sort()
527 for vuid in vuid_list:
528 db_list = self.vj.vuid_db[vuid]
529 db_list.sort(key=operator.itemgetter('ext')) # sort list to ease diffs of output file
530 for db_entry in db_list:
531 checked = 'N'
532 if vuid in self.vs.all_vuids:
533 checked = 'Y'
534 test = 'None'
535 if vuid in self.vt.vuid_to_tests:
536 test_list = list(self.vt.vuid_to_tests[vuid])
537 test_list.sort() # sort tests, for diff-ability
538 sep = ', '
539 test = sep.join(test_list)
540
541 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']))
542
543 def dump_csv(self):
544 print("\n Dumping database to csv file: %s" % csv_filename)
545 with open (csv_filename, 'w', newline='') as csvfile:
546 cw = csv.writer(csvfile)
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700547 cw.writerow(['VUID_NAME','CHECKED','TEST','TYPE','API/STRUCT','EXTENSION','VUID_TEXT'])
Dave Houltoncacef472018-05-29 13:00:42 -0600548 vuid_list = list(self.vj.all_vuids)
549 vuid_list.sort()
550 for vuid in vuid_list:
551 for db_entry in self.vj.vuid_db[vuid]:
552 row = [vuid]
553 if vuid in self.vs.all_vuids:
554 row.append('Y')
555 else:
556 row.append('N')
557 test = 'None'
558 if vuid in self.vt.vuid_to_tests:
559 sep = ', '
560 test = sep.join(self.vt.vuid_to_tests[vuid])
561 row.append(test)
562 row.append(db_entry['type'])
563 row.append(db_entry['api'])
564 row.append(db_entry['ext'])
565 row.append(db_entry['text'])
566 cw.writerow(row)
567
568 def dump_html(self):
569 print("\n Dumping database to html file: %s" % html_filename)
570 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'
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700571 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'
Dave Houltoncacef472018-05-29 13:00:42 -0600572 with open (html_filename, 'w') as hfile:
573 hfile.write(preamble)
574 hfile.write(headers)
575 vuid_list = list(self.vj.all_vuids)
576 vuid_list.sort()
577 for vuid in vuid_list:
578 for db_entry in self.vj.vuid_db[vuid]:
579 hfile.write('<tr><th>%s</th>' % vuid)
580 checked = '<span style="color:red;">N</span>'
581 if vuid in self.vs.all_vuids:
582 checked = '<span style="color:limegreen;">Y</span>'
583 hfile.write('<th>%s</th>' % checked)
584 test = 'None'
585 if vuid in self.vt.vuid_to_tests:
586 sep = ', '
587 test = sep.join(self.vt.vuid_to_tests[vuid])
588 hfile.write('<th>%s</th>' % test)
589 hfile.write('<th>%s</th>' % db_entry['type'])
590 hfile.write('<th>%s</th>' % db_entry['api'])
591 hfile.write('<th>%s</th>' % db_entry['ext'])
592 hfile.write('<th>%s</th></tr>\n' % db_entry['text'])
593 hfile.write('</table>\n</body>\n</html>\n')
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600594
Dave Houlton407df732018-08-06 17:58:24 -0600595 def export_header(self):
596 print("\n Exporting header file to: %s" % header_filename)
597 with open (header_filename, 'w') as hfile:
Dave Houlton729c7822018-11-19 11:52:23 -0700598 hfile.write(self.header_version)
Dave Houlton407df732018-08-06 17:58:24 -0600599 hfile.write(self.header_preamble)
600 vuid_list = list(self.vj.all_vuids)
601 vuid_list.sort()
602 for vuid in vuid_list:
603 db_entry = self.vj.vuid_db[vuid][0]
604 hfile.write(' {"%s", "%s (%s#%s)"},\n' % (vuid, db_entry['text'].strip(' '), self.spec_url, vuid))
605 # For multiply-defined VUIDs, include versions with extension appended
606 if len(self.vj.vuid_db[vuid]) > 1:
607 for db_entry in self.vj.vuid_db[vuid]:
608 hfile.write(' {"%s[%s]", "%s (%s#%s)"},\n' % (vuid, db_entry['ext'].strip(' '), db_entry['text'].strip(' '), self.spec_url, vuid))
609 hfile.write(self.header_postamble)
610
Mark Lobodzinskib44c54a2017-06-12 12:02:38 -0600611def main(argv):
Dave Houltoncacef472018-05-29 13:00:42 -0600612 global verbose_mode
613 global txt_filename
614 global csv_filename
615 global html_filename
616
617 run_consistency = False
618 report_unimplemented = False
619 get_vuid_status = ''
620 txt_out = False
621 csv_out = False
622 html_out = False
Dave Houlton407df732018-08-06 17:58:24 -0600623 header_out = False
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700624
Dave Houltoncacef472018-05-29 13:00:42 -0600625 if (1 > len(argv)):
626 printHelp()
627 sys.exit()
628
629 # Parse script args
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700630 json_filename = argv[0]
Dave Houltoncacef472018-05-29 13:00:42 -0600631 i = 1
632 while (i < len(argv)):
633 arg = argv[i]
634 i = i + 1
635 if (arg == '-c'):
636 run_consistency = True
637 elif (arg == '-vuid'):
638 get_vuid_status = argv[i]
639 i = i + 1
640 elif (arg == '-todo'):
641 report_unimplemented = True
Karl Schultz49d66bb2018-07-09 16:24:46 -0600642 elif (arg == '-text'):
Dave Houltoncacef472018-05-29 13:00:42 -0600643 txt_out = True
644 # Set filename if supplied, else use default
645 if i < len(argv) and not argv[i].startswith('-'):
646 txt_filename = argv[i]
647 i = i + 1
648 elif (arg == '-csv'):
649 csv_out = True
650 # Set filename if supplied, else use default
651 if i < len(argv) and not argv[i].startswith('-'):
652 csv_filename = argv[i]
653 i = i + 1
654 elif (arg == '-html'):
655 html_out = True
656 # Set filename if supplied, else use default
657 if i < len(argv) and not argv[i].startswith('-'):
658 html_filename = argv[i]
659 i = i + 1
Dave Houlton407df732018-08-06 17:58:24 -0600660 elif (arg == '-export_header'):
661 header_out = True
Dave Houltoncacef472018-05-29 13:00:42 -0600662 elif (arg in ['-verbose']):
663 verbose_mode = True
664 elif (arg in ['-help', '-h']):
665 printHelp()
666 sys.exit()
667 else:
668 print("Unrecognized argument: %s\n" % arg)
669 printHelp()
670 sys.exit()
671
Tobin Ehlis20e32582016-12-05 14:50:03 -0700672 result = 0 # Non-zero result indicates an error case
Dave Houltoncacef472018-05-29 13:00:42 -0600673
674 # Parse validusage json
675 val_json = ValidationJSON(json_filename)
676 val_json.read()
677 exp_json = len(val_json.explicit_vuids)
678 imp_json = len(val_json.implicit_vuids)
679 all_json = len(val_json.all_vuids)
680 if verbose_mode:
681 print("Found %d unique error vuids in validusage.json file." % all_json)
682 print(" %d explicit" % exp_json)
683 print(" %d implicit" % imp_json)
684 if len(val_json.duplicate_vuids) > 0:
685 print("%d VUIDs appear in validusage.json more than once." % len(val_json.duplicate_vuids))
686 for vuid in val_json.duplicate_vuids:
687 print(" %s" % vuid)
688 for ext in val_json.vuid_db[vuid]:
689 print(" with extension: %s" % ext['ext'])
690
691 # Parse layer source files
Mark Lobodzinski05849f02017-06-21 14:44:14 -0600692 val_source = ValidationSource(layer_source_files, generated_layer_source_files, generated_layer_source_directories)
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600693 val_source.parse()
Dave Houltoncacef472018-05-29 13:00:42 -0600694 exp_checks = len(val_source.explicit_vuids)
695 imp_checks = len(val_source.implicit_vuids)
696 all_checks = len(val_source.vuid_count_dict.keys())
697 if verbose_mode:
698 print("Found %d unique vuid checks in layer source code." % all_checks)
699 print(" %d explicit" % exp_checks)
700 print(" %d implicit" % imp_checks)
701 print(" %d unassigned" % len(val_source.unassigned_vuids))
702 print(" %d checks are implemented more that once" % val_source.duplicated_checks)
703
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600704 # Parse test files
Dave Houltoncacef472018-05-29 13:00:42 -0600705 val_tests = ValidationTests([test_file, ])
706 val_tests.parse()
707 exp_tests = len(val_tests.explicit_vuids)
708 imp_tests = len(val_tests.implicit_vuids)
709 all_tests = len(val_tests.all_vuids)
Mark Lobodzinski060a8e32018-01-08 09:08:06 -0700710 if verbose_mode:
Dave Houltoncacef472018-05-29 13:00:42 -0600711 print("Found %d unique error vuids in test file %s." % (all_tests, test_file))
712 print(" %d explicit" % exp_tests)
713 print(" %d implicit" % imp_tests)
714 print(" %d unassigned" % len(val_tests.unassigned_vuids))
Mike Weiblenfe186122017-02-03 12:44:53 -0700715
Dave Houltoncacef472018-05-29 13:00:42 -0600716 # Process stats
717 print("\nValidation Statistics (using validusage.json version %s)" % val_json.apiversion)
718 print(" VUIDs defined in JSON file: %04d explicit, %04d implicit, %04d total." % (exp_json, imp_json, all_json))
719 print(" VUIDs checked in layer code: %04d explicit, %04d implicit, %04d total." % (exp_checks, imp_checks, all_checks))
720 print(" VUIDs tested in layer tests: %04d explicit, %04d implicit, %04d total." % (exp_tests, imp_tests, all_tests))
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700721
Dave Houltoncacef472018-05-29 13:00:42 -0600722 print("\nVUID check coverage")
723 print(" Explicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * exp_checks / exp_json), exp_checks, exp_json))
724 print(" Implicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * imp_checks / imp_json), imp_checks, imp_json))
725 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 -0700726
Dave Houltoncacef472018-05-29 13:00:42 -0600727 print("\nVUID test coverage")
728 print(" Explicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * exp_tests / exp_checks), exp_tests, exp_checks))
729 print(" Implicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * imp_tests / imp_checks), imp_tests, imp_checks))
730 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 -0700731
Dave Houltoncacef472018-05-29 13:00:42 -0600732 # Report status of a single VUID
733 if len(get_vuid_status) > 1:
734 print("\n\nChecking status of <%s>" % get_vuid_status);
735 if get_vuid_status not in val_json.all_vuids:
736 print(' Not a valid VUID string.')
737 else:
738 if get_vuid_status in val_source.explicit_vuids:
739 print(' Implemented!')
740 line_list = val_source.vuid_count_dict[get_vuid_status]['file_line']
741 for line in line_list:
742 print(' => %s' % line)
Dave Houltonf93bbab2018-06-26 17:21:12 -0600743 elif get_vuid_status in val_source.implicit_vuids:
744 print(' Implemented! (Implicit)')
745 line_list = val_source.vuid_count_dict[get_vuid_status]['file_line']
746 for line in line_list:
747 print(' => %s' % line)
Tobin Ehlis9a68c982016-12-29 14:51:17 -0700748 else:
Dave Houltoncacef472018-05-29 13:00:42 -0600749 print(' Not implemented.')
Dave Houltonf93bbab2018-06-26 17:21:12 -0600750 if get_vuid_status in val_tests.all_vuids:
Dave Houltoncacef472018-05-29 13:00:42 -0600751 print(' Has a test!')
752 test_list = val_tests.vuid_to_tests[get_vuid_status]
753 for test in test_list:
754 print(' => %s' % test)
755 else:
756 print(' Not tested.')
Mike Weiblenfe186122017-02-03 12:44:53 -0700757
Dave Houltoncacef472018-05-29 13:00:42 -0600758 # Report unimplemented explicit VUIDs
759 if report_unimplemented:
760 unim_explicit = val_json.explicit_vuids - val_source.explicit_vuids
761 print("\n\n%d explicit VUID checks remain unimplemented:" % len(unim_explicit))
762 ulist = list(unim_explicit)
763 ulist.sort()
764 for vuid in ulist:
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700765 print(" => %s" % vuid)
Dave Houltoncacef472018-05-29 13:00:42 -0600766
767 # Consistency tests
768 if run_consistency:
769 print("\n\nRunning consistency tests...")
770 con = Consistency(val_json.all_vuids, val_source.all_vuids, val_tests.all_vuids)
771 ok = con.undef_vuids_in_layer_code()
772 ok &= con.undef_vuids_in_tests()
Mark Lobodzinski02e23172019-03-04 15:27:55 -0700773 ok &= con.vuids_tested_not_checked()
Dave Houltoncacef472018-05-29 13:00:42 -0600774
775 if ok:
776 print(" OK! No inconsistencies found.")
777
778 # Output database in requested format(s)
779 db_out = OutputDatabase(val_json, val_source, val_tests)
780 if txt_out:
781 db_out.dump_txt()
782 if csv_out:
783 db_out.dump_csv()
784 if html_out:
785 db_out.dump_html()
Dave Houlton407df732018-08-06 17:58:24 -0600786 if header_out:
787 db_out.export_header()
Tobin Ehlis20e32582016-12-05 14:50:03 -0700788 return result
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600789
790if __name__ == "__main__":
Mark Lobodzinskib44c54a2017-06-12 12:02:38 -0600791 sys.exit(main(sys.argv[1:]))
Tobin Ehlis35308dd2016-10-31 13:27:36 -0600792