1 /**
2 * Defines tests for validating CPER-JSON IR output from the cper-parse library.
3 *
4 * Author: Lawrence.Tang@arm.com
5 **/
6
7 #include <cctype>
8 #include "gtest/gtest.h"
9 #include "test-utils.hpp"
10 #include <json.h>
11 #include "../cper-parse.h"
12 #include "../json-schema.h"
13 #include "../generator/cper-generate.h"
14 #include "../sections/cper-section.h"
15 #include "../generator/sections/gen-section.h"
16
17 /*
18 * Test templates.
19 */
20
21 //Tests a single randomly generated CPER section of the given type to ensure CPER-JSON IR validity.
cper_log_section_ir_test(const char * section_name,int single_section)22 void cper_log_section_ir_test(const char *section_name, int single_section)
23 {
24 //Generate full CPER record for the given type.
25 char *buf;
26 size_t size;
27 FILE *record = generate_record_memstream(§ion_name, 1, &buf, &size,
28 single_section);
29
30 //Convert to IR, free resources.
31 json_object *ir;
32 if (single_section) {
33 ir = cper_single_section_to_ir(record);
34 } else {
35 ir = cper_to_ir(record);
36 }
37 fclose(record);
38 free(buf);
39
40 //Validate against schema.
41 char error_message[JSON_ERROR_MSG_MAX_LEN] = { 0 };
42 int valid =
43 validate_schema_from_file(LIBCPER_JSON_SPEC, ir, error_message);
44 json_object_put(ir);
45 ASSERT_TRUE(valid)
46 << "IR validation test failed (single section mode = "
47 << single_section << ") with message: " << error_message;
48 }
49
50 //Checks for binary round-trip equality for a given randomly generated CPER record.
cper_log_section_binary_test(const char * section_name,int single_section)51 void cper_log_section_binary_test(const char *section_name, int single_section)
52 {
53 //Generate CPER record for the given type.
54 char *buf;
55 size_t size;
56 FILE *record = generate_record_memstream(§ion_name, 1, &buf, &size,
57 single_section);
58
59 //Convert to IR.
60 json_object *ir;
61 if (single_section) {
62 ir = cper_single_section_to_ir(record);
63 } else {
64 ir = cper_to_ir(record);
65 }
66
67 //Now convert back to binary, and get a stream out.
68 char *cper_buf;
69 size_t cper_buf_size;
70 FILE *stream = open_memstream(&cper_buf, &cper_buf_size);
71 if (single_section) {
72 ir_single_section_to_cper(ir, stream);
73 } else {
74 ir_to_cper(ir, stream);
75 }
76 size_t cper_len = ftell(stream);
77 fclose(stream);
78
79 //Validate the two are identical.
80 ASSERT_GE(size, cper_len);
81 ASSERT_EQ(memcmp(buf, cper_buf, cper_len), 0)
82 << "Binary output was not identical to input (single section mode = "
83 << single_section << ").";
84
85 //Free everything up.
86 fclose(record);
87 free(buf);
88 free(cper_buf);
89 json_object_put(ir);
90 }
91
92 //Tests randomly generated CPER sections for IR validity of a given type, in both single section mode and full CPER log mode.
cper_log_section_dual_ir_test(const char * section_name)93 void cper_log_section_dual_ir_test(const char *section_name)
94 {
95 cper_log_section_ir_test(section_name, 0);
96 cper_log_section_ir_test(section_name, 1);
97 }
98
99 //Tests randomly generated CPER sections for binary compatibility of a given type, in both single section mode and full CPER log mode.
cper_log_section_dual_binary_test(const char * section_name)100 void cper_log_section_dual_binary_test(const char *section_name)
101 {
102 cper_log_section_binary_test(section_name, 0);
103 cper_log_section_binary_test(section_name, 1);
104 }
105
106 /*
107 * Non-single section assertions.
108 */
TEST(CompileTimeAssertions,TwoWayConversion)109 TEST(CompileTimeAssertions, TwoWayConversion)
110 {
111 for (size_t i = 0; i < section_definitions_len; i++) {
112 //If a conversion one way exists, a conversion the other way must exist.
113 std::string err =
114 "If a CPER conversion exists one way, there must be an equivalent method in reverse.";
115 if (section_definitions[i].ToCPER != NULL) {
116 ASSERT_NE(section_definitions[i].ToIR, nullptr) << err;
117 }
118 if (section_definitions[i].ToIR != NULL) {
119 ASSERT_NE(section_definitions[i].ToCPER, nullptr)
120 << err;
121 }
122 }
123 }
124
TEST(CompileTimeAssertions,ShortcodeNoSpaces)125 TEST(CompileTimeAssertions, ShortcodeNoSpaces)
126 {
127 for (size_t i = 0; i < generator_definitions_len; i++) {
128 for (int j = 0;
129 generator_definitions[i].ShortName[j + 1] != '\0'; j++) {
130 ASSERT_FALSE(
131 isspace(generator_definitions[i].ShortName[j]))
132 << "Illegal space character detected in shortcode '"
133 << generator_definitions[i].ShortName << "'.";
134 }
135 }
136 }
137
138 /*
139 * Single section tests.
140 */
141
142 //Generic processor tests.
TEST(GenericProcessorTests,IRValid)143 TEST(GenericProcessorTests, IRValid)
144 {
145 cper_log_section_dual_ir_test("generic");
146 }
TEST(GenericProcessorTests,BinaryEqual)147 TEST(GenericProcessorTests, BinaryEqual)
148 {
149 cper_log_section_dual_binary_test("generic");
150 }
151
152 //IA32/x64 tests.
TEST(IA32x64Tests,IRValid)153 TEST(IA32x64Tests, IRValid)
154 {
155 cper_log_section_dual_ir_test("ia32x64");
156 }
TEST(IA32x64Tests,BinaryEqual)157 TEST(IA32x64Tests, BinaryEqual)
158 {
159 cper_log_section_dual_binary_test("ia32x64");
160 }
161
162 // TEST(IPFTests, IRValid) {
163 // cper_log_section_dual_ir_test("ipf");
164 // }
165
166 //ARM tests.
TEST(ArmTests,IRValid)167 TEST(ArmTests, IRValid)
168 {
169 cper_log_section_dual_ir_test("arm");
170 }
TEST(ArmTests,BinaryEqual)171 TEST(ArmTests, BinaryEqual)
172 {
173 cper_log_section_dual_binary_test("arm");
174 }
175
176 //Memory tests.
TEST(MemoryTests,IRValid)177 TEST(MemoryTests, IRValid)
178 {
179 cper_log_section_dual_ir_test("memory");
180 }
TEST(MemoryTests,BinaryEqual)181 TEST(MemoryTests, BinaryEqual)
182 {
183 cper_log_section_dual_binary_test("memory");
184 }
185
186 //Memory 2 tests.
TEST(Memory2Tests,IRValid)187 TEST(Memory2Tests, IRValid)
188 {
189 cper_log_section_dual_ir_test("memory2");
190 }
TEST(Memory2Tests,BinaryEqual)191 TEST(Memory2Tests, BinaryEqual)
192 {
193 cper_log_section_dual_binary_test("memory2");
194 }
195
196 //PCIe tests.
TEST(PCIeTests,IRValid)197 TEST(PCIeTests, IRValid)
198 {
199 cper_log_section_dual_ir_test("pcie");
200 }
TEST(PCIeTests,BinaryEqual)201 TEST(PCIeTests, BinaryEqual)
202 {
203 cper_log_section_dual_binary_test("pcie");
204 }
205
206 //Firmware tests.
TEST(FirmwareTests,IRValid)207 TEST(FirmwareTests, IRValid)
208 {
209 cper_log_section_dual_ir_test("firmware");
210 }
TEST(FirmwareTests,BinaryEqual)211 TEST(FirmwareTests, BinaryEqual)
212 {
213 cper_log_section_dual_binary_test("firmware");
214 }
215
216 //PCI Bus tests.
TEST(PCIBusTests,IRValid)217 TEST(PCIBusTests, IRValid)
218 {
219 cper_log_section_dual_ir_test("pcibus");
220 }
TEST(PCIBusTests,BinaryEqual)221 TEST(PCIBusTests, BinaryEqual)
222 {
223 cper_log_section_dual_binary_test("pcibus");
224 }
225
226 //PCI Device tests.
TEST(PCIDevTests,IRValid)227 TEST(PCIDevTests, IRValid)
228 {
229 cper_log_section_dual_ir_test("pcidev");
230 }
TEST(PCIDevTests,BinaryEqual)231 TEST(PCIDevTests, BinaryEqual)
232 {
233 cper_log_section_dual_binary_test("pcidev");
234 }
235
236 //Generic DMAr tests.
TEST(DMArGenericTests,IRValid)237 TEST(DMArGenericTests, IRValid)
238 {
239 cper_log_section_dual_ir_test("dmargeneric");
240 }
TEST(DMArGenericTests,BinaryEqual)241 TEST(DMArGenericTests, BinaryEqual)
242 {
243 cper_log_section_dual_binary_test("dmargeneric");
244 }
245
246 //VT-d DMAr tests.
TEST(DMArVtdTests,IRValid)247 TEST(DMArVtdTests, IRValid)
248 {
249 cper_log_section_dual_ir_test("dmarvtd");
250 }
TEST(DMArVtdTests,BinaryEqual)251 TEST(DMArVtdTests, BinaryEqual)
252 {
253 cper_log_section_dual_binary_test("dmarvtd");
254 }
255
256 //IOMMU DMAr tests.
TEST(DMArIOMMUTests,IRValid)257 TEST(DMArIOMMUTests, IRValid)
258 {
259 cper_log_section_dual_ir_test("dmariommu");
260 }
TEST(DMArIOMMUTests,BinaryEqual)261 TEST(DMArIOMMUTests, BinaryEqual)
262 {
263 cper_log_section_dual_binary_test("dmariommu");
264 }
265
266 //CCIX PER tests.
TEST(CCIXPERTests,IRValid)267 TEST(CCIXPERTests, IRValid)
268 {
269 cper_log_section_dual_ir_test("ccixper");
270 }
TEST(CCIXPERTests,BinaryEqual)271 TEST(CCIXPERTests, BinaryEqual)
272 {
273 cper_log_section_dual_binary_test("ccixper");
274 }
275
276 //CXL Protocol tests.
TEST(CXLProtocolTests,IRValid)277 TEST(CXLProtocolTests, IRValid)
278 {
279 cper_log_section_dual_ir_test("cxlprotocol");
280 }
TEST(CXLProtocolTests,BinaryEqual)281 TEST(CXLProtocolTests, BinaryEqual)
282 {
283 cper_log_section_dual_binary_test("cxlprotocol");
284 }
285
286 //CXL Component tests.
TEST(CXLComponentTests,IRValid)287 TEST(CXLComponentTests, IRValid)
288 {
289 cper_log_section_dual_ir_test("cxlcomponent-media");
290 }
TEST(CXLComponentTests,BinaryEqual)291 TEST(CXLComponentTests, BinaryEqual)
292 {
293 cper_log_section_dual_binary_test("cxlcomponent-media");
294 }
295
296 //NVIDIA section tests.
TEST(NVIDIASectionTests,IRValid)297 TEST(NVIDIASectionTests, IRValid)
298 {
299 cper_log_section_dual_ir_test("nvidia");
300 }
TEST(NVIDIASectionTests,BinaryEqual)301 TEST(NVIDIASectionTests, BinaryEqual)
302 {
303 cper_log_section_dual_binary_test("nvidia");
304 }
305
306 //Unknown section tests.
TEST(UnknownSectionTests,IRValid)307 TEST(UnknownSectionTests, IRValid)
308 {
309 cper_log_section_dual_ir_test("unknown");
310 }
TEST(UnknownSectionTests,BinaryEqual)311 TEST(UnknownSectionTests, BinaryEqual)
312 {
313 cper_log_section_dual_binary_test("unknown");
314 }
315
316 //Entrypoint for the testing program.
main()317 int main()
318 {
319 testing::InitGoogleTest();
320 return RUN_ALL_TESTS();
321 }
322