1*b7893ccfSSadaf Ebrahimi#!/usr/bin/env python3 2*b7893ccfSSadaf Ebrahimi# Copyright (c) 2015-2019 The Khronos Group Inc. 3*b7893ccfSSadaf Ebrahimi# Copyright (c) 2015-2019 Valve Corporation 4*b7893ccfSSadaf Ebrahimi# Copyright (c) 2015-2019 LunarG, Inc. 5*b7893ccfSSadaf Ebrahimi# Copyright (c) 2015-2019 Google Inc. 6*b7893ccfSSadaf Ebrahimi# 7*b7893ccfSSadaf Ebrahimi# Licensed under the Apache License, Version 2.0 (the "License"); 8*b7893ccfSSadaf Ebrahimi# you may not use this file except in compliance with the License. 9*b7893ccfSSadaf Ebrahimi# You may obtain a copy of the License at 10*b7893ccfSSadaf Ebrahimi# 11*b7893ccfSSadaf Ebrahimi# http://www.apache.org/licenses/LICENSE-2.0 12*b7893ccfSSadaf Ebrahimi# 13*b7893ccfSSadaf Ebrahimi# Unless required by applicable law or agreed to in writing, software 14*b7893ccfSSadaf Ebrahimi# distributed under the License is distributed on an "AS IS" BASIS, 15*b7893ccfSSadaf Ebrahimi# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16*b7893ccfSSadaf Ebrahimi# See the License for the specific language governing permissions and 17*b7893ccfSSadaf Ebrahimi# limitations under the License. 18*b7893ccfSSadaf Ebrahimi# 19*b7893ccfSSadaf Ebrahimi# Author: Tobin Ehlis <[email protected]> 20*b7893ccfSSadaf Ebrahimi# Author: Dave Houlton <[email protected]> 21*b7893ccfSSadaf Ebrahimi# Author: Shannon McPherson <[email protected]> 22*b7893ccfSSadaf Ebrahimi 23*b7893ccfSSadaf Ebrahimiimport argparse 24*b7893ccfSSadaf Ebrahimiimport common_codegen 25*b7893ccfSSadaf Ebrahimiimport csv 26*b7893ccfSSadaf Ebrahimiimport glob 27*b7893ccfSSadaf Ebrahimiimport html 28*b7893ccfSSadaf Ebrahimiimport json 29*b7893ccfSSadaf Ebrahimiimport operator 30*b7893ccfSSadaf Ebrahimiimport os 31*b7893ccfSSadaf Ebrahimiimport platform 32*b7893ccfSSadaf Ebrahimiimport re 33*b7893ccfSSadaf Ebrahimiimport sys 34*b7893ccfSSadaf Ebrahimiimport time 35*b7893ccfSSadaf Ebrahimifrom collections import defaultdict 36*b7893ccfSSadaf Ebrahimi 37*b7893ccfSSadaf Ebrahimiverbose_mode = False 38*b7893ccfSSadaf Ebrahimitxt_db = False 39*b7893ccfSSadaf Ebrahimicsv_db = False 40*b7893ccfSSadaf Ebrahimihtml_db = False 41*b7893ccfSSadaf Ebrahimitxt_filename = "validation_error_database.txt" 42*b7893ccfSSadaf Ebrahimicsv_filename = "validation_error_database.csv" 43*b7893ccfSSadaf Ebrahimihtml_filename = "validation_error_database.html" 44*b7893ccfSSadaf Ebrahimiheader_filename = "vk_validation_error_messages.h" 45*b7893ccfSSadaf Ebrahimivuid_prefixes = ['VUID-', 'UNASSIGNED-'] 46*b7893ccfSSadaf Ebrahimi 47*b7893ccfSSadaf Ebrahimi# Hard-coded flags that could be command line args, if we decide that's useful 48*b7893ccfSSadaf Ebrahimi# replace KHR vuids with non-KHR during consistency checking 49*b7893ccfSSadaf Ebrahimidealias_khr = True 50*b7893ccfSSadaf Ebrahimiignore_unassigned = True # These are not found in layer code unless they appear explicitly (most don't), so produce false positives 51*b7893ccfSSadaf Ebrahimi 52*b7893ccfSSadaf Ebrahimilayer_source_files = [common_codegen.repo_relative(path) for path in [ 53*b7893ccfSSadaf Ebrahimi 'layers/buffer_validation.cpp', 54*b7893ccfSSadaf Ebrahimi 'layers/core_validation.cpp', 55*b7893ccfSSadaf Ebrahimi 'layers/descriptor_sets.cpp', 56*b7893ccfSSadaf Ebrahimi 'layers/drawdispatch.cpp', 57*b7893ccfSSadaf Ebrahimi 'layers/parameter_validation_utils.cpp', 58*b7893ccfSSadaf Ebrahimi 'layers/object_tracker_utils.cpp', 59*b7893ccfSSadaf Ebrahimi 'layers/shader_validation.cpp', 60*b7893ccfSSadaf Ebrahimi 'layers/stateless_validation.h', 61*b7893ccfSSadaf Ebrahimi 'layers/generated/parameter_validation.cpp', 62*b7893ccfSSadaf Ebrahimi 'layers/generated/object_tracker.cpp', 63*b7893ccfSSadaf Ebrahimi]] 64*b7893ccfSSadaf Ebrahimi 65*b7893ccfSSadaf Ebrahimitest_source_files = glob.glob(os.path.join(common_codegen.repo_relative('tests'), '*.cpp')) 66*b7893ccfSSadaf Ebrahimi 67*b7893ccfSSadaf Ebrahimi# This needs to be updated as new extensions roll in 68*b7893ccfSSadaf Ebrahimikhr_aliases = { 69*b7893ccfSSadaf Ebrahimi 'VUID-vkBindBufferMemory2KHR-device-parameter' : 'VUID-vkBindBufferMemory2-device-parameter', 70*b7893ccfSSadaf Ebrahimi 'VUID-vkBindBufferMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindBufferMemory2-pBindInfos-parameter', 71*b7893ccfSSadaf Ebrahimi 'VUID-vkBindImageMemory2KHR-device-parameter' : 'VUID-vkBindImageMemory2-device-parameter', 72*b7893ccfSSadaf Ebrahimi 'VUID-vkBindImageMemory2KHR-pBindInfos-parameter' : 'VUID-vkBindImageMemory2-pBindInfos-parameter', 73*b7893ccfSSadaf Ebrahimi 'VUID-vkCmdDispatchBaseKHR-commandBuffer-parameter' : 'VUID-vkCmdDispatchBase-commandBuffer-parameter', 74*b7893ccfSSadaf Ebrahimi 'VUID-vkCmdSetDeviceMaskKHR-commandBuffer-parameter' : 'VUID-vkCmdSetDeviceMask-commandBuffer-parameter', 75*b7893ccfSSadaf Ebrahimi 'VUID-vkCreateDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-device-parameter', 76*b7893ccfSSadaf Ebrahimi 'VUID-vkCreateDescriptorUpdateTemplateKHR-pDescriptorUpdateTemplate-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pDescriptorUpdateTemplate-parameter', 77*b7893ccfSSadaf Ebrahimi 'VUID-vkCreateSamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-device-parameter', 78*b7893ccfSSadaf Ebrahimi 'VUID-vkCreateSamplerYcbcrConversionKHR-pYcbcrConversion-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pYcbcrConversion-parameter', 79*b7893ccfSSadaf Ebrahimi 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parameter', 80*b7893ccfSSadaf Ebrahimi 'VUID-vkDestroyDescriptorUpdateTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkDestroyDescriptorUpdateTemplate-descriptorUpdateTemplate-parent', 81*b7893ccfSSadaf Ebrahimi 'VUID-vkDestroyDescriptorUpdateTemplateKHR-device-parameter' : 'VUID-vkDestroyDescriptorUpdateTemplate-device-parameter', 82*b7893ccfSSadaf Ebrahimi 'VUID-vkDestroySamplerYcbcrConversionKHR-device-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-device-parameter', 83*b7893ccfSSadaf Ebrahimi 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parameter' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parameter', 84*b7893ccfSSadaf Ebrahimi 'VUID-vkDestroySamplerYcbcrConversionKHR-ycbcrConversion-parent' : 'VUID-vkDestroySamplerYcbcrConversion-ycbcrConversion-parent', 85*b7893ccfSSadaf Ebrahimi 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-instance-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-instance-parameter', 86*b7893ccfSSadaf Ebrahimi 'VUID-vkEnumeratePhysicalDeviceGroupsKHR-pPhysicalDeviceGroupProperties-parameter' : 'VUID-vkEnumeratePhysicalDeviceGroups-pPhysicalDeviceGroupProperties-parameter', 87*b7893ccfSSadaf Ebrahimi 'VUID-vkGetBufferMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetBufferMemoryRequirements2-device-parameter', 88*b7893ccfSSadaf Ebrahimi 'VUID-vkGetDescriptorSetLayoutSupportKHR-device-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-device-parameter', 89*b7893ccfSSadaf Ebrahimi 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-device-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-device-parameter', 90*b7893ccfSSadaf Ebrahimi 'VUID-vkGetDeviceGroupPeerMemoryFeaturesKHR-pPeerMemoryFeatures-parameter' : 'VUID-vkGetDeviceGroupPeerMemoryFeatures-pPeerMemoryFeatures-parameter', 91*b7893ccfSSadaf Ebrahimi 'VUID-vkGetImageMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageMemoryRequirements2-device-parameter', 92*b7893ccfSSadaf Ebrahimi 'VUID-vkGetImageSparseMemoryRequirements2KHR-device-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-device-parameter', 93*b7893ccfSSadaf Ebrahimi 'VUID-vkGetImageSparseMemoryRequirements2KHR-pSparseMemoryRequirements-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pSparseMemoryRequirements-parameter', 94*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-physicalDevice-parameter', 95*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-physicalDevice-parameter', 96*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-physicalDevice-parameter', 97*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceFeatures2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-physicalDevice-parameter', 98*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-format-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-format-parameter', 99*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-physicalDevice-parameter', 100*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-physicalDevice-parameter', 101*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-physicalDevice-parameter', 102*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-physicalDevice-parameter', 103*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2KHR-pQueueFamilyProperties-parameter' : 'VUID-vkGetPhysicalDeviceQueueFamilyProperties2-pQueueFamilyProperties-parameter', 104*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pProperties-parameter', 105*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-physicalDevice-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-physicalDevice-parameter', 106*b7893ccfSSadaf Ebrahimi 'VUID-vkTrimCommandPoolKHR-commandPool-parameter' : 'VUID-vkTrimCommandPool-commandPool-parameter', 107*b7893ccfSSadaf Ebrahimi 'VUID-vkTrimCommandPoolKHR-commandPool-parent' : 'VUID-vkTrimCommandPool-commandPool-parent', 108*b7893ccfSSadaf Ebrahimi 'VUID-vkTrimCommandPoolKHR-device-parameter' : 'VUID-vkTrimCommandPool-device-parameter', 109*b7893ccfSSadaf Ebrahimi 'VUID-vkTrimCommandPoolKHR-flags-zerobitmask' : 'VUID-vkTrimCommandPool-flags-zerobitmask', 110*b7893ccfSSadaf Ebrahimi 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorSet-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorSet-parameter', 111*b7893ccfSSadaf Ebrahimi 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parameter', 112*b7893ccfSSadaf Ebrahimi 'VUID-vkUpdateDescriptorSetWithTemplateKHR-descriptorUpdateTemplate-parent' : 'VUID-vkUpdateDescriptorSetWithTemplate-descriptorUpdateTemplate-parent', 113*b7893ccfSSadaf Ebrahimi 'VUID-vkUpdateDescriptorSetWithTemplateKHR-device-parameter' : 'VUID-vkUpdateDescriptorSetWithTemplate-device-parameter', 114*b7893ccfSSadaf Ebrahimi 'VUID-vkCreateDescriptorUpdateTemplateKHR-pCreateInfo-parameter' : 'VUID-vkCreateDescriptorUpdateTemplate-pCreateInfo-parameter', 115*b7893ccfSSadaf Ebrahimi 'VUID-vkCreateSamplerYcbcrConversionKHR-pCreateInfo-parameter' : 'VUID-vkCreateSamplerYcbcrConversion-pCreateInfo-parameter', 116*b7893ccfSSadaf Ebrahimi 'VUID-vkGetBufferMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pInfo-parameter', 117*b7893ccfSSadaf Ebrahimi 'VUID-vkGetBufferMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetBufferMemoryRequirements2-pMemoryRequirements-parameter', 118*b7893ccfSSadaf Ebrahimi 'VUID-vkGetDescriptorSetLayoutSupportKHR-pCreateInfo-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pCreateInfo-parameter', 119*b7893ccfSSadaf Ebrahimi 'VUID-vkGetDescriptorSetLayoutSupportKHR-pSupport-parameter' : 'VUID-vkGetDescriptorSetLayoutSupport-pSupport-parameter', 120*b7893ccfSSadaf Ebrahimi 'VUID-vkGetImageMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageMemoryRequirements2-pInfo-parameter', 121*b7893ccfSSadaf Ebrahimi 'VUID-vkGetImageMemoryRequirements2KHR-pMemoryRequirements-parameter' : 'VUID-vkGetImageMemoryRequirements2-pMemoryRequirements-parameter', 122*b7893ccfSSadaf Ebrahimi 'VUID-vkGetImageSparseMemoryRequirements2KHR-pInfo-parameter' : 'VUID-vkGetImageSparseMemoryRequirements2-pInfo-parameter', 123*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferInfo-parameter', 124*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceExternalBufferPropertiesKHR-pExternalBufferProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalBufferProperties-pExternalBufferProperties-parameter', 125*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceInfo-parameter', 126*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceExternalFencePropertiesKHR-pExternalFenceProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalFenceProperties-pExternalFenceProperties-parameter', 127*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreInfo-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreInfo-parameter', 128*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceExternalSemaphorePropertiesKHR-pExternalSemaphoreProperties-parameter' : 'VUID-vkGetPhysicalDeviceExternalSemaphoreProperties-pExternalSemaphoreProperties-parameter', 129*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceFeatures2KHR-pFeatures-parameter' : 'VUID-vkGetPhysicalDeviceFeatures2-pFeatures-parameter', 130*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceFormatProperties2KHR-pFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceFormatProperties2-pFormatProperties-parameter', 131*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatInfo-parameter', 132*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceImageFormatProperties2KHR-pImageFormatProperties-parameter' : 'VUID-vkGetPhysicalDeviceImageFormatProperties2-pImageFormatProperties-parameter', 133*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceMemoryProperties2KHR-pMemoryProperties-parameter' : 'VUID-vkGetPhysicalDeviceMemoryProperties2-pMemoryProperties-parameter', 134*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceProperties2KHR-pProperties-parameter' : 'VUID-vkGetPhysicalDeviceProperties2-pProperties-parameter', 135*b7893ccfSSadaf Ebrahimi 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2KHR-pFormatInfo-parameter' : 'VUID-vkGetPhysicalDeviceSparseImageFormatProperties2-pFormatInfo-parameter' } 136*b7893ccfSSadaf Ebrahimi 137*b7893ccfSSadaf Ebrahimidef printHelp(): 138*b7893ccfSSadaf Ebrahimi print ("Usage:") 139*b7893ccfSSadaf Ebrahimi print (" python vk_validation_stats.py <json_file>") 140*b7893ccfSSadaf Ebrahimi print (" [ -c ]") 141*b7893ccfSSadaf Ebrahimi print (" [ -todo ]") 142*b7893ccfSSadaf Ebrahimi print (" [ -vuid <vuid_name> ]") 143*b7893ccfSSadaf Ebrahimi print (" [ -text [ <text_out_filename>] ]") 144*b7893ccfSSadaf Ebrahimi print (" [ -csv [ <csv_out_filename>] ]") 145*b7893ccfSSadaf Ebrahimi print (" [ -html [ <html_out_filename>] ]") 146*b7893ccfSSadaf Ebrahimi print (" [ -export_header ]") 147*b7893ccfSSadaf Ebrahimi print (" [ -summary ]") 148*b7893ccfSSadaf Ebrahimi print (" [ -verbose ]") 149*b7893ccfSSadaf Ebrahimi print (" [ -help ]") 150*b7893ccfSSadaf Ebrahimi print ("\n The vk_validation_stats script parses validation layer source files to") 151*b7893ccfSSadaf Ebrahimi print (" determine the set of valid usage checks and tests currently implemented,") 152*b7893ccfSSadaf Ebrahimi print (" and generates coverage values by comparing against the full set of valid") 153*b7893ccfSSadaf Ebrahimi print (" usage identifiers in the Vulkan-Headers registry file 'validusage.json'") 154*b7893ccfSSadaf Ebrahimi print ("\nArguments: ") 155*b7893ccfSSadaf Ebrahimi print (" <json-file> (required) registry file 'validusage.json'") 156*b7893ccfSSadaf Ebrahimi print (" -c report consistency warnings") 157*b7893ccfSSadaf Ebrahimi print (" -todo report unimplemented VUIDs") 158*b7893ccfSSadaf Ebrahimi print (" -vuid <vuid_name> report status of individual VUID <vuid_name>") 159*b7893ccfSSadaf Ebrahimi print (" -text [filename] output the error database text to <text_database_filename>,") 160*b7893ccfSSadaf Ebrahimi print (" defaults to 'validation_error_database.txt'") 161*b7893ccfSSadaf Ebrahimi print (" -csv [filename] output the error database in csv to <csv_database_filename>,") 162*b7893ccfSSadaf Ebrahimi print (" defaults to 'validation_error_database.csv'") 163*b7893ccfSSadaf Ebrahimi print (" -html [filename] output the error database in html to <html_database_filename>,") 164*b7893ccfSSadaf Ebrahimi print (" defaults to 'validation_error_database.html'") 165*b7893ccfSSadaf Ebrahimi print (" -export_header export a new VUID error text header file to <%s>" % header_filename) 166*b7893ccfSSadaf Ebrahimi print (" -summary output summary of VUID coverage") 167*b7893ccfSSadaf Ebrahimi print (" -verbose show your work (to stdout)") 168*b7893ccfSSadaf Ebrahimi 169*b7893ccfSSadaf Ebrahimiclass ValidationJSON: 170*b7893ccfSSadaf Ebrahimi def __init__(self, filename): 171*b7893ccfSSadaf Ebrahimi self.filename = filename 172*b7893ccfSSadaf Ebrahimi self.explicit_vuids = set() 173*b7893ccfSSadaf Ebrahimi self.implicit_vuids = set() 174*b7893ccfSSadaf Ebrahimi self.all_vuids = set() 175*b7893ccfSSadaf Ebrahimi self.vuid_db = defaultdict(list) # Maps VUID string to list of json-data dicts 176*b7893ccfSSadaf Ebrahimi self.apiversion = "" 177*b7893ccfSSadaf Ebrahimi self.duplicate_vuids = set() 178*b7893ccfSSadaf Ebrahimi 179*b7893ccfSSadaf Ebrahimi # A set of specific regular expression substitutions needed to clean up VUID text 180*b7893ccfSSadaf Ebrahimi self.regex_dict = {} 181*b7893ccfSSadaf Ebrahimi self.regex_dict[re.compile('<.*?>|&(amp;)+lt;|&(amp;)+gt;')] = "" 182*b7893ccfSSadaf Ebrahimi self.regex_dict[re.compile(r'\\\(codeSize \\over 4\\\)')] = "(codeSize/4)" 183*b7893ccfSSadaf Ebrahimi self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{height}{maxFragmentDensityTexelSize_{height}}}\\rceil\\\)')] = "the ceiling of height/maxFragmentDensityTexelSize.height" 184*b7893ccfSSadaf Ebrahimi self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{width}{maxFragmentDensityTexelSize_{width}}}\\rceil\\\)')] = "the ceiling of width/maxFragmentDensityTexelSize.width" 185*b7893ccfSSadaf Ebrahimi self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{maxFramebufferHeight}{minFragmentDensityTexelSize_{height}}}\\rceil\\\)')] = "the ceiling of maxFramebufferHeight/minFragmentDensityTexelSize.height" 186*b7893ccfSSadaf Ebrahimi self.regex_dict[re.compile(r'\\\(\\lceil{\\frac{maxFramebufferWidth}{minFragmentDensityTexelSize_{width}}}\\rceil\\\)')] = "the ceiling of maxFramebufferWidth/minFragmentDensityTexelSize.width" 187*b7893ccfSSadaf Ebrahimi self.regex_dict[re.compile(r'\\\(\\lceil\{\\mathit\{rasterizationSamples} \\over 32}\\rceil\\\)')] = "(rasterizationSamples/32)" 188*b7893ccfSSadaf Ebrahimi self.regex_dict[re.compile(r'\\\(\\textrm\{codeSize} \\over 4\\\)')] = "(codeSize/4)" 189*b7893ccfSSadaf Ebrahimi # Some fancy punctuation chars that break the Android build... 190*b7893ccfSSadaf Ebrahimi self.regex_dict[re.compile('→')] = "->" # Arrow char 191*b7893ccfSSadaf Ebrahimi self.regex_dict[re.compile('’')] = "'" # Left-slanting apostrophe to apostrophe 192*b7893ccfSSadaf Ebrahimi self.regex_dict[re.compile('̶(0|1);')] = "'" # L/R-slanting quotes to apostrophe 193*b7893ccfSSadaf Ebrahimi 194*b7893ccfSSadaf Ebrahimi def read(self): 195*b7893ccfSSadaf Ebrahimi self.json_dict = {} 196*b7893ccfSSadaf Ebrahimi if os.path.isfile(self.filename): 197*b7893ccfSSadaf Ebrahimi json_file = open(self.filename, 'r', encoding='utf-8') 198*b7893ccfSSadaf Ebrahimi self.json_dict = json.load(json_file) 199*b7893ccfSSadaf Ebrahimi json_file.close() 200*b7893ccfSSadaf Ebrahimi if len(self.json_dict) == 0: 201*b7893ccfSSadaf Ebrahimi print("Error: Error loading validusage.json file <%s>" % self.filename) 202*b7893ccfSSadaf Ebrahimi sys.exit(-1) 203*b7893ccfSSadaf Ebrahimi try: 204*b7893ccfSSadaf Ebrahimi version = self.json_dict['version info'] 205*b7893ccfSSadaf Ebrahimi validation = self.json_dict['validation'] 206*b7893ccfSSadaf Ebrahimi self.apiversion = version['api version'] 207*b7893ccfSSadaf Ebrahimi except: 208*b7893ccfSSadaf Ebrahimi print("Error: Failure parsing validusage.json object") 209*b7893ccfSSadaf Ebrahimi sys.exit(-1) 210*b7893ccfSSadaf Ebrahimi 211*b7893ccfSSadaf Ebrahimi # Parse vuid from json into local databases 212*b7893ccfSSadaf Ebrahimi for apiname in validation.keys(): 213*b7893ccfSSadaf Ebrahimi # print("entrypoint:%s"%apiname) 214*b7893ccfSSadaf Ebrahimi apidict = validation[apiname] 215*b7893ccfSSadaf Ebrahimi for ext in apidict.keys(): 216*b7893ccfSSadaf Ebrahimi vlist = apidict[ext] 217*b7893ccfSSadaf Ebrahimi for ventry in vlist: 218*b7893ccfSSadaf Ebrahimi vuid_string = ventry['vuid'] 219*b7893ccfSSadaf Ebrahimi if (vuid_string[-5:-1].isdecimal()): 220*b7893ccfSSadaf Ebrahimi self.explicit_vuids.add(vuid_string) # explicit end in 5 numeric chars 221*b7893ccfSSadaf Ebrahimi vtype = 'explicit' 222*b7893ccfSSadaf Ebrahimi else: 223*b7893ccfSSadaf Ebrahimi self.implicit_vuids.add(vuid_string) # otherwise, implicit 224*b7893ccfSSadaf Ebrahimi vtype = 'implicit' 225*b7893ccfSSadaf Ebrahimi vuid_text = ventry['text'] 226*b7893ccfSSadaf Ebrahimi for regex, replacement in self.regex_dict.items(): 227*b7893ccfSSadaf Ebrahimi vuid_text = re.sub(regex, replacement, vuid_text) # do regex substitution 228*b7893ccfSSadaf Ebrahimi vuid_text = html.unescape(vuid_text) # anything missed by the regex 229*b7893ccfSSadaf Ebrahimi self.vuid_db[vuid_string].append({'api':apiname, 'ext':ext, 'type':vtype, 'text':vuid_text}) 230*b7893ccfSSadaf Ebrahimi self.all_vuids = self.explicit_vuids | self.implicit_vuids 231*b7893ccfSSadaf Ebrahimi self.duplicate_vuids = set({v for v in self.vuid_db if len(self.vuid_db[v]) > 1}) 232*b7893ccfSSadaf Ebrahimi if len(self.duplicate_vuids) > 0: 233*b7893ccfSSadaf Ebrahimi print("Warning: duplicate VUIDs found in validusage.json") 234*b7893ccfSSadaf Ebrahimi 235*b7893ccfSSadaf Ebrahimi 236*b7893ccfSSadaf Ebrahimiclass ValidationSource: 237*b7893ccfSSadaf Ebrahimi def __init__(self, source_file_list): 238*b7893ccfSSadaf Ebrahimi self.source_files = source_file_list 239*b7893ccfSSadaf Ebrahimi self.vuid_count_dict = {} # dict of vuid values to the count of how much they're used, and location of where they're used 240*b7893ccfSSadaf Ebrahimi self.duplicated_checks = 0 241*b7893ccfSSadaf Ebrahimi self.explicit_vuids = set() 242*b7893ccfSSadaf Ebrahimi self.implicit_vuids = set() 243*b7893ccfSSadaf Ebrahimi self.unassigned_vuids = set() 244*b7893ccfSSadaf Ebrahimi self.all_vuids = set() 245*b7893ccfSSadaf Ebrahimi 246*b7893ccfSSadaf Ebrahimi def parse(self): 247*b7893ccfSSadaf Ebrahimi prepend = None 248*b7893ccfSSadaf Ebrahimi for sf in self.source_files: 249*b7893ccfSSadaf Ebrahimi line_num = 0 250*b7893ccfSSadaf Ebrahimi with open(sf) as f: 251*b7893ccfSSadaf Ebrahimi for line in f: 252*b7893ccfSSadaf Ebrahimi line_num = line_num + 1 253*b7893ccfSSadaf Ebrahimi if True in [line.strip().startswith(comment) for comment in ['//', '/*']]: 254*b7893ccfSSadaf Ebrahimi continue 255*b7893ccfSSadaf Ebrahimi # Find vuid strings 256*b7893ccfSSadaf Ebrahimi if prepend is not None: 257*b7893ccfSSadaf Ebrahimi line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char 258*b7893ccfSSadaf Ebrahimi prepend = None 259*b7893ccfSSadaf Ebrahimi if any(prefix in line for prefix in vuid_prefixes): 260*b7893ccfSSadaf Ebrahimi # Replace the '(' of lines containing validation helper functions with ' ' to make them easier to parse 261*b7893ccfSSadaf Ebrahimi line = line.replace("(", " ") 262*b7893ccfSSadaf Ebrahimi line_list = line.split() 263*b7893ccfSSadaf Ebrahimi 264*b7893ccfSSadaf Ebrahimi # 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 265*b7893ccfSSadaf Ebrahimi broken_vuid = line_list[-1].strip('"') 266*b7893ccfSSadaf Ebrahimi if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'): 267*b7893ccfSSadaf Ebrahimi prepend = line 268*b7893ccfSSadaf Ebrahimi continue 269*b7893ccfSSadaf Ebrahimi 270*b7893ccfSSadaf Ebrahimi vuid_list = [] 271*b7893ccfSSadaf Ebrahimi for str in line_list: 272*b7893ccfSSadaf Ebrahimi if any(prefix in str for prefix in vuid_prefixes): 273*b7893ccfSSadaf Ebrahimi vuid_list.append(str.strip(',);{}"')) 274*b7893ccfSSadaf Ebrahimi for vuid in vuid_list: 275*b7893ccfSSadaf Ebrahimi if vuid not in self.vuid_count_dict: 276*b7893ccfSSadaf Ebrahimi self.vuid_count_dict[vuid] = {} 277*b7893ccfSSadaf Ebrahimi self.vuid_count_dict[vuid]['count'] = 1 278*b7893ccfSSadaf Ebrahimi self.vuid_count_dict[vuid]['file_line'] = [] 279*b7893ccfSSadaf Ebrahimi else: 280*b7893ccfSSadaf Ebrahimi if self.vuid_count_dict[vuid]['count'] == 1: # only count first time duplicated 281*b7893ccfSSadaf Ebrahimi self.duplicated_checks = self.duplicated_checks + 1 282*b7893ccfSSadaf Ebrahimi self.vuid_count_dict[vuid]['count'] = self.vuid_count_dict[vuid]['count'] + 1 283*b7893ccfSSadaf Ebrahimi self.vuid_count_dict[vuid]['file_line'].append('%s,%d' % (sf, line_num)) 284*b7893ccfSSadaf Ebrahimi # Sort vuids by type 285*b7893ccfSSadaf Ebrahimi for vuid in self.vuid_count_dict.keys(): 286*b7893ccfSSadaf Ebrahimi if (vuid.startswith('VUID-')): 287*b7893ccfSSadaf Ebrahimi if (vuid[-5:-1].isdecimal()): 288*b7893ccfSSadaf Ebrahimi self.explicit_vuids.add(vuid) # explicit end in 5 numeric chars 289*b7893ccfSSadaf Ebrahimi else: 290*b7893ccfSSadaf Ebrahimi self.implicit_vuids.add(vuid) 291*b7893ccfSSadaf Ebrahimi elif (vuid.startswith('UNASSIGNED-')): 292*b7893ccfSSadaf Ebrahimi self.unassigned_vuids.add(vuid) 293*b7893ccfSSadaf Ebrahimi else: 294*b7893ccfSSadaf Ebrahimi print("Unable to categorize VUID: %s" % vuid) 295*b7893ccfSSadaf Ebrahimi print("Confused while parsing VUIDs in layer source code - cannot proceed. (FIXME)") 296*b7893ccfSSadaf Ebrahimi exit(-1) 297*b7893ccfSSadaf Ebrahimi self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids 298*b7893ccfSSadaf Ebrahimi 299*b7893ccfSSadaf Ebrahimi# Class to parse the validation layer test source and store testnames 300*b7893ccfSSadaf Ebrahimiclass ValidationTests: 301*b7893ccfSSadaf Ebrahimi def __init__(self, test_file_list, test_group_name=['VkLayerTest', 'VkPositiveLayerTest', 'VkWsiEnabledLayerTest']): 302*b7893ccfSSadaf Ebrahimi self.test_files = test_file_list 303*b7893ccfSSadaf Ebrahimi self.test_trigger_txt_list = [] 304*b7893ccfSSadaf Ebrahimi for tg in test_group_name: 305*b7893ccfSSadaf Ebrahimi self.test_trigger_txt_list.append('TEST_F(%s' % tg) 306*b7893ccfSSadaf Ebrahimi self.explicit_vuids = set() 307*b7893ccfSSadaf Ebrahimi self.implicit_vuids = set() 308*b7893ccfSSadaf Ebrahimi self.unassigned_vuids = set() 309*b7893ccfSSadaf Ebrahimi self.all_vuids = set() 310*b7893ccfSSadaf Ebrahimi #self.test_to_vuids = {} # Map test name to VUIDs tested 311*b7893ccfSSadaf Ebrahimi self.vuid_to_tests = defaultdict(set) # Map VUIDs to set of test names where implemented 312*b7893ccfSSadaf Ebrahimi 313*b7893ccfSSadaf Ebrahimi # Parse test files into internal data struct 314*b7893ccfSSadaf Ebrahimi def parse(self): 315*b7893ccfSSadaf Ebrahimi # For each test file, parse test names into set 316*b7893ccfSSadaf Ebrahimi grab_next_line = False # handle testname on separate line than wildcard 317*b7893ccfSSadaf Ebrahimi testname = '' 318*b7893ccfSSadaf Ebrahimi prepend = None 319*b7893ccfSSadaf Ebrahimi for test_file in self.test_files: 320*b7893ccfSSadaf Ebrahimi with open(test_file) as tf: 321*b7893ccfSSadaf Ebrahimi for line in tf: 322*b7893ccfSSadaf Ebrahimi if True in [line.strip().startswith(comment) for comment in ['//', '/*']]: 323*b7893ccfSSadaf Ebrahimi continue 324*b7893ccfSSadaf Ebrahimi 325*b7893ccfSSadaf Ebrahimi # if line ends in a broken VUID string, fix that before proceeding 326*b7893ccfSSadaf Ebrahimi if prepend is not None: 327*b7893ccfSSadaf Ebrahimi line = prepend[:-2] + line.lstrip().lstrip('"') # join lines skipping CR, whitespace and trailing/leading quote char 328*b7893ccfSSadaf Ebrahimi prepend = None 329*b7893ccfSSadaf Ebrahimi if any(prefix in line for prefix in vuid_prefixes): 330*b7893ccfSSadaf Ebrahimi line_list = line.split() 331*b7893ccfSSadaf Ebrahimi 332*b7893ccfSSadaf Ebrahimi # 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 333*b7893ccfSSadaf Ebrahimi broken_vuid = line_list[-1].strip('"') 334*b7893ccfSSadaf Ebrahimi if any(broken_vuid.startswith(prefix) for prefix in vuid_prefixes) and broken_vuid.endswith('-'): 335*b7893ccfSSadaf Ebrahimi prepend = line 336*b7893ccfSSadaf Ebrahimi continue 337*b7893ccfSSadaf Ebrahimi 338*b7893ccfSSadaf Ebrahimi if any(ttt in line for ttt in self.test_trigger_txt_list): 339*b7893ccfSSadaf Ebrahimi testname = line.split(',')[-1] 340*b7893ccfSSadaf Ebrahimi testname = testname.strip().strip(' {)') 341*b7893ccfSSadaf Ebrahimi if ('' == testname): 342*b7893ccfSSadaf Ebrahimi grab_next_line = True 343*b7893ccfSSadaf Ebrahimi continue 344*b7893ccfSSadaf Ebrahimi #self.test_to_vuids[testname] = [] 345*b7893ccfSSadaf Ebrahimi if grab_next_line: # test name on its own line 346*b7893ccfSSadaf Ebrahimi grab_next_line = False 347*b7893ccfSSadaf Ebrahimi testname = testname.strip().strip(' {)') 348*b7893ccfSSadaf Ebrahimi #self.test_to_vuids[testname] = [] 349*b7893ccfSSadaf Ebrahimi if any(prefix in line for prefix in vuid_prefixes): 350*b7893ccfSSadaf Ebrahimi line_list = re.split('[\s{}[\]()"]+',line) 351*b7893ccfSSadaf Ebrahimi for sub_str in line_list: 352*b7893ccfSSadaf Ebrahimi if any(prefix in sub_str for prefix in vuid_prefixes): 353*b7893ccfSSadaf Ebrahimi vuid_str = sub_str.strip(',);:"') 354*b7893ccfSSadaf Ebrahimi self.vuid_to_tests[vuid_str].add(testname) 355*b7893ccfSSadaf Ebrahimi #self.test_to_vuids[testname].append(vuid_str) 356*b7893ccfSSadaf Ebrahimi if (vuid_str.startswith('VUID-')): 357*b7893ccfSSadaf Ebrahimi if (vuid_str[-5:-1].isdecimal()): 358*b7893ccfSSadaf Ebrahimi self.explicit_vuids.add(vuid_str) # explicit end in 5 numeric chars 359*b7893ccfSSadaf Ebrahimi else: 360*b7893ccfSSadaf Ebrahimi self.implicit_vuids.add(vuid_str) 361*b7893ccfSSadaf Ebrahimi elif (vuid_str.startswith('UNASSIGNED-')): 362*b7893ccfSSadaf Ebrahimi self.unassigned_vuids.add(vuid_str) 363*b7893ccfSSadaf Ebrahimi else: 364*b7893ccfSSadaf Ebrahimi print("Unable to categorize VUID: %s" % vuid_str) 365*b7893ccfSSadaf Ebrahimi print("Confused while parsing VUIDs in test code - cannot proceed. (FIXME)") 366*b7893ccfSSadaf Ebrahimi exit(-1) 367*b7893ccfSSadaf Ebrahimi self.all_vuids = self.explicit_vuids | self.implicit_vuids | self.unassigned_vuids 368*b7893ccfSSadaf Ebrahimi 369*b7893ccfSSadaf Ebrahimi# Class to do consistency checking 370*b7893ccfSSadaf Ebrahimi# 371*b7893ccfSSadaf Ebrahimiclass Consistency: 372*b7893ccfSSadaf Ebrahimi def __init__(self, all_json, all_checks, all_tests): 373*b7893ccfSSadaf Ebrahimi self.valid = all_json 374*b7893ccfSSadaf Ebrahimi self.checks = all_checks 375*b7893ccfSSadaf Ebrahimi self.tests = all_tests 376*b7893ccfSSadaf Ebrahimi 377*b7893ccfSSadaf Ebrahimi if (dealias_khr): 378*b7893ccfSSadaf Ebrahimi dk = set() 379*b7893ccfSSadaf Ebrahimi for vuid in self.checks: 380*b7893ccfSSadaf Ebrahimi if vuid in khr_aliases: 381*b7893ccfSSadaf Ebrahimi dk.add(khr_aliases[vuid]) 382*b7893ccfSSadaf Ebrahimi else: 383*b7893ccfSSadaf Ebrahimi dk.add(vuid) 384*b7893ccfSSadaf Ebrahimi self.checks = dk 385*b7893ccfSSadaf Ebrahimi 386*b7893ccfSSadaf Ebrahimi dk = set() 387*b7893ccfSSadaf Ebrahimi for vuid in self.tests: 388*b7893ccfSSadaf Ebrahimi if vuid in khr_aliases: 389*b7893ccfSSadaf Ebrahimi dk.add(khr_aliases[vuid]) 390*b7893ccfSSadaf Ebrahimi else: 391*b7893ccfSSadaf Ebrahimi dk.add(vuid) 392*b7893ccfSSadaf Ebrahimi self.tests = dk 393*b7893ccfSSadaf Ebrahimi 394*b7893ccfSSadaf Ebrahimi # Report undefined VUIDs in source code 395*b7893ccfSSadaf Ebrahimi def undef_vuids_in_layer_code(self): 396*b7893ccfSSadaf Ebrahimi undef_set = self.checks - self.valid 397*b7893ccfSSadaf Ebrahimi undef_set.discard('VUID-Undefined') # don't report Undefined 398*b7893ccfSSadaf Ebrahimi if ignore_unassigned: 399*b7893ccfSSadaf Ebrahimi unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')}) 400*b7893ccfSSadaf Ebrahimi undef_set = undef_set - unassigned 401*b7893ccfSSadaf Ebrahimi if (len(undef_set) > 0): 402*b7893ccfSSadaf Ebrahimi print("\nFollowing VUIDs found in layer code are not defined in validusage.json (%d):" % len(undef_set)) 403*b7893ccfSSadaf Ebrahimi undef = list(undef_set) 404*b7893ccfSSadaf Ebrahimi undef.sort() 405*b7893ccfSSadaf Ebrahimi for vuid in undef: 406*b7893ccfSSadaf Ebrahimi print(" %s" % vuid) 407*b7893ccfSSadaf Ebrahimi return False 408*b7893ccfSSadaf Ebrahimi return True 409*b7893ccfSSadaf Ebrahimi 410*b7893ccfSSadaf Ebrahimi # Report undefined VUIDs in tests 411*b7893ccfSSadaf Ebrahimi def undef_vuids_in_tests(self): 412*b7893ccfSSadaf Ebrahimi undef_set = self.tests - self.valid 413*b7893ccfSSadaf Ebrahimi undef_set.discard('VUID-Undefined') # don't report Undefined 414*b7893ccfSSadaf Ebrahimi if ignore_unassigned: 415*b7893ccfSSadaf Ebrahimi unassigned = set({uv for uv in undef_set if uv.startswith('UNASSIGNED-')}) 416*b7893ccfSSadaf Ebrahimi undef_set = undef_set - unassigned 417*b7893ccfSSadaf Ebrahimi if (len(undef_set) > 0): 418*b7893ccfSSadaf Ebrahimi ok = False 419*b7893ccfSSadaf Ebrahimi print("\nFollowing VUIDs found in layer tests are not defined in validusage.json (%d):" % len(undef_set)) 420*b7893ccfSSadaf Ebrahimi undef = list(undef_set) 421*b7893ccfSSadaf Ebrahimi undef.sort() 422*b7893ccfSSadaf Ebrahimi for vuid in undef: 423*b7893ccfSSadaf Ebrahimi print(" %s" % vuid) 424*b7893ccfSSadaf Ebrahimi return False 425*b7893ccfSSadaf Ebrahimi return True 426*b7893ccfSSadaf Ebrahimi 427*b7893ccfSSadaf Ebrahimi # Report vuids in tests that are not in source 428*b7893ccfSSadaf Ebrahimi def vuids_tested_not_checked(self): 429*b7893ccfSSadaf Ebrahimi undef_set = self.tests - self.checks 430*b7893ccfSSadaf Ebrahimi undef_set.discard('VUID-Undefined') # don't report Undefined 431*b7893ccfSSadaf Ebrahimi if ignore_unassigned: 432*b7893ccfSSadaf Ebrahimi unassigned = set() 433*b7893ccfSSadaf Ebrahimi for vuid in undef_set: 434*b7893ccfSSadaf Ebrahimi if vuid.startswith('UNASSIGNED-'): 435*b7893ccfSSadaf Ebrahimi unassigned.add(vuid) 436*b7893ccfSSadaf Ebrahimi undef_set = undef_set - unassigned 437*b7893ccfSSadaf Ebrahimi if (len(undef_set) > 0): 438*b7893ccfSSadaf Ebrahimi ok = False 439*b7893ccfSSadaf Ebrahimi print("\nFollowing VUIDs found in tests but are not checked in layer code (%d):" % len(undef_set)) 440*b7893ccfSSadaf Ebrahimi undef = list(undef_set) 441*b7893ccfSSadaf Ebrahimi undef.sort() 442*b7893ccfSSadaf Ebrahimi for vuid in undef: 443*b7893ccfSSadaf Ebrahimi print(" %s" % vuid) 444*b7893ccfSSadaf Ebrahimi return False 445*b7893ccfSSadaf Ebrahimi return True 446*b7893ccfSSadaf Ebrahimi 447*b7893ccfSSadaf Ebrahimi # TODO: Explicit checked VUIDs which have no test 448*b7893ccfSSadaf Ebrahimi # def explicit_vuids_checked_not_tested(self): 449*b7893ccfSSadaf Ebrahimi 450*b7893ccfSSadaf Ebrahimi 451*b7893ccfSSadaf Ebrahimi# Class to output database in various flavors 452*b7893ccfSSadaf Ebrahimi# 453*b7893ccfSSadaf Ebrahimiclass OutputDatabase: 454*b7893ccfSSadaf Ebrahimi def __init__(self, val_json, val_source, val_tests): 455*b7893ccfSSadaf Ebrahimi self.vj = val_json 456*b7893ccfSSadaf Ebrahimi self.vs = val_source 457*b7893ccfSSadaf Ebrahimi self.vt = val_tests 458*b7893ccfSSadaf Ebrahimi self.header_version = "/* THIS FILE IS GENERATED - DO NOT EDIT (scripts/vk_validation_stats.py) */" 459*b7893ccfSSadaf Ebrahimi self.header_version += "\n/* Vulkan specification version: %s */" % val_json.apiversion 460*b7893ccfSSadaf Ebrahimi self.header_preamble = """ 461*b7893ccfSSadaf Ebrahimi/* 462*b7893ccfSSadaf Ebrahimi * Vulkan 463*b7893ccfSSadaf Ebrahimi * 464*b7893ccfSSadaf Ebrahimi * Copyright (c) 2016-2019 Google Inc. 465*b7893ccfSSadaf Ebrahimi * Copyright (c) 2016-2019 LunarG, Inc. 466*b7893ccfSSadaf Ebrahimi * 467*b7893ccfSSadaf Ebrahimi * Licensed under the Apache License, Version 2.0 (the "License"); 468*b7893ccfSSadaf Ebrahimi * you may not use this file except in compliance with the License. 469*b7893ccfSSadaf Ebrahimi * You may obtain a copy of the License at 470*b7893ccfSSadaf Ebrahimi * 471*b7893ccfSSadaf Ebrahimi * http://www.apache.org/licenses/LICENSE-2.0 472*b7893ccfSSadaf Ebrahimi * 473*b7893ccfSSadaf Ebrahimi * Unless required by applicable law or agreed to in writing, software 474*b7893ccfSSadaf Ebrahimi * distributed under the License is distributed on an "AS IS" BASIS, 475*b7893ccfSSadaf Ebrahimi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 476*b7893ccfSSadaf Ebrahimi * See the License for the specific language governing permissions and 477*b7893ccfSSadaf Ebrahimi * limitations under the License. 478*b7893ccfSSadaf Ebrahimi * 479*b7893ccfSSadaf Ebrahimi * Author: Tobin Ehlis <[email protected]> 480*b7893ccfSSadaf Ebrahimi * Author: Dave Houlton <[email protected]> 481*b7893ccfSSadaf Ebrahimi */ 482*b7893ccfSSadaf Ebrahimi 483*b7893ccfSSadaf Ebrahimi#pragma once 484*b7893ccfSSadaf Ebrahimi 485*b7893ccfSSadaf Ebrahimi// Disable auto-formatting for generated file 486*b7893ccfSSadaf Ebrahimi// clang-format off 487*b7893ccfSSadaf Ebrahimi 488*b7893ccfSSadaf Ebrahimi// Mapping from VUID string to the corresponding spec text 489*b7893ccfSSadaf Ebrahimitypedef struct _vuid_spec_text_pair { 490*b7893ccfSSadaf Ebrahimi const char * vuid; 491*b7893ccfSSadaf Ebrahimi const char * spec_text; 492*b7893ccfSSadaf Ebrahimi} vuid_spec_text_pair; 493*b7893ccfSSadaf Ebrahimi 494*b7893ccfSSadaf Ebrahimistatic const vuid_spec_text_pair vuid_spec_text[] = { 495*b7893ccfSSadaf Ebrahimi""" 496*b7893ccfSSadaf Ebrahimi self.header_postamble = """}; 497*b7893ccfSSadaf Ebrahimi""" 498*b7893ccfSSadaf Ebrahimi self.spec_url = "https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html" 499*b7893ccfSSadaf Ebrahimi 500*b7893ccfSSadaf Ebrahimi def dump_txt(self): 501*b7893ccfSSadaf Ebrahimi print("\n Dumping database to text file: %s" % txt_filename) 502*b7893ccfSSadaf Ebrahimi with open (txt_filename, 'w') as txt: 503*b7893ccfSSadaf Ebrahimi txt.write("## VUID Database\n") 504*b7893ccfSSadaf Ebrahimi txt.write("## Format: VUID_NAME | CHECKED | TEST | TYPE | API/STRUCT | EXTENSION | VUID_TEXT\n##\n") 505*b7893ccfSSadaf Ebrahimi vuid_list = list(self.vj.all_vuids) 506*b7893ccfSSadaf Ebrahimi vuid_list.sort() 507*b7893ccfSSadaf Ebrahimi for vuid in vuid_list: 508*b7893ccfSSadaf Ebrahimi db_list = self.vj.vuid_db[vuid] 509*b7893ccfSSadaf Ebrahimi db_list.sort(key=operator.itemgetter('ext')) # sort list to ease diffs of output file 510*b7893ccfSSadaf Ebrahimi for db_entry in db_list: 511*b7893ccfSSadaf Ebrahimi checked = 'N' 512*b7893ccfSSadaf Ebrahimi if vuid in self.vs.all_vuids: 513*b7893ccfSSadaf Ebrahimi checked = 'Y' 514*b7893ccfSSadaf Ebrahimi test = 'None' 515*b7893ccfSSadaf Ebrahimi if vuid in self.vt.vuid_to_tests: 516*b7893ccfSSadaf Ebrahimi test_list = list(self.vt.vuid_to_tests[vuid]) 517*b7893ccfSSadaf Ebrahimi test_list.sort() # sort tests, for diff-ability 518*b7893ccfSSadaf Ebrahimi sep = ', ' 519*b7893ccfSSadaf Ebrahimi test = sep.join(test_list) 520*b7893ccfSSadaf Ebrahimi 521*b7893ccfSSadaf Ebrahimi 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'])) 522*b7893ccfSSadaf Ebrahimi 523*b7893ccfSSadaf Ebrahimi def dump_csv(self): 524*b7893ccfSSadaf Ebrahimi print("\n Dumping database to csv file: %s" % csv_filename) 525*b7893ccfSSadaf Ebrahimi with open (csv_filename, 'w', newline='') as csvfile: 526*b7893ccfSSadaf Ebrahimi cw = csv.writer(csvfile) 527*b7893ccfSSadaf Ebrahimi cw.writerow(['VUID_NAME','CHECKED','TEST','TYPE','API/STRUCT','EXTENSION','VUID_TEXT']) 528*b7893ccfSSadaf Ebrahimi vuid_list = list(self.vj.all_vuids) 529*b7893ccfSSadaf Ebrahimi vuid_list.sort() 530*b7893ccfSSadaf Ebrahimi for vuid in vuid_list: 531*b7893ccfSSadaf Ebrahimi for db_entry in self.vj.vuid_db[vuid]: 532*b7893ccfSSadaf Ebrahimi row = [vuid] 533*b7893ccfSSadaf Ebrahimi if vuid in self.vs.all_vuids: 534*b7893ccfSSadaf Ebrahimi row.append('Y') 535*b7893ccfSSadaf Ebrahimi else: 536*b7893ccfSSadaf Ebrahimi row.append('N') 537*b7893ccfSSadaf Ebrahimi test = 'None' 538*b7893ccfSSadaf Ebrahimi if vuid in self.vt.vuid_to_tests: 539*b7893ccfSSadaf Ebrahimi sep = ', ' 540*b7893ccfSSadaf Ebrahimi test = sep.join(self.vt.vuid_to_tests[vuid]) 541*b7893ccfSSadaf Ebrahimi row.append(test) 542*b7893ccfSSadaf Ebrahimi row.append(db_entry['type']) 543*b7893ccfSSadaf Ebrahimi row.append(db_entry['api']) 544*b7893ccfSSadaf Ebrahimi row.append(db_entry['ext']) 545*b7893ccfSSadaf Ebrahimi row.append(db_entry['text']) 546*b7893ccfSSadaf Ebrahimi cw.writerow(row) 547*b7893ccfSSadaf Ebrahimi 548*b7893ccfSSadaf Ebrahimi def dump_html(self): 549*b7893ccfSSadaf Ebrahimi print("\n Dumping database to html file: %s" % html_filename) 550*b7893ccfSSadaf Ebrahimi 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' 551*b7893ccfSSadaf Ebrahimi 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' 552*b7893ccfSSadaf Ebrahimi with open (html_filename, 'w') as hfile: 553*b7893ccfSSadaf Ebrahimi hfile.write(preamble) 554*b7893ccfSSadaf Ebrahimi hfile.write(headers) 555*b7893ccfSSadaf Ebrahimi vuid_list = list(self.vj.all_vuids) 556*b7893ccfSSadaf Ebrahimi vuid_list.sort() 557*b7893ccfSSadaf Ebrahimi for vuid in vuid_list: 558*b7893ccfSSadaf Ebrahimi for db_entry in self.vj.vuid_db[vuid]: 559*b7893ccfSSadaf Ebrahimi hfile.write('<tr><th>%s</th>' % vuid) 560*b7893ccfSSadaf Ebrahimi checked = '<span style="color:red;">N</span>' 561*b7893ccfSSadaf Ebrahimi if vuid in self.vs.all_vuids: 562*b7893ccfSSadaf Ebrahimi checked = '<span style="color:limegreen;">Y</span>' 563*b7893ccfSSadaf Ebrahimi hfile.write('<th>%s</th>' % checked) 564*b7893ccfSSadaf Ebrahimi test = 'None' 565*b7893ccfSSadaf Ebrahimi if vuid in self.vt.vuid_to_tests: 566*b7893ccfSSadaf Ebrahimi sep = ', ' 567*b7893ccfSSadaf Ebrahimi test = sep.join(self.vt.vuid_to_tests[vuid]) 568*b7893ccfSSadaf Ebrahimi hfile.write('<th>%s</th>' % test) 569*b7893ccfSSadaf Ebrahimi hfile.write('<th>%s</th>' % db_entry['type']) 570*b7893ccfSSadaf Ebrahimi hfile.write('<th>%s</th>' % db_entry['api']) 571*b7893ccfSSadaf Ebrahimi hfile.write('<th>%s</th>' % db_entry['ext']) 572*b7893ccfSSadaf Ebrahimi hfile.write('<th>%s</th></tr>\n' % db_entry['text']) 573*b7893ccfSSadaf Ebrahimi hfile.write('</table>\n</body>\n</html>\n') 574*b7893ccfSSadaf Ebrahimi 575*b7893ccfSSadaf Ebrahimi def export_header(self): 576*b7893ccfSSadaf Ebrahimi if verbose_mode: 577*b7893ccfSSadaf Ebrahimi print("\n Exporting header file to: %s" % header_filename) 578*b7893ccfSSadaf Ebrahimi with open (header_filename, 'w') as hfile: 579*b7893ccfSSadaf Ebrahimi hfile.write(self.header_version) 580*b7893ccfSSadaf Ebrahimi hfile.write(self.header_preamble) 581*b7893ccfSSadaf Ebrahimi vuid_list = list(self.vj.all_vuids) 582*b7893ccfSSadaf Ebrahimi vuid_list.sort() 583*b7893ccfSSadaf Ebrahimi cmd_dict = {} 584*b7893ccfSSadaf Ebrahimi for vuid in vuid_list: 585*b7893ccfSSadaf Ebrahimi db_entry = self.vj.vuid_db[vuid][0] 586*b7893ccfSSadaf Ebrahimi db_text = db_entry['text'].strip(' ') 587*b7893ccfSSadaf Ebrahimi hfile.write(' {"%s", "%s (%s#%s)"},\n' % (vuid, db_text, self.spec_url, vuid)) 588*b7893ccfSSadaf Ebrahimi # For multiply-defined VUIDs, include versions with extension appended 589*b7893ccfSSadaf Ebrahimi if len(self.vj.vuid_db[vuid]) > 1: 590*b7893ccfSSadaf Ebrahimi for db_entry in self.vj.vuid_db[vuid]: 591*b7893ccfSSadaf Ebrahimi hfile.write(' {"%s[%s]", "%s (%s#%s)"},\n' % (vuid, db_entry['ext'].strip(' '), db_text, self.spec_url, vuid)) 592*b7893ccfSSadaf Ebrahimi if 'commandBuffer must be in the recording state' in db_text: 593*b7893ccfSSadaf Ebrahimi cmd_dict[vuid] = db_text 594*b7893ccfSSadaf Ebrahimi hfile.write(self.header_postamble) 595*b7893ccfSSadaf Ebrahimi 596*b7893ccfSSadaf Ebrahimi # Generate the information for validating recording state VUID's 597*b7893ccfSSadaf Ebrahimi cmd_prefix = 'prefix##' 598*b7893ccfSSadaf Ebrahimi cmd_regex = re.compile(r'VUID-vk(Cmd|End)(\w+)') 599*b7893ccfSSadaf Ebrahimi cmd_vuid_vector = [' "VUID_Undefined"'] 600*b7893ccfSSadaf Ebrahimi cmd_name_vector = [ ' "Command_Undefined"' ] 601*b7893ccfSSadaf Ebrahimi cmd_enum = [' ' + cmd_prefix + 'NONE = 0'] 602*b7893ccfSSadaf Ebrahimi 603*b7893ccfSSadaf Ebrahimi cmd_ordinal = 1 604*b7893ccfSSadaf Ebrahimi for vuid, db_text in sorted(cmd_dict.items()): 605*b7893ccfSSadaf Ebrahimi cmd_match = cmd_regex.match(vuid) 606*b7893ccfSSadaf Ebrahimi if cmd_match.group(1) == "End": 607*b7893ccfSSadaf Ebrahimi end = "END" 608*b7893ccfSSadaf Ebrahimi else: 609*b7893ccfSSadaf Ebrahimi end = "" 610*b7893ccfSSadaf Ebrahimi cmd_name_vector.append(' "vk'+ cmd_match.group(1) + cmd_match.group(2) + '"') 611*b7893ccfSSadaf Ebrahimi cmd_name = cmd_prefix + end + cmd_match.group(2).upper() 612*b7893ccfSSadaf Ebrahimi cmd_enum.append(' {} = {}'.format(cmd_name, cmd_ordinal)) 613*b7893ccfSSadaf Ebrahimi cmd_ordinal += 1 614*b7893ccfSSadaf Ebrahimi cmd_vuid_vector.append(' "{}"'.format(vuid)) 615*b7893ccfSSadaf Ebrahimi 616*b7893ccfSSadaf Ebrahimi hfile.write('\n// Defines to allow creating "must be recording" meta data\n') 617*b7893ccfSSadaf Ebrahimi cmd_enum.append(' {}RANGE_SIZE = {}'.format(cmd_prefix, cmd_ordinal)) 618*b7893ccfSSadaf Ebrahimi cmd_enum_string = '#define VUID_CMD_ENUM_LIST(prefix)\\\n' + ',\\\n'.join(cmd_enum) + '\n\n' 619*b7893ccfSSadaf Ebrahimi hfile.write(cmd_enum_string) 620*b7893ccfSSadaf Ebrahimi cmd_name_list_string = '#define VUID_CMD_NAME_LIST\\\n' + ',\\\n'.join(cmd_name_vector) + '\n\n' 621*b7893ccfSSadaf Ebrahimi hfile.write(cmd_name_list_string) 622*b7893ccfSSadaf Ebrahimi vuid_vector_string = '#define VUID_MUST_BE_RECORDING_LIST\\\n' + ',\\\n'.join(cmd_vuid_vector) + '\n' 623*b7893ccfSSadaf Ebrahimi hfile.write(vuid_vector_string) 624*b7893ccfSSadaf Ebrahimi 625*b7893ccfSSadaf Ebrahimidef main(argv): 626*b7893ccfSSadaf Ebrahimi global verbose_mode 627*b7893ccfSSadaf Ebrahimi global txt_filename 628*b7893ccfSSadaf Ebrahimi global csv_filename 629*b7893ccfSSadaf Ebrahimi global html_filename 630*b7893ccfSSadaf Ebrahimi 631*b7893ccfSSadaf Ebrahimi run_consistency = False 632*b7893ccfSSadaf Ebrahimi report_unimplemented = False 633*b7893ccfSSadaf Ebrahimi get_vuid_status = '' 634*b7893ccfSSadaf Ebrahimi txt_out = False 635*b7893ccfSSadaf Ebrahimi csv_out = False 636*b7893ccfSSadaf Ebrahimi html_out = False 637*b7893ccfSSadaf Ebrahimi header_out = False 638*b7893ccfSSadaf Ebrahimi show_summary = False 639*b7893ccfSSadaf Ebrahimi 640*b7893ccfSSadaf Ebrahimi if (1 > len(argv)): 641*b7893ccfSSadaf Ebrahimi printHelp() 642*b7893ccfSSadaf Ebrahimi sys.exit() 643*b7893ccfSSadaf Ebrahimi 644*b7893ccfSSadaf Ebrahimi # Parse script args 645*b7893ccfSSadaf Ebrahimi json_filename = argv[0] 646*b7893ccfSSadaf Ebrahimi i = 1 647*b7893ccfSSadaf Ebrahimi while (i < len(argv)): 648*b7893ccfSSadaf Ebrahimi arg = argv[i] 649*b7893ccfSSadaf Ebrahimi i = i + 1 650*b7893ccfSSadaf Ebrahimi if (arg == '-c'): 651*b7893ccfSSadaf Ebrahimi run_consistency = True 652*b7893ccfSSadaf Ebrahimi elif (arg == '-vuid'): 653*b7893ccfSSadaf Ebrahimi get_vuid_status = argv[i] 654*b7893ccfSSadaf Ebrahimi i = i + 1 655*b7893ccfSSadaf Ebrahimi elif (arg == '-todo'): 656*b7893ccfSSadaf Ebrahimi report_unimplemented = True 657*b7893ccfSSadaf Ebrahimi elif (arg == '-text'): 658*b7893ccfSSadaf Ebrahimi txt_out = True 659*b7893ccfSSadaf Ebrahimi # Set filename if supplied, else use default 660*b7893ccfSSadaf Ebrahimi if i < len(argv) and not argv[i].startswith('-'): 661*b7893ccfSSadaf Ebrahimi txt_filename = argv[i] 662*b7893ccfSSadaf Ebrahimi i = i + 1 663*b7893ccfSSadaf Ebrahimi elif (arg == '-csv'): 664*b7893ccfSSadaf Ebrahimi csv_out = True 665*b7893ccfSSadaf Ebrahimi # Set filename if supplied, else use default 666*b7893ccfSSadaf Ebrahimi if i < len(argv) and not argv[i].startswith('-'): 667*b7893ccfSSadaf Ebrahimi csv_filename = argv[i] 668*b7893ccfSSadaf Ebrahimi i = i + 1 669*b7893ccfSSadaf Ebrahimi elif (arg == '-html'): 670*b7893ccfSSadaf Ebrahimi html_out = True 671*b7893ccfSSadaf Ebrahimi # Set filename if supplied, else use default 672*b7893ccfSSadaf Ebrahimi if i < len(argv) and not argv[i].startswith('-'): 673*b7893ccfSSadaf Ebrahimi html_filename = argv[i] 674*b7893ccfSSadaf Ebrahimi i = i + 1 675*b7893ccfSSadaf Ebrahimi elif (arg == '-export_header'): 676*b7893ccfSSadaf Ebrahimi header_out = True 677*b7893ccfSSadaf Ebrahimi elif (arg in ['-verbose']): 678*b7893ccfSSadaf Ebrahimi verbose_mode = True 679*b7893ccfSSadaf Ebrahimi elif (arg in ['-summary']): 680*b7893ccfSSadaf Ebrahimi show_summary = True 681*b7893ccfSSadaf Ebrahimi elif (arg in ['-help', '-h']): 682*b7893ccfSSadaf Ebrahimi printHelp() 683*b7893ccfSSadaf Ebrahimi sys.exit() 684*b7893ccfSSadaf Ebrahimi else: 685*b7893ccfSSadaf Ebrahimi print("Unrecognized argument: %s\n" % arg) 686*b7893ccfSSadaf Ebrahimi printHelp() 687*b7893ccfSSadaf Ebrahimi sys.exit() 688*b7893ccfSSadaf Ebrahimi 689*b7893ccfSSadaf Ebrahimi result = 0 # Non-zero result indicates an error case 690*b7893ccfSSadaf Ebrahimi 691*b7893ccfSSadaf Ebrahimi # Parse validusage json 692*b7893ccfSSadaf Ebrahimi val_json = ValidationJSON(json_filename) 693*b7893ccfSSadaf Ebrahimi val_json.read() 694*b7893ccfSSadaf Ebrahimi exp_json = len(val_json.explicit_vuids) 695*b7893ccfSSadaf Ebrahimi imp_json = len(val_json.implicit_vuids) 696*b7893ccfSSadaf Ebrahimi all_json = len(val_json.all_vuids) 697*b7893ccfSSadaf Ebrahimi if verbose_mode: 698*b7893ccfSSadaf Ebrahimi print("Found %d unique error vuids in validusage.json file." % all_json) 699*b7893ccfSSadaf Ebrahimi print(" %d explicit" % exp_json) 700*b7893ccfSSadaf Ebrahimi print(" %d implicit" % imp_json) 701*b7893ccfSSadaf Ebrahimi if len(val_json.duplicate_vuids) > 0: 702*b7893ccfSSadaf Ebrahimi print("%d VUIDs appear in validusage.json more than once." % len(val_json.duplicate_vuids)) 703*b7893ccfSSadaf Ebrahimi for vuid in val_json.duplicate_vuids: 704*b7893ccfSSadaf Ebrahimi print(" %s" % vuid) 705*b7893ccfSSadaf Ebrahimi for ext in val_json.vuid_db[vuid]: 706*b7893ccfSSadaf Ebrahimi print(" with extension: %s" % ext['ext']) 707*b7893ccfSSadaf Ebrahimi 708*b7893ccfSSadaf Ebrahimi # Parse layer source files 709*b7893ccfSSadaf Ebrahimi val_source = ValidationSource(layer_source_files) 710*b7893ccfSSadaf Ebrahimi val_source.parse() 711*b7893ccfSSadaf Ebrahimi exp_checks = len(val_source.explicit_vuids) 712*b7893ccfSSadaf Ebrahimi imp_checks = len(val_source.implicit_vuids) 713*b7893ccfSSadaf Ebrahimi all_checks = len(val_source.vuid_count_dict.keys()) 714*b7893ccfSSadaf Ebrahimi if verbose_mode: 715*b7893ccfSSadaf Ebrahimi print("Found %d unique vuid checks in layer source code." % all_checks) 716*b7893ccfSSadaf Ebrahimi print(" %d explicit" % exp_checks) 717*b7893ccfSSadaf Ebrahimi print(" %d implicit" % imp_checks) 718*b7893ccfSSadaf Ebrahimi print(" %d unassigned" % len(val_source.unassigned_vuids)) 719*b7893ccfSSadaf Ebrahimi print(" %d checks are implemented more that once" % val_source.duplicated_checks) 720*b7893ccfSSadaf Ebrahimi 721*b7893ccfSSadaf Ebrahimi # Parse test files 722*b7893ccfSSadaf Ebrahimi val_tests = ValidationTests(test_source_files) 723*b7893ccfSSadaf Ebrahimi val_tests.parse() 724*b7893ccfSSadaf Ebrahimi exp_tests = len(val_tests.explicit_vuids) 725*b7893ccfSSadaf Ebrahimi imp_tests = len(val_tests.implicit_vuids) 726*b7893ccfSSadaf Ebrahimi all_tests = len(val_tests.all_vuids) 727*b7893ccfSSadaf Ebrahimi if verbose_mode: 728*b7893ccfSSadaf Ebrahimi print("Found %d unique error vuids in test source code." % all_tests) 729*b7893ccfSSadaf Ebrahimi print(" %d explicit" % exp_tests) 730*b7893ccfSSadaf Ebrahimi print(" %d implicit" % imp_tests) 731*b7893ccfSSadaf Ebrahimi print(" %d unassigned" % len(val_tests.unassigned_vuids)) 732*b7893ccfSSadaf Ebrahimi 733*b7893ccfSSadaf Ebrahimi # Process stats 734*b7893ccfSSadaf Ebrahimi if show_summary: 735*b7893ccfSSadaf Ebrahimi print("\nValidation Statistics (using validusage.json version %s)" % val_json.apiversion) 736*b7893ccfSSadaf Ebrahimi print(" VUIDs defined in JSON file: %04d explicit, %04d implicit, %04d total." % (exp_json, imp_json, all_json)) 737*b7893ccfSSadaf Ebrahimi print(" VUIDs checked in layer code: %04d explicit, %04d implicit, %04d total." % (exp_checks, imp_checks, all_checks)) 738*b7893ccfSSadaf Ebrahimi print(" VUIDs tested in layer tests: %04d explicit, %04d implicit, %04d total." % (exp_tests, imp_tests, all_tests)) 739*b7893ccfSSadaf Ebrahimi 740*b7893ccfSSadaf Ebrahimi print("\nVUID check coverage") 741*b7893ccfSSadaf Ebrahimi print(" Explicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * exp_checks / exp_json), exp_checks, exp_json)) 742*b7893ccfSSadaf Ebrahimi print(" Implicit VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * imp_checks / imp_json), imp_checks, imp_json)) 743*b7893ccfSSadaf Ebrahimi print(" Overall VUIDs checked: %.1f%% (%d checked vs %d defined)" % ((100.0 * all_checks / all_json), all_checks, all_json)) 744*b7893ccfSSadaf Ebrahimi 745*b7893ccfSSadaf Ebrahimi print("\nVUID test coverage") 746*b7893ccfSSadaf Ebrahimi print(" Explicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * exp_tests / exp_checks), exp_tests, exp_checks)) 747*b7893ccfSSadaf Ebrahimi print(" Implicit VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * imp_tests / imp_checks), imp_tests, imp_checks)) 748*b7893ccfSSadaf Ebrahimi print(" Overall VUIDs tested: %.1f%% (%d tested vs %d checks)" % ((100.0 * all_tests / all_checks), all_tests, all_checks)) 749*b7893ccfSSadaf Ebrahimi 750*b7893ccfSSadaf Ebrahimi # Report status of a single VUID 751*b7893ccfSSadaf Ebrahimi if len(get_vuid_status) > 1: 752*b7893ccfSSadaf Ebrahimi print("\n\nChecking status of <%s>" % get_vuid_status); 753*b7893ccfSSadaf Ebrahimi if get_vuid_status not in val_json.all_vuids: 754*b7893ccfSSadaf Ebrahimi print(' Not a valid VUID string.') 755*b7893ccfSSadaf Ebrahimi else: 756*b7893ccfSSadaf Ebrahimi if get_vuid_status in val_source.explicit_vuids: 757*b7893ccfSSadaf Ebrahimi print(' Implemented!') 758*b7893ccfSSadaf Ebrahimi line_list = val_source.vuid_count_dict[get_vuid_status]['file_line'] 759*b7893ccfSSadaf Ebrahimi for line in line_list: 760*b7893ccfSSadaf Ebrahimi print(' => %s' % line) 761*b7893ccfSSadaf Ebrahimi elif get_vuid_status in val_source.implicit_vuids: 762*b7893ccfSSadaf Ebrahimi print(' Implemented! (Implicit)') 763*b7893ccfSSadaf Ebrahimi line_list = val_source.vuid_count_dict[get_vuid_status]['file_line'] 764*b7893ccfSSadaf Ebrahimi for line in line_list: 765*b7893ccfSSadaf Ebrahimi print(' => %s' % line) 766*b7893ccfSSadaf Ebrahimi else: 767*b7893ccfSSadaf Ebrahimi print(' Not implemented.') 768*b7893ccfSSadaf Ebrahimi if get_vuid_status in val_tests.all_vuids: 769*b7893ccfSSadaf Ebrahimi print(' Has a test!') 770*b7893ccfSSadaf Ebrahimi test_list = val_tests.vuid_to_tests[get_vuid_status] 771*b7893ccfSSadaf Ebrahimi for test in test_list: 772*b7893ccfSSadaf Ebrahimi print(' => %s' % test) 773*b7893ccfSSadaf Ebrahimi else: 774*b7893ccfSSadaf Ebrahimi print(' Not tested.') 775*b7893ccfSSadaf Ebrahimi 776*b7893ccfSSadaf Ebrahimi # Report unimplemented explicit VUIDs 777*b7893ccfSSadaf Ebrahimi if report_unimplemented: 778*b7893ccfSSadaf Ebrahimi unim_explicit = val_json.explicit_vuids - val_source.explicit_vuids 779*b7893ccfSSadaf Ebrahimi print("\n\n%d explicit VUID checks remain unimplemented:" % len(unim_explicit)) 780*b7893ccfSSadaf Ebrahimi ulist = list(unim_explicit) 781*b7893ccfSSadaf Ebrahimi ulist.sort() 782*b7893ccfSSadaf Ebrahimi for vuid in ulist: 783*b7893ccfSSadaf Ebrahimi print(" => %s" % vuid) 784*b7893ccfSSadaf Ebrahimi 785*b7893ccfSSadaf Ebrahimi # Consistency tests 786*b7893ccfSSadaf Ebrahimi if run_consistency: 787*b7893ccfSSadaf Ebrahimi print("\n\nRunning consistency tests...") 788*b7893ccfSSadaf Ebrahimi con = Consistency(val_json.all_vuids, val_source.all_vuids, val_tests.all_vuids) 789*b7893ccfSSadaf Ebrahimi ok = con.undef_vuids_in_layer_code() 790*b7893ccfSSadaf Ebrahimi ok &= con.undef_vuids_in_tests() 791*b7893ccfSSadaf Ebrahimi ok &= con.vuids_tested_not_checked() 792*b7893ccfSSadaf Ebrahimi 793*b7893ccfSSadaf Ebrahimi if ok: 794*b7893ccfSSadaf Ebrahimi print(" OK! No inconsistencies found.") 795*b7893ccfSSadaf Ebrahimi 796*b7893ccfSSadaf Ebrahimi # Output database in requested format(s) 797*b7893ccfSSadaf Ebrahimi db_out = OutputDatabase(val_json, val_source, val_tests) 798*b7893ccfSSadaf Ebrahimi if txt_out: 799*b7893ccfSSadaf Ebrahimi db_out.dump_txt() 800*b7893ccfSSadaf Ebrahimi if csv_out: 801*b7893ccfSSadaf Ebrahimi db_out.dump_csv() 802*b7893ccfSSadaf Ebrahimi if html_out: 803*b7893ccfSSadaf Ebrahimi db_out.dump_html() 804*b7893ccfSSadaf Ebrahimi if header_out: 805*b7893ccfSSadaf Ebrahimi db_out.export_header() 806*b7893ccfSSadaf Ebrahimi return result 807*b7893ccfSSadaf Ebrahimi 808*b7893ccfSSadaf Ebrahimiif __name__ == "__main__": 809*b7893ccfSSadaf Ebrahimi sys.exit(main(sys.argv[1:])) 810*b7893ccfSSadaf Ebrahimi 811