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
32using AbstractTestReference = const AbstractTest *;
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 tblJson["action_profile"] = actionProfile->getProfileDecl()->controlPlaneName();
94 // Check if we have an Action Selector too.
95 // TODO: Change this to check in ActionSelector with table
96 // property "action_selectors".
97 const auto *asObject = tblConfig->getProperty("action_selector"_cs, false);
98 if (asObject != nullptr) {
99 const auto *actionSelector = asObject->checkedTo<SelectorType>();
100 apAsMap[actionProfile->getProfileDecl()->controlPlaneName()] =
101 actionSelector->getSelectorDecl()->controlPlaneName();
102 tblJson["has_as"] = true;
103 tblJson["action_selector"] = actionSelector->getSelectorDecl()->controlPlaneName();
104 }
105 }
106 }
107
110 static void checkForDefaultActionOverride(inja::json &tblJson, const TableConfig *tblConfig) {
111 const auto *defaultOverrideObj =
112 tblConfig->getProperty("overriden_default_action"_cs, false);
113 if (defaultOverrideObj != nullptr) {
114 const auto *defaultAction = defaultOverrideObj->checkedTo<ActionCall>();
115 inja::json a;
116 a["action_name"] = defaultAction->getActionName();
117 auto const *actionArgs = defaultAction->getArgs();
118 inja::json b = inja::json::array();
119 for (const auto &actArg : *actionArgs) {
120 inja::json j;
121 j["param"] = actArg.getActionParamName().c_str();
122 j["value"] = formatHexExpr(actArg.getEvaluatedValue());
123 b.push_back(j);
124 }
125 a["act_args"] = b;
126 tblJson["default_override"] = a;
127 }
128 }
129
131 template <class ProfileType>
132 static void collectActionProfileDeclarations(const TestSpec *testSpec,
133 inja::json &controlPlaneJson,
134 const std::map<cstring, cstring> &apAsMap) {
135 auto actionProfiles = testSpec->getTestObjectCategory("action_profiles"_cs);
136 if (!actionProfiles.empty()) {
137 controlPlaneJson["action_profiles"] = inja::json::array();
138 }
139 for (auto const &testObject : actionProfiles) {
140 const auto *const actionProfile = testObject.second->checkedTo<ProfileType>();
141 const auto *actions = actionProfile->getActions();
142 inja::json j;
143 j["profile"] = actionProfile->getProfileDecl()->controlPlaneName();
144 j["actions"] = inja::json::array();
145 for (size_t idx = 0; idx < actions->size(); ++idx) {
146 const auto &action = actions->at(idx);
147 auto actionName = action.first;
148 auto actionArgs = action.second;
149 inja::json a;
150 a["action_name"] = actionName;
151 a["action_idx"] = std::to_string(idx);
152 inja::json b = inja::json::array();
153 for (const auto &actArg : actionArgs) {
154 inja::json c;
155 c["param"] = actArg.getActionParamName().c_str();
156 c["value"] = formatHexExpr(actArg.getEvaluatedValue()).c_str();
157 b.push_back(c);
158 }
159 a["act_args"] = b;
160 j["actions"].push_back(a);
161 }
162 // Look up the selectors associated with the profile.
163 if (apAsMap.find(actionProfile->getProfileDecl()->controlPlaneName()) !=
164 apAsMap.end()) {
165 j["selector"] = apAsMap.at(actionProfile->getProfileDecl()->controlPlaneName());
166 }
167 controlPlaneJson["action_profiles"].push_back(j);
168 }
169 }
170
172 [[nodiscard]] const TestBackendConfiguration &getTestBackendConfiguration() const;
173
174 public:
175 virtual ~TestFramework() = default;
176
185 virtual void writeTestToFile(const TestSpec *spec, cstring selectedBranches, size_t testIdx,
186 float currentCoverage) = 0;
187
193 virtual AbstractTestReferenceOrError produceTest(const TestSpec *spec, cstring selectedBranches,
194 size_t testIdx, float currentCoverage);
195
197 [[nodiscard]] bool isInFileMode() const;
198};
199
200} // namespace P4::P4Tools::P4Testgen
201
202#endif /* BACKENDS_P4TOOLS_MODULES_TESTGEN_LIB_TEST_FRAMEWORK_H_ */
Definition castable.h:36
Definition lib/test_spec.h:94
cstring getActionName() const
Definition lib/test_spec.cpp:92
Definition lib/test_spec.h:254
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:132
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:110
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:297
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
Type definitions for abstract tests.
Definition test_framework.h:29
Definition test_backend_configuration.h:16