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