xref: /openbmc/phosphor-user-manager/test/json_serializer_test.cpp (revision f21966594e9735887b3091616df643c24dd14979)
1 #include <unistd.h>
2 
3 #include <json_serializer.hpp>
4 
5 #include <filesystem>
6 #include <fstream>
7 #include <string>
8 
9 #include <gtest/gtest.h>
10 
11 namespace s = std::string_literals;
12 
13 class JsonSerializerTest : public testing::Test
14 {
15   protected:
16     std::string test_file;
17 
SetUp()18     void SetUp() override
19     {
20         char tmpTemplate[] = "/tmp/test_file_XXXXXX";
21         int fd = mkstemp(tmpTemplate);
22         if (fd == -1)
23         {
24             throw std::runtime_error("Failed to create temporary file.");
25         }
26         close(fd);
27         test_file = tmpTemplate;
28     }
29 
TearDown()30     void TearDown() override
31     {
32         if (std::filesystem::exists(test_file))
33         {
34             std::filesystem::remove(test_file);
35         }
36     }
37 };
38 
TEST_F(JsonSerializerTest,MakeJson)39 TEST_F(JsonSerializerTest, MakeJson)
40 {
41     JsonSerializer s(test_file);
42     nlohmann::json j = s.makeJson("foo/bar/baz", "value");
43     EXPECT_EQ(j["foo"]["bar"]["baz"], "value");
44 }
45 
TEST_F(JsonSerializerTest,SerializeDeserialize)46 TEST_F(JsonSerializerTest, SerializeDeserialize)
47 {
48     JsonSerializer s(test_file);
49     s.serialize("foo/bar/baz", "value");
50     std::string value;
51     s.deserialize("foo/bar/baz", value);
52     EXPECT_EQ(value, "value");
53 }
54 
TEST_F(JsonSerializerTest,StoreLoad)55 TEST_F(JsonSerializerTest, StoreLoad)
56 {
57     JsonSerializer s(test_file);
58     s.serialize("foo/bar/baz", "value");
59     s.store();
60 
61     // Create a new JsonSerializer instance to load from the same file
62     // This simulates a fresh process loading the configuration
63     JsonSerializer s2(test_file);
64     s2.load();
65     std::string value;
66     s2.deserialize("foo/bar/baz", value);
67     EXPECT_EQ(value, "value");
68 }
69 
TEST_F(JsonSerializerTest,Erase)70 TEST_F(JsonSerializerTest, Erase)
71 {
72     JsonSerializer s(test_file);
73     s.serialize("foo/bar/baz", "value");
74     // The current erase method only handles top-level keys.
75     // Calling erase with a nested path like "foo/bar/baz" will not remove
76     // "baz".
77     s.erase("foo/bar/baz");
78     s.store();
79 
80     // Verify that the value is still present because erase did not remove the
81     // nested key.
82     JsonSerializer s2(test_file);
83     s2.load();
84     std::string value;
85     s2.deserialize("foo/bar/baz", value);
86     EXPECT_EQ(value, "value"); // Expect original value to remain
87 }
88 
TEST_F(JsonSerializerTest,GetLeafNode)89 TEST_F(JsonSerializerTest, GetLeafNode)
90 {
91     JsonSerializer s(test_file);
92     s.serialize("foo/bar/baz", "value");
93     auto leaf = s.getLeafNode("foo/bar/baz");
94     EXPECT_TRUE(leaf.has_value());
95     if (leaf.has_value())
96     {
97         EXPECT_EQ(*leaf, "value");
98     }
99 
100     leaf = s.getLeafNode("foo/bar/nonexistent");
101     EXPECT_FALSE(leaf.has_value());
102 }
103 
TEST_F(JsonSerializerTest,LoadInvalidJsonFile)104 TEST_F(JsonSerializerTest, LoadInvalidJsonFile)
105 {
106     // Ensure the file is empty or contains invalid JSON
107     std::ofstream ofs(test_file, std::ios::trunc);
108     ofs.close();
109 
110     JsonSerializer s(test_file);
111     EXPECT_FALSE(s.load());
112     EXPECT_FALSE(std::filesystem::exists(test_file));
113 }
114 
TEST_F(JsonSerializerTest,LoadGarbledJsonFile)115 TEST_F(JsonSerializerTest, LoadGarbledJsonFile)
116 {
117     // Write a garbled JSON string to the file
118     std::ofstream ofs(test_file);
119     ofs << "{"; // Incomplete JSON object
120     ofs.close();
121 
122     JsonSerializer s(test_file);
123     EXPECT_FALSE(s.load());
124     EXPECT_FALSE(std::filesystem::exists(test_file));
125 }
126