/* * This is an auditd plugin for sending auditd data * to clickhouse DB. * Copyright (C) 2020 Aleksei Nikiforov * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include #include #include #include #include #include "auditd-record.hpp" static AuditRecord generateTestRecord() { AuditRecord original_record; original_record.time = 12345678; original_record.milliseconds = 9876; original_record.serial = 12345; original_record.node = "test node name"; original_record.filename = "some random file name"; auto string_field = InterpretedStringRecordField::createRecord("string_record"); string_field->setStringValue(std::string("string_record_value")); original_record.fields[string_field->getName()] = string_field; auto integer_field = IntegerRecordField::createRecord("integer_record"); integer_field->setIntValue(500); integer_field->setStringValue(std::string("five hundred")); original_record.fields[integer_field->getName()] = integer_field; auto array_field = InterpretedStringArrayRecordField::createRecord("array_record"); array_field->setArrays({"first name", "second name"}, {"first value", "second value"}); original_record.fields[array_field->getName()] = array_field; return original_record; } TEST(AuditRecord, Serialization) { AuditRecord original_record = generateTestRecord(); boost::property_tree::ptree ptree_data = original_record.toPtree(); std::stringstream stream_data; boost::property_tree::write_json(stream_data, ptree_data); boost::property_tree::ptree ptree_restored_data; boost::property_tree::read_json(stream_data, ptree_restored_data); auto restored_record = AuditRecord::fromPtree(ptree_restored_data); EXPECT_EQ(original_record.time, restored_record.time); EXPECT_EQ(original_record.milliseconds, restored_record.milliseconds); EXPECT_EQ(original_record.serial, restored_record.serial); EXPECT_EQ(original_record.node, restored_record.node); EXPECT_FALSE(original_record.filename.empty()); EXPECT_TRUE (restored_record.filename.empty()); EXPECT_EQ(original_record.fields.size(), restored_record.fields.size()); for (auto iter = original_record.fields.begin(); iter != original_record.fields.end(); ++iter) { auto second_iter = restored_record.fields.find(iter->first); EXPECT_TRUE(second_iter != restored_record.fields.end()); if (second_iter == restored_record.fields.end()) { continue; } EXPECT_EQ(iter->second->getType(), second_iter->second->getType()); if (iter->second->getType() != second_iter->second->getType()) { continue; } EXPECT_EQ(iter->second->getName(), second_iter->second->getName()); switch (iter->second->getType()) { case AbstractRecordField::Type::Int: { auto original_field = std::dynamic_pointer_cast(iter->second); auto restored_field = std::dynamic_pointer_cast(second_iter->second); EXPECT_TRUE(original_field); EXPECT_TRUE(restored_field); if ((!original_field) || (!restored_field)) { break; } EXPECT_EQ(original_field->getIntValue(), restored_field->getIntValue()); EXPECT_EQ(original_field->getStringValue(), restored_field->getStringValue()); } break; case AbstractRecordField::Type::String: { auto original_field = std::dynamic_pointer_cast(iter->second); auto restored_field = std::dynamic_pointer_cast(second_iter->second); EXPECT_TRUE(original_field); EXPECT_TRUE(restored_field); if ((!original_field) || (!restored_field)) { break; } EXPECT_EQ(original_field->getStringValue(), restored_field->getStringValue()); } break; case AbstractRecordField::Type::InterpretedString: { auto original_field = std::dynamic_pointer_cast(iter->second); auto restored_field = std::dynamic_pointer_cast(second_iter->second); EXPECT_TRUE(original_field); EXPECT_TRUE(restored_field); if ((!original_field) || (!restored_field)) { break; } EXPECT_EQ(original_field->getStringValue(), restored_field->getStringValue()); } break; case AbstractRecordField::Type::InterpretedStringArray: { auto original_field = std::dynamic_pointer_cast(iter->second); auto restored_field = std::dynamic_pointer_cast(second_iter->second); EXPECT_TRUE(original_field); EXPECT_TRUE(restored_field); if ((!original_field) || (!restored_field)) { break; } auto original_names = original_field->getNamesArray(); auto original_values = original_field->getValuesArray(); auto restored_names = restored_field->getNamesArray(); auto restored_values = restored_field->getValuesArray(); EXPECT_EQ(original_names.size(), restored_names.size()); if (original_names.size() == restored_names.size()) { auto original_iter = original_names.begin(); auto restored_iter = restored_names.begin(); for ( ; (original_iter != original_names.end()) && (restored_iter != restored_names.end()); ++original_iter, ++restored_iter) { EXPECT_EQ(*original_iter, *restored_iter); } } EXPECT_EQ(original_values.size(), restored_values.size()); if (original_values.size() == restored_values.size()) { auto original_iter = original_values.begin(); auto restored_iter = restored_values.begin(); for ( ; (original_iter != original_values.end()) && (restored_iter != restored_values.end()); ++original_iter, ++restored_iter) { EXPECT_EQ(*original_iter, *restored_iter); } } } break; } } }