xref: /openbmc/libcper/tests/ir-tests.c (revision 7c410e29164b3509cae16ee8297d4226f02674e9)
1 /**
2  * SPDX-License-Identifier: Apache-2.0
3  * SPDX-FileCopyrightText: Copyright OpenBMC Authors
4  *
5  * Defines tests for validating CPER-JSON IR output from the cper-parse library.
6  *
7  * Author: Lawrence.Tang@arm.com
8  **/
9 
10 #include "test-utils.h"
11 #include "string.h"
12 #include "assert.h"
13 #include <ctype.h>
14 #include <json.h>
15 #include <libcper/log.h>
16 #include <libcper/cper-utils.h>
17 
18 #include <libcper/cper-parse.h>
19 #include <libcper/generator/cper-generate.h>
20 #include <libcper/generator/sections/gen-section.h>
21 #include <libcper/json-schema.h>
22 #include <libcper/sections/cper-section.h>
23 #include <libcper/sections/cper-section-nvidia-events.h>
24 
25 #include "base64_test.h"
26 #include "hex_test.h"
27 
28 /*
29 * Test templates.
30 */
31 static const GEN_VALID_BITS_TEST_TYPE allValidbitsSet = ALL_VALID;
32 static const GEN_VALID_BITS_TEST_TYPE fixedValidbitsSet = SOME_VALID;
33 static const int GEN_EXAMPLES = 0;
34 
35 static const char *cper_ext = "cperhex";
36 static const char *json_ext = "json";
37 
38 struct file_info {
39 	char *cper_out;
40 	char *json_out;
41 };
42 
free_file_info(struct file_info * info)43 void free_file_info(struct file_info *info)
44 {
45 	if (info == NULL) {
46 		return;
47 	}
48 	free(info->cper_out);
49 	free(info->json_out);
50 	free(info);
51 }
52 
file_info_init(const char * section_name)53 struct file_info *file_info_init(const char *section_name)
54 {
55 	struct file_info *info = NULL;
56 	char *buf = NULL;
57 	size_t size;
58 	int ret;
59 
60 	info = (struct file_info *)calloc(1, sizeof(struct file_info));
61 	if (info == NULL) {
62 		goto fail;
63 	}
64 
65 	size = strlen(LIBCPER_EXAMPLES) + 1 + strlen(section_name) + 1 +
66 	       strlen(cper_ext) + 1;
67 	info->cper_out = (char *)malloc(size);
68 	ret = snprintf(info->cper_out, size, "%s/%s.%s", LIBCPER_EXAMPLES,
69 		       section_name, cper_ext);
70 	if (ret != (int)size - 1) {
71 		printf("snprintf0 failed\n");
72 		goto fail;
73 	}
74 	size = strlen(LIBCPER_EXAMPLES) + 1 + strlen(section_name) + 1 +
75 	       strlen(json_ext) + 1;
76 	info->json_out = (char *)malloc(size);
77 	ret = snprintf(info->json_out, size, "%s/%s.%s", LIBCPER_EXAMPLES,
78 		       section_name, json_ext);
79 	if (ret != (int)size - 1) {
80 		printf("snprintf3 failed\n");
81 		goto fail;
82 	}
83 	free(buf);
84 	return info;
85 
86 fail:
87 	free(buf);
88 	free_file_info(info);
89 	return NULL;
90 }
91 
cper_create_examples(const char * section_name)92 void cper_create_examples(const char *section_name)
93 {
94 	//Generate full CPER record for the given type.
95 	json_object *ir = NULL;
96 	size_t size;
97 	size_t file_size;
98 	FILE *outFile = NULL;
99 	unsigned char *file_data;
100 	FILE *record = NULL;
101 	char *buf = NULL;
102 	struct file_info *info = file_info_init(section_name);
103 	if (info == NULL) {
104 		goto done;
105 	}
106 
107 	record = generate_record_memstream(&section_name, 1, &buf, &size, 0,
108 					   fixedValidbitsSet);
109 
110 	// Write example CPER to disk
111 	outFile = fopen(info->cper_out, "wb");
112 	if (outFile == NULL) {
113 		printf("Failed to create/open CPER output file: %s\n",
114 		       info->cper_out);
115 		goto done;
116 	}
117 
118 	fseek(record, 0, SEEK_END);
119 	file_size = ftell(record);
120 	rewind(record);
121 	file_data = malloc(file_size);
122 	if (fread(file_data, 1, file_size, record) != file_size) {
123 		printf("Failed to read CPER data from memstream.");
124 		fclose(outFile);
125 		outFile = NULL;
126 		assert(0);
127 
128 		goto done;
129 	}
130 	for (size_t index = 0; index < file_size; index++) {
131 		char hex_str[3];
132 		int out = snprintf(hex_str, sizeof(hex_str), "%02x",
133 				   file_data[index]);
134 		if (out != 2) {
135 			printf("snprintf1 failed\n");
136 			goto done;
137 		}
138 		fwrite(hex_str, sizeof(char), 2, outFile);
139 		if (index % 30 == 29) {
140 			fwrite("\n", sizeof(char), 1, outFile);
141 		}
142 	}
143 	fclose(outFile);
144 	outFile = NULL;
145 
146 	//Convert to IR, free resources.
147 	rewind(record);
148 	ir = cper_to_ir(record);
149 	if (ir == NULL) {
150 		printf("Empty JSON from CPER bin2\n");
151 		assert(0);
152 		goto done;
153 	}
154 
155 	//Write json output to disk
156 	json_object_to_file_ext(info->json_out, ir, JSON_C_TO_STRING_PRETTY);
157 	json_object_put(ir);
158 
159 done:
160 	free_file_info(info);
161 	if (record != NULL) {
162 		fclose(record);
163 	}
164 	if (outFile != NULL) {
165 		fclose(outFile);
166 	}
167 	free(buf);
168 }
169 
hex2int(char ch)170 int hex2int(char ch)
171 {
172 	if ((ch >= '0') && (ch <= '9')) {
173 		return ch - '0';
174 	}
175 	if ((ch >= 'A') && (ch <= 'F')) {
176 		return ch - 'A' + 10;
177 	}
178 	if ((ch >= 'a') && (ch <= 'f')) {
179 		return ch - 'a' + 10;
180 	}
181 	return -1;
182 }
183 
string_to_binary(const char * source,size_t length,unsigned char ** retval)184 int string_to_binary(const char *source, size_t length, unsigned char **retval)
185 {
186 	size_t retval_size = length * 2;
187 	*retval = malloc(retval_size);
188 	int uppernibble = 1;
189 
190 	size_t ret_index = 0;
191 
192 	for (size_t i = 0; i < length; i++) {
193 		char c = source[i];
194 		if (c == '\n') {
195 			continue;
196 		}
197 		int val = hex2int(c);
198 		if (val < 0) {
199 			printf("Invalid hex character in test file: %c at offset %zu\n",
200 			       c, i);
201 			return -1;
202 		}
203 
204 		if (uppernibble) {
205 			(*retval)[ret_index] = (unsigned char)(val << 4);
206 		} else {
207 			(*retval)[ret_index] += (unsigned char)val;
208 			ret_index++;
209 		}
210 		uppernibble = !uppernibble;
211 	}
212 	return ret_index;
213 }
214 
215 //Tests fixed CPER sections for IR validity with an example set.
cper_example_section_ir_test(const char * section_name)216 void cper_example_section_ir_test(const char *section_name)
217 {
218 	printf("cper_example_section_ir_test: %s\n", section_name);
219 	//Open CPER record for the given type.
220 	printf("Testing: %s\n", section_name);
221 	struct file_info *info = file_info_init(section_name);
222 	if (info == NULL) {
223 		return;
224 	}
225 
226 	FILE *cper_file = fopen(info->cper_out, "rb");
227 	if (cper_file == NULL) {
228 		printf("Failed to open CPER file: %s\n", info->cper_out);
229 		free_file_info(info);
230 		assert(0);
231 		return;
232 	}
233 	fseek(cper_file, 0, SEEK_END);
234 	size_t length = ftell(cper_file);
235 	fseek(cper_file, 0, SEEK_SET);
236 	char *buffer = (char *)malloc(length);
237 	if (!buffer) {
238 		free_file_info(info);
239 		return;
240 	}
241 	if (fread(buffer, 1, length, cper_file) != length) {
242 		printf("Failed to read CPER file: %s\n", info->cper_out);
243 		free(buffer);
244 		free_file_info(info);
245 		return;
246 	}
247 	fclose(cper_file);
248 
249 	unsigned char *cper_bin;
250 	int cper_bin_len = string_to_binary(buffer, length, &cper_bin);
251 	if (cper_bin_len <= 0) {
252 		free(buffer);
253 		free_file_info(info);
254 		assert(0);
255 		return;
256 	}
257 	printf("cper_bin: %s\n", cper_bin);
258 	printf("cper_bin_len: %d\n", cper_bin_len);
259 
260 	//Convert to IR, free resources.
261 	json_object *ir = cper_buf_to_ir(cper_bin, cper_bin_len);
262 	if (ir == NULL) {
263 		printf("Empty JSON from CPER bin3\n");
264 		free(cper_bin);
265 		free(buffer);
266 		free_file_info(info);
267 		assert(0);
268 		return;
269 	}
270 
271 	json_object *expected = json_object_from_file(info->json_out);
272 	if (expected == NULL) {
273 		printf("ERROR: Failed to load expected JSON file: %s\n",
274 		       info->json_out);
275 	}
276 	assert(expected != NULL);
277 	if (expected == NULL) {
278 		free(buffer);
279 		free(cper_bin);
280 		free_file_info(info);
281 		const char *str = json_object_to_json_string(ir);
282 
283 		const char *expected_str = json_object_to_json_string(expected);
284 		assert(strcmp(str, expected_str) == 0);
285 		return;
286 	}
287 	cper_print_log("section_name: %s", section_name);
288 
289 	cper_print_log("ir: %s", json_object_to_json_string_ext(
290 					 ir, JSON_C_TO_STRING_PRETTY));
291 	cper_print_log("expected: %s",
292 		       json_object_to_json_string_ext(expected,
293 						      JSON_C_TO_STRING_PRETTY));
294 	assert(json_object_equal(ir, expected));
295 
296 	free(buffer);
297 	free(cper_bin);
298 	json_object_put(ir);
299 	json_object_put(expected);
300 	free_file_info(info);
301 }
302 
303 //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,GEN_VALID_BITS_TEST_TYPE validBitsType)304 void cper_log_section_ir_test(const char *section_name, int single_section,
305 			      GEN_VALID_BITS_TEST_TYPE validBitsType)
306 {
307 	//Generate full CPER record for the given type.
308 	char *buf;
309 	size_t size;
310 	FILE *record = generate_record_memstream(&section_name, 1, &buf, &size,
311 						 single_section, validBitsType);
312 
313 	//Convert to IR, free resources.
314 	json_object *ir;
315 	if (single_section) {
316 		ir = cper_single_section_to_ir(record);
317 	} else {
318 		ir = cper_to_ir(record);
319 	}
320 
321 	fclose(record);
322 	free(buf);
323 
324 	//Validate against schema.
325 	int valid = schema_validate_from_file(ir, single_section,
326 					      /*all_valid_bits*/ 1);
327 	json_object_put(ir);
328 
329 	if (valid < 0) {
330 		printf("IR validation test failed (single section mode = %d)\n",
331 		       single_section);
332 		assert(0);
333 	}
334 }
335 
336 //Tests a single randomly generated CPER section of the given type to ensure CPER-JSON IR validity.
cper_buf_log_section_ir_test(const char * section_name,int single_section,GEN_VALID_BITS_TEST_TYPE validBitsType)337 void cper_buf_log_section_ir_test(const char *section_name, int single_section,
338 				  GEN_VALID_BITS_TEST_TYPE validBitsType)
339 {
340 	//Generate full CPER record for the given type.
341 	char *buf;
342 	size_t size;
343 	FILE *record = generate_record_memstream(&section_name, 1, &buf, &size,
344 						 single_section, validBitsType);
345 
346 	//Convert.
347 	json_object *ir;
348 	if (single_section) {
349 		ir = cper_buf_single_section_to_ir((UINT8 *)buf, size);
350 	} else {
351 		ir = cper_buf_to_ir((UINT8 *)buf, size);
352 	}
353 	fclose(record);
354 	free(buf);
355 
356 	if (!ir) {
357 		printf("IR validation test failed (%d) : json object empty \n",
358 		       single_section);
359 		assert(0);
360 	}
361 
362 	//Validate against schema.
363 	int valid = schema_validate_from_file(ir, single_section,
364 					      /*all_valid_bits*/ 1);
365 	json_object_put(ir);
366 
367 	if (valid < 0) {
368 		printf("IR validation test failed (single section mode = %d)\n",
369 		       single_section);
370 		assert(0);
371 	}
372 }
373 
to_hex(const unsigned char * input,size_t size,char ** out)374 int to_hex(const unsigned char *input, size_t size, char **out)
375 {
376 	*out = (char *)malloc(size * 2);
377 	if (out == NULL) {
378 		return -1;
379 	}
380 	int out_index = 0;
381 	for (size_t i = 0; i < size; i++) {
382 		unsigned char c = input[i];
383 		char hex_str[3];
384 		int n = snprintf(hex_str, sizeof(hex_str), "%02x", c);
385 		if (n != 2) {
386 			printf("snprintf2 failed with code %d\n", n);
387 			return -1;
388 		}
389 		(*out)[out_index] = hex_str[0];
390 		out_index++;
391 		(*out)[out_index] = hex_str[1];
392 		out_index++;
393 	}
394 	return out_index;
395 }
396 
397 //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,GEN_VALID_BITS_TEST_TYPE validBitsType)398 void cper_log_section_binary_test(const char *section_name, int single_section,
399 				  GEN_VALID_BITS_TEST_TYPE validBitsType)
400 {
401 	//Generate CPER record for the given type.
402 	char *buf;
403 	size_t size;
404 	FILE *record = generate_record_memstream(&section_name, 1, &buf, &size,
405 						 single_section, validBitsType);
406 	if (record == NULL) {
407 		printf("Could not generate memstream for binary test");
408 		return;
409 	}
410 
411 	//Convert to IR.
412 	json_object *ir;
413 	if (single_section) {
414 		ir = cper_single_section_to_ir(record);
415 	} else {
416 		ir = cper_to_ir(record);
417 	}
418 
419 	cper_print_log("decoded:\n%s\n", json_object_to_json_string_ext(
420 						 ir, JSON_C_TO_STRING_PRETTY));
421 
422 	//Now convert back to binary, and get a stream out.
423 	char *cper_buf;
424 	size_t cper_buf_size;
425 	FILE *stream = open_memstream(&cper_buf, &cper_buf_size);
426 	if (single_section) {
427 		ir_single_section_to_cper(ir, stream);
428 	} else {
429 		ir_to_cper(ir, stream);
430 	}
431 	fclose(stream);
432 
433 	printf("size: %zu, cper_buf_size: %zu\n", size, cper_buf_size);
434 
435 	char *buf_hex;
436 	int buf_hex_len = to_hex((unsigned char *)buf, size, &buf_hex);
437 	char *cper_buf_hex;
438 	int cper_buf_hex_len =
439 		to_hex((unsigned char *)cper_buf, cper_buf_size, &cper_buf_hex);
440 
441 	printf("%.*s\n", cper_buf_hex_len, cper_buf_hex);
442 	printf("%.*s\n", buf_hex_len, buf_hex);
443 	assert(buf_hex_len == cper_buf_hex_len);
444 	assert(memcmp(buf_hex, cper_buf_hex, buf_hex_len) == 0);
445 
446 	free(buf_hex);
447 	free(cper_buf_hex);
448 
449 	//Free everything up.
450 	fclose(record);
451 	free(buf);
452 	free(cper_buf);
453 	json_object_put(ir);
454 }
455 
456 //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)457 void cper_log_section_dual_ir_test(const char *section_name)
458 {
459 	// Test with file based APIs
460 	cper_log_section_ir_test(section_name, 0, allValidbitsSet);
461 	cper_log_section_ir_test(section_name, 1, allValidbitsSet);
462 
463 	// Test with buffer based APIs
464 	cper_buf_log_section_ir_test(section_name, 0, allValidbitsSet);
465 	cper_buf_log_section_ir_test(section_name, 1, allValidbitsSet);
466 
467 	//Validate against examples
468 	cper_example_section_ir_test(section_name);
469 }
470 
471 //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)472 void cper_log_section_dual_binary_test(const char *section_name)
473 {
474 	cper_log_section_binary_test(section_name, 0, allValidbitsSet);
475 	cper_log_section_binary_test(section_name, 1, allValidbitsSet);
476 }
477 
478 /*
479 * Non-single section assertions.
480 */
CompileTimeAssertions_TwoWayConversion(void)481 void CompileTimeAssertions_TwoWayConversion(void)
482 {
483 	for (size_t i = 0; i < section_definitions_len; i++) {
484 		//If a conversion one way exists, a conversion the other way must exist.
485 		if (section_definitions[i].ToCPER != NULL) {
486 			assert(section_definitions[i].ToIR != NULL);
487 		}
488 		if (section_definitions[i].ToIR != NULL) {
489 			assert(section_definitions[i].ToCPER != NULL);
490 		}
491 	}
492 }
493 
CompileTimeAssertions_ShortcodeNoSpaces(void)494 void CompileTimeAssertions_ShortcodeNoSpaces(void)
495 {
496 	for (size_t i = 0; i < generator_definitions_len; i++) {
497 		for (int j = 0;
498 		     generator_definitions[i].ShortName[j + 1] != '\0'; j++) {
499 			assert(isspace(generator_definitions[i].ShortName[j]) ==
500 			       0);
501 		}
502 	}
503 }
504 
505 /*
506 * Single section tests.
507 */
508 
509 //Generic processor tests.
GenericProcessorTests_IRValid(void)510 void GenericProcessorTests_IRValid(void)
511 {
512 	cper_log_section_dual_ir_test("generic");
513 }
GenericProcessorTests_BinaryEqual(void)514 void GenericProcessorTests_BinaryEqual(void)
515 {
516 	cper_log_section_dual_binary_test("generic");
517 }
518 
519 //IA32/x64 tests.
IA32x64Tests_IRValid(void)520 void IA32x64Tests_IRValid(void)
521 {
522 	cper_log_section_dual_ir_test("ia32x64");
523 }
IA32x64Tests_BinaryEqual(void)524 void IA32x64Tests_BinaryEqual(void)
525 {
526 	cper_log_section_dual_binary_test("ia32x64");
527 }
528 
529 // void IPFTests_IRValid() {
530 //     cper_log_section_dual_ir_test("ipf");
531 // }
532 
533 //ARM tests.
ArmTests_IRValid(void)534 void ArmTests_IRValid(void)
535 {
536 	cper_log_section_dual_ir_test("arm");
537 }
ArmTests_BinaryEqual(void)538 void ArmTests_BinaryEqual(void)
539 {
540 	cper_log_section_dual_binary_test("arm");
541 }
542 
543 // ARM RAS tests.
ArmRasTests_IRValid(void)544 void ArmRasTests_IRValid(void)
545 {
546 	cper_log_section_dual_ir_test("arm-ras");
547 }
ArmRasTests_BinaryEqual(void)548 void ArmRasTests_BinaryEqual(void)
549 {
550 	cper_log_section_dual_binary_test("arm-ras");
551 }
552 
553 //Memory tests.
MemoryTests_IRValid(void)554 void MemoryTests_IRValid(void)
555 {
556 	cper_log_section_dual_ir_test("memory");
557 }
MemoryTests_BinaryEqual(void)558 void MemoryTests_BinaryEqual(void)
559 {
560 	cper_log_section_dual_binary_test("memory");
561 }
562 
563 //Memory 2 tests.
Memory2Tests_IRValid(void)564 void Memory2Tests_IRValid(void)
565 {
566 	cper_log_section_dual_ir_test("memory2");
567 }
Memory2Tests_BinaryEqual(void)568 void Memory2Tests_BinaryEqual(void)
569 {
570 	cper_log_section_dual_binary_test("memory2");
571 }
572 
573 //PCIe tests.
PCIeTests_IRValid(void)574 void PCIeTests_IRValid(void)
575 {
576 	cper_log_section_dual_ir_test("pcie");
577 }
PCIeTests_BinaryEqual(void)578 void PCIeTests_BinaryEqual(void)
579 {
580 	cper_log_section_dual_binary_test("pcie");
581 }
582 
583 //Firmware tests.
FirmwareTests_IRValid(void)584 void FirmwareTests_IRValid(void)
585 {
586 	cper_log_section_dual_ir_test("firmware");
587 }
FirmwareTests_BinaryEqual(void)588 void FirmwareTests_BinaryEqual(void)
589 {
590 	cper_log_section_dual_binary_test("firmware");
591 }
592 
593 //PCI Bus tests.
PCIBusTests_IRValid(void)594 void PCIBusTests_IRValid(void)
595 {
596 	cper_log_section_dual_ir_test("pcibus");
597 }
PCIBusTests_BinaryEqual(void)598 void PCIBusTests_BinaryEqual(void)
599 {
600 	cper_log_section_dual_binary_test("pcibus");
601 }
602 
603 //PCI Device tests.
PCIDevTests_IRValid(void)604 void PCIDevTests_IRValid(void)
605 {
606 	cper_log_section_dual_ir_test("pcidev");
607 }
PCIDevTests_BinaryEqual(void)608 void PCIDevTests_BinaryEqual(void)
609 {
610 	cper_log_section_dual_binary_test("pcidev");
611 }
612 
613 //Generic DMAr tests.
DMArGenericTests_IRValid(void)614 void DMArGenericTests_IRValid(void)
615 {
616 	cper_log_section_dual_ir_test("dmargeneric");
617 }
DMArGenericTests_BinaryEqual(void)618 void DMArGenericTests_BinaryEqual(void)
619 {
620 	cper_log_section_dual_binary_test("dmargeneric");
621 }
622 
623 //VT-d DMAr tests.
DMArVtdTests_IRValid(void)624 void DMArVtdTests_IRValid(void)
625 {
626 	cper_log_section_dual_ir_test("dmarvtd");
627 }
DMArVtdTests_BinaryEqual(void)628 void DMArVtdTests_BinaryEqual(void)
629 {
630 	cper_log_section_dual_binary_test("dmarvtd");
631 }
632 
633 //IOMMU DMAr tests.
DMArIOMMUTests_IRValid(void)634 void DMArIOMMUTests_IRValid(void)
635 {
636 	cper_log_section_dual_ir_test("dmariommu");
637 }
DMArIOMMUTests_BinaryEqual(void)638 void DMArIOMMUTests_BinaryEqual(void)
639 {
640 	cper_log_section_dual_binary_test("dmariommu");
641 }
642 
643 //CCIX PER tests.
CCIXPERTests_IRValid(void)644 void CCIXPERTests_IRValid(void)
645 {
646 	cper_log_section_dual_ir_test("ccixper");
647 }
CCIXPERTests_BinaryEqual(void)648 void CCIXPERTests_BinaryEqual(void)
649 {
650 	cper_log_section_dual_binary_test("ccixper");
651 }
652 
653 //CXL Protocol tests.
CXLProtocolTests_IRValid(void)654 void CXLProtocolTests_IRValid(void)
655 {
656 	cper_log_section_dual_ir_test("cxlprotocol");
657 }
CXLProtocolTests_BinaryEqual(void)658 void CXLProtocolTests_BinaryEqual(void)
659 {
660 	cper_log_section_dual_binary_test("cxlprotocol");
661 }
662 
663 //CXL Component tests.
CXLComponentTests_IRValid(void)664 void CXLComponentTests_IRValid(void)
665 {
666 	cper_log_section_dual_ir_test("cxlcomponent-media");
667 }
CXLComponentTests_BinaryEqual(void)668 void CXLComponentTests_BinaryEqual(void)
669 {
670 	cper_log_section_dual_binary_test("cxlcomponent-media");
671 }
672 
673 //NVIDIA section tests.
NVIDIASectionTests_IRValid(void)674 void NVIDIASectionTests_IRValid(void)
675 {
676 	cper_log_section_dual_ir_test("nvidia");
677 }
NVIDIASectionTests_BinaryEqual(void)678 void NVIDIASectionTests_BinaryEqual(void)
679 {
680 	cper_log_section_dual_binary_test("nvidia");
681 }
682 
NVIDIACMETSectionTests_IRValid(void)683 void NVIDIACMETSectionTests_IRValid(void)
684 {
685 	cper_example_section_ir_test("nvidia_cmet_info");
686 }
687 
NVIDIAEVENTALLTYPESSectionTests_IRValid(void)688 void NVIDIAEVENTALLTYPESSectionTests_IRValid(void)
689 {
690 	cper_example_section_ir_test("nvidia_event_all_types");
691 }
692 
NVIDIAEVENTGPUINITSectionTests_IRValid(void)693 void NVIDIAEVENTGPUINITSectionTests_IRValid(void)
694 {
695 	cper_example_section_ir_test("nvidia_event_gpu_init");
696 }
697 
NVIDIAEVENTGPUUCEECCSectionTests_IRValid(void)698 void NVIDIAEVENTGPUUCEECCSectionTests_IRValid(void)
699 {
700 	cper_example_section_ir_test("nvidia_event_gpu_uce_ecc");
701 }
702 
NVIDIAEventSectionTests_BinaryEqual(void)703 void NVIDIAEventSectionTests_BinaryEqual(void)
704 {
705 	cper_log_section_dual_binary_test("nvidiaevent");
706 }
707 
708 // Test Event Header version mismatch during IR to CPER conversion (should error and skip)
NVIDIAEVENTEventHeaderVersionMismatch_IRValid(void)709 void NVIDIAEVENTEventHeaderVersionMismatch_IRValid(void)
710 {
711 	printf("Testing Event Header version mismatch (IR to CPER)...\n");
712 
713 	// Create a test JSON with EventVersion != 1
714 	json_object *test_ir = json_object_new_object();
715 	json_object *header_ir = json_object_new_object();
716 	add_int(header_ir, "revision", 0);
717 	add_int(header_ir, "sectionCount", 1);
718 	add_int(header_ir, "severity", 0);
719 	add_int(header_ir, "recordLength", 256);
720 	add_string(header_ir, "timestamp", "0000-00-00T00:00:00+00:00");
721 	add_bool(header_ir, "timestampIsPrecise", 0);
722 	add_string(header_ir, "platformID",
723 		   "00000000-0000-0000-0000-000000000000");
724 	add_string(header_ir, "creatorID",
725 		   "00000000-0000-0000-0000-000000000000");
726 	add_string(header_ir, "notificationType",
727 		   "00000000-0000-0000-0000-000000000000");
728 	json_object_object_add(test_ir, "header", header_ir);
729 
730 	json_object *sections_arr = json_object_new_array();
731 	json_object *section_obj = json_object_new_object();
732 	json_object *nvidiaevent_obj = json_object_new_object();
733 	json_object *event_header = json_object_new_object();
734 
735 	// Set EventVersion to 99 (not matching expected version 1)
736 	add_int(event_header, "version", 99);
737 	add_int(event_header, "deviceType", 0);
738 	add_int(event_header, "eventType", 0);
739 	add_int(event_header, "eventSubtype", 0);
740 	add_string(event_header, "eventLinkId", "0x0");
741 	add_string(event_header, "signature", "TEST-EVENT-00000");
742 
743 	json_object *event_info = json_object_new_object();
744 	add_int(event_info, "version", 0);
745 	add_int(event_info, "size", 19);
746 
747 	json_object *info_data = json_object_new_object();
748 	add_int(info_data, "socketNum", 0);
749 	add_int(info_data, "architecture", 0);
750 	add_int(info_data, "ecid0", 0);
751 	add_int(info_data, "ecid1", 0);
752 	add_int(info_data, "ecid2", 0);
753 	add_int(info_data, "ecid3", 0);
754 	add_string(info_data, "instanceBase", "0x0");
755 	json_object_object_add(event_info, "data", info_data);
756 
757 	json_object_object_add(nvidiaevent_obj, "eventHeader", event_header);
758 	json_object_object_add(nvidiaevent_obj, "eventInfo", event_info);
759 	json_object *event_contexts = json_object_new_array();
760 	json_object_object_add(nvidiaevent_obj, "eventContexts",
761 			       event_contexts);
762 
763 	add_string(section_obj, "sectionType", "nvidiaevent");
764 	json_object_object_add(section_obj, "nvidiaevent", nvidiaevent_obj);
765 	json_object_array_add(sections_arr, section_obj);
766 	json_object_object_add(test_ir, "sections", sections_arr);
767 
768 	// Add section descriptors (required by ir_to_cper)
769 	json_object *section_descriptors = json_object_new_array();
770 	json_object *descriptor = json_object_new_object();
771 	add_int(descriptor, "sectionOffset", 200);
772 	add_int(descriptor, "sectionLength", 100);
773 	add_string(descriptor, "sectionType", "nvidiaevent");
774 	json_object_array_add(section_descriptors, descriptor);
775 	json_object_object_add(test_ir, "sectionDescriptors",
776 			       section_descriptors);
777 
778 	// Try to convert to CPER - this should log an error
779 	char *cper_buf;
780 	size_t cper_buf_size;
781 	FILE *stream = open_memstream(&cper_buf, &cper_buf_size);
782 
783 	if (stream == NULL) {
784 		printf("Failed to open memstream\n");
785 		json_object_put(test_ir);
786 		assert(0);
787 		return;
788 	}
789 
790 	ir_to_cper(test_ir, stream);
791 	fclose(stream);
792 
793 	printf("Event Header version mismatch (IR to CPER) handled correctly\n");
794 
795 	free(cper_buf);
796 	json_object_put(test_ir);
797 }
798 
799 // Test Event Header version mismatch during binary to IR conversion (should error and return NULL)
NVIDIAEVENTEventHeaderVersionMismatch_BinaryEqual(void)800 void NVIDIAEVENTEventHeaderVersionMismatch_BinaryEqual(void)
801 {
802 	printf("Testing Event Header version mismatch (binary to IR)...\n");
803 
804 	// Create a minimal CPER binary with EventVersion = 99
805 	// CPER header (128 bytes) + section descriptor (72 bytes) + NvidiaEvent section
806 	uint8_t test_cper[256] = { 0 };
807 
808 	// CPER header signature
809 	memcpy(test_cper, "CPER", 4);
810 
811 	// Section count = 1
812 	test_cper[0x10] = 1;
813 
814 	// Record length = 256
815 	*(uint32_t *)(test_cper + 0x14) = 256;
816 
817 	// Section descriptor at 0x80
818 	// Section length
819 	*(uint32_t *)(test_cper + 0x80) =
820 		56; // Event header (28) + info header (3) + CPU info (16) + padding
821 	// Section offset (from start of record)
822 	*(uint32_t *)(test_cper + 0x84) = 200; // 0xC8
823 
824 	// NvidiaEvent section GUID at 0x88
825 	// {9068e568-a06c-f011-aeaf-159343591eac}
826 	uint8_t nvidiaevent_guid[] = { 0x68, 0xe5, 0x68, 0x90, 0xa0, 0x6c,
827 				       0xf0, 0x11, 0xae, 0xaf, 0x15, 0x93,
828 				       0x43, 0x59, 0x1e, 0xac };
829 	memcpy(test_cper + 0x88, nvidiaevent_guid, 16);
830 
831 	// Event header at 0xC8 (200)
832 	test_cper[0xC8] = 99; // EventVersion = 99 (not 1)
833 	test_cper[0xC9] = 0;  // EventContextCount = 0
834 	test_cper[0xCA] = 0;  // SourceDeviceType = CPU
835 	test_cper[0xCB] = 0;  // Reserved
836 
837 	// Parse this CPER - should return NULL due to version mismatch
838 	json_object *ir =
839 		cper_section_nvidia_events_to_ir(test_cper + 0xC8, 56, NULL);
840 
841 	if (ir == NULL) {
842 		printf("Event Header version mismatch (binary to IR) handled correctly (returned NULL)\n");
843 	} else {
844 		printf("ERROR: Event Header version mismatch should have returned NULL\n");
845 		json_object_put(ir);
846 		assert(0);
847 	}
848 }
849 
850 //Memory section test for validation bits.
MemoryValidationBitsSectionTests_IRValid()851 void MemoryValidationBitsSectionTests_IRValid()
852 {
853 	cper_example_section_ir_test("memory-validation-bits");
854 }
855 
856 //Unknown section tests.
UnknownSectionTests_IRValid(void)857 void UnknownSectionTests_IRValid(void)
858 {
859 	cper_log_section_dual_ir_test("unknown");
860 }
UnknownSectionTests_BinaryEqual(void)861 void UnknownSectionTests_BinaryEqual(void)
862 {
863 	cper_log_section_dual_binary_test("unknown");
864 }
865 
866 //Entrypoint for the testing program.
main(void)867 int main(void)
868 {
869 	if (GEN_EXAMPLES) {
870 		cper_create_examples("generic");
871 		cper_create_examples("arm");
872 		cper_create_examples("ia32x64");
873 		cper_create_examples("memory");
874 		cper_create_examples("memory2");
875 		cper_create_examples("pcie");
876 		cper_create_examples("firmware");
877 		cper_create_examples("pcibus");
878 		cper_create_examples("pcidev");
879 		cper_create_examples("dmargeneric");
880 		cper_create_examples("dmarvtd");
881 		cper_create_examples("dmariommu");
882 		cper_create_examples("ccixper");
883 		cper_create_examples("cxlprotocol");
884 		cper_create_examples("cxlcomponent-media");
885 		cper_create_examples("nvidia");
886 		cper_create_examples("unknown");
887 	}
888 	test_base64_encode_good();
889 	test_base64_decode_good();
890 	test_hex_encode_good();
891 	test_hex_decode_good();
892 	test_hex_error_cases();
893 	test_hex_roundtrip();
894 	GenericProcessorTests_IRValid();
895 	GenericProcessorTests_BinaryEqual();
896 	IA32x64Tests_IRValid();
897 	IA32x64Tests_BinaryEqual();
898 	ArmTests_IRValid();
899 	ArmTests_BinaryEqual();
900 	ArmRasTests_IRValid();
901 	ArmRasTests_BinaryEqual();
902 	MemoryTests_IRValid();
903 	MemoryTests_BinaryEqual();
904 	Memory2Tests_IRValid();
905 	Memory2Tests_BinaryEqual();
906 	PCIeTests_IRValid();
907 	PCIeTests_BinaryEqual();
908 	FirmwareTests_IRValid();
909 	FirmwareTests_BinaryEqual();
910 	PCIBusTests_IRValid();
911 	PCIBusTests_BinaryEqual();
912 	PCIDevTests_IRValid();
913 	PCIDevTests_BinaryEqual();
914 	DMArGenericTests_IRValid();
915 	DMArGenericTests_BinaryEqual();
916 	DMArVtdTests_IRValid();
917 	DMArVtdTests_BinaryEqual();
918 	DMArIOMMUTests_IRValid();
919 	DMArIOMMUTests_BinaryEqual();
920 	CCIXPERTests_IRValid();
921 	CCIXPERTests_BinaryEqual();
922 	CXLProtocolTests_IRValid();
923 	CXLProtocolTests_BinaryEqual();
924 	CXLComponentTests_IRValid();
925 	CXLComponentTests_BinaryEqual();
926 	NVIDIASectionTests_IRValid();
927 	NVIDIASectionTests_BinaryEqual();
928 	NVIDIAEventSectionTests_BinaryEqual();
929 	NVIDIACMETSectionTests_IRValid();
930 	NVIDIAEVENTALLTYPESSectionTests_IRValid();
931 	NVIDIAEVENTGPUINITSectionTests_IRValid();
932 	NVIDIAEVENTGPUUCEECCSectionTests_IRValid();
933 	NVIDIAEVENTEventHeaderVersionMismatch_IRValid();
934 	NVIDIAEVENTEventHeaderVersionMismatch_BinaryEqual();
935 	MemoryValidationBitsSectionTests_IRValid();
936 	UnknownSectionTests_IRValid();
937 	UnknownSectionTests_BinaryEqual();
938 	CompileTimeAssertions_TwoWayConversion();
939 	CompileTimeAssertions_ShortcodeNoSpaces();
940 
941 	printf("\n\nTest completed successfully.\n");
942 
943 	return 0;
944 }
945