xref: /openbmc/phosphor-user-manager/test/json_serializer_test.cpp (revision f21966594e9735887b3091616df643c24dd14979)
15cf5ddf3SPatrick Williams #include <unistd.h>
25cf5ddf3SPatrick Williams 
35cf5ddf3SPatrick Williams #include <json_serializer.hpp>
45cf5ddf3SPatrick Williams 
55cf5ddf3SPatrick Williams #include <filesystem>
65cf5ddf3SPatrick Williams #include <fstream>
75cf5ddf3SPatrick Williams #include <string>
85cf5ddf3SPatrick Williams 
95cf5ddf3SPatrick Williams #include <gtest/gtest.h>
105cf5ddf3SPatrick Williams 
115cf5ddf3SPatrick Williams namespace s = std::string_literals;
125cf5ddf3SPatrick Williams 
135cf5ddf3SPatrick Williams class JsonSerializerTest : public testing::Test
145cf5ddf3SPatrick Williams {
155cf5ddf3SPatrick Williams   protected:
165cf5ddf3SPatrick Williams     std::string test_file;
175cf5ddf3SPatrick Williams 
SetUp()185cf5ddf3SPatrick Williams     void SetUp() override
195cf5ddf3SPatrick Williams     {
205cf5ddf3SPatrick Williams         char tmpTemplate[] = "/tmp/test_file_XXXXXX";
215cf5ddf3SPatrick Williams         int fd = mkstemp(tmpTemplate);
225cf5ddf3SPatrick Williams         if (fd == -1)
235cf5ddf3SPatrick Williams         {
245cf5ddf3SPatrick Williams             throw std::runtime_error("Failed to create temporary file.");
255cf5ddf3SPatrick Williams         }
265cf5ddf3SPatrick Williams         close(fd);
275cf5ddf3SPatrick Williams         test_file = tmpTemplate;
285cf5ddf3SPatrick Williams     }
295cf5ddf3SPatrick Williams 
TearDown()305cf5ddf3SPatrick Williams     void TearDown() override
315cf5ddf3SPatrick Williams     {
325cf5ddf3SPatrick Williams         if (std::filesystem::exists(test_file))
335cf5ddf3SPatrick Williams         {
345cf5ddf3SPatrick Williams             std::filesystem::remove(test_file);
355cf5ddf3SPatrick Williams         }
365cf5ddf3SPatrick Williams     }
375cf5ddf3SPatrick Williams };
385cf5ddf3SPatrick Williams 
TEST_F(JsonSerializerTest,MakeJson)395cf5ddf3SPatrick Williams TEST_F(JsonSerializerTest, MakeJson)
405cf5ddf3SPatrick Williams {
415cf5ddf3SPatrick Williams     JsonSerializer s(test_file);
425cf5ddf3SPatrick Williams     nlohmann::json j = s.makeJson("foo/bar/baz", "value");
435cf5ddf3SPatrick Williams     EXPECT_EQ(j["foo"]["bar"]["baz"], "value");
445cf5ddf3SPatrick Williams }
455cf5ddf3SPatrick Williams 
TEST_F(JsonSerializerTest,SerializeDeserialize)465cf5ddf3SPatrick Williams TEST_F(JsonSerializerTest, SerializeDeserialize)
475cf5ddf3SPatrick Williams {
485cf5ddf3SPatrick Williams     JsonSerializer s(test_file);
495cf5ddf3SPatrick Williams     s.serialize("foo/bar/baz", "value");
505cf5ddf3SPatrick Williams     std::string value;
515cf5ddf3SPatrick Williams     s.deserialize("foo/bar/baz", value);
525cf5ddf3SPatrick Williams     EXPECT_EQ(value, "value");
535cf5ddf3SPatrick Williams }
545cf5ddf3SPatrick Williams 
TEST_F(JsonSerializerTest,StoreLoad)555cf5ddf3SPatrick Williams TEST_F(JsonSerializerTest, StoreLoad)
565cf5ddf3SPatrick Williams {
575cf5ddf3SPatrick Williams     JsonSerializer s(test_file);
585cf5ddf3SPatrick Williams     s.serialize("foo/bar/baz", "value");
595cf5ddf3SPatrick Williams     s.store();
605cf5ddf3SPatrick Williams 
615cf5ddf3SPatrick Williams     // Create a new JsonSerializer instance to load from the same file
625cf5ddf3SPatrick Williams     // This simulates a fresh process loading the configuration
635cf5ddf3SPatrick Williams     JsonSerializer s2(test_file);
645cf5ddf3SPatrick Williams     s2.load();
655cf5ddf3SPatrick Williams     std::string value;
665cf5ddf3SPatrick Williams     s2.deserialize("foo/bar/baz", value);
675cf5ddf3SPatrick Williams     EXPECT_EQ(value, "value");
685cf5ddf3SPatrick Williams }
695cf5ddf3SPatrick Williams 
TEST_F(JsonSerializerTest,Erase)705cf5ddf3SPatrick Williams TEST_F(JsonSerializerTest, Erase)
715cf5ddf3SPatrick Williams {
725cf5ddf3SPatrick Williams     JsonSerializer s(test_file);
735cf5ddf3SPatrick Williams     s.serialize("foo/bar/baz", "value");
745cf5ddf3SPatrick Williams     // The current erase method only handles top-level keys.
755cf5ddf3SPatrick Williams     // Calling erase with a nested path like "foo/bar/baz" will not remove
765cf5ddf3SPatrick Williams     // "baz".
775cf5ddf3SPatrick Williams     s.erase("foo/bar/baz");
785cf5ddf3SPatrick Williams     s.store();
795cf5ddf3SPatrick Williams 
805cf5ddf3SPatrick Williams     // Verify that the value is still present because erase did not remove the
815cf5ddf3SPatrick Williams     // nested key.
825cf5ddf3SPatrick Williams     JsonSerializer s2(test_file);
835cf5ddf3SPatrick Williams     s2.load();
845cf5ddf3SPatrick Williams     std::string value;
855cf5ddf3SPatrick Williams     s2.deserialize("foo/bar/baz", value);
865cf5ddf3SPatrick Williams     EXPECT_EQ(value, "value"); // Expect original value to remain
875cf5ddf3SPatrick Williams }
885cf5ddf3SPatrick Williams 
TEST_F(JsonSerializerTest,GetLeafNode)895cf5ddf3SPatrick Williams TEST_F(JsonSerializerTest, GetLeafNode)
905cf5ddf3SPatrick Williams {
915cf5ddf3SPatrick Williams     JsonSerializer s(test_file);
925cf5ddf3SPatrick Williams     s.serialize("foo/bar/baz", "value");
935cf5ddf3SPatrick Williams     auto leaf = s.getLeafNode("foo/bar/baz");
945cf5ddf3SPatrick Williams     EXPECT_TRUE(leaf.has_value());
955cf5ddf3SPatrick Williams     if (leaf.has_value())
965cf5ddf3SPatrick Williams     {
975cf5ddf3SPatrick Williams         EXPECT_EQ(*leaf, "value");
985cf5ddf3SPatrick Williams     }
995cf5ddf3SPatrick Williams 
1005cf5ddf3SPatrick Williams     leaf = s.getLeafNode("foo/bar/nonexistent");
1015cf5ddf3SPatrick Williams     EXPECT_FALSE(leaf.has_value());
1025cf5ddf3SPatrick Williams }
1035cf5ddf3SPatrick Williams 
TEST_F(JsonSerializerTest,LoadInvalidJsonFile)1045cf5ddf3SPatrick Williams TEST_F(JsonSerializerTest, LoadInvalidJsonFile)
1055cf5ddf3SPatrick Williams {
1065cf5ddf3SPatrick Williams     // Ensure the file is empty or contains invalid JSON
1075cf5ddf3SPatrick Williams     std::ofstream ofs(test_file, std::ios::trunc);
1085cf5ddf3SPatrick Williams     ofs.close();
1095cf5ddf3SPatrick Williams 
1105cf5ddf3SPatrick Williams     JsonSerializer s(test_file);
111*f2196659SPatrick Williams     EXPECT_FALSE(s.load());
112*f2196659SPatrick Williams     EXPECT_FALSE(std::filesystem::exists(test_file));
1135cf5ddf3SPatrick Williams }
1145cf5ddf3SPatrick Williams 
TEST_F(JsonSerializerTest,LoadGarbledJsonFile)1155cf5ddf3SPatrick Williams TEST_F(JsonSerializerTest, LoadGarbledJsonFile)
1165cf5ddf3SPatrick Williams {
1175cf5ddf3SPatrick Williams     // Write a garbled JSON string to the file
1185cf5ddf3SPatrick Williams     std::ofstream ofs(test_file);
1195cf5ddf3SPatrick Williams     ofs << "{"; // Incomplete JSON object
1205cf5ddf3SPatrick Williams     ofs.close();
1215cf5ddf3SPatrick Williams 
1225cf5ddf3SPatrick Williams     JsonSerializer s(test_file);
123*f2196659SPatrick Williams     EXPECT_FALSE(s.load());
124*f2196659SPatrick Williams     EXPECT_FALSE(std::filesystem::exists(test_file));
1255cf5ddf3SPatrick Williams }
126