1 /* 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_RUNTIME_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_TEST_H_ 18 #define ART_RUNTIME_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_TEST_H_ 19 20 #include <errno.h> 21 #include <memory> 22 #include <string> 23 24 #include "common_runtime_test.h" 25 26 namespace unix_file { 27 28 class RandomAccessFileTest : public testing::Test { 29 protected: ~RandomAccessFileTest()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 SetUp()37 virtual void SetUp() { 38 art::CommonRuntimeTest::SetUpAndroidData(android_data_); 39 } 40 TearDown()41 virtual void TearDown() { 42 art::CommonRuntimeTest::TearDownAndroidData(android_data_, true); 43 } 44 GetTmpPath(const std::string & name)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. ReadString(RandomAccessFile * f,std::string * s)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 TestRead()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 TestReadContent(const std::string & content,RandomAccessFile * file)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 TestSetLength()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 TestWrite()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 CleanUp(RandomAccessFile * file ATTRIBUTE_UNUSED)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_RUNTIME_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_TEST_H_ 184