P4C
The P4 Compiler
 
Loading...
Searching...
No Matches
test_framework.h
1#ifndef BACKENDS_P4TOOLS_MODULES_TESTGEN_LIB_TEST_FRAMEWORK_H_
2#define BACKENDS_P4TOOLS_MODULES_TESTGEN_LIB_TEST_FRAMEWORK_H_
3
4#include <cstddef>
5#include <filesystem>
6#include <functional>
7#include <iosfwd>
8#include <map>
9#include <optional>
10#include <string>
11#include <utility>
12
13#include <inja/inja.hpp>
14
15#include "backends/p4tools/common/lib/format_int.h"
16#include "backends/p4tools/common/lib/trace_event.h"
17#include "lib/castable.h"
18#include "lib/cstring.h"
19
20#include "backends/p4tools/modules/testgen/lib/test_backend_configuration.h"
21#include "backends/p4tools/modules/testgen/lib/test_object.h"
22#include "backends/p4tools/modules/testgen/lib/test_spec.h"
23
24namespace P4Tools::P4Testgen {
25
31using AbstractTestReferenceOrError = std::optional<AbstractTestReference>;
32using AbstractTestList = std::vector<AbstractTestReference>;
33
36template <class ConcreteTest,
37 typename = std::enable_if_t<std::is_base_of_v<AbstractTest, ConcreteTest>>>
38std::vector<const ConcreteTest *> convertAbstractTestsToConcreteTests(
39 const P4Tools::P4Testgen::AbstractTestList &testList) {
40 std::vector<const ConcreteTest *> result;
41 std::transform(testList.begin(), testList.end(), std::back_inserter(result),
42 [](AbstractTestReference test) { return test->checkedTo<ConcreteTest>(); });
43 return result;
44}
45
48using OptionalFilePath = std::optional<std::filesystem::path>;
49
53 private:
55 std::reference_wrapper<const TestBackendConfiguration> testBackendConfiguration;
56
57 protected:
59 explicit TestFramework(const TestBackendConfiguration &testBackendConfiguration);
60
62 static inja::json getTrace(const TestSpec *testSpec) {
63 inja::json traceList = inja::json::array();
64 const auto *traces = testSpec->getTraces();
65 if (traces != nullptr) {
66 for (const auto &trace : *traces) {
67 std::stringstream ss;
68 ss << trace;
69 traceList.push_back(ss.str());
70 }
71 }
72 return traceList;
73 }
74
77 template <class ProfileType, class SelectorType>
78 static void checkForTableActionProfile(inja::json &tblJson, std::map<cstring, cstring> &apAsMap,
79 const TableConfig *tblConfig) {
80 const auto *apObject = tblConfig->getProperty("action_profile", false);
81 if (apObject != nullptr) {
82 const auto *actionProfile = apObject->checkedTo<ProfileType>();
83 tblJson["has_ap"] = true;
84 // Check if we have an Action Selector too.
85 // TODO: Change this to check in ActionSelector with table
86 // property "action_selectors".
87 const auto *asObject = tblConfig->getProperty("action_selector", false);
88 if (asObject != nullptr) {
89 const auto *actionSelector = asObject->checkedTo<SelectorType>();
90 apAsMap[actionProfile->getProfileDecl()->controlPlaneName()] =
91 actionSelector->getSelectorDecl()->controlPlaneName();
92 tblJson["has_as"] = true;
93 }
94 }
95 }
96
99 static void checkForDefaultActionOverride(inja::json &tblJson, const TableConfig *tblConfig) {
100 const auto *defaultOverrideObj = tblConfig->getProperty("overriden_default_action", false);
101 if (defaultOverrideObj != nullptr) {
102 const auto *defaultAction = defaultOverrideObj->checkedTo<ActionCall>();
103 inja::json a;
104 a["action_name"] = defaultAction->getActionName();
105 auto const *actionArgs = defaultAction->getArgs();
106 inja::json b = inja::json::array();
107 for (const auto &actArg : *actionArgs) {
108 inja::json j;
109 j["param"] = actArg.getActionParamName().c_str();
110 j["value"] = formatHexExpr(actArg.getEvaluatedValue());
111 b.push_back(j);
112 }
113 a["act_args"] = b;
114 tblJson["default_override"] = a;
115 }
116 }
117
119 template <class ProfileType>
120 static void collectActionProfileDeclarations(const TestSpec *testSpec,
121 inja::json &controlPlaneJson,
122 const std::map<cstring, cstring> &apAsMap) {
123 auto actionProfiles = testSpec->getTestObjectCategory("action_profiles");
124 if (!actionProfiles.empty()) {
125 controlPlaneJson["action_profiles"] = inja::json::array();
126 }
127 for (auto const &testObject : actionProfiles) {
128 const auto *const actionProfile = testObject.second->checkedTo<ProfileType>();
129 const auto *actions = actionProfile->getActions();
130 inja::json j;
131 j["profile"] = actionProfile->getProfileDecl()->controlPlaneName();
132 j["actions"] = inja::json::array();
133 for (size_t idx = 0; idx < actions->size(); ++idx) {
134 const auto &action = actions->at(idx);
135 auto actionName = action.first;
136 auto actionArgs = action.second;
137 inja::json a;
138 a["action_name"] = actionName;
139 a["action_idx"] = std::to_string(idx);
140 inja::json b = inja::json::array();
141 for (const auto &actArg : actionArgs) {
142 inja::json c;
143 c["param"] = actArg.getActionParamName().c_str();
144 c["value"] = formatHexExpr(actArg.getEvaluatedValue()).c_str();
145 b.push_back(c);
146 }
147 a["act_args"] = b;
148 j["actions"].push_back(a);
149 }
150 // Look up the selectors associated with the profile.
151 if (apAsMap.find(actionProfile->getProfileDecl()->controlPlaneName()) !=
152 apAsMap.end()) {
153 j["selector"] = apAsMap.at(actionProfile->getProfileDecl()->controlPlaneName());
154 }
155 controlPlaneJson["action_profiles"].push_back(j);
156 }
157 }
158
160 [[nodiscard]] const TestBackendConfiguration &getTestBackendConfiguration() const;
161
162 public:
163 virtual ~TestFramework() = default;
164
173 virtual void writeTestToFile(const TestSpec *spec, cstring selectedBranches, size_t testIdx,
174 float currentCoverage) = 0;
175
181 virtual AbstractTestReferenceOrError produceTest(const TestSpec *spec, cstring selectedBranches,
182 size_t testIdx, float currentCoverage);
183
185 [[nodiscard]] bool isInFileMode() const;
186};
187
188} // namespace P4Tools::P4Testgen
189
190#endif /* BACKENDS_P4TOOLS_MODULES_TESTGEN_LIB_TEST_FRAMEWORK_H_ */
Definition castable.h:34
const T * checkedTo() const
Performs a checked cast. A BUG occurs if the cast fails.
Definition castable.h:52
Definition test_spec.h:93
cstring getActionName() const
Definition test_spec.cpp:90
Definition test_spec.h:253
const TestObject * getProperty(cstring propertyName, bool checked) const
Definition test_spec.cpp:228
Definition test_framework.h:52
static void checkForTableActionProfile(inja::json &tblJson, std::map< cstring, cstring > &apAsMap, const TableConfig *tblConfig)
Definition test_framework.h:78
bool isInFileMode() const
@Returns true if the test framework is configured to write to a file.
Definition test_framework.cpp:14
static inja::json getTrace(const TestSpec *testSpec)
Converts the traces of this test into a string representation and Inja object.
Definition test_framework.h:62
TestFramework(const TestBackendConfiguration &testBackendConfiguration)
Creates a generic test framework.
Definition test_framework.cpp:7
static void checkForDefaultActionOverride(inja::json &tblJson, const TableConfig *tblConfig)
Definition test_framework.h:99
const TestBackendConfiguration & getTestBackendConfiguration() const
Returns the configuration options for the test back end.
Definition test_framework.cpp:10
static void collectActionProfileDeclarations(const TestSpec *testSpec, inja::json &controlPlaneJson, const std::map< cstring, cstring > &apAsMap)
Collect all the action profile objects. These will have to be declared in the test.
Definition test_framework.h:120
virtual AbstractTestReferenceOrError produceTest(const TestSpec *spec, cstring selectedBranches, size_t testIdx, float currentCoverage)
Definition test_framework.cpp:18
virtual void writeTestToFile(const TestSpec *spec, cstring selectedBranches, size_t testIdx, float currentCoverage)=0
Definition test_spec.h:296
TestObjectMap getTestObjectCategory(cstring category) const
Definition test_spec.cpp:301
const std::vector< std::reference_wrapper< const TraceEvent > > * getTraces() const
Definition test_spec.cpp:279
Definition cstring.h:72
std::string formatHexExpr(const IR::Expression *expr, const FormatOptions &formatOptions)
Definition format_int.cpp:197
Type definitions for abstract tests.
Definition test_framework.h:27
Definition test_backend_configuration.h:16