blob: 905a2cdd668dcd9c8e060c3debbcfacf4b4af167 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#include "aos/util/file.h"
Brian Silverman61175fb2016-03-13 15:35:56 -04002
Tyler Chatowbf0609c2021-07-31 16:13:27 -07003#include <cstdlib>
payton.rehlf8cb3932023-06-13 11:20:44 -07004#include <optional>
Brian Silverman61175fb2016-03-13 15:35:56 -04005#include <string>
6
Adam Snaider96a0f4b2023-05-18 20:41:19 -07007#include "gmock/gmock-matchers.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07008#include "gtest/gtest.h"
9
James Kuszmaul0625b0d2022-09-21 11:38:48 -070010#include "aos/realtime.h"
James Kuszmaulfd43f4e2022-12-16 15:19:35 -080011#include "aos/testing/tmpdir.h"
James Kuszmaul0625b0d2022-09-21 11:38:48 -070012
Brian Silverman61175fb2016-03-13 15:35:56 -040013namespace aos {
14namespace util {
15namespace testing {
16
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);
90
James Kuszmaul0625b0d2022-09-21 11:38:48 -070091 aos::ScopedRealtime realtime;
James Kuszmaul5a88d412023-01-27 15:55:55 -080092 {
93 std::array<char, 20> contents;
Austin Schuh73ff6412023-09-01 14:42:24 -070094 std::optional<absl::Span<char>> read_result =
James Kuszmaul5a88d412023-01-27 15:55:55 -080095 reader.ReadContents({contents.data(), contents.size()});
96 EXPECT_EQ("123456789\n",
Austin Schuh73ff6412023-09-01 14:42:24 -070097 std::string_view(read_result->data(), read_result->size()));
James Kuszmaul5a88d412023-01-27 15:55:55 -080098 }
99 {
100 std::optional<std::array<char, 10>> read_result = reader.ReadString<10>();
101 ASSERT_TRUE(read_result.has_value());
102 EXPECT_EQ("123456789\n",
103 std::string_view(read_result->data(), read_result->size()));
104 }
105 EXPECT_EQ(123456789, reader.ReadInt32());
James Kuszmaulfd43f4e2022-12-16 15:19:35 -0800106}
107
108// Tests that we can write to a file without malloc'ing.
109TEST(FileTest, WriteNormalFileNoMalloc) {
110 const ::std::string tmpdir(aos::testing::TestTmpDir());
111 const ::std::string test_file = tmpdir + "/test_file";
112
113 FileWriter writer(test_file);
114
James Kuszmaulfd43f4e2022-12-16 15:19:35 -0800115 FileWriter::WriteResult result;
116 {
117 aos::ScopedRealtime realtime;
118 result = writer.WriteBytes("123456789");
119 }
120 EXPECT_EQ(9, result.bytes_written);
121 EXPECT_EQ(9, result.return_code);
122 EXPECT_EQ("123456789", ReadFileToStringOrDie(test_file));
123}
124
125// Tests that if we fail to write a file that the error code propagates
126// correctly.
127TEST(FileTest, WriteFileError) {
128 const ::std::string tmpdir(aos::testing::TestTmpDir());
129 const ::std::string test_file = tmpdir + "/test_file";
130
131 // Open with only read permissions; this should cause things to fail.
132 FileWriter writer(test_file, S_IRUSR);
133
134 // Mess up the file management by closing the file descriptor.
135 PCHECK(0 == close(writer.fd()));
136
James Kuszmaulfd43f4e2022-12-16 15:19:35 -0800137 FileWriter::WriteResult result;
138 {
139 aos::ScopedRealtime realtime;
140 result = writer.WriteBytes("123456789");
141 }
142 EXPECT_EQ(0, result.bytes_written);
143 EXPECT_EQ(-1, result.return_code);
144 EXPECT_EQ("", ReadFileToStringOrDie(test_file));
James Kuszmaul0625b0d2022-09-21 11:38:48 -0700145}
146
Brian Silverman61175fb2016-03-13 15:35:56 -0400147} // namespace testing
148} // namespace util
149} // namespace aos