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