xref: /openbmc/phosphor-power/phosphor-regulators/test/ffdc_file_tests.cpp (revision f3633f6339235ea7459121936e0f7e2bc1ab976e)
1  /**
2   * Copyright © 2020 IBM Corporation
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *     http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  #include "ffdc_file.hpp"
17  #include "test_utils.hpp"
18  
19  #include <errno.h>     // for errno
20  #include <fcntl.h>     // for fcntl()
21  #include <string.h>    // for memset(), size_t
22  #include <sys/types.h> // for lseek()
23  #include <unistd.h>    // for read(), write(), lseek(), fcntl(), close()
24  
25  #include <exception>
26  #include <filesystem>
27  
28  #include <gtest/gtest.h>
29  
30  using namespace phosphor::power::regulators;
31  using namespace phosphor::power::regulators::test_utils;
32  namespace fs = std::filesystem;
33  
34  /**
35   * Returns whether the specified file descriptor is valid/open.
36   *
37   * @param[in] fd - File descriptor
38   * @return true if descriptor is valid/open, false otherwise
39   */
isValid(int fd)40  bool isValid(int fd)
41  {
42      return (fcntl(fd, F_GETFL) != -1) || (errno != EBADF);
43  }
44  
TEST(FFDCFileTests,Constructor)45  TEST(FFDCFileTests, Constructor)
46  {
47      // Test where only the FFDCFormat parameter is specified
48      {
49          FFDCFile file{FFDCFormat::JSON};
50          EXPECT_NE(file.getFileDescriptor(), -1);
51          EXPECT_TRUE(isValid(file.getFileDescriptor()));
52          EXPECT_EQ(file.getFormat(), FFDCFormat::JSON);
53          EXPECT_FALSE(file.getPath().empty());
54          EXPECT_TRUE(fs::exists(file.getPath()));
55          EXPECT_EQ(file.getSubType(), 0);
56          EXPECT_EQ(file.getVersion(), 0);
57      }
58  
59      // Test where all constructor parameters are specified
60      {
61          FFDCFile file{FFDCFormat::Custom, 2, 3};
62          EXPECT_NE(file.getFileDescriptor(), -1);
63          EXPECT_TRUE(isValid(file.getFileDescriptor()));
64          EXPECT_EQ(file.getFormat(), FFDCFormat::Custom);
65          EXPECT_FALSE(file.getPath().empty());
66          EXPECT_TRUE(fs::exists(file.getPath()));
67          EXPECT_EQ(file.getSubType(), 2);
68          EXPECT_EQ(file.getVersion(), 3);
69      }
70  
71      // Note: The case where open() fails currently needs to be tested manually
72  }
73  
TEST(FFDCFileTests,GetFileDescriptor)74  TEST(FFDCFileTests, GetFileDescriptor)
75  {
76      FFDCFile file{FFDCFormat::JSON};
77      int fd = file.getFileDescriptor();
78      EXPECT_NE(fd, -1);
79      EXPECT_TRUE(isValid(fd));
80  
81      // Write some data to the file
82      char buffer[] = "This is some sample data";
83      size_t count = sizeof(buffer);
84      EXPECT_EQ(write(fd, buffer, count), count);
85  
86      // Seek back to the beginning of the file
87      EXPECT_EQ(lseek(fd, 0, SEEK_SET), 0);
88  
89      // Clear buffer
90      memset(buffer, '\0', count);
91      EXPECT_STREQ(buffer, "");
92  
93      // Read and verify file contents
94      EXPECT_EQ(read(fd, buffer, count), count);
95      EXPECT_STREQ(buffer, "This is some sample data");
96  }
97  
TEST(FFDCFileTests,GetFormat)98  TEST(FFDCFileTests, GetFormat)
99  {
100      // Test where 'Text' was specified
101      {
102          FFDCFile file{FFDCFormat::Text};
103          EXPECT_EQ(file.getFormat(), FFDCFormat::Text);
104      }
105  
106      // Test where 'Custom' was specified
107      {
108          FFDCFile file{FFDCFormat::Custom, 2, 3};
109          EXPECT_EQ(file.getFormat(), FFDCFormat::Custom);
110      }
111  }
112  
TEST(FFDCFileTests,GetPath)113  TEST(FFDCFileTests, GetPath)
114  {
115      FFDCFile file{FFDCFormat::JSON};
116      EXPECT_FALSE(file.getPath().empty());
117      EXPECT_TRUE(fs::exists(file.getPath()));
118  }
119  
TEST(FFDCFileTests,GetSubType)120  TEST(FFDCFileTests, GetSubType)
121  {
122      // Test where subType was not specified
123      {
124          FFDCFile file{FFDCFormat::JSON};
125          EXPECT_EQ(file.getSubType(), 0);
126      }
127  
128      // Test where subType was specified
129      {
130          FFDCFile file{FFDCFormat::Custom, 3, 2};
131          EXPECT_EQ(file.getSubType(), 3);
132      }
133  }
134  
TEST(FFDCFileTests,GetVersion)135  TEST(FFDCFileTests, GetVersion)
136  {
137      // Test where version was not specified
138      {
139          FFDCFile file{FFDCFormat::JSON};
140          EXPECT_EQ(file.getVersion(), 0);
141      }
142  
143      // Test where version was specified
144      {
145          FFDCFile file{FFDCFormat::Custom, 2, 5};
146          EXPECT_EQ(file.getVersion(), 5);
147      }
148  }
149  
TEST(FFDCFileTests,Remove)150  TEST(FFDCFileTests, Remove)
151  {
152      // Test where works
153      {
154          FFDCFile file{FFDCFormat::JSON};
155          EXPECT_NE(file.getFileDescriptor(), -1);
156          EXPECT_TRUE(isValid(file.getFileDescriptor()));
157          EXPECT_FALSE(file.getPath().empty());
158          EXPECT_TRUE(fs::exists(file.getPath()));
159  
160          int fd = file.getFileDescriptor();
161          fs::path path = file.getPath();
162  
163          file.remove();
164          EXPECT_EQ(file.getFileDescriptor(), -1);
165          EXPECT_TRUE(file.getPath().empty());
166  
167          EXPECT_FALSE(isValid(fd));
168          EXPECT_FALSE(fs::exists(path));
169      }
170  
171      // Test where file was already removed
172      {
173          FFDCFile file{FFDCFormat::JSON};
174          EXPECT_NE(file.getFileDescriptor(), -1);
175          EXPECT_FALSE(file.getPath().empty());
176  
177          file.remove();
178          EXPECT_EQ(file.getFileDescriptor(), -1);
179          EXPECT_TRUE(file.getPath().empty());
180  
181          file.remove();
182          EXPECT_EQ(file.getFileDescriptor(), -1);
183          EXPECT_TRUE(file.getPath().empty());
184      }
185  
186      // Test where closing the file fails
187      {
188          FFDCFile file{FFDCFormat::JSON};
189          int fd = file.getFileDescriptor();
190          EXPECT_TRUE(isValid(fd));
191  
192          EXPECT_EQ(close(fd), 0);
193          EXPECT_FALSE(isValid(fd));
194  
195          try
196          {
197              file.remove();
198              ADD_FAILURE() << "Should not have reached this line.";
199          }
200          catch (const std::exception& e)
201          {
202              EXPECT_NE(std::string{e.what()}.find("Unable to close FFDC file: "),
203                        std::string::npos);
204          }
205      }
206  
207      // Test where deleting the file fails
208      {
209          FFDCFile file{FFDCFormat::JSON};
210          fs::path path = file.getPath();
211          EXPECT_TRUE(fs::exists(path));
212  
213          makeFileUnRemovable(path);
214          try
215          {
216              file.remove();
217              ADD_FAILURE() << "Should not have reached this line.";
218          }
219          catch (const std::exception& e)
220          {
221              // This is expected.  Exception message will vary.
222          }
223          makeFileRemovable(path);
224      }
225  }
226