| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723 |
- # Copyright (c) 2018 Google LLC
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- """A number of common spirv result checks coded in mixin classes.
- A test case can use these checks by declaring their enclosing mixin classes
- as superclass and providing the expected_* variables required by the check_*()
- methods in the mixin classes.
- """
- import difflib
- import functools
- import os
- import re
- import subprocess
- import traceback
- from spirv_test_framework import SpirvTest
- from builtins import bytes
- DEFAULT_SPIRV_VERSION = 0x010000
- def convert_to_unix_line_endings(source):
- """Converts all line endings in source to be unix line endings."""
- result = source.replace('\r\n', '\n').replace('\r', '\n')
- return result
- def substitute_file_extension(filename, extension):
- """Substitutes file extension, respecting known shader extensions.
- foo.vert -> foo.vert.[extension] [similarly for .frag, .comp, etc.]
- foo.glsl -> foo.[extension]
- foo.unknown -> foo.[extension]
- foo -> foo.[extension]
- """
- if filename[-5:] not in [
- '.vert', '.frag', '.tesc', '.tese', '.geom', '.comp', '.spvasm'
- ]:
- return filename.rsplit('.', 1)[0] + '.' + extension
- else:
- return filename + '.' + extension
- def get_object_filename(source_filename):
- """Gets the object filename for the given source file."""
- return substitute_file_extension(source_filename, 'spv')
- def get_assembly_filename(source_filename):
- """Gets the assembly filename for the given source file."""
- return substitute_file_extension(source_filename, 'spvasm')
- def verify_file_non_empty(filename):
- """Checks that a given file exists and is not empty."""
- if not os.path.isfile(filename):
- return False, 'Cannot find file: ' + filename
- if not os.path.getsize(filename):
- return False, 'Empty file: ' + filename
- return True, ''
- class ReturnCodeIsZero(SpirvTest):
- """Mixin class for checking that the return code is zero."""
- def check_return_code_is_zero(self, status):
- if status.returncode:
- return False, 'Non-zero return code: {ret}\n'.format(
- ret=status.returncode)
- return True, ''
- class ReturnCodeIsNonZero(SpirvTest):
- """Mixin class for checking that the return code is not zero."""
- def check_return_code_is_nonzero(self, status):
- if not status.returncode:
- return False, 'return code is 0'
- return True, ''
- class NoOutputOnStdout(SpirvTest):
- """Mixin class for checking that there is no output on stdout."""
- def check_no_output_on_stdout(self, status):
- if status.stdout:
- return False, 'Non empty stdout: {out}\n'.format(out=status.stdout)
- return True, ''
- class NoOutputOnStderr(SpirvTest):
- """Mixin class for checking that there is no output on stderr."""
- def check_no_output_on_stderr(self, status):
- if status.stderr:
- return False, 'Non empty stderr: {err}\n'.format(err=status.stderr)
- return True, ''
- class SuccessfulReturn(ReturnCodeIsZero, NoOutputOnStdout, NoOutputOnStderr):
- """Mixin class for checking that return code is zero and no output on
- stdout and stderr."""
- pass
- class NoGeneratedFiles(SpirvTest):
- """Mixin class for checking that there is no file generated."""
- def check_no_generated_files(self, status):
- all_files = os.listdir(status.directory)
- input_files = status.input_filenames
- if all([f.startswith(status.directory) for f in input_files]):
- all_files = [os.path.join(status.directory, f) for f in all_files]
- generated_files = set(all_files) - set(input_files)
- if len(generated_files) == 0:
- return True, ''
- else:
- return False, 'Extra files generated: {}'.format(generated_files)
- class CorrectBinaryLengthAndPreamble(SpirvTest):
- """Provides methods for verifying preamble for a SPIR-V binary."""
- def verify_binary_length_and_header(self, binary, spv_version=0x10000):
- """Checks that the given SPIR-V binary has valid length and header.
- Returns:
- False, error string if anything is invalid
- True, '' otherwise
- Args:
- binary: a bytes object containing the SPIR-V binary
- spv_version: target SPIR-V version number, with same encoding
- as the version word in a SPIR-V header.
- """
- def read_word(binary, index, little_endian):
- """Reads the index-th word from the given binary file."""
- word = binary[index * 4:(index + 1) * 4]
- if little_endian:
- word = reversed(word)
- return functools.reduce(lambda w, b: (w << 8) | b, word, 0)
- def check_endianness(binary):
- """Checks the endianness of the given SPIR-V binary.
- Returns:
- True if it's little endian, False if it's big endian.
- None if magic number is wrong.
- """
- first_word = read_word(binary, 0, True)
- if first_word == 0x07230203:
- return True
- first_word = read_word(binary, 0, False)
- if first_word == 0x07230203:
- return False
- return None
- num_bytes = len(binary)
- if num_bytes % 4 != 0:
- return False, ('Incorrect SPV binary: size should be a multiple'
- ' of words')
- if num_bytes < 20:
- return False, 'Incorrect SPV binary: size less than 5 words'
- preamble = binary[0:19]
- little_endian = check_endianness(preamble)
- # SPIR-V module magic number
- if little_endian is None:
- return False, 'Incorrect SPV binary: wrong magic number'
- # SPIR-V version number
- version = read_word(preamble, 1, little_endian)
- # TODO(dneto): Recent Glslang uses version word 0 for opengl_compat
- # profile
- if version != spv_version and version != 0:
- return False, 'Incorrect SPV binary: wrong version number: ' + hex(version) + ' expected ' + hex(spv_version)
- # Shaderc-over-Glslang (0x000d....) or
- # SPIRV-Tools (0x0007....) generator number
- if read_word(preamble, 2, little_endian) != 0x000d0007 and \
- read_word(preamble, 2, little_endian) != 0x00070000:
- return False, ('Incorrect SPV binary: wrong generator magic ' 'number')
- # reserved for instruction schema
- if read_word(preamble, 4, little_endian) != 0:
- return False, 'Incorrect SPV binary: the 5th byte should be 0'
- return True, ''
- class CorrectObjectFilePreamble(CorrectBinaryLengthAndPreamble):
- """Provides methods for verifying preamble for a SPV object file."""
- def verify_object_file_preamble(self,
- filename,
- spv_version=DEFAULT_SPIRV_VERSION):
- """Checks that the given SPIR-V binary file has correct preamble."""
- success, message = verify_file_non_empty(filename)
- if not success:
- return False, message
- with open(filename, 'rb') as object_file:
- object_file.seek(0, os.SEEK_END)
- num_bytes = object_file.tell()
- object_file.seek(0)
- binary = bytes(object_file.read())
- return self.verify_binary_length_and_header(binary, spv_version)
- return True, ''
- class CorrectAssemblyFilePreamble(SpirvTest):
- """Provides methods for verifying preamble for a SPV assembly file."""
- def verify_assembly_file_preamble(self, filename):
- success, message = verify_file_non_empty(filename)
- if not success:
- return False, message
- with open(filename) as assembly_file:
- line1 = assembly_file.readline()
- line2 = assembly_file.readline()
- line3 = assembly_file.readline()
- if (line1 != '; SPIR-V\n' or line2 != '; Version: 1.0\n' or
- (not line3.startswith('; Generator: Google Shaderc over Glslang;'))):
- return False, 'Incorrect SPV assembly'
- return True, ''
- class ValidObjectFile(SuccessfulReturn, CorrectObjectFilePreamble):
- """Mixin class for checking that every input file generates a valid SPIR-V 1.0
- object file following the object file naming rule, and there is no output on
- stdout/stderr."""
- def check_object_file_preamble(self, status):
- for input_filename in status.input_filenames:
- object_filename = get_object_filename(input_filename)
- success, message = self.verify_object_file_preamble(
- os.path.join(status.directory, object_filename))
- if not success:
- return False, message
- return True, ''
- class ValidObjectFile1_3(ReturnCodeIsZero, CorrectObjectFilePreamble):
- """Mixin class for checking that every input file generates a valid SPIR-V 1.3
- object file following the object file naming rule, and there is no output on
- stdout/stderr."""
- def check_object_file_preamble(self, status):
- for input_filename in status.input_filenames:
- object_filename = get_object_filename(input_filename)
- success, message = self.verify_object_file_preamble(
- os.path.join(status.directory, object_filename), 0x10300)
- if not success:
- return False, message
- return True, ''
- class ValidObjectFile1_5(ReturnCodeIsZero, CorrectObjectFilePreamble):
- """Mixin class for checking that every input file generates a valid SPIR-V 1.5
- object file following the object file naming rule, and there is no output on
- stdout/stderr."""
- def check_object_file_preamble(self, status):
- for input_filename in status.input_filenames:
- object_filename = get_object_filename(input_filename)
- success, message = self.verify_object_file_preamble(
- os.path.join(status.directory, object_filename), 0x10500)
- if not success:
- return False, message
- return True, ''
- class ValidObjectFile1_6(ReturnCodeIsZero, CorrectObjectFilePreamble):
- """Mixin class for checking that every input file generates a valid SPIR-V 1.6
- object file following the object file naming rule, and there is no output on
- stdout/stderr."""
- def check_object_file_preamble(self, status):
- for input_filename in status.input_filenames:
- object_filename = get_object_filename(input_filename)
- success, message = self.verify_object_file_preamble(
- os.path.join(status.directory, object_filename), 0x10600)
- if not success:
- return False, message
- return True, ''
- class ValidObjectFileWithAssemblySubstr(SuccessfulReturn,
- CorrectObjectFilePreamble):
- """Mixin class for checking that every input file generates a valid object
- file following the object file naming rule, there is no output on
- stdout/stderr, and the disassmbly contains a specified substring per
- input.
- """
- def check_object_file_disassembly(self, status):
- for an_input in status.inputs:
- object_filename = get_object_filename(an_input.filename)
- obj_file = str(os.path.join(status.directory, object_filename))
- success, message = self.verify_object_file_preamble(obj_file)
- if not success:
- return False, message
- cmd = [status.test_manager.disassembler_path, '--no-color', obj_file]
- process = subprocess.Popen(
- args=cmd,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- cwd=status.directory)
- output = process.communicate(None)
- disassembly = output[0]
- if not isinstance(an_input.assembly_substr, str):
- return False, 'Missing assembly_substr member'
- if an_input.assembly_substr not in disassembly:
- return False, ('Incorrect disassembly output:\n{asm}\n'
- 'Expected substring not found:\n{exp}'.format(
- asm=disassembly, exp=an_input.assembly_substr))
- return True, ''
- class ValidNamedObjectFile(SuccessfulReturn, CorrectObjectFilePreamble):
- """Mixin class for checking that a list of object files with the given
- names are correctly generated, and there is no output on stdout/stderr.
- To mix in this class, subclasses need to provide expected_object_filenames
- as the expected object filenames.
- """
- def check_object_file_preamble(self, status):
- for object_filename in self.expected_object_filenames:
- success, message = self.verify_object_file_preamble(
- os.path.join(status.directory, object_filename))
- if not success:
- return False, message
- return True, ''
- class ValidFileContents(SpirvTest):
- """Mixin class to test that a specific file contains specific text
- To mix in this class, subclasses need to provide expected_file_contents as
- the contents of the file and target_filename to determine the location."""
- def check_file(self, status):
- target_filename = os.path.join(status.directory, self.target_filename)
- if not os.path.isfile(target_filename):
- return False, 'Cannot find file: ' + target_filename
- with open(target_filename, 'r') as target_file:
- file_contents = target_file.read()
- if isinstance(self.expected_file_contents, str):
- if file_contents == self.expected_file_contents:
- return True, ''
- return False, ('Incorrect file output: \n{act}\n'
- 'Expected:\n{exp}'
- 'With diff:\n{diff}'.format(
- act=file_contents,
- exp=self.expected_file_contents,
- diff='\n'.join(
- list(
- difflib.unified_diff(
- self.expected_file_contents.split('\n'),
- file_contents.split('\n'),
- fromfile='expected_output',
- tofile='actual_output')))))
- elif isinstance(self.expected_file_contents, type(re.compile(''))):
- if self.expected_file_contents.search(file_contents):
- return True, ''
- return False, ('Incorrect file output: \n{act}\n'
- 'Expected matching regex pattern:\n{exp}'.format(
- act=file_contents,
- exp=self.expected_file_contents.pattern))
- return False, (
- 'Could not open target file ' + target_filename + ' for reading')
- class ValidAssemblyFile(SuccessfulReturn, CorrectAssemblyFilePreamble):
- """Mixin class for checking that every input file generates a valid assembly
- file following the assembly file naming rule, and there is no output on
- stdout/stderr."""
- def check_assembly_file_preamble(self, status):
- for input_filename in status.input_filenames:
- assembly_filename = get_assembly_filename(input_filename)
- success, message = self.verify_assembly_file_preamble(
- os.path.join(status.directory, assembly_filename))
- if not success:
- return False, message
- return True, ''
- class ValidAssemblyFileWithSubstr(ValidAssemblyFile):
- """Mixin class for checking that every input file generates a valid assembly
- file following the assembly file naming rule, there is no output on
- stdout/stderr, and all assembly files have the given substring specified
- by expected_assembly_substr.
- To mix in this class, subclasses need to provde expected_assembly_substr
- as the expected substring.
- """
- def check_assembly_with_substr(self, status):
- for input_filename in status.input_filenames:
- assembly_filename = get_assembly_filename(input_filename)
- success, message = self.verify_assembly_file_preamble(
- os.path.join(status.directory, assembly_filename))
- if not success:
- return False, message
- with open(assembly_filename, 'r') as f:
- content = f.read()
- if self.expected_assembly_substr not in convert_to_unix_line_endings(
- content):
- return False, ('Incorrect assembly output:\n{asm}\n'
- 'Expected substring not found:\n{exp}'.format(
- asm=content, exp=self.expected_assembly_substr))
- return True, ''
- class ValidAssemblyFileWithoutSubstr(ValidAssemblyFile):
- """Mixin class for checking that every input file generates a valid assembly
- file following the assembly file naming rule, there is no output on
- stdout/stderr, and no assembly files have the given substring specified
- by unexpected_assembly_substr.
- To mix in this class, subclasses need to provde unexpected_assembly_substr
- as the substring we expect not to see.
- """
- def check_assembly_for_substr(self, status):
- for input_filename in status.input_filenames:
- assembly_filename = get_assembly_filename(input_filename)
- success, message = self.verify_assembly_file_preamble(
- os.path.join(status.directory, assembly_filename))
- if not success:
- return False, message
- with open(assembly_filename, 'r') as f:
- content = f.read()
- if self.unexpected_assembly_substr in convert_to_unix_line_endings(
- content):
- return False, ('Incorrect assembly output:\n{asm}\n'
- 'Unexpected substring found:\n{unexp}'.format(
- asm=content, exp=self.unexpected_assembly_substr))
- return True, ''
- class ValidNamedAssemblyFile(SuccessfulReturn, CorrectAssemblyFilePreamble):
- """Mixin class for checking that a list of assembly files with the given
- names are correctly generated, and there is no output on stdout/stderr.
- To mix in this class, subclasses need to provide expected_assembly_filenames
- as the expected assembly filenames.
- """
- def check_object_file_preamble(self, status):
- for assembly_filename in self.expected_assembly_filenames:
- success, message = self.verify_assembly_file_preamble(
- os.path.join(status.directory, assembly_filename))
- if not success:
- return False, message
- return True, ''
- class ErrorMessage(SpirvTest):
- """Mixin class for tests that fail with a specific error message.
- To mix in this class, subclasses need to provide expected_error as the
- expected error message.
- The test should fail if the subprocess was terminated by a signal.
- """
- def check_has_error_message(self, status):
- if not status.returncode:
- return False, ('Expected error message, but returned success from '
- 'command execution')
- if status.returncode < 0:
- # On Unix, a negative value -N for Popen.returncode indicates
- # termination by signal N.
- # https://docs.python.org/2/library/subprocess.html
- return False, ('Expected error message, but command was terminated by '
- 'signal ' + str(status.returncode))
- if not status.stderr:
- return False, 'Expected error message, but no output on stderr'
- if self.expected_error != convert_to_unix_line_endings(status.stderr):
- return False, ('Incorrect stderr output:\n{act}\n'
- 'Expected:\n{exp}'.format(
- act=status.stderr, exp=self.expected_error))
- return True, ''
- class ErrorMessageSubstr(SpirvTest):
- """Mixin class for tests that fail with a specific substring in the error
- message.
- To mix in this class, subclasses need to provide expected_error_substr as
- the expected error message substring.
- The test should fail if the subprocess was terminated by a signal.
- """
- def check_has_error_message_as_substring(self, status):
- if not status.returncode:
- return False, ('Expected error message, but returned success from '
- 'command execution')
- if status.returncode < 0:
- # On Unix, a negative value -N for Popen.returncode indicates
- # termination by signal N.
- # https://docs.python.org/2/library/subprocess.html
- return False, ('Expected error message, but command was terminated by '
- 'signal ' + str(status.returncode))
- if not status.stderr:
- return False, 'Expected error message, but no output on stderr'
- if self.expected_error_substr not in convert_to_unix_line_endings(
- status.stderr):
- return False, ('Incorrect stderr output:\n{act}\n'
- 'Expected substring not found in stderr:\n{exp}'.format(
- act=status.stderr, exp=self.expected_error_substr))
- return True, ''
- class WarningMessage(SpirvTest):
- """Mixin class for tests that succeed but have a specific warning message.
- To mix in this class, subclasses need to provide expected_warning as the
- expected warning message.
- """
- def check_has_warning_message(self, status):
- if status.returncode:
- return False, ('Expected warning message, but returned failure from'
- ' command execution')
- if not status.stderr:
- return False, 'Expected warning message, but no output on stderr'
- if self.expected_warning != convert_to_unix_line_endings(status.stderr):
- return False, ('Incorrect stderr output:\n{act}\n'
- 'Expected:\n{exp}'.format(
- act=status.stderr, exp=self.expected_warning))
- return True, ''
- class ValidObjectFileWithWarning(NoOutputOnStdout, CorrectObjectFilePreamble,
- WarningMessage):
- """Mixin class for checking that every input file generates a valid object
- file following the object file naming rule, with a specific warning message.
- """
- def check_object_file_preamble(self, status):
- for input_filename in status.input_filenames:
- object_filename = get_object_filename(input_filename)
- success, message = self.verify_object_file_preamble(
- os.path.join(status.directory, object_filename))
- if not success:
- return False, message
- return True, ''
- class ValidAssemblyFileWithWarning(NoOutputOnStdout,
- CorrectAssemblyFilePreamble, WarningMessage):
- """Mixin class for checking that every input file generates a valid assembly
- file following the assembly file naming rule, with a specific warning
- message."""
- def check_assembly_file_preamble(self, status):
- for input_filename in status.input_filenames:
- assembly_filename = get_assembly_filename(input_filename)
- success, message = self.verify_assembly_file_preamble(
- os.path.join(status.directory, assembly_filename))
- if not success:
- return False, message
- return True, ''
- class StdoutMatch(SpirvTest):
- """Mixin class for tests that can expect output on stdout.
- To mix in this class, subclasses need to provide expected_stdout as the
- expected stdout output.
- For expected_stdout, if it's True, then they expect something on stdout but
- will not check what it is. If it's a string, expect an exact match. If it's
- anything else, it is assumed to be a compiled regular expression which will
- be matched against re.search(). It will expect
- expected_stdout.search(status.stdout) to be true.
- """
- def check_stdout_match(self, status):
- # "True" in this case means we expect something on stdout, but we do not
- # care what it is, we want to distinguish this from "blah" which means we
- # expect exactly the string "blah".
- if self.expected_stdout is True:
- if not status.stdout:
- return False, 'Expected something on stdout'
- elif type(self.expected_stdout) == str:
- if self.expected_stdout != convert_to_unix_line_endings(status.stdout):
- return False, ('Incorrect stdout output:\n{ac}\n'
- 'Expected:\n{ex}'.format(
- ac=status.stdout, ex=self.expected_stdout))
- else:
- converted = convert_to_unix_line_endings(status.stdout)
- if not self.expected_stdout.search(converted):
- return False, ('Incorrect stdout output:\n{ac}\n'
- 'Expected to match regex:\n{ex}'.format(
- ac=status.stdout, ex=self.expected_stdout.pattern))
- return True, ''
- class StderrMatch(SpirvTest):
- """Mixin class for tests that can expect output on stderr.
- To mix in this class, subclasses need to provide expected_stderr as the
- expected stderr output.
- For expected_stderr, if it's True, then they expect something on stderr,
- but will not check what it is. If it's a string, expect an exact match.
- If it's anything else, it is assumed to be a compiled regular expression
- which will be matched against re.search(). It will expect
- expected_stderr.search(status.stderr) to be true.
- """
- def check_stderr_match(self, status):
- # "True" in this case means we expect something on stderr, but we do not
- # care what it is, we want to distinguish this from "blah" which means we
- # expect exactly the string "blah".
- if self.expected_stderr is True:
- if not status.stderr:
- return False, 'Expected something on stderr'
- elif type(self.expected_stderr) == str:
- if self.expected_stderr != convert_to_unix_line_endings(status.stderr):
- return False, ('Incorrect stderr output:\n{ac}\n'
- 'Expected:\n{ex}'.format(
- ac=status.stderr, ex=self.expected_stderr))
- else:
- if not self.expected_stderr.search(
- convert_to_unix_line_endings(status.stderr)):
- return False, ('Incorrect stderr output:\n{ac}\n'
- 'Expected to match regex:\n{ex}'.format(
- ac=status.stderr, ex=self.expected_stderr.pattern))
- return True, ''
- class StdoutNoWiderThan80Columns(SpirvTest):
- """Mixin class for tests that require stdout to 80 characters or narrower.
- To mix in this class, subclasses need to provide expected_stdout as the
- expected stdout output.
- """
- def check_stdout_not_too_wide(self, status):
- if not status.stdout:
- return True, ''
- else:
- for line in status.stdout.splitlines():
- if len(line) > 80:
- return False, ('Stdout line longer than 80 columns: %s' % line)
- return True, ''
- class NoObjectFile(SpirvTest):
- """Mixin class for checking that no input file has a corresponding object
- file."""
- def check_no_object_file(self, status):
- for input_filename in status.input_filenames:
- object_filename = get_object_filename(input_filename)
- full_object_file = os.path.join(status.directory, object_filename)
- print('checking %s' % full_object_file)
- if os.path.isfile(full_object_file):
- return False, (
- 'Expected no object file, but found: %s' % full_object_file)
- return True, ''
- class NoNamedOutputFiles(SpirvTest):
- """Mixin class for checking that no specified output files exist.
- The expected_output_filenames member should be full pathnames."""
- def check_no_named_output_files(self, status):
- for object_filename in self.expected_output_filenames:
- if os.path.isfile(object_filename):
- return False, (
- 'Expected no output file, but found: %s' % object_filename)
- return True, ''
- class ExecutedListOfPasses(SpirvTest):
- """Mixin class for checking that a list of passes where executed.
- It works by analyzing the output of the --print-all flag to spirv-opt.
- For this mixin to work, the class member expected_passes should be a sequence
- of pass names as returned by Pass::name().
- """
- def check_list_of_executed_passes(self, status):
- # Collect all the output lines containing a pass name.
- pass_names = []
- pass_name_re = re.compile(r'.*IR before pass (?P<pass_name>[\S]+)')
- for line in status.stderr.splitlines():
- match = pass_name_re.match(line)
- if match:
- pass_names.append(match.group('pass_name'))
- for (expected, actual) in zip(self.expected_passes, pass_names):
- if expected != actual:
- return False, (
- 'Expected pass "%s" but found pass "%s"\n' % (expected, actual))
- return True, ''
|