CIRCT 20.0.0git
Loading...
Searching...
No Matches
Tester.cpp
Go to the documentation of this file.
1//===- Tester.cpp ---------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the Tester class used in the CIRCT reduce tool.
10//
11//===----------------------------------------------------------------------===//
12
13#include "circt/Reduce/Tester.h"
14#include "mlir/IR/Verifier.h"
15#include "llvm/Support/ToolOutputFile.h"
16
17using namespace llvm;
18using namespace mlir;
19using namespace circt;
20
21//===----------------------------------------------------------------------===//
22// Tester
23//===----------------------------------------------------------------------===//
24
25Tester::Tester(StringRef testScript, ArrayRef<std::string> testScriptArgs,
26 bool testMustFail)
27 : testScript(testScript), testScriptArgs(testScriptArgs),
28 testMustFail(testMustFail) {}
29
30std::pair<bool, size_t> Tester::isInteresting(ModuleOp module) const {
31 auto test = get(module);
32 return std::make_pair(test.isInteresting(), test.getSize());
33}
34
35/// Runs the interestingness testing script on a MLIR test case file. Returns
36/// true if the interesting behavior is present in the test case or false
37/// otherwise.
38bool Tester::isInteresting(StringRef testCase) const {
39 // Assemble the arguments to the tester. Note that the first one has to be the
40 // name of the program.
41 SmallVector<StringRef> testerArgs;
42 testerArgs.push_back(testScript);
43 testerArgs.append(testScriptArgs.begin(), testScriptArgs.end());
44 testerArgs.push_back(testCase);
45
46 // Run the tester.
47 std::string errMsg;
48 int result = llvm::sys::ExecuteAndWait(
49 testScript, testerArgs, /*Env=*/std::nullopt, /*Redirects=*/std::nullopt,
50 /*SecondsToWait=*/0, /*MemoryLimit=*/0, &errMsg);
51 if (result < 0)
52 llvm::report_fatal_error(
53 Twine("Error running interestingness test: ") + errMsg, false);
54
55 if (testMustFail)
56 return result > 0;
57
58 return result == 0;
59}
60
61/// Create a new test case for the given `module`.
62TestCase Tester::get(mlir::ModuleOp module) const {
63 return TestCase(*this, module);
64}
65
66/// Create a new test case for the given file already on disk.
67TestCase Tester::get(llvm::Twine filepath) const {
68 return TestCase(*this, filepath);
69}
70
71//===----------------------------------------------------------------------===//
72// Test Case
73//===----------------------------------------------------------------------===//
74
75/// Check whether the MLIR module is valid. Actual validation is only
76/// performed on the first call; subsequent calls return the cached result.
78 // Assume already-provided test cases on disk are valid.
79 if (!module)
80 return true;
81 if (!valid)
82 valid = succeeded(verify(module));
83 return *valid;
84}
85
86/// Determine the path to the MLIR module on disk. Actual writing to disk is
87/// only performed on the first call; subsequent calls return the cached result.
89 if (!isValid())
90 return "";
92 return filepath;
93}
94
95/// Determine the size of the MLIR module on disk. Actual writing to disk is
96/// only performed on the first call; subsequent calls return the cached result.
98 if (!isValid())
99 return 0;
101 return *size;
102}
103
104/// Run the tester on the MLIR module and return whether it is deemed
105/// interesting. Actual testing is only performed on the first call; subsequent
106/// calls return the cached result.
108 if (!isValid())
109 return false;
111 if (!interesting)
113 return *interesting;
114}
115
116/// Ensure `filepath` and `size` are populated, and that the test case is in a
117/// file on disk.
119 // Write the module to a temporary file if no already-prepared file path has
120 // been provided to the test.
121 if (filepath.empty()) {
122 assert(module);
123
124 // Pick a temporary output file path.
125 int fd;
126 std::error_code ec = llvm::sys::fs::createTemporaryFile(
127 "circt-reduce", "mlir", fd, filepath);
128 if (ec)
129 llvm::report_fatal_error(
130 Twine("Error making unique filename: ") + ec.message(), false);
131
132 // Write to the output.
133 file = std::make_unique<llvm::ToolOutputFile>(filepath, fd);
134 module.print(file->os());
135 file->os().close();
136 if (file->os().has_error())
137 llvm::report_fatal_error(llvm::Twine("Error emitting the IR to file `") +
138 filepath + "`",
139 false);
140
141 // Update the file size.
142 size = file->os().tell();
143 return;
144 }
145
146 // Otherwise just determine the size of the already-prepared file on disk.
147 if (!size) {
148 uint64_t fileSize;
149 std::error_code ec = llvm::sys::fs::file_size(filepath, fileSize);
150 if (ec)
151 llvm::report_fatal_error(Twine("Error determining size of file `") +
152 filepath + "`: " + ec.message(),
153 false);
154 size = fileSize;
155 }
156}
assert(baseType &&"element must be base type")
A single test case to be run by a tester.
Definition Tester.h:74
std::optional< bool > interesting
Whether the tester has run on this test case, and its result.
Definition Tester.h:132
mlir::ModuleOp llvm::SmallString< 32 > filepath
The module to be tested.
Definition Tester.h:118
size_t getSize()
Determine the size of the MLIR module on disk.
Definition Tester.cpp:97
bool isValid()
Check whether the MLIR module is valid.
Definition Tester.cpp:77
std::optional< size_t > size
Whether the size of the test case on disk has already been determined, and if yes,...
Definition Tester.h:130
void ensureFileOnDisk()
Ensure filepath and size are populated, and that the test case is in a file on disk.
Definition Tester.cpp:118
std::optional< bool > valid
Whether the MLIR module validation has run, and its result.
Definition Tester.h:127
bool isInteresting()
Run the tester on the MLIR module and return whether it is deemed interesting.
Definition Tester.cpp:107
const Tester & tester
The tester that is used to run this test case.
Definition Tester.h:114
llvm::StringRef getFilepath()
Determine the path to the MLIR module on disk.
Definition Tester.cpp:88
std::unique_ptr< llvm::ToolOutputFile > file
In case this test case has created a temporary file on disk, this is the ToolOutputFile that did the ...
Definition Tester.h:124
llvm::StringRef testScript
The binary to execute in order to check a reduction attempt for interestingness.
Definition Tester.h:59
Tester(llvm::StringRef testScript, llvm::ArrayRef< std::string > testScriptArgs, bool testMustFail)
Definition Tester.cpp:25
std::pair< bool, size_t > isInteresting(mlir::ModuleOp module) const
Runs the interestingness testing script on a MLIR test case file.
bool testMustFail
Consider the testcase to be interesting if it fails rather than on exit code 0.
Definition Tester.h:66
TestCase get(mlir::ModuleOp module) const
Create a new test case for the given module.
Definition Tester.cpp:62
llvm::ArrayRef< std::string > testScriptArgs
Additional arguments to pass to testScript.
Definition Tester.h:62
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.