blob: b3f1e66d0d33804f81c1d4ec0c81a497f077c1da [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
Stephan Pleinesf63bde82024-01-13 15:59:33 -080013namespace aos::util::testing {
Brian Silverman61175fb2016-03-13 15:35:56 -040014
Adam Snaider96a0f4b2023-05-18 20:41:19 -070015using ::testing::ElementsAre;
16
Brian Silverman61175fb2016-03-13 15:35:56 -040017// Basic test of reading a normal file.
Alex Perrycb7da4b2019-08-28 19:35:56 -070018TEST(FileTest, ReadNormalFile) {
payton.rehlf8cb3932023-06-13 11:20:44 -070019 const std::string tmpdir(aos::testing::TestTmpDir());
20 const std::string test_file = tmpdir + "/test_file";
Brian Silverman61175fb2016-03-13 15:35:56 -040021 ASSERT_EQ(0, system(("echo contents > " + test_file).c_str()));
22 EXPECT_EQ("contents\n", ReadFileToStringOrDie(test_file));
23}
24
Adam Snaider96a0f4b2023-05-18 20:41:19 -070025// Basic test of reading a normal file.
26TEST(FileTest, ReadNormalFileToBytes) {
27 const std::string tmpdir(aos::testing::TestTmpDir());
28 const std::string test_file = tmpdir + "/test_file";
29 ASSERT_EQ(0, system(("echo contents > " + test_file).c_str()));
30 EXPECT_THAT(ReadFileToVecOrDie(test_file),
31 ElementsAre('c', 'o', 'n', 't', 'e', 'n', 't', 's', '\n'));
32}
33
Brian Silverman61175fb2016-03-13 15:35:56 -040034// Tests reading a file with 0 size, among other weird things.
Alex Perrycb7da4b2019-08-28 19:35:56 -070035TEST(FileTest, ReadSpecialFile) {
payton.rehlf8cb3932023-06-13 11:20:44 -070036 const std::string stat = ReadFileToStringOrDie("/proc/self/stat");
Brian Silverman61175fb2016-03-13 15:35:56 -040037 EXPECT_EQ('\n', stat[stat.size() - 1]);
payton.rehlf8cb3932023-06-13 11:20:44 -070038 const std::string my_pid = ::std::to_string(getpid());
Brian Silverman61175fb2016-03-13 15:35:56 -040039 EXPECT_EQ(my_pid, stat.substr(0, my_pid.size()));
40}
41
payton.rehlf8cb3932023-06-13 11:20:44 -070042// Basic test of maybe reading a normal file.
43TEST(FileTest, MaybeReadNormalFile) {
44 const std::string tmpdir(aos::testing::TestTmpDir());
45 const std::string test_file = tmpdir + "/test_file";
46 ASSERT_EQ(0, system(("echo contents > " + test_file).c_str()));
47 EXPECT_EQ("contents\n", MaybeReadFileToString(test_file).value());
48}
49
50// Tests maybe reading a file with 0 size, among other weird things.
51TEST(FileTest, MaybeReadSpecialFile) {
52 const std::optional<std::string> stat =
53 MaybeReadFileToString("/proc/self/stat");
54 ASSERT_TRUE(stat.has_value());
55 EXPECT_EQ('\n', (*stat)[stat->size() - 1]);
56 const std::string my_pid = std::to_string(getpid());
57 EXPECT_EQ(my_pid, stat->substr(0, my_pid.size()));
58}
59
60// Tests maybe reading a non-existent file, and not fatally erroring.
61TEST(FileTest, MaybeReadNonexistentFile) {
62 const std::optional<std::string> contents = MaybeReadFileToString("/dne");
63 ASSERT_FALSE(contents.has_value());
64}
65
James Kuszmaulf8178092020-05-10 18:46:45 -070066// Tests that the PathExists function works under normal conditions.
67TEST(FileTest, PathExistsTest) {
James Kuszmaulfd43f4e2022-12-16 15:19:35 -080068 const std::string tmpdir(aos::testing::TestTmpDir());
James Kuszmaulf8178092020-05-10 18:46:45 -070069 const std::string test_file = tmpdir + "/test_file";
70 // Make sure the test_file doesn't exist.
71 unlink(test_file.c_str());
72 EXPECT_FALSE(PathExists(test_file));
73
74 WriteStringToFileOrDie(test_file, "abc");
75
76 EXPECT_TRUE(PathExists(test_file));
77}
78
James Kuszmaul0625b0d2022-09-21 11:38:48 -070079// Basic test of reading a normal file.
80TEST(FileTest, ReadNormalFileNoMalloc) {
James Kuszmaulfd43f4e2022-12-16 15:19:35 -080081 const ::std::string tmpdir(aos::testing::TestTmpDir());
James Kuszmaul0625b0d2022-09-21 11:38:48 -070082 const ::std::string test_file = tmpdir + "/test_file";
James Kuszmaulfd43f4e2022-12-16 15:19:35 -080083 // Make sure to include a string long enough to avoid small string
84 // optimization.
85 ASSERT_EQ(0, system(("echo 123456789 > " + test_file).c_str()));
James Kuszmaul0625b0d2022-09-21 11:38:48 -070086
87 FileReader reader(test_file);
88
James Kuszmaul0625b0d2022-09-21 11:38:48 -070089 aos::ScopedRealtime realtime;
James Kuszmaul5a88d412023-01-27 15:55:55 -080090 {
91 std::array<char, 20> contents;
Austin Schuh73ff6412023-09-01 14:42:24 -070092 std::optional<absl::Span<char>> read_result =
James Kuszmaul5a88d412023-01-27 15:55:55 -080093 reader.ReadContents({contents.data(), contents.size()});
94 EXPECT_EQ("123456789\n",
Austin Schuh73ff6412023-09-01 14:42:24 -070095 std::string_view(read_result->data(), read_result->size()));
James Kuszmaul5a88d412023-01-27 15:55:55 -080096 }
97 {
98 std::optional<std::array<char, 10>> read_result = reader.ReadString<10>();
99 ASSERT_TRUE(read_result.has_value());
100 EXPECT_EQ("123456789\n",
101 std::string_view(read_result->data(), read_result->size()));
102 }
103 EXPECT_EQ(123456789, reader.ReadInt32());
James Kuszmaulfd43f4e2022-12-16 15:19:35 -0800104}
105
106// Tests that we can write to a file without malloc'ing.
107TEST(FileTest, WriteNormalFileNoMalloc) {
108 const ::std::string tmpdir(aos::testing::TestTmpDir());
109 const ::std::string test_file = tmpdir + "/test_file";
110
111 FileWriter writer(test_file);
112
James Kuszmaulfd43f4e2022-12-16 15:19:35 -0800113 FileWriter::WriteResult result;
114 {
115 aos::ScopedRealtime realtime;
116 result = writer.WriteBytes("123456789");
117 }
118 EXPECT_EQ(9, result.bytes_written);
119 EXPECT_EQ(9, result.return_code);
120 EXPECT_EQ("123456789", ReadFileToStringOrDie(test_file));
121}
122
123// Tests that if we fail to write a file that the error code propagates
124// correctly.
125TEST(FileTest, WriteFileError) {
126 const ::std::string tmpdir(aos::testing::TestTmpDir());
127 const ::std::string test_file = tmpdir + "/test_file";
128
129 // Open with only read permissions; this should cause things to fail.
130 FileWriter writer(test_file, S_IRUSR);
131
132 // Mess up the file management by closing the file descriptor.
133 PCHECK(0 == close(writer.fd()));
134
James Kuszmaulfd43f4e2022-12-16 15:19:35 -0800135 FileWriter::WriteResult result;
136 {
137 aos::ScopedRealtime realtime;
138 result = writer.WriteBytes("123456789");
139 }
140 EXPECT_EQ(0, result.bytes_written);
141 EXPECT_EQ(-1, result.return_code);
142 EXPECT_EQ("", ReadFileToStringOrDie(test_file));
James Kuszmaul0625b0d2022-09-21 11:38:48 -0700143}
144
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800145} // namespace aos::util::testing