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