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