nir/tests: Do not rely on __LINE__
__LINE__ can be inconsistent when using different compilers. This patch changes the test runner to do a simple string find/replace of the test source file instead of looking for the line where the reference string starts. Acked-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33980>
This commit is contained in:
@@ -13,15 +13,44 @@ import tempfile
|
|||||||
import textwrap
|
import textwrap
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
class TestFileChange:
|
def trim_blank_lines(string, trailing):
|
||||||
def __init__(self, line, result):
|
lines = string.split('\n')
|
||||||
self.line = line
|
string = ''
|
||||||
self.result = result
|
empty_line = True
|
||||||
|
for i in range(len(lines)):
|
||||||
|
line_index = len(lines) - 1 - i if trailing else i
|
||||||
|
if empty_line and lines[line_index].strip() == '':
|
||||||
|
continue
|
||||||
|
|
||||||
class TestFileChanges:
|
write_newline = not empty_line if trailing else line_index < len(lines) - 1
|
||||||
def __init__(self, name):
|
newline = '\n' if write_newline else ''
|
||||||
self.name = name
|
if trailing:
|
||||||
self.changes = []
|
string = lines[line_index] + newline + string
|
||||||
|
else:
|
||||||
|
string += lines[line_index] + newline
|
||||||
|
|
||||||
|
empty_line = False
|
||||||
|
|
||||||
|
return string
|
||||||
|
|
||||||
|
class TestFileChange:
|
||||||
|
def __init__(self, expected, result):
|
||||||
|
self.expected = expected
|
||||||
|
|
||||||
|
# Apply the indentation of the expectation to the result
|
||||||
|
indentation = 1000
|
||||||
|
for expected_line in expected.split('\n'):
|
||||||
|
if match := re.match(r'^(\s*)\S', expected_line):
|
||||||
|
line_indentation = len(match.group(1))
|
||||||
|
if indentation > line_indentation:
|
||||||
|
indentation = line_indentation
|
||||||
|
|
||||||
|
self.result = ''
|
||||||
|
result = result.split('\n')
|
||||||
|
for i in range(len(result)):
|
||||||
|
result_line = result[i]
|
||||||
|
indentation_str = '' if result_line.strip() == '' else ' '*indentation
|
||||||
|
self.result += indentation_str + result_line + ('\n' if i < len(result) - 1 else '')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
@@ -53,31 +82,52 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
output = subprocess.run(test_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, env=env)
|
output = subprocess.run(test_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, env=env)
|
||||||
|
|
||||||
expected_pattern = re.compile(r'Expected \(([\d\w\W/.-_]+):(\d+)\):')
|
expected_pattern = re.compile(r'BEGIN EXPECTED\(([\d\w\W/.-_]+)\)')
|
||||||
|
|
||||||
test_result = None
|
|
||||||
expectations = collections.defaultdict(list)
|
expectations = collections.defaultdict(list)
|
||||||
|
|
||||||
|
current_file = None
|
||||||
|
current_result = None
|
||||||
|
current_expected = None
|
||||||
|
inside_result = False
|
||||||
|
inside_expected = False
|
||||||
|
|
||||||
# Parse the output of the test binary and gather the changed shaders.
|
# Parse the output of the test binary and gather the changed shaders.
|
||||||
for output_line in output.stdout.split('\n'):
|
for output_line in output.stdout.split('\n'):
|
||||||
if output_line.startswith('Got:'):
|
if output_line.startswith('BEGIN RESULT'):
|
||||||
test_result = ''
|
inside_result = True
|
||||||
|
current_result = ''
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if output_line.startswith('Expected ('):
|
if output_line.startswith('BEGIN EXPECTED'):
|
||||||
match = expected_pattern.match(output_line)
|
match = expected_pattern.match(output_line)
|
||||||
file = match.group(1).removeprefix('../')
|
current_file = match.group(1).removeprefix('../')
|
||||||
line = int(match.group(2))
|
inside_expected = True
|
||||||
|
current_expected = ''
|
||||||
expectations[file].append(TestFileChange(line, test_result.strip()))
|
|
||||||
|
|
||||||
test_result = None
|
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if test_result is not None:
|
if output_line.startswith('END'):
|
||||||
test_result += output_line + '\n'
|
if current_result is not None and current_expected is not None:
|
||||||
|
# remove trailing and leading blank lines
|
||||||
|
current_result = trim_blank_lines(current_result, True)
|
||||||
|
current_result = trim_blank_lines(current_result, False)
|
||||||
|
current_expected = trim_blank_lines(current_expected, True)
|
||||||
|
current_expected = trim_blank_lines(current_expected, False)
|
||||||
|
|
||||||
|
expectations[current_file].append(TestFileChange(current_expected, current_result))
|
||||||
|
|
||||||
|
current_result = None
|
||||||
|
current_expected = None
|
||||||
|
|
||||||
|
inside_result = False
|
||||||
|
inside_expected = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
if inside_result:
|
||||||
|
current_result += output_line + '\n'
|
||||||
|
|
||||||
|
if inside_expected:
|
||||||
|
current_expected += output_line + '\n'
|
||||||
|
|
||||||
patches = []
|
patches = []
|
||||||
|
|
||||||
@@ -86,25 +136,17 @@ if __name__ == '__main__':
|
|||||||
changes = expectations[file]
|
changes = expectations[file]
|
||||||
|
|
||||||
updated_test_file = ''
|
updated_test_file = ''
|
||||||
change_index = 0
|
|
||||||
line_index = 1
|
|
||||||
inside_expectation = False
|
|
||||||
|
|
||||||
with open(file) as test_file:
|
with open(file) as test_file:
|
||||||
for test_line in test_file:
|
updated_test_file = str(test_file.read())
|
||||||
if test_line.strip().startswith(')\"'):
|
|
||||||
inside_expectation = False
|
|
||||||
|
|
||||||
if not inside_expectation:
|
for change in changes:
|
||||||
updated_test_file += test_line
|
updated_test_file = updated_test_file.replace(change.expected, change.result)
|
||||||
|
|
||||||
if change_index < len(changes) and line_index == changes[change_index].line:
|
# change.expected == change.result can be the case when using NIR_TEST_DUMP_SHADERS.
|
||||||
inside_expectation = True
|
if change.expected in updated_test_file and change.expected != change.result:
|
||||||
indentation = len(test_line) - len(test_line.lstrip()) + 3
|
print(f'Duplicate test case in {file}!')
|
||||||
updated_test_file += textwrap.indent(changes[change_index].result, " " * indentation) + '\n'
|
exit(1)
|
||||||
change_index += 1
|
|
||||||
|
|
||||||
line_index += 1
|
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(delete_on_close=False) as tmp:
|
with tempfile.NamedTemporaryFile(delete_on_close=False) as tmp:
|
||||||
tmp.write(bytes(updated_test_file, encoding="utf-8"))
|
tmp.write(bytes(updated_test_file, encoding="utf-8"))
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
struct nir_reference_shader {
|
struct nir_reference_shader {
|
||||||
const char *string;
|
const char *string;
|
||||||
const char *file;
|
const char *file;
|
||||||
uint32_t line;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class nir_test : public ::testing::Test {
|
class nir_test : public ::testing::Test {
|
||||||
@@ -121,7 +120,7 @@ class nir_test : public ::testing::Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (failed || debug_get_bool_option("NIR_TEST_DUMP_SHADERS", false))
|
if (failed || debug_get_bool_option("NIR_TEST_DUMP_SHADERS", false))
|
||||||
printf("Got:\n%s\nExpected (%s:%u):\n%s\n", result, reference.file, reference.line, expected);
|
printf("BEGIN RESULT\n%s\nEND\nBEGIN EXPECTED(%s)\n%s\nEND\n", result, reference.file, expected);
|
||||||
|
|
||||||
free(result);
|
free(result);
|
||||||
}
|
}
|
||||||
@@ -131,6 +130,6 @@ class nir_test : public ::testing::Test {
|
|||||||
nir_builder *b;
|
nir_builder *b;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NIR_REFERENCE_SHADER(expected) nir_reference_shader{.string = expected, .file = __FILE__, .line = __LINE__}
|
#define NIR_REFERENCE_SHADER(expected) nir_reference_shader{.string = expected, .file = __FILE__}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user