]>
Commit | Line | Data |
---|---|---|
f67539c2 | 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. |
7c673cae | 2 | // Copyright (c) 2015, Red Hat, Inc. All rights reserved. |
11fdf7f2 TL |
3 | // This source code is licensed under both the GPLv2 (found in the |
4 | // COPYING file in the root directory) and Apache 2.0 License | |
5 | // (found in the LICENSE.Apache file in the root directory). | |
7c673cae FG |
6 | |
7 | #ifndef ROCKSDB_LITE | |
8 | ||
9 | #include "rocksdb/utilities/env_mirror.h" | |
10 | #include "env/mock_env.h" | |
f67539c2 | 11 | #include "test_util/testharness.h" |
7c673cae | 12 | |
f67539c2 | 13 | namespace ROCKSDB_NAMESPACE { |
7c673cae FG |
14 | |
15 | class EnvMirrorTest : public testing::Test { | |
16 | public: | |
17 | Env* default_; | |
18 | MockEnv* a_, *b_; | |
19 | EnvMirror* env_; | |
20 | const EnvOptions soptions_; | |
21 | ||
22 | EnvMirrorTest() | |
23 | : default_(Env::Default()), | |
24 | a_(new MockEnv(default_)), | |
25 | b_(new MockEnv(default_)), | |
26 | env_(new EnvMirror(a_, b_)) {} | |
27 | ~EnvMirrorTest() { | |
28 | delete env_; | |
29 | delete a_; | |
30 | delete b_; | |
31 | } | |
32 | }; | |
33 | ||
34 | TEST_F(EnvMirrorTest, Basics) { | |
35 | uint64_t file_size; | |
494da23a | 36 | std::unique_ptr<WritableFile> writable_file; |
7c673cae FG |
37 | std::vector<std::string> children; |
38 | ||
39 | ASSERT_OK(env_->CreateDir("/dir")); | |
40 | ||
41 | // Check that the directory is empty. | |
42 | ASSERT_EQ(Status::NotFound(), env_->FileExists("/dir/non_existent")); | |
43 | ASSERT_TRUE(!env_->GetFileSize("/dir/non_existent", &file_size).ok()); | |
44 | ASSERT_OK(env_->GetChildren("/dir", &children)); | |
45 | ASSERT_EQ(0U, children.size()); | |
46 | ||
47 | // Create a file. | |
48 | ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file, soptions_)); | |
49 | writable_file.reset(); | |
50 | ||
51 | // Check that the file exists. | |
52 | ASSERT_OK(env_->FileExists("/dir/f")); | |
53 | ASSERT_OK(a_->FileExists("/dir/f")); | |
54 | ASSERT_OK(b_->FileExists("/dir/f")); | |
55 | ASSERT_OK(env_->GetFileSize("/dir/f", &file_size)); | |
56 | ASSERT_EQ(0U, file_size); | |
57 | ASSERT_OK(env_->GetChildren("/dir", &children)); | |
58 | ASSERT_EQ(1U, children.size()); | |
59 | ASSERT_EQ("f", children[0]); | |
60 | ASSERT_OK(a_->GetChildren("/dir", &children)); | |
61 | ASSERT_EQ(1U, children.size()); | |
62 | ASSERT_EQ("f", children[0]); | |
63 | ASSERT_OK(b_->GetChildren("/dir", &children)); | |
64 | ASSERT_EQ(1U, children.size()); | |
65 | ASSERT_EQ("f", children[0]); | |
66 | ||
67 | // Write to the file. | |
68 | ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file, soptions_)); | |
69 | ASSERT_OK(writable_file->Append("abc")); | |
70 | writable_file.reset(); | |
71 | ||
72 | // Check for expected size. | |
73 | ASSERT_OK(env_->GetFileSize("/dir/f", &file_size)); | |
74 | ASSERT_EQ(3U, file_size); | |
75 | ASSERT_OK(a_->GetFileSize("/dir/f", &file_size)); | |
76 | ASSERT_EQ(3U, file_size); | |
77 | ASSERT_OK(b_->GetFileSize("/dir/f", &file_size)); | |
78 | ASSERT_EQ(3U, file_size); | |
79 | ||
80 | // Check that renaming works. | |
81 | ASSERT_TRUE(!env_->RenameFile("/dir/non_existent", "/dir/g").ok()); | |
82 | ASSERT_OK(env_->RenameFile("/dir/f", "/dir/g")); | |
83 | ASSERT_EQ(Status::NotFound(), env_->FileExists("/dir/f")); | |
84 | ASSERT_OK(env_->FileExists("/dir/g")); | |
85 | ASSERT_OK(env_->GetFileSize("/dir/g", &file_size)); | |
86 | ASSERT_EQ(3U, file_size); | |
87 | ASSERT_OK(a_->FileExists("/dir/g")); | |
88 | ASSERT_OK(a_->GetFileSize("/dir/g", &file_size)); | |
89 | ASSERT_EQ(3U, file_size); | |
90 | ASSERT_OK(b_->FileExists("/dir/g")); | |
91 | ASSERT_OK(b_->GetFileSize("/dir/g", &file_size)); | |
92 | ASSERT_EQ(3U, file_size); | |
93 | ||
94 | // Check that opening non-existent file fails. | |
494da23a TL |
95 | std::unique_ptr<SequentialFile> seq_file; |
96 | std::unique_ptr<RandomAccessFile> rand_file; | |
7c673cae FG |
97 | ASSERT_TRUE( |
98 | !env_->NewSequentialFile("/dir/non_existent", &seq_file, soptions_).ok()); | |
99 | ASSERT_TRUE(!seq_file); | |
100 | ASSERT_TRUE(!env_->NewRandomAccessFile("/dir/non_existent", &rand_file, | |
101 | soptions_).ok()); | |
102 | ASSERT_TRUE(!rand_file); | |
103 | ||
104 | // Check that deleting works. | |
105 | ASSERT_TRUE(!env_->DeleteFile("/dir/non_existent").ok()); | |
106 | ASSERT_OK(env_->DeleteFile("/dir/g")); | |
107 | ASSERT_EQ(Status::NotFound(), env_->FileExists("/dir/g")); | |
108 | ASSERT_OK(env_->GetChildren("/dir", &children)); | |
109 | ASSERT_EQ(0U, children.size()); | |
110 | ASSERT_OK(env_->DeleteDir("/dir")); | |
111 | } | |
112 | ||
113 | TEST_F(EnvMirrorTest, ReadWrite) { | |
494da23a TL |
114 | std::unique_ptr<WritableFile> writable_file; |
115 | std::unique_ptr<SequentialFile> seq_file; | |
116 | std::unique_ptr<RandomAccessFile> rand_file; | |
7c673cae FG |
117 | Slice result; |
118 | char scratch[100]; | |
119 | ||
120 | ASSERT_OK(env_->CreateDir("/dir")); | |
121 | ||
122 | ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file, soptions_)); | |
123 | ASSERT_OK(writable_file->Append("hello ")); | |
124 | ASSERT_OK(writable_file->Append("world")); | |
125 | writable_file.reset(); | |
126 | ||
127 | // Read sequentially. | |
128 | ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file, soptions_)); | |
129 | ASSERT_OK(seq_file->Read(5, &result, scratch)); // Read "hello". | |
130 | ASSERT_EQ(0, result.compare("hello")); | |
131 | ASSERT_OK(seq_file->Skip(1)); | |
132 | ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Read "world". | |
133 | ASSERT_EQ(0, result.compare("world")); | |
134 | ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Try reading past EOF. | |
135 | ASSERT_EQ(0U, result.size()); | |
136 | ASSERT_OK(seq_file->Skip(100)); // Try to skip past end of file. | |
137 | ASSERT_OK(seq_file->Read(1000, &result, scratch)); | |
138 | ASSERT_EQ(0U, result.size()); | |
139 | ||
140 | // Random reads. | |
141 | ASSERT_OK(env_->NewRandomAccessFile("/dir/f", &rand_file, soptions_)); | |
142 | ASSERT_OK(rand_file->Read(6, 5, &result, scratch)); // Read "world". | |
143 | ASSERT_EQ(0, result.compare("world")); | |
144 | ASSERT_OK(rand_file->Read(0, 5, &result, scratch)); // Read "hello". | |
145 | ASSERT_EQ(0, result.compare("hello")); | |
146 | ASSERT_OK(rand_file->Read(10, 100, &result, scratch)); // Read "d". | |
147 | ASSERT_EQ(0, result.compare("d")); | |
148 | ||
149 | // Too high offset. | |
150 | ASSERT_TRUE(!rand_file->Read(1000, 5, &result, scratch).ok()); | |
151 | } | |
152 | ||
153 | TEST_F(EnvMirrorTest, Locks) { | |
154 | FileLock* lock; | |
155 | ||
156 | // These are no-ops, but we test they return success. | |
157 | ASSERT_OK(env_->LockFile("some file", &lock)); | |
158 | ASSERT_OK(env_->UnlockFile(lock)); | |
159 | } | |
160 | ||
161 | TEST_F(EnvMirrorTest, Misc) { | |
162 | std::string test_dir; | |
163 | ASSERT_OK(env_->GetTestDirectory(&test_dir)); | |
164 | ASSERT_TRUE(!test_dir.empty()); | |
165 | ||
494da23a | 166 | std::unique_ptr<WritableFile> writable_file; |
7c673cae FG |
167 | ASSERT_OK(env_->NewWritableFile("/a/b", &writable_file, soptions_)); |
168 | ||
169 | // These are no-ops, but we test they return success. | |
170 | ASSERT_OK(writable_file->Sync()); | |
171 | ASSERT_OK(writable_file->Flush()); | |
172 | ASSERT_OK(writable_file->Close()); | |
173 | writable_file.reset(); | |
174 | } | |
175 | ||
176 | TEST_F(EnvMirrorTest, LargeWrite) { | |
177 | const size_t kWriteSize = 300 * 1024; | |
178 | char* scratch = new char[kWriteSize * 2]; | |
179 | ||
180 | std::string write_data; | |
181 | for (size_t i = 0; i < kWriteSize; ++i) { | |
182 | write_data.append(1, static_cast<char>(i)); | |
183 | } | |
184 | ||
494da23a | 185 | std::unique_ptr<WritableFile> writable_file; |
7c673cae FG |
186 | ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file, soptions_)); |
187 | ASSERT_OK(writable_file->Append("foo")); | |
188 | ASSERT_OK(writable_file->Append(write_data)); | |
189 | writable_file.reset(); | |
190 | ||
494da23a | 191 | std::unique_ptr<SequentialFile> seq_file; |
7c673cae FG |
192 | Slice result; |
193 | ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file, soptions_)); | |
194 | ASSERT_OK(seq_file->Read(3, &result, scratch)); // Read "foo". | |
195 | ASSERT_EQ(0, result.compare("foo")); | |
196 | ||
197 | size_t read = 0; | |
198 | std::string read_data; | |
199 | while (read < kWriteSize) { | |
200 | ASSERT_OK(seq_file->Read(kWriteSize - read, &result, scratch)); | |
201 | read_data.append(result.data(), result.size()); | |
202 | read += result.size(); | |
203 | } | |
204 | ASSERT_TRUE(write_data == read_data); | |
205 | delete[] scratch; | |
206 | } | |
207 | ||
f67539c2 | 208 | } // namespace ROCKSDB_NAMESPACE |
7c673cae FG |
209 | |
210 | int main(int argc, char** argv) { | |
211 | ::testing::InitGoogleTest(&argc, argv); | |
212 | return RUN_ALL_TESTS(); | |
213 | } | |
214 | ||
215 | #else | |
216 | #include <stdio.h> | |
217 | ||
218 | int main(int argc, char** argv) { | |
219 | fprintf(stderr, "SKIPPED as EnvMirror is not supported in ROCKSDB_LITE\n"); | |
220 | return 0; | |
221 | } | |
222 | ||
223 | #endif // !ROCKSDB_LITE |