blob: fb1befc09a88d64ec253e0b3a75c458f06c5460f [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#include "aos/util/file.h"
Brian Silverman61175fb2016-03-13 15:35:56 -04002
Stephan Pleinesb1177672024-05-27 17:48:32 -07003#include <unistd.h>
4
Tyler Chatowbf0609c2021-07-31 16:13:27 -07005#include <cstdlib>
payton.rehlf8cb3932023-06-13 11:20:44 -07006#include <optional>
Brian Silverman61175fb2016-03-13 15:35:56 -04007#include <string>
8
Stephan Pleinesb1177672024-05-27 17:48:32 -07009#include "gmock/gmock.h"
Philipp Schrader790cb542023-07-05 21:06:52 -070010#include "gtest/gtest.h"
11
James Kuszmaul0625b0d2022-09-21 11:38:48 -070012#include "aos/realtime.h"
James Kuszmaulfd43f4e2022-12-16 15:19:35 -080013#include "aos/testing/tmpdir.h"
James Kuszmaul0625b0d2022-09-21 11:38:48 -070014
Stephan Pleinesf63bde82024-01-13 15:59:33 -080015namespace aos::util::testing {
Brian Silverman61175fb2016-03-13 15:35:56 -040016
Adam Snaider96a0f4b2023-05-18 20:41:19 -070017using ::testing::ElementsAre;
18
Brian Silverman61175fb2016-03-13 15:35:56 -040019// Basic test of reading a normal file.
Alex Perrycb7da4b2019-08-28 19:35:56 -070020TEST(FileTest, ReadNormalFile) {
payton.rehlf8cb3932023-06-13 11:20:44 -070021 const std::string tmpdir(aos::testing::TestTmpDir());
22 const std::string test_file = tmpdir + "/test_file";
Brian Silverman61175fb2016-03-13 15:35:56 -040023 ASSERT_EQ(0, system(("echo contents > " + test_file).c_str()));
24 EXPECT_EQ("contents\n", ReadFileToStringOrDie(test_file));
25}
26
Adam Snaider96a0f4b2023-05-18 20:41:19 -070027// Basic test of reading a normal file.
28TEST(FileTest, ReadNormalFileToBytes) {
29 const std::string tmpdir(aos::testing::TestTmpDir());
30 const std::string test_file = tmpdir + "/test_file";
31 ASSERT_EQ(0, system(("echo contents > " + test_file).c_str()));
32 EXPECT_THAT(ReadFileToVecOrDie(test_file),
33 ElementsAre('c', 'o', 'n', 't', 'e', 'n', 't', 's', '\n'));
34}
35
Brian Silverman61175fb2016-03-13 15:35:56 -040036// Tests reading a file with 0 size, among other weird things.
Alex Perrycb7da4b2019-08-28 19:35:56 -070037TEST(FileTest, ReadSpecialFile) {
payton.rehlf8cb3932023-06-13 11:20:44 -070038 const std::string stat = ReadFileToStringOrDie("/proc/self/stat");
Brian Silverman61175fb2016-03-13 15:35:56 -040039 EXPECT_EQ('\n', stat[stat.size() - 1]);
payton.rehlf8cb3932023-06-13 11:20:44 -070040 const std::string my_pid = ::std::to_string(getpid());
Brian Silverman61175fb2016-03-13 15:35:56 -040041 EXPECT_EQ(my_pid, stat.substr(0, my_pid.size()));
42}
43
payton.rehlf8cb3932023-06-13 11:20:44 -070044// Basic test of maybe reading a normal file.
45TEST(FileTest, MaybeReadNormalFile) {
46 const std::string tmpdir(aos::testing::TestTmpDir());
47 const std::string test_file = tmpdir + "/test_file";
48 ASSERT_EQ(0, system(("echo contents > " + test_file).c_str()));
49 EXPECT_EQ("contents\n", MaybeReadFileToString(test_file).value());
50}
51
52// Tests maybe reading a file with 0 size, among other weird things.
53TEST(FileTest, MaybeReadSpecialFile) {
54 const std::optional<std::string> stat =
55 MaybeReadFileToString("/proc/self/stat");
56 ASSERT_TRUE(stat.has_value());
57 EXPECT_EQ('\n', (*stat)[stat->size() - 1]);
58 const std::string my_pid = std::to_string(getpid());
59 EXPECT_EQ(my_pid, stat->substr(0, my_pid.size()));
60}
61
62// Tests maybe reading a non-existent file, and not fatally erroring.
63TEST(FileTest, MaybeReadNonexistentFile) {
64 const std::optional<std::string> contents = MaybeReadFileToString("/dne");
65 ASSERT_FALSE(contents.has_value());
66}
67
James Kuszmaulf8178092020-05-10 18:46:45 -070068// Tests that the PathExists function works under normal conditions.
69TEST(FileTest, PathExistsTest) {
James Kuszmaulfd43f4e2022-12-16 15:19:35 -080070 const std::string tmpdir(aos::testing::TestTmpDir());
James Kuszmaulf8178092020-05-10 18:46:45 -070071 const std::string test_file = tmpdir + "/test_file";
72 // Make sure the test_file doesn't exist.
73 unlink(test_file.c_str());
74 EXPECT_FALSE(PathExists(test_file));
75
76 WriteStringToFileOrDie(test_file, "abc");
77
78 EXPECT_TRUE(PathExists(test_file));
79}
80
James Kuszmaul0625b0d2022-09-21 11:38:48 -070081// Basic test of reading a normal file.
82TEST(FileTest, ReadNormalFileNoMalloc) {
James Kuszmaulfd43f4e2022-12-16 15:19:35 -080083 const ::std::string tmpdir(aos::testing::TestTmpDir());
James Kuszmaul0625b0d2022-09-21 11:38:48 -070084 const ::std::string test_file = tmpdir + "/test_file";
James Kuszmaulfd43f4e2022-12-16 15:19:35 -080085 // Make sure to include a string long enough to avoid small string
86 // optimization.
87 ASSERT_EQ(0, system(("echo 123456789 > " + test_file).c_str()));
James Kuszmaul0625b0d2022-09-21 11:38:48 -070088
89 FileReader reader(test_file);
Pallavi Madhukar1d391462024-05-13 18:46:48 -070090 EXPECT_TRUE(reader.is_open());
James Kuszmaul0625b0d2022-09-21 11:38:48 -070091
James Kuszmaul0625b0d2022-09-21 11:38:48 -070092 aos::ScopedRealtime realtime;
James Kuszmaul5a88d412023-01-27 15:55:55 -080093 {
94 std::array<char, 20> contents;
Austin Schuh73ff6412023-09-01 14:42:24 -070095 std::optional<absl::Span<char>> read_result =
James Kuszmaul5a88d412023-01-27 15:55:55 -080096 reader.ReadContents({contents.data(), contents.size()});
97 EXPECT_EQ("123456789\n",
Austin Schuh73ff6412023-09-01 14:42:24 -070098 std::string_view(read_result->data(), read_result->size()));
James Kuszmaul5a88d412023-01-27 15:55:55 -080099 }
100 {
101 std::optional<std::array<char, 10>> read_result = reader.ReadString<10>();
102 ASSERT_TRUE(read_result.has_value());
103 EXPECT_EQ("123456789\n",
104 std::string_view(read_result->data(), read_result->size()));
105 }
106 EXPECT_EQ(123456789, reader.ReadInt32());
James Kuszmaulfd43f4e2022-12-16 15:19:35 -0800107}
108
Pallavi Madhukar1d391462024-05-13 18:46:48 -0700109// Test reading a non-existent file.
110TEST(FileDeathTest, ReadNonExistentFile) {
111 const ::std::string test_file = "/dne";
112
113 // If error_type flag is not set or set to kFatal, this should fail.
114 EXPECT_DEATH(FileReader reader(test_file),
115 "opening " + test_file + ": No such file or directory");
116
117 FileReaderErrorType error_type = FileReaderErrorType::kFatal;
118 EXPECT_DEATH(FileReader reader(test_file, error_type),
119 "opening " + test_file + ": No such file or directory");
120
121 // If warning flag is set to true, read should not fail, is_open() should
122 // return false, ReadContents() and ReadInt32() should fail.
123 error_type = FileReaderErrorType::kNonFatal;
124 FileReader reader(test_file, error_type);
125 EXPECT_FALSE(reader.is_open());
126 std::array<char, 16> contents;
127 EXPECT_DEATH(
128 reader.ReadContents(absl::Span<char>(contents.data(), contents.size())),
129 "Bad file descriptor");
130 EXPECT_DEATH(reader.ReadInt32(), "Bad file descriptor");
131}
132
James Kuszmaulfd43f4e2022-12-16 15:19:35 -0800133// Tests that we can write to a file without malloc'ing.
134TEST(FileTest, WriteNormalFileNoMalloc) {
135 const ::std::string tmpdir(aos::testing::TestTmpDir());
136 const ::std::string test_file = tmpdir + "/test_file";
137
138 FileWriter writer(test_file);
139
James Kuszmaulfd43f4e2022-12-16 15:19:35 -0800140 FileWriter::WriteResult result;
141 {
142 aos::ScopedRealtime realtime;
143 result = writer.WriteBytes("123456789");
144 }
145 EXPECT_EQ(9, result.bytes_written);
146 EXPECT_EQ(9, result.return_code);
147 EXPECT_EQ("123456789", ReadFileToStringOrDie(test_file));
148}
149
150// Tests that if we fail to write a file that the error code propagates
151// correctly.
152TEST(FileTest, WriteFileError) {
153 const ::std::string tmpdir(aos::testing::TestTmpDir());
154 const ::std::string test_file = tmpdir + "/test_file";
155
156 // Open with only read permissions; this should cause things to fail.
157 FileWriter writer(test_file, S_IRUSR);
158
159 // Mess up the file management by closing the file descriptor.
160 PCHECK(0 == close(writer.fd()));
161
James Kuszmaulfd43f4e2022-12-16 15:19:35 -0800162 FileWriter::WriteResult result;
163 {
164 aos::ScopedRealtime realtime;
165 result = writer.WriteBytes("123456789");
166 }
167 EXPECT_EQ(0, result.bytes_written);
168 EXPECT_EQ(-1, result.return_code);
169 EXPECT_EQ("", ReadFileToStringOrDie(test_file));
James Kuszmaul0625b0d2022-09-21 11:38:48 -0700170}
171
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800172} // namespace aos::util::testing