blob: 178f89d5a54f84f25fbbe605aae9bf0c76bd98f3 [file] [log] [blame]
Martin Stjernholm4fb51112021-04-30 11:53:52 +01001/*
2 * Copyright (C) 2009 The Android Open Source Project
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
17#ifndef ART_LIBARTBASE_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_TEST_H_
18#define ART_LIBARTBASE_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_TEST_H_
19
20#include <errno.h>
21#include <memory>
22#include <string>
23
24#include "base/common_art_test.h"
25
26namespace unix_file {
27
28class RandomAccessFileTest : public testing::Test {
29 protected:
30 virtual ~RandomAccessFileTest() {
31 }
32
33 // Override this to return an instance of the subclass under test that's
34 // backed by a temporary file.
35 virtual RandomAccessFile* MakeTestFile() = 0;
36
37 virtual void SetUp() {
38 art::CommonArtTest::SetUpAndroidDataDir(android_data_);
39 }
40
41 virtual void TearDown() {
42 art::CommonArtTest::TearDownAndroidDataDir(android_data_, true);
43 }
44
45 std::string GetTmpPath(const std::string& name) {
46 std::string path;
47 path = android_data_;
48 path += "/";
49 path += name;
50 return path;
51 }
52
53 // TODO(enh): ReadString (and WriteString) might be generally useful.
54 static bool ReadString(RandomAccessFile* f, std::string* s) {
55 s->clear();
56 char buf[256];
57 int64_t n = 0;
58 int64_t offset = 0;
59 while ((n = f->Read(buf, sizeof(buf), offset)) > 0) {
60 s->append(buf, n);
61 offset += n;
62 }
63 return n != -1;
64 }
65
66 void TestRead() {
67 char buf[256];
68 std::unique_ptr<RandomAccessFile> file(MakeTestFile());
69
70 // Reading from the start of an empty file gets you zero bytes, however many
71 // you ask for.
72 ASSERT_EQ(0, file->Read(buf, 0, 0));
73 ASSERT_EQ(0, file->Read(buf, 123, 0));
74
75 const std::string content("hello");
76 ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
77
78 TestReadContent(content, file.get());
79
80 CleanUp(file.get());
81 }
82
83 void TestReadContent(const std::string& content, RandomAccessFile* file) {
84 const int buf_size = content.size() + 10;
85 std::unique_ptr<char[]> buf(new char[buf_size]);
86 // Can't read from a negative offset.
87 ASSERT_EQ(-EINVAL, file->Read(buf.get(), 0, -123));
88
89 // Reading too much gets us just what's in the file.
90 ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Read(buf.get(), buf_size, 0)));
91 ASSERT_EQ(std::string(buf.get(), content.size()), content);
92
93 // We only get as much as we ask for.
94 const size_t short_request = 2;
95 ASSERT_LT(short_request, content.size());
96 ASSERT_EQ(short_request, static_cast<uint64_t>(file->Read(buf.get(), short_request, 0)));
97 ASSERT_EQ(std::string(buf.get(), short_request),
98 content.substr(0, short_request));
99
100 // We don't have to start at the beginning.
101 const int non_zero_offset = 2;
102 ASSERT_GT(non_zero_offset, 0);
103 ASSERT_EQ(short_request, static_cast<uint64_t>(file->Read(buf.get(), short_request,
104 non_zero_offset)));
105 ASSERT_EQ(std::string(buf.get(), short_request),
106 content.substr(non_zero_offset, short_request));
107
108 // Reading past the end gets us nothing.
109 ASSERT_EQ(0, file->Read(buf.get(), buf_size, file->GetLength()));
110 ASSERT_EQ(0, file->Read(buf.get(), buf_size, file->GetLength() + 1));
111 }
112
113 void TestSetLength() {
114 const std::string content("hello");
115 std::unique_ptr<RandomAccessFile> file(MakeTestFile());
116 ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
117 ASSERT_EQ(content.size(), static_cast<uint64_t>(file->GetLength()));
118
119 // Can't give a file a negative length.
120 ASSERT_EQ(-EINVAL, file->SetLength(-123));
121
122 // Can truncate the file.
123 int64_t new_length = 2;
124 ASSERT_EQ(0, file->SetLength(new_length));
125 ASSERT_EQ(new_length, file->GetLength());
126 std::string new_content;
127 ASSERT_TRUE(ReadString(file.get(), &new_content));
128 ASSERT_EQ(content.substr(0, 2), new_content);
129
130 // Expanding the file appends zero bytes.
131 new_length = file->GetLength() + 1;
132 ASSERT_EQ(0, file->SetLength(new_length));
133 ASSERT_EQ(new_length, file->GetLength());
134 ASSERT_TRUE(ReadString(file.get(), &new_content));
135 ASSERT_EQ('\0', new_content[new_length - 1]);
136
137 CleanUp(file.get());
138 }
139
140 void TestWrite() {
141 const std::string content("hello");
142 std::unique_ptr<RandomAccessFile> file(MakeTestFile());
143
144 // Can't write to a negative offset.
145 ASSERT_EQ(-EINVAL, file->Write(content.data(), 0, -123));
146
147 // Writing zero bytes of data is a no-op.
148 ASSERT_EQ(0, file->Write(content.data(), 0, 0));
149 ASSERT_EQ(0, file->GetLength());
150
151 // We can write data.
152 ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
153 ASSERT_EQ(content.size(), static_cast<uint64_t>(file->GetLength()));
154 std::string new_content;
155 ASSERT_TRUE(ReadString(file.get(), &new_content));
156 ASSERT_EQ(new_content, content);
157
158 // We can read it back.
159 char buf[256];
160 ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Read(buf, sizeof(buf), 0)));
161 ASSERT_EQ(std::string(buf, content.size()), content);
162
163 // We can append data past the end.
164 ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(),
165 file->GetLength() + 1)));
166 int64_t new_length = 2*content.size() + 1;
167 ASSERT_EQ(file->GetLength(), new_length);
168 ASSERT_TRUE(ReadString(file.get(), &new_content));
169 ASSERT_EQ(std::string("hello\0hello", new_length), new_content);
170
171 CleanUp(file.get());
172 }
173
174 virtual void CleanUp(RandomAccessFile* file ATTRIBUTE_UNUSED) {
175 }
176
177 protected:
178 std::string android_data_;
179};
180
181} // namespace unix_file
182
183#endif // ART_LIBARTBASE_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_TEST_H_