CIRCT  20.0.0git
Tester.h
Go to the documentation of this file.
1 //===- Tester.h -------------------------------------------------*- C++ -*-===//
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 #ifndef CIRCT_REDUCE_TESTER_H
14 #define CIRCT_REDUCE_TESTER_H
15 
16 #include "circt/Support/LLVM.h"
17 #include "mlir/IR/BuiltinOps.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/Support/Error.h"
20 #include "llvm/Support/FileSystem.h"
21 #include "llvm/Support/Program.h"
22 
23 namespace llvm {
24 class ToolOutputFile;
25 } // namespace llvm
26 
27 namespace circt {
28 
29 class TestCase;
30 
31 /// A testing environment for reduction attempts.
32 ///
33 /// This class tracks the program used to check reduction attempts for
34 /// interestingness and additional arguments to pass to that tool. Use `get()`
35 /// to obtain a new test case that can be queried for information on an
36 /// individual MLIR module.
37 class Tester {
38 public:
39  Tester(llvm::StringRef testScript, llvm::ArrayRef<std::string> testScriptArgs,
40  bool testMustFail);
41 
42  /// Runs the interestingness testing script on a MLIR test case file. Returns
43  /// true if the interesting behavior is present in the test case or false
44  /// otherwise.
45  std::pair<bool, size_t> isInteresting(mlir::ModuleOp module) const;
46 
47  /// Return whether the file in the given path is interesting.
48  bool isInteresting(llvm::StringRef testCase) const;
49 
50  /// Create a new test case for the given `module`.
51  TestCase get(mlir::ModuleOp module) const;
52 
53  /// Create a new test case for the given file already on disk.
54  TestCase get(llvm::Twine filepath) const;
55 
56 private:
57  /// The binary to execute in order to check a reduction attempt for
58  /// interestingness.
59  llvm::StringRef testScript;
60 
61  /// Additional arguments to pass to `testScript`.
62  llvm::ArrayRef<std::string> testScriptArgs;
63 
64  /// Consider the testcase to be interesting if it fails rather than on exit
65  /// code 0.
67 };
68 
69 /// A single test case to be run by a tester.
70 ///
71 /// This is a helper object that wraps a `ModuleOp` and can be used to query
72 /// initial information about the test, such as validity of the module and size
73 /// on disk, before the test is actually executed.
74 class TestCase {
75 public:
76  /// Create a test case with an MLIR module that will be written to a temporary
77  /// file on disk. The `TestCase` will clean up the temporary file after use.
78  TestCase(const Tester &tester, mlir::ModuleOp module)
79  : tester(tester), module(module) {}
80 
81  /// Create a test case for an already-prepared file on disk. The caller
82  /// remains responsible for cleaning up the file on disk.
83  TestCase(const Tester &tester, llvm::Twine filepath) : tester(tester) {
84  filepath.toVector(this->filepath);
85  }
86 
87  /// Check whether the MLIR module is valid. Actual validation is only
88  /// performed on the first call; subsequent calls return the cached result.
89  bool isValid();
90 
91  /// Determine the path to the MLIR module on disk. Actual writing to disk is
92  /// only performed on the first call; subsequent calls return the cached
93  /// result.
94  llvm::StringRef getFilepath();
95 
96  /// Determine the size of the MLIR module on disk. Actual writing to disk is
97  /// only performed on the first call; subsequent calls return the cached
98  /// result.
99  size_t getSize();
100 
101  /// Run the tester on the MLIR module and return whether it is deemed
102  /// interesting. Actual testing is only performed on the first call;
103  /// subsequent calls return the cached result.
104  bool isInteresting();
105 
106 private:
107  friend class Tester;
108 
109  /// Ensure `filepath` and `size` are populated, and that the test case is in a
110  /// file on disk.
111  void ensureFileOnDisk();
112 
113  /// The tester that is used to run this test case.
114  const Tester &tester;
115  /// The module to be tested.
116  mlir::ModuleOp module;
117  /// The path on disk where the test case is located.
118  llvm::SmallString<32> filepath;
119 
120  /// In case this test case has created a temporary file on disk, this is the
121  /// `ToolOutputFile` that did the writing. Keeping this class around ensures
122  /// that the file will be cleaned up properly afterwards. This field remains
123  /// null if the user already has provided a filepath in the constructor.
124  std::unique_ptr<llvm::ToolOutputFile> file;
125 
126  /// Whether the MLIR module validation has run, and its result.
127  std::optional<bool> valid;
128  /// Whether the size of the test case on disk has already been determined, and
129  /// if yes, that size.
130  std::optional<size_t> size;
131  /// Whether the tester has run on this test case, and its result.
132  std::optional<bool> interesting;
133 };
134 
135 } // namespace circt
136 
137 #endif // CIRCT_REDUCE_TESTER_H
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
TestCase(const Tester &tester, llvm::Twine filepath)
Create a test case for an already-prepared file on disk.
Definition: Tester.h:83
TestCase(const Tester &tester, mlir::ModuleOp module)
Create a test case with an MLIR module that will be written to a temporary file on disk.
Definition: Tester.h:78
llvm::SmallString< 32 > filepath
The path on disk where the test case is located.
Definition: Tester.h:118
mlir::ModuleOp module
The module to be tested.
Definition: Tester.h:116
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
A testing environment for reduction attempts.
Definition: Tester.h:37
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
bool isInteresting(llvm::StringRef testCase) const
Return whether the file in the given path is interesting.
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
std::pair< bool, size_t > isInteresting(mlir::ModuleOp module) const
Runs the interestingness testing script on a MLIR test case file.
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.
Definition: DebugAnalysis.h:21