Add test suite, fix a mountain of small errors.
diff --git a/tests/ir-tests.cpp b/tests/ir-tests.cpp
new file mode 100644
index 0000000..1344379
--- /dev/null
+++ b/tests/ir-tests.cpp
@@ -0,0 +1,97 @@
+/**
+ * Defines tests for validating CPER-JSON IR output from the cper-parse library.
+ * 
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include "gtest/gtest.h"
+#include "test-utils.hpp"
+extern "C" {
+#include "json.h"
+#include "../cper-parse.h"
+#include "../json-schema.h"
+#include "../generator/cper-generate.h"
+}
+
+/*
+* Test templates.
+*/
+void single_section_ir_test(const char* section_name)
+{
+    //Generate CPER record for generic processor.
+    char* buf;
+    size_t size;
+    FILE* record = generate_record_memstream(&section_name, 1, &buf, &size);
+
+    //Convert to IR, free resources.
+    json_object* ir = cper_to_ir(record);
+    fclose(record);
+    free(buf);
+
+    //Validate against schema.
+    char error_message[JSON_ERROR_MSG_MAX_LEN] = {0};
+    int valid = validate_schema_from_file("./specification/cper-json.json", ir, error_message);
+    ASSERT_TRUE(valid) << error_message;
+}
+
+/*
+* Single section tests.
+*/
+TEST(GenericProcessorTests, IRValid) {
+    single_section_ir_test("generic");
+}
+TEST(IA32x64Tests, IRValid) {
+    single_section_ir_test("ia32x64");
+}
+// TEST(IPFTests, IRValid) {
+//     single_section_ir_test("ipf");
+// }
+TEST(ArmTests, IRValid) {
+    single_section_ir_test("arm");
+}
+TEST(MemoryTests, IRValid) {
+    single_section_ir_test("memory");
+}
+TEST(Memory2Tests, IRValid) {
+    single_section_ir_test("memory2");
+}
+TEST(PCIeTests, IRValid) {
+    single_section_ir_test("pcie");
+}
+TEST(FirmwareTests, IRValid) {
+    single_section_ir_test("firmware");
+}
+TEST(PCIBusTests, IRValid) {
+    single_section_ir_test("pcibus");
+}
+TEST(PCIDevTests, IRValid) {
+    single_section_ir_test("pcidev");
+}
+TEST(DMArGenericTests, IRValid) {
+    single_section_ir_test("dmargeneric");
+}
+TEST(DMArVtdTests, IRValid) {
+    single_section_ir_test("dmarvtd");
+}
+TEST(DMArIOMMUTests, IRValid) {
+    single_section_ir_test("dmariommu");
+}
+TEST(CCIXPERTests, IRValid) {
+    single_section_ir_test("ccixper");
+}
+TEST(CXLProtocolTests, IRValid) {
+    single_section_ir_test("cxlprotocol");
+}
+TEST(CXLComponentTests, IRValid) {
+    single_section_ir_test("cxlcomponent");
+}
+TEST(UnknownSectionTests, IRValid) {
+    single_section_ir_test("unknown");
+}
+
+//Entrypoint for the testing program.
+int main()
+{
+    testing::InitGoogleTest();
+    return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/tests/test-utils.cpp b/tests/test-utils.cpp
new file mode 100644
index 0000000..0d4cabf
--- /dev/null
+++ b/tests/test-utils.cpp
@@ -0,0 +1,27 @@
+/**
+ * Defines utility functions for testing CPER-JSON IR output from the cper-parse library.
+ * 
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "test-utils.hpp"
+extern "C" {
+#include "../edk/BaseTypes.h"
+#include "../generator/cper-generate.h"
+}
+
+//Returns a ready-for-use memory stream containing a CPER record with the given sections inside.
+FILE* generate_record_memstream(const char** types, UINT16 num_types, char** buf, size_t* buf_size)
+{
+    //Open a memory stream.
+    FILE* stream = open_memstream(buf, buf_size);
+
+    //Generate a section to the stream, close & return.
+    generate_cper_record((char**)types, num_types, stream);
+    fclose(stream);
+
+    //Return fmemopen() buffer for reading.
+    return fmemopen(*buf, *buf_size, "r");
+}
\ No newline at end of file
diff --git a/tests/test-utils.hpp b/tests/test-utils.hpp
new file mode 100644
index 0000000..d13f5f0
--- /dev/null
+++ b/tests/test-utils.hpp
@@ -0,0 +1,10 @@
+#ifndef CPER_IR_TEST_UTILS_H
+#define CPER_IR_TEST_UTILS_H
+
+extern "C" {
+#include "../edk/BaseTypes.h"
+}
+
+FILE* generate_record_memstream(const char** types, UINT16 num_types, char** buf, size_t* buf_size);
+
+#endif
\ No newline at end of file