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 P4::P4Tools::P4Testgen {
25
26using namespace P4::literals;
27
33using AbstractTestReferenceOrError = std::optional<AbstractTestReference>;
34using AbstractTestList = std::vector<AbstractTestReference>;
35
38template <class ConcreteTest,
39 typename = std::enable_if_t<std::is_base_of_v<AbstractTest, ConcreteTest>>>
40std::vector<const ConcreteTest *> convertAbstractTestsToConcreteTests(
41 const P4Tools::P4Testgen::AbstractTestList &testList) {
42 std::vector<const ConcreteTest *> result;
43 std::transform(testList.begin(), testList.end(), std::back_inserter(result),
44 [](AbstractTestReference test) { return test->checkedTo<ConcreteTest>(); });
45 return result;
46}
47
50using OptionalFilePath = std::optional<std::filesystem::path>;
51
55 private:
57 std::reference_wrapper<const TestBackendConfiguration> testBackendConfiguration;
58
59 protected:
61 explicit TestFramework(const TestBackendConfiguration &testBackendConfiguration);
62
66 static inja::json getTrace(const TestSpec *testSpec, bool stripNewline = true) {
67 inja::json traceList = inja::json::array();
68 const auto *traces = testSpec->getTraces();
69 if (traces != nullptr) {
70 for (const auto &trace : *traces) {
71 std::stringstream ss;
72 ss << trace;
73 std::string traceStr = ss.str();
74 if (stripNewline) {
75 traceStr.erase(std::remove(traceStr.begin(), traceStr.end(), '\n'),
76 traceStr.cend());
77 }
78 traceList.push_back(traceStr);
79 }
80 }
81 return traceList;
82 }
83
86 template <class ProfileType, class SelectorType>
87 static void checkForTableActionProfile(inja::json &tblJson, std::map<cstring, cstring> &apAsMap,
88 const TableConfig *tblConfig) {
89 const auto *apObject = tblConfig->getProperty("action_profile"_cs, false);
90 if (apObject != nullptr) {
91 const auto *actionProfile = apObject->checkedTo<ProfileType>();
92 tblJson["has_ap"] = true;
93 // Check if we have an Action Selector too.
94 // TODO: Change this to check in ActionSelector with table
95 // property "action_selectors".
96 const auto *asObject = tblConfig->getProperty("action_selector"_cs, false);
97 if (asObject != nullptr) {
98 const auto *actionSelector = asObject->checkedTo<SelectorType>();
99 apAsMap[actionProfile->getProfileDecl()->controlPlaneName()] =
100 actionSelector->getSelectorDecl()->controlPlaneName();
101 tblJson["has_as"] = true;
102 }
103 }
104 }
105
108 static void checkForDefaultActionOverride(inja::json &tblJson, const TableConfig *tblConfig) {
109 const auto *defaultOverrideObj =
110 tblConfig->getProperty("overriden_default_action"_cs, false);
111 if (defaultOverrideObj != nullptr) {
112 const auto *defaultAction = defaultOverrideObj->checkedTo<ActionCall>();
113 inja::json a;
114 a["action_name"] = defaultAction->getActionName();
115 auto const *actionArgs = defaultAction->getArgs();
116 inja::json b = inja::json::array();
117 for (const auto &actArg : *actionArgs) {
118 inja::json j;
119 j["param"] = actArg.getActionParamName().c_str();
120 j["value"] = formatHexExpr(actArg.getEvaluatedValue());
121 b.push_back(j);
122 }
123 a["act_args"] = b;
124 tblJson["default_override"] = a;
125 }
126 }
127
129 template <class ProfileType>
130 static void collectActionProfileDeclarations(const TestSpec *testSpec,
131 inja::json &controlPlaneJson,
132 const std::map<cstring, cstring> &apAsMap) {
133 auto actionProfiles = testSpec->getTestObjectCategory("action_profiles"_cs);
134 if (!actionProfiles.empty()) {
135 controlPlaneJson["action_profiles"] = inja::json::array();
136 }
137 for (auto const &testObject : actionProfiles) {
138 const auto *const actionProfile = testObject.second->checkedTo<ProfileType>();
139 const auto *actions = actionProfile->getActions();
140 inja::json j;
141 j["profile"] = actionProfile->getProfileDecl()->controlPlaneName();
142 j["actions"] = inja::json::array();
143 for (size_t idx = 0; idx < actions->size(); ++idx) {
144 const auto &action = actions->at(idx);
145 auto actionName = action.first;
146 auto actionArgs = action.second;
147 inja::json a;
148 a["action_name"] = actionName;
149 a["action_idx"] = std::to_string(idx);
150 inja::json b = inja::json::array();
151 for (const auto &actArg : actionArgs) {
152 inja::json c;
153 c["param"] = actArg.getActionParamName().c_str();
154 c["value"] = formatHexExpr(actArg.getEvaluatedValue()).c_str();
155 b.push_back(c);
156 }
157 a["act_args"] = b;
158 j["actions"].push_back(a);
159 }
160 // Look up the selectors associated with the profile.
161 if (apAsMap.find(actionProfile->getProfileDecl()->controlPlaneName()) !=
162 apAsMap.end()) {
163 j["selector"] = apAsMap.at(actionProfile->getProfileDecl()->controlPlaneName());
164 }
165 controlPlaneJson["action_profiles"].push_back(j);
166 }
167 }
168
170 [[nodiscard]] const TestBackendConfiguration &getTestBackendConfiguration() const;
171
172 public:
173 virtual ~TestFramework() = default;
174
183 virtual void writeTestToFile(const TestSpec *spec, cstring selectedBranches, size_t testIdx,
184 float currentCoverage) = 0;
185
191 virtual AbstractTestReferenceOrError produceTest(const TestSpec *spec, cstring selectedBranches,
192 size_t testIdx, float currentCoverage);
193
195 [[nodiscard]] bool isInFileMode() const;
196};
197
198} // namespace P4::P4Tools::P4Testgen
199
200#endif /* BACKENDS_P4TOOLS_MODULES_TESTGEN_LIB_TEST_FRAMEWORK_H_ */
Definition castable.h:36
Definition lib/test_spec.h:93
cstring getActionName() const
Definition lib/test_spec.cpp:92
Definition lib/test_spec.h:253
const TestObject * getProperty(cstring propertyName, bool checked) const
Definition lib/test_spec.cpp:230
Definition test_framework.h:54
static void checkForTableActionProfile(inja::json &tblJson, std::map< cstring, cstring > &apAsMap, const TableConfig *tblConfig)
Definition test_framework.h:87
virtual AbstractTestReferenceOrError produceTest(const TestSpec *spec, cstring selectedBranches, size_t testIdx, float currentCoverage)
Definition test_framework.cpp:18
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:130
virtual void writeTestToFile(const TestSpec *spec, cstring selectedBranches, size_t testIdx, float currentCoverage)=0
static void checkForDefaultActionOverride(inja::json &tblJson, const TableConfig *tblConfig)
Definition test_framework.h:108
TestFramework(const TestBackendConfiguration &testBackendConfiguration)
Creates a generic test framework.
Definition test_framework.cpp:7
bool isInFileMode() const
@Returns true if the test framework is configured to write to a file.
Definition test_framework.cpp:14
const TestBackendConfiguration & getTestBackendConfiguration() const
Returns the configuration options for the test back end.
Definition test_framework.cpp:10
static inja::json getTrace(const TestSpec *testSpec, bool stripNewline=true)
Definition test_framework.h:66
Definition lib/test_spec.h:296
const std::vector< std::reference_wrapper< const TraceEvent > > * getTraces() const
Definition lib/test_spec.cpp:281
TestObjectMap getTestObjectCategory(cstring category) const
Definition lib/test_spec.cpp:303
Definition cstring.h:85
std::string formatHexExpr(const IR::Expression *expr, const FormatOptions &formatOptions)
Definition common/lib/format_int.cpp:185
Definition cstring.h:80
Type definitions for abstract tests.
Definition test_framework.h:29
Definition test_backend_configuration.h:16