diff options
author | Michael Ryleev | 2016-03-08 17:16:22 -0600 |
---|---|---|
committer | Michael Ryleev | 2016-05-18 15:31:36 -0500 |
commit | e2d656481840cf9d5f39405ecdfd2c0f40cf64b0 (patch) | |
tree | ba733d076ab3bf74904bdc07a6a7373ed275b0de /trusty/storage | |
parent | abebb89359d7388fee8d1ca1411e2ae435dd3210 (diff) | |
download | platform-system-core-e2d656481840cf9d5f39405ecdfd2c0f40cf64b0.tar.gz platform-system-core-e2d656481840cf9d5f39405ecdfd2c0f40cf64b0.tar.xz platform-system-core-e2d656481840cf9d5f39405ecdfd2c0f40cf64b0.zip |
trusty: storage: add tests
Change-Id: I40c9ea47e1304ef35db3d5936b001b63f3a9795e
Diffstat (limited to 'trusty/storage')
-rw-r--r-- | trusty/storage/tests/Android.mk | 29 | ||||
-rw-r--r-- | trusty/storage/tests/main.cpp | 3040 |
2 files changed, 3069 insertions, 0 deletions
diff --git a/trusty/storage/tests/Android.mk b/trusty/storage/tests/Android.mk new file mode 100644 index 000000000..71c904df1 --- /dev/null +++ b/trusty/storage/tests/Android.mk | |||
@@ -0,0 +1,29 @@ | |||
1 | # | ||
2 | # Copyright (C) 2016 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 | LOCAL_PATH:= $(call my-dir) | ||
18 | |||
19 | include $(CLEAR_VARS) | ||
20 | LOCAL_MODULE := secure-storage-unit-test | ||
21 | LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers | ||
22 | LOCAL_STATIC_LIBRARIES := \ | ||
23 | libtrustystorageinterface \ | ||
24 | libtrustystorage \ | ||
25 | libtrusty \ | ||
26 | liblog | ||
27 | LOCAL_SRC_FILES := main.cpp | ||
28 | include $(BUILD_NATIVE_TEST) | ||
29 | |||
diff --git a/trusty/storage/tests/main.cpp b/trusty/storage/tests/main.cpp new file mode 100644 index 000000000..a771b877d --- /dev/null +++ b/trusty/storage/tests/main.cpp | |||
@@ -0,0 +1,3040 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 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 | #include <assert.h> | ||
18 | #include <stdint.h> | ||
19 | #include <stdbool.h> | ||
20 | #include <gtest/gtest.h> | ||
21 | |||
22 | #include <trusty/lib/storage.h> | ||
23 | |||
24 | #define TRUSTY_DEVICE_NAME "/dev/trusty-ipc-dev0" | ||
25 | |||
26 | #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) | ||
27 | |||
28 | static inline bool is_32bit_aligned(size_t sz) | ||
29 | { | ||
30 | return ((sz & 0x3) == 0); | ||
31 | } | ||
32 | |||
33 | static inline bool is_valid_size(size_t sz) { | ||
34 | return (sz > 0) && is_32bit_aligned(sz); | ||
35 | } | ||
36 | |||
37 | static bool is_valid_offset(storage_off_t off) | ||
38 | { | ||
39 | return (off & 0x3) == 0ULL; | ||
40 | } | ||
41 | |||
42 | static void fill_pattern32(uint32_t *buf, size_t len, storage_off_t off) | ||
43 | { | ||
44 | size_t cnt = len / sizeof(uint32_t); | ||
45 | uint32_t pattern = (uint32_t)(off / sizeof(uint32_t)); | ||
46 | while (cnt--) { | ||
47 | *buf++ = pattern++; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static bool check_pattern32(const uint32_t *buf, size_t len, storage_off_t off) | ||
52 | { | ||
53 | size_t cnt = len / sizeof(uint32_t); | ||
54 | uint32_t pattern = (uint32_t)(off / sizeof(uint32_t)); | ||
55 | while (cnt--) { | ||
56 | if (*buf != pattern) | ||
57 | return false; | ||
58 | buf++; | ||
59 | pattern++; | ||
60 | } | ||
61 | return true; | ||
62 | } | ||
63 | |||
64 | static bool check_value32(const uint32_t *buf, size_t len, uint32_t val) | ||
65 | { | ||
66 | size_t cnt = len / sizeof(uint32_t); | ||
67 | while (cnt--) { | ||
68 | if (*buf != val) | ||
69 | return false; | ||
70 | buf++; | ||
71 | } | ||
72 | return true; | ||
73 | } | ||
74 | |||
75 | using testing::TestWithParam; | ||
76 | |||
77 | class StorageServiceTest : public virtual TestWithParam<const char *> { | ||
78 | public: | ||
79 | StorageServiceTest() {} | ||
80 | virtual ~StorageServiceTest() {} | ||
81 | |||
82 | virtual void SetUp() { | ||
83 | port_ = GetParam(); | ||
84 | test_buf_ = NULL; | ||
85 | aux_session_ = STORAGE_INVALID_SESSION; | ||
86 | int rc = storage_open_session(TRUSTY_DEVICE_NAME, &session_, port_); | ||
87 | ASSERT_EQ(0, rc); | ||
88 | } | ||
89 | |||
90 | virtual void TearDown() { | ||
91 | if (test_buf_) { | ||
92 | delete[] test_buf_; | ||
93 | test_buf_ = NULL; | ||
94 | } | ||
95 | storage_close_session(session_); | ||
96 | |||
97 | if (aux_session_ != STORAGE_INVALID_SESSION) { | ||
98 | storage_close_session(aux_session_); | ||
99 | aux_session_ = STORAGE_INVALID_SESSION; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | void WriteReadAtOffsetHelper(file_handle_t handle, size_t blk, size_t cnt, bool complete); | ||
104 | |||
105 | void WriteZeroChunk(file_handle_t handle, storage_off_t off, size_t chunk_len, bool complete ); | ||
106 | void WritePatternChunk(file_handle_t handle, storage_off_t off, size_t chunk_len, bool complete); | ||
107 | void WritePattern(file_handle_t handle, storage_off_t off, size_t data_len, size_t chunk_len, bool complete); | ||
108 | |||
109 | void ReadChunk(file_handle_t handle, storage_off_t off, size_t chunk_len, | ||
110 | size_t head_len, size_t pattern_len, size_t tail_len); | ||
111 | void ReadPattern(file_handle_t handle, storage_off_t off, size_t data_len, size_t chunk_len); | ||
112 | void ReadPatternEOF(file_handle_t handle, storage_off_t off, size_t chunk_len, size_t exp_len); | ||
113 | |||
114 | protected: | ||
115 | const char *port_; | ||
116 | uint32_t *test_buf_; | ||
117 | storage_session_t session_; | ||
118 | storage_session_t aux_session_; | ||
119 | }; | ||
120 | |||
121 | INSTANTIATE_TEST_CASE_P(SS_TD_Tests, StorageServiceTest, ::testing::Values(STORAGE_CLIENT_TD_PORT)); | ||
122 | INSTANTIATE_TEST_CASE_P(SS_TDEA_Tests, StorageServiceTest, ::testing::Values(STORAGE_CLIENT_TDEA_PORT)); | ||
123 | INSTANTIATE_TEST_CASE_P(SS_TP_Tests, StorageServiceTest, ::testing::Values(STORAGE_CLIENT_TP_PORT)); | ||
124 | |||
125 | |||
126 | void StorageServiceTest::WriteZeroChunk(file_handle_t handle, storage_off_t off, | ||
127 | size_t chunk_len, bool complete) | ||
128 | { | ||
129 | int rc; | ||
130 | uint32_t data_buf[chunk_len/sizeof(uint32_t)]; | ||
131 | |||
132 | ASSERT_PRED1(is_valid_size, chunk_len); | ||
133 | ASSERT_PRED1(is_valid_offset, off); | ||
134 | |||
135 | memset(data_buf, 0, chunk_len); | ||
136 | |||
137 | rc = storage_write(handle, off, data_buf, sizeof(data_buf), | ||
138 | complete ? STORAGE_OP_COMPLETE : 0); | ||
139 | ASSERT_EQ((int)chunk_len, rc); | ||
140 | } | ||
141 | |||
142 | void StorageServiceTest::WritePatternChunk(file_handle_t handle, storage_off_t off, | ||
143 | size_t chunk_len, bool complete) | ||
144 | { | ||
145 | int rc; | ||
146 | uint32_t data_buf[chunk_len/sizeof(uint32_t)]; | ||
147 | |||
148 | ASSERT_PRED1(is_valid_size, chunk_len); | ||
149 | ASSERT_PRED1(is_valid_offset, off); | ||
150 | |||
151 | fill_pattern32(data_buf, chunk_len, off); | ||
152 | |||
153 | rc = storage_write(handle, off, data_buf, sizeof(data_buf), | ||
154 | complete ? STORAGE_OP_COMPLETE : 0); | ||
155 | ASSERT_EQ((int)chunk_len, rc); | ||
156 | } | ||
157 | |||
158 | void StorageServiceTest::WritePattern(file_handle_t handle, storage_off_t off, | ||
159 | size_t data_len, size_t chunk_len, bool complete) | ||
160 | { | ||
161 | ASSERT_PRED1(is_valid_size, data_len); | ||
162 | ASSERT_PRED1(is_valid_size, chunk_len); | ||
163 | |||
164 | while (data_len) { | ||
165 | if (data_len < chunk_len) | ||
166 | chunk_len = data_len; | ||
167 | WritePatternChunk(handle, off, chunk_len, (chunk_len == data_len) && complete); | ||
168 | ASSERT_FALSE(HasFatalFailure()); | ||
169 | off += chunk_len; | ||
170 | data_len -= chunk_len; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | void StorageServiceTest::ReadChunk(file_handle_t handle, | ||
175 | storage_off_t off, size_t chunk_len, | ||
176 | size_t head_len, size_t pattern_len, | ||
177 | size_t tail_len) | ||
178 | { | ||
179 | int rc; | ||
180 | uint32_t data_buf[chunk_len/sizeof(uint32_t)]; | ||
181 | uint8_t *data_ptr = (uint8_t *)data_buf; | ||
182 | |||
183 | ASSERT_PRED1(is_valid_size, chunk_len); | ||
184 | ASSERT_PRED1(is_valid_offset, off); | ||
185 | ASSERT_EQ(head_len + pattern_len + tail_len, chunk_len); | ||
186 | |||
187 | rc = storage_read(handle, off, data_buf, chunk_len); | ||
188 | ASSERT_EQ((int)chunk_len, rc); | ||
189 | |||
190 | if (head_len) { | ||
191 | ASSERT_TRUE(check_value32((const uint32_t *)data_ptr, head_len, 0)); | ||
192 | data_ptr += head_len; | ||
193 | off += head_len; | ||
194 | } | ||
195 | |||
196 | if (pattern_len) { | ||
197 | ASSERT_TRUE(check_pattern32((const uint32_t *)data_ptr, pattern_len, off)); | ||
198 | data_ptr += pattern_len; | ||
199 | } | ||
200 | |||
201 | if (tail_len) { | ||
202 | ASSERT_TRUE(check_value32((const uint32_t *)data_ptr, tail_len, 0)); | ||
203 | } | ||
204 | } | ||
205 | |||
206 | void StorageServiceTest::ReadPattern(file_handle_t handle, storage_off_t off, | ||
207 | size_t data_len, size_t chunk_len) | ||
208 | { | ||
209 | int rc; | ||
210 | uint32_t data_buf[chunk_len/sizeof(uint32_t)]; | ||
211 | |||
212 | ASSERT_PRED1(is_valid_size, chunk_len); | ||
213 | ASSERT_PRED1(is_valid_size, data_len); | ||
214 | ASSERT_PRED1(is_valid_offset, off); | ||
215 | |||
216 | while (data_len) { | ||
217 | if (chunk_len > data_len) | ||
218 | chunk_len = data_len; | ||
219 | rc = storage_read(handle, off, data_buf, sizeof(data_buf)); | ||
220 | ASSERT_EQ((int)chunk_len, rc); | ||
221 | ASSERT_TRUE(check_pattern32(data_buf, chunk_len, off)); | ||
222 | off += chunk_len; | ||
223 | data_len -= chunk_len; | ||
224 | } | ||
225 | } | ||
226 | |||
227 | void StorageServiceTest::ReadPatternEOF(file_handle_t handle, storage_off_t off, | ||
228 | size_t chunk_len, size_t exp_len) | ||
229 | { | ||
230 | int rc; | ||
231 | size_t bytes_read = 0; | ||
232 | uint32_t data_buf[chunk_len/sizeof(uint32_t)]; | ||
233 | |||
234 | ASSERT_PRED1(is_valid_size, chunk_len); | ||
235 | ASSERT_PRED1(is_32bit_aligned, exp_len); | ||
236 | |||
237 | while (true) { | ||
238 | rc = storage_read(handle, off, data_buf, sizeof(data_buf)); | ||
239 | ASSERT_GE(rc, 0); | ||
240 | if (rc == 0) | ||
241 | break; // end of file reached | ||
242 | ASSERT_PRED1(is_valid_size, (size_t)rc); | ||
243 | ASSERT_TRUE(check_pattern32(data_buf, rc, off)); | ||
244 | off += rc; | ||
245 | bytes_read += rc; | ||
246 | } | ||
247 | ASSERT_EQ(bytes_read, exp_len); | ||
248 | } | ||
249 | |||
250 | TEST_P(StorageServiceTest, CreateDelete) { | ||
251 | int rc; | ||
252 | file_handle_t handle; | ||
253 | const char *fname = "test_create_delete_file"; | ||
254 | |||
255 | // make sure test file does not exist (expect success or -ENOENT) | ||
256 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
257 | rc = (rc == -ENOENT) ? 0 : rc; | ||
258 | ASSERT_EQ(0, rc); | ||
259 | |||
260 | // one more time (expect -ENOENT only) | ||
261 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
262 | ASSERT_EQ(-ENOENT, rc); | ||
263 | |||
264 | // create file (expect 0) | ||
265 | rc = storage_open_file(session_, &handle, fname, | ||
266 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
267 | STORAGE_OP_COMPLETE); | ||
268 | ASSERT_EQ(0, rc); | ||
269 | |||
270 | // try to create it again while it is still opened (expect -EEXIST) | ||
271 | rc = storage_open_file(session_, &handle, fname, | ||
272 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
273 | STORAGE_OP_COMPLETE); | ||
274 | ASSERT_EQ(-EEXIST, rc); | ||
275 | |||
276 | // close it | ||
277 | storage_close_file(handle); | ||
278 | |||
279 | // try to create it again while it is closed (expect -EEXIST) | ||
280 | rc = storage_open_file(session_, &handle, fname, | ||
281 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
282 | STORAGE_OP_COMPLETE); | ||
283 | ASSERT_EQ(-EEXIST, rc); | ||
284 | |||
285 | // delete file (expect 0) | ||
286 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
287 | ASSERT_EQ(0, rc); | ||
288 | |||
289 | // one more time (expect -ENOENT) | ||
290 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
291 | ASSERT_EQ(-ENOENT, rc); | ||
292 | } | ||
293 | |||
294 | |||
295 | TEST_P(StorageServiceTest, DeleteOpened) { | ||
296 | int rc; | ||
297 | file_handle_t handle; | ||
298 | const char *fname = "delete_opened_test_file"; | ||
299 | |||
300 | // make sure test file does not exist (expect success or -ENOENT) | ||
301 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
302 | rc = (rc == -ENOENT) ? 0 : rc; | ||
303 | ASSERT_EQ(0, rc); | ||
304 | |||
305 | // one more time (expect -ENOENT) | ||
306 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
307 | ASSERT_EQ(-ENOENT, rc); | ||
308 | |||
309 | // open/create file (expect 0) | ||
310 | rc = storage_open_file(session_, &handle, fname, | ||
311 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
312 | STORAGE_OP_COMPLETE); | ||
313 | ASSERT_EQ(0, rc); | ||
314 | |||
315 | // delete opened file (expect 0) | ||
316 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
317 | ASSERT_EQ(0, rc); | ||
318 | |||
319 | // one more time (expect -ENOENT) | ||
320 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
321 | ASSERT_EQ(-ENOENT, rc); | ||
322 | |||
323 | // close file | ||
324 | storage_close_file(handle); | ||
325 | |||
326 | // one more time (expect -ENOENT) | ||
327 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
328 | ASSERT_EQ(-ENOENT, rc); | ||
329 | } | ||
330 | |||
331 | |||
332 | TEST_P(StorageServiceTest, OpenNoCreate) { | ||
333 | int rc; | ||
334 | file_handle_t handle; | ||
335 | const char *fname = "test_open_no_create_file"; | ||
336 | |||
337 | // make sure test file does not exist (expect success or -ENOENT) | ||
338 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
339 | rc = (rc == -ENOENT) ? 0 : rc; | ||
340 | ASSERT_EQ(0, rc); | ||
341 | |||
342 | // open non-existing file (expect -ENOENT) | ||
343 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
344 | ASSERT_EQ(-ENOENT, rc); | ||
345 | |||
346 | // create file (expect 0) | ||
347 | rc = storage_open_file(session_, &handle, fname, | ||
348 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
349 | STORAGE_OP_COMPLETE); | ||
350 | ASSERT_EQ(0, rc); | ||
351 | storage_close_file(handle); | ||
352 | |||
353 | // open existing file (expect 0) | ||
354 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
355 | ASSERT_EQ(0, rc); | ||
356 | |||
357 | // close it | ||
358 | storage_close_file(handle); | ||
359 | |||
360 | // delete file (expect 0) | ||
361 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
362 | ASSERT_EQ(0, rc); | ||
363 | } | ||
364 | |||
365 | |||
366 | TEST_P(StorageServiceTest, OpenOrCreate) { | ||
367 | int rc; | ||
368 | file_handle_t handle; | ||
369 | const char *fname = "test_open_create_file"; | ||
370 | |||
371 | // make sure test file does not exist (expect success or -ENOENT) | ||
372 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
373 | rc = (rc == -ENOENT) ? 0 : rc; | ||
374 | ASSERT_EQ(0, rc); | ||
375 | |||
376 | // open/create a non-existing file (expect 0) | ||
377 | rc = storage_open_file(session_, &handle, fname, | ||
378 | STORAGE_FILE_OPEN_CREATE, STORAGE_OP_COMPLETE); | ||
379 | ASSERT_EQ(0, rc); | ||
380 | storage_close_file(handle); | ||
381 | |||
382 | // open/create an existing file (expect 0) | ||
383 | rc = storage_open_file(session_, &handle, fname, | ||
384 | STORAGE_FILE_OPEN_CREATE, STORAGE_OP_COMPLETE); | ||
385 | ASSERT_EQ(0, rc); | ||
386 | storage_close_file(handle); | ||
387 | |||
388 | // delete file (expect 0) | ||
389 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
390 | ASSERT_EQ(0, rc); | ||
391 | } | ||
392 | |||
393 | |||
394 | TEST_P(StorageServiceTest, OpenCreateDeleteCharset) { | ||
395 | int rc; | ||
396 | file_handle_t handle; | ||
397 | const char *fname = "ABCDEFGHIJKLMNOPQRSTUVWXYZ-abcdefghijklmnopqrstuvwxyz_01234.56789"; | ||
398 | |||
399 | // open/create file (expect 0) | ||
400 | rc = storage_open_file(session_, &handle, fname, | ||
401 | STORAGE_FILE_OPEN_CREATE, STORAGE_OP_COMPLETE); | ||
402 | ASSERT_EQ(0, rc); | ||
403 | storage_close_file(handle); | ||
404 | |||
405 | // open/create an existing file (expect 0) | ||
406 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
407 | ASSERT_EQ(0, rc); | ||
408 | storage_close_file(handle); | ||
409 | |||
410 | // delete file (expect 0) | ||
411 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
412 | ASSERT_EQ(0, rc); | ||
413 | |||
414 | // open again | ||
415 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
416 | ASSERT_EQ(-ENOENT, rc); | ||
417 | } | ||
418 | |||
419 | |||
420 | TEST_P(StorageServiceTest, WriteReadSequential) { | ||
421 | int rc; | ||
422 | size_t blk = 2048; | ||
423 | file_handle_t handle; | ||
424 | const char *fname = "test_write_read_sequential"; | ||
425 | |||
426 | // make sure test file does not exist (expect success or -ENOENT) | ||
427 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
428 | rc = (rc == -ENOENT) ? 0 : rc; | ||
429 | ASSERT_EQ(0, rc); | ||
430 | |||
431 | // create file. | ||
432 | rc = storage_open_file(session_, &handle, fname, | ||
433 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
434 | STORAGE_OP_COMPLETE); | ||
435 | ASSERT_EQ(0, rc); | ||
436 | |||
437 | // write a bunch of blocks (sequentially) | ||
438 | WritePattern(handle, 0, 32 * blk, blk, true); | ||
439 | ASSERT_FALSE(HasFatalFailure()); | ||
440 | |||
441 | ReadPattern(handle, 0, 32 * blk, blk); | ||
442 | ASSERT_FALSE(HasFatalFailure()); | ||
443 | |||
444 | // close file | ||
445 | storage_close_file(handle); | ||
446 | |||
447 | // open the same file again | ||
448 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
449 | ASSERT_EQ(0, rc); | ||
450 | |||
451 | // read data back (sequentially) and check pattern again | ||
452 | ReadPattern(handle, 0, 32 * blk, blk); | ||
453 | ASSERT_FALSE(HasFatalFailure()); | ||
454 | |||
455 | // cleanup | ||
456 | storage_close_file(handle); | ||
457 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
458 | } | ||
459 | |||
460 | |||
461 | TEST_P(StorageServiceTest, OpenTruncate) { | ||
462 | int rc; | ||
463 | uint32_t val; | ||
464 | size_t blk = 2048; | ||
465 | file_handle_t handle; | ||
466 | const char *fname = "test_open_truncate"; | ||
467 | |||
468 | // make sure test file does not exist (expect success or -ENOENT) | ||
469 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
470 | rc = (rc == -ENOENT) ? 0 : rc; | ||
471 | ASSERT_EQ(0, rc); | ||
472 | |||
473 | // create file. | ||
474 | rc = storage_open_file(session_, &handle, fname, | ||
475 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
476 | STORAGE_OP_COMPLETE); | ||
477 | ASSERT_EQ(0, rc); | ||
478 | |||
479 | // write some data and read it back | ||
480 | WritePatternChunk(handle, 0, blk, true); | ||
481 | ASSERT_FALSE(HasFatalFailure()); | ||
482 | |||
483 | ReadPattern(handle, 0, blk, blk); | ||
484 | ASSERT_FALSE(HasFatalFailure()); | ||
485 | |||
486 | // close file | ||
487 | storage_close_file(handle); | ||
488 | |||
489 | // reopen with truncate | ||
490 | rc = storage_open_file(session_, &handle, fname, | ||
491 | STORAGE_FILE_OPEN_TRUNCATE, STORAGE_OP_COMPLETE); | ||
492 | ASSERT_EQ(0, rc); | ||
493 | |||
494 | /* try to read data back (expect no data) */ | ||
495 | rc = storage_read(handle, 0LL, &val, sizeof(val)); | ||
496 | ASSERT_EQ(0, rc); | ||
497 | |||
498 | // cleanup | ||
499 | storage_close_file(handle); | ||
500 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
501 | } | ||
502 | |||
503 | |||
504 | TEST_P(StorageServiceTest, OpenSame) { | ||
505 | int rc; | ||
506 | file_handle_t handle1; | ||
507 | file_handle_t handle2; | ||
508 | file_handle_t handle3; | ||
509 | const char *fname = "test_open_same_file"; | ||
510 | |||
511 | // open/create file (expect 0) | ||
512 | rc = storage_open_file(session_, &handle1, fname, STORAGE_FILE_OPEN_CREATE, | ||
513 | STORAGE_OP_COMPLETE); | ||
514 | ASSERT_EQ(0, rc); | ||
515 | storage_close_file(handle1); | ||
516 | |||
517 | // open an existing file first time (expect 0) | ||
518 | rc = storage_open_file(session_, &handle1, fname, 0, 0); | ||
519 | ASSERT_EQ(0, rc); | ||
520 | |||
521 | // open the same file second time (expect error) | ||
522 | rc = storage_open_file(session_, &handle2, fname, 0, 0); | ||
523 | ASSERT_NE(0, rc); | ||
524 | |||
525 | storage_close_file(handle1); | ||
526 | |||
527 | // delete file (expect 0) | ||
528 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
529 | ASSERT_EQ(0, rc); | ||
530 | |||
531 | // open deleted file (expect -ENOENT) | ||
532 | rc = storage_open_file(session_, &handle3, fname, 0, 0); | ||
533 | ASSERT_EQ(-ENOENT, rc); | ||
534 | } | ||
535 | |||
536 | |||
537 | TEST_P(StorageServiceTest, OpenMany) { | ||
538 | int rc; | ||
539 | file_handle_t handles[10]; | ||
540 | char filename[10]; | ||
541 | const char *fname_fmt = "mf%d"; | ||
542 | |||
543 | // open or create a bunch of files (expect 0) | ||
544 | for (uint i = 0; i < ARRAY_SIZE(handles); ++i) { | ||
545 | snprintf(filename, sizeof(filename), fname_fmt, i); | ||
546 | rc = storage_open_file(session_, &handles[i], filename, | ||
547 | STORAGE_FILE_OPEN_CREATE, STORAGE_OP_COMPLETE); | ||
548 | ASSERT_EQ(0, rc); | ||
549 | } | ||
550 | |||
551 | // check that all handles are different | ||
552 | for (uint i = 0; i < ARRAY_SIZE(handles)-1; i++) { | ||
553 | for (uint j = i+1; j < ARRAY_SIZE(handles); j++) { | ||
554 | ASSERT_NE(handles[i], handles[j]); | ||
555 | } | ||
556 | } | ||
557 | |||
558 | // close them all | ||
559 | for (uint i = 0; i < ARRAY_SIZE(handles); ++i) { | ||
560 | storage_close_file(handles[i]); | ||
561 | } | ||
562 | |||
563 | // open all files without CREATE flags (expect 0) | ||
564 | for (uint i = 0; i < ARRAY_SIZE(handles); ++i) { | ||
565 | snprintf(filename, sizeof(filename), fname_fmt, i); | ||
566 | rc = storage_open_file(session_, &handles[i], filename, 0, 0); | ||
567 | ASSERT_EQ(0, rc); | ||
568 | } | ||
569 | |||
570 | // check that all handles are different | ||
571 | for (uint i = 0; i < ARRAY_SIZE(handles)-1; i++) { | ||
572 | for (uint j = i+1; j < ARRAY_SIZE(handles); j++) { | ||
573 | ASSERT_NE(handles[i], handles[j]); | ||
574 | } | ||
575 | } | ||
576 | |||
577 | // close and remove all test files | ||
578 | for (uint i = 0; i < ARRAY_SIZE(handles); ++i) { | ||
579 | storage_close_file(handles[i]); | ||
580 | snprintf(filename, sizeof(filename), fname_fmt, i); | ||
581 | rc = storage_delete_file(session_, filename, STORAGE_OP_COMPLETE); | ||
582 | ASSERT_EQ(0, rc); | ||
583 | } | ||
584 | } | ||
585 | |||
586 | |||
587 | TEST_P(StorageServiceTest, ReadAtEOF) { | ||
588 | int rc; | ||
589 | uint32_t val; | ||
590 | size_t blk = 2048; | ||
591 | file_handle_t handle; | ||
592 | const char *fname = "test_read_eof"; | ||
593 | |||
594 | // open/create/truncate file | ||
595 | rc = storage_open_file(session_, &handle, fname, | ||
596 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
597 | STORAGE_OP_COMPLETE); | ||
598 | ASSERT_EQ(0, rc); | ||
599 | |||
600 | // write block at offset 0 | ||
601 | WritePatternChunk(handle, 0, blk, true); | ||
602 | ASSERT_FALSE(HasFatalFailure()); | ||
603 | |||
604 | // close file | ||
605 | storage_close_file(handle); | ||
606 | |||
607 | // open same file again | ||
608 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
609 | ASSERT_EQ(0, rc); | ||
610 | |||
611 | // read the whole block back and check pattern again | ||
612 | ReadPattern(handle, 0, blk, blk); | ||
613 | ASSERT_FALSE(HasFatalFailure()); | ||
614 | |||
615 | // read at end of file (expected 0 bytes) | ||
616 | rc = storage_read(handle, blk, &val, sizeof(val)); | ||
617 | ASSERT_EQ(0, rc); | ||
618 | |||
619 | // partial read at end of the file (expected partial data) | ||
620 | ReadPatternEOF(handle, blk/2, blk, blk/2); | ||
621 | ASSERT_FALSE(HasFatalFailure()); | ||
622 | |||
623 | // read past end of file | ||
624 | rc = storage_read(handle, blk + 2, &val, sizeof(val)); | ||
625 | ASSERT_EQ(-EINVAL, rc); | ||
626 | |||
627 | // cleanup | ||
628 | storage_close_file(handle); | ||
629 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
630 | } | ||
631 | |||
632 | |||
633 | TEST_P(StorageServiceTest, GetFileSize) { | ||
634 | int rc; | ||
635 | size_t blk = 2048; | ||
636 | storage_off_t size; | ||
637 | file_handle_t handle; | ||
638 | const char *fname = "test_get_file_size"; | ||
639 | |||
640 | // open/create/truncate file. | ||
641 | rc = storage_open_file(session_, &handle, fname, | ||
642 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
643 | STORAGE_OP_COMPLETE); | ||
644 | ASSERT_EQ(0, rc); | ||
645 | |||
646 | // check file size (expect success and size == 0) | ||
647 | size = 1; | ||
648 | rc = storage_get_file_size(handle, &size); | ||
649 | ASSERT_EQ(0, rc); | ||
650 | ASSERT_EQ((storage_off_t)0, size); | ||
651 | |||
652 | // write block | ||
653 | WritePatternChunk(handle, 0, blk, true); | ||
654 | ASSERT_FALSE(HasFatalFailure()); | ||
655 | |||
656 | // check size | ||
657 | rc = storage_get_file_size(handle, &size); | ||
658 | ASSERT_EQ(0, rc); | ||
659 | ASSERT_EQ(blk, size); | ||
660 | |||
661 | // write another block | ||
662 | WritePatternChunk(handle, blk, blk, true); | ||
663 | ASSERT_FALSE(HasFatalFailure()); | ||
664 | |||
665 | // check size again | ||
666 | rc = storage_get_file_size(handle, &size); | ||
667 | ASSERT_EQ(0, rc); | ||
668 | ASSERT_EQ(blk*2, size); | ||
669 | |||
670 | // cleanup | ||
671 | storage_close_file(handle); | ||
672 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
673 | } | ||
674 | |||
675 | |||
676 | TEST_P(StorageServiceTest, SetFileSize) { | ||
677 | int rc; | ||
678 | size_t blk = 2048; | ||
679 | storage_off_t size; | ||
680 | file_handle_t handle; | ||
681 | const char *fname = "test_set_file_size"; | ||
682 | |||
683 | // open/create/truncate file. | ||
684 | rc = storage_open_file(session_, &handle, fname, | ||
685 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
686 | STORAGE_OP_COMPLETE); | ||
687 | ASSERT_EQ(0, rc); | ||
688 | |||
689 | // check file size (expect success and size == 0) | ||
690 | size = 1; | ||
691 | rc = storage_get_file_size(handle, &size); | ||
692 | ASSERT_EQ(0, rc); | ||
693 | ASSERT_EQ((storage_off_t)0, size); | ||
694 | |||
695 | // write block | ||
696 | WritePatternChunk(handle, 0, blk, true); | ||
697 | ASSERT_FALSE(HasFatalFailure()); | ||
698 | |||
699 | // check size | ||
700 | rc = storage_get_file_size(handle, &size); | ||
701 | ASSERT_EQ(0, rc); | ||
702 | ASSERT_EQ(blk, size); | ||
703 | |||
704 | storage_close_file(handle); | ||
705 | |||
706 | // reopen normally | ||
707 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
708 | ASSERT_EQ(0, rc); | ||
709 | |||
710 | // check size again | ||
711 | rc = storage_get_file_size(handle, &size); | ||
712 | ASSERT_EQ(0, rc); | ||
713 | ASSERT_EQ(blk, size); | ||
714 | |||
715 | // set file size to half | ||
716 | rc = storage_set_file_size(handle, blk/2, STORAGE_OP_COMPLETE); | ||
717 | ASSERT_EQ(0, rc); | ||
718 | |||
719 | // check size again (should be half of original size) | ||
720 | rc = storage_get_file_size(handle, &size); | ||
721 | ASSERT_EQ(0, rc); | ||
722 | ASSERT_EQ(blk/2, size); | ||
723 | |||
724 | // read data back | ||
725 | ReadPatternEOF(handle, 0, blk, blk/2); | ||
726 | ASSERT_FALSE(HasFatalFailure()); | ||
727 | |||
728 | // set file size to 0 | ||
729 | rc = storage_set_file_size(handle, 0, STORAGE_OP_COMPLETE); | ||
730 | ASSERT_EQ(0, rc); | ||
731 | |||
732 | // check size again (should be 0) | ||
733 | rc = storage_get_file_size(handle, &size); | ||
734 | ASSERT_EQ(0, rc); | ||
735 | ASSERT_EQ((storage_off_t)0LL, size); | ||
736 | |||
737 | // try to read again | ||
738 | ReadPatternEOF(handle, 0, blk, 0); | ||
739 | ASSERT_FALSE(HasFatalFailure()); | ||
740 | |||
741 | // cleanup | ||
742 | storage_close_file(handle); | ||
743 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
744 | } | ||
745 | |||
746 | |||
747 | void StorageServiceTest::WriteReadAtOffsetHelper(file_handle_t handle, size_t blk, size_t cnt, bool complete) | ||
748 | { | ||
749 | storage_off_t off1 = blk; | ||
750 | storage_off_t off2 = blk * (cnt-1); | ||
751 | |||
752 | // write known pattern data at non-zero offset1 | ||
753 | WritePatternChunk(handle, off1, blk, complete); | ||
754 | ASSERT_FALSE(HasFatalFailure()); | ||
755 | |||
756 | // write known pattern data at non-zero offset2 | ||
757 | WritePatternChunk(handle, off2, blk, complete); | ||
758 | ASSERT_FALSE(HasFatalFailure()); | ||
759 | |||
760 | // read data back at offset1 | ||
761 | ReadPattern(handle, off1, blk, blk); | ||
762 | ASSERT_FALSE(HasFatalFailure()); | ||
763 | |||
764 | // read data back at offset2 | ||
765 | ReadPattern(handle, off2, blk, blk); | ||
766 | ASSERT_FALSE(HasFatalFailure()); | ||
767 | |||
768 | // read partially written data at end of file(expect to get data only, no padding) | ||
769 | ReadPatternEOF(handle, off2 + blk/2, blk, blk/2); | ||
770 | ASSERT_FALSE(HasFatalFailure()); | ||
771 | |||
772 | // read data at offset 0 (expect success and zero data) | ||
773 | ReadChunk(handle, 0, blk, blk, 0, 0); | ||
774 | ASSERT_FALSE(HasFatalFailure()); | ||
775 | |||
776 | // read data from gap (expect success and zero data) | ||
777 | ReadChunk(handle, off1 + blk, blk, blk, 0, 0); | ||
778 | ASSERT_FALSE(HasFatalFailure()); | ||
779 | |||
780 | // read partially written data (start pointing within written data) | ||
781 | // (expect to get written data back and zeroes at the end) | ||
782 | ReadChunk(handle, off1 + blk/2, blk, 0, blk/2, blk/2); | ||
783 | ASSERT_FALSE(HasFatalFailure()); | ||
784 | |||
785 | // read partially written data (start pointing withing unwritten data) | ||
786 | // expect to get zeroes at the beginning and proper data at the end | ||
787 | ReadChunk(handle, off1 - blk/2, blk, blk/2, blk/2, 0); | ||
788 | ASSERT_FALSE(HasFatalFailure()); | ||
789 | } | ||
790 | |||
791 | |||
792 | TEST_P(StorageServiceTest, WriteReadAtOffset) { | ||
793 | int rc; | ||
794 | file_handle_t handle; | ||
795 | size_t blk = 2048; | ||
796 | size_t blk_cnt = 32; | ||
797 | const char *fname = "test_write_at_offset"; | ||
798 | |||
799 | // create/truncate file. | ||
800 | rc = storage_open_file(session_, &handle, fname, | ||
801 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
802 | STORAGE_OP_COMPLETE); | ||
803 | ASSERT_EQ(0, rc); | ||
804 | |||
805 | // write a bunch of blocks filled with zeroes | ||
806 | for (uint i = 0; i < blk_cnt; i++) { | ||
807 | WriteZeroChunk(handle, i * blk, blk, true); | ||
808 | ASSERT_FALSE(HasFatalFailure()); | ||
809 | } | ||
810 | |||
811 | WriteReadAtOffsetHelper(handle, blk, blk_cnt, true); | ||
812 | ASSERT_FALSE(HasFatalFailure()); | ||
813 | |||
814 | // cleanup | ||
815 | storage_close_file(handle); | ||
816 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
817 | } | ||
818 | |||
819 | |||
820 | TEST_P(StorageServiceTest, WriteSparse) { | ||
821 | int rc; | ||
822 | file_handle_t handle; | ||
823 | const char *fname = "test_write_sparse"; | ||
824 | |||
825 | // open/create/truncate file. | ||
826 | rc = storage_open_file(session_, &handle, fname, | ||
827 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
828 | STORAGE_OP_COMPLETE); | ||
829 | ASSERT_EQ(0, rc); | ||
830 | |||
831 | // write value past en of file | ||
832 | uint32_t val = 0xDEADBEEF; | ||
833 | rc = storage_write(handle, 1, &val, sizeof(val), STORAGE_OP_COMPLETE); | ||
834 | ASSERT_EQ(-EINVAL, rc); | ||
835 | |||
836 | // cleanup | ||
837 | storage_close_file(handle); | ||
838 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
839 | } | ||
840 | |||
841 | // Persistent 32k | ||
842 | |||
843 | TEST_P(StorageServiceTest, CreatePersistent32K) { | ||
844 | int rc; | ||
845 | file_handle_t handle; | ||
846 | size_t blk = 2048; | ||
847 | size_t file_size = 32768; | ||
848 | const char *fname = "test_persistent_32K_file"; | ||
849 | |||
850 | // create/truncate file. | ||
851 | rc = storage_open_file(session_, &handle, fname, | ||
852 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
853 | STORAGE_OP_COMPLETE); | ||
854 | ASSERT_EQ(0, rc); | ||
855 | |||
856 | // write a bunch of blocks filled with pattern | ||
857 | WritePattern(handle, 0, file_size, blk, true); | ||
858 | ASSERT_FALSE(HasFatalFailure()); | ||
859 | |||
860 | // close but do not delete file | ||
861 | storage_close_file(handle); | ||
862 | } | ||
863 | |||
864 | TEST_P(StorageServiceTest, ReadPersistent32k) { | ||
865 | int rc; | ||
866 | file_handle_t handle; | ||
867 | size_t exp_len = 32 * 1024; | ||
868 | const char *fname = "test_persistent_32K_file"; | ||
869 | |||
870 | // create/truncate file. | ||
871 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
872 | ASSERT_EQ(0, rc); | ||
873 | |||
874 | ReadPatternEOF(handle, 0, 2048, exp_len); | ||
875 | ASSERT_FALSE(HasFatalFailure()); | ||
876 | |||
877 | ReadPatternEOF(handle, 0, 1024, exp_len); | ||
878 | ASSERT_FALSE(HasFatalFailure()); | ||
879 | |||
880 | ReadPatternEOF(handle, 0, 332, exp_len); | ||
881 | ASSERT_FALSE(HasFatalFailure()); | ||
882 | |||
883 | // close but do not delete file | ||
884 | storage_close_file(handle); | ||
885 | } | ||
886 | |||
887 | TEST_P(StorageServiceTest, CleanUpPersistent32K) { | ||
888 | int rc; | ||
889 | const char *fname = "test_persistent_32K_file"; | ||
890 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
891 | rc = (rc == -ENOENT) ? 0 : rc; | ||
892 | ASSERT_EQ(0, rc); | ||
893 | } | ||
894 | |||
895 | // Persistent 1M | ||
896 | TEST_P(StorageServiceTest, CreatePersistent1M_4040) { | ||
897 | int rc; | ||
898 | file_handle_t handle; | ||
899 | size_t file_size = 1024 * 1024; | ||
900 | const char *fname = "test_persistent_1M_file"; | ||
901 | |||
902 | // create/truncate file. | ||
903 | rc = storage_open_file(session_, &handle, fname, | ||
904 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
905 | STORAGE_OP_COMPLETE); | ||
906 | ASSERT_EQ(0, rc); | ||
907 | |||
908 | // write a bunch of blocks filled with pattern | ||
909 | WritePattern(handle, 0, file_size, 4040, true); | ||
910 | ASSERT_FALSE(HasFatalFailure()); | ||
911 | |||
912 | // close but do not delete file | ||
913 | storage_close_file(handle); | ||
914 | } | ||
915 | |||
916 | TEST_P(StorageServiceTest, CreatePersistent1M_2032) { | ||
917 | int rc; | ||
918 | file_handle_t handle; | ||
919 | size_t file_size = 1024 * 1024; | ||
920 | const char *fname = "test_persistent_1M_file"; | ||
921 | |||
922 | // create/truncate file. | ||
923 | rc = storage_open_file(session_, &handle, fname, | ||
924 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
925 | STORAGE_OP_COMPLETE); | ||
926 | ASSERT_EQ(0, rc); | ||
927 | |||
928 | // write a bunch of blocks filled with pattern | ||
929 | WritePattern(handle, 0, file_size, 2032, true); | ||
930 | ASSERT_FALSE(HasFatalFailure()); | ||
931 | |||
932 | // close but do not delete file | ||
933 | storage_close_file(handle); | ||
934 | } | ||
935 | |||
936 | |||
937 | TEST_P(StorageServiceTest, CreatePersistent1M_496) { | ||
938 | int rc; | ||
939 | file_handle_t handle; | ||
940 | size_t file_size = 1024 * 1024; | ||
941 | const char *fname = "test_persistent_1M_file"; | ||
942 | |||
943 | // create/truncate file. | ||
944 | rc = storage_open_file(session_, &handle, fname, | ||
945 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
946 | STORAGE_OP_COMPLETE); | ||
947 | ASSERT_EQ(0, rc); | ||
948 | |||
949 | // write a bunch of blocks filled with pattern | ||
950 | WritePattern(handle, 0, file_size, 496, true); | ||
951 | ASSERT_FALSE(HasFatalFailure()); | ||
952 | |||
953 | // close but do not delete file | ||
954 | storage_close_file(handle); | ||
955 | } | ||
956 | |||
957 | TEST_P(StorageServiceTest, CreatePersistent1M_240) { | ||
958 | int rc; | ||
959 | file_handle_t handle; | ||
960 | size_t file_size = 1024 * 1024; | ||
961 | const char *fname = "test_persistent_1M_file"; | ||
962 | |||
963 | // create/truncate file. | ||
964 | rc = storage_open_file(session_, &handle, fname, | ||
965 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
966 | STORAGE_OP_COMPLETE); | ||
967 | ASSERT_EQ(0, rc); | ||
968 | |||
969 | // write a bunch of blocks filled with pattern | ||
970 | WritePattern(handle, 0, file_size, 240, true); | ||
971 | ASSERT_FALSE(HasFatalFailure()); | ||
972 | |||
973 | // close but do not delete file | ||
974 | storage_close_file(handle); | ||
975 | } | ||
976 | |||
977 | TEST_P(StorageServiceTest, ReadPersistent1M_4040) { | ||
978 | int rc; | ||
979 | file_handle_t handle; | ||
980 | size_t exp_len = 1024 * 1024; | ||
981 | const char *fname = "test_persistent_1M_file"; | ||
982 | |||
983 | // create/truncate file. | ||
984 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
985 | ASSERT_EQ(0, rc); | ||
986 | |||
987 | ReadPatternEOF(handle, 0, 4040, exp_len); | ||
988 | ASSERT_FALSE(HasFatalFailure()); | ||
989 | |||
990 | // close but do not delete file | ||
991 | storage_close_file(handle); | ||
992 | } | ||
993 | |||
994 | TEST_P(StorageServiceTest, ReadPersistent1M_2032) { | ||
995 | int rc; | ||
996 | file_handle_t handle; | ||
997 | size_t exp_len = 1024 * 1024; | ||
998 | const char *fname = "test_persistent_1M_file"; | ||
999 | |||
1000 | // create/truncate file. | ||
1001 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
1002 | ASSERT_EQ(0, rc); | ||
1003 | |||
1004 | ReadPatternEOF(handle, 0, 2032, exp_len); | ||
1005 | ASSERT_FALSE(HasFatalFailure()); | ||
1006 | |||
1007 | // close but do not delete file | ||
1008 | storage_close_file(handle); | ||
1009 | } | ||
1010 | |||
1011 | TEST_P(StorageServiceTest, ReadPersistent1M_496) { | ||
1012 | int rc; | ||
1013 | file_handle_t handle; | ||
1014 | size_t exp_len = 1024 * 1024; | ||
1015 | const char *fname = "test_persistent_1M_file"; | ||
1016 | |||
1017 | // create/truncate file. | ||
1018 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
1019 | ASSERT_EQ(0, rc); | ||
1020 | |||
1021 | ReadPatternEOF(handle, 0, 496, exp_len); | ||
1022 | ASSERT_FALSE(HasFatalFailure()); | ||
1023 | |||
1024 | // close but do not delete file | ||
1025 | storage_close_file(handle); | ||
1026 | } | ||
1027 | |||
1028 | TEST_P(StorageServiceTest, ReadPersistent1M_240) { | ||
1029 | int rc; | ||
1030 | file_handle_t handle; | ||
1031 | size_t exp_len = 1024 * 1024; | ||
1032 | const char *fname = "test_persistent_1M_file"; | ||
1033 | |||
1034 | // create/truncate file. | ||
1035 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
1036 | ASSERT_EQ(0, rc); | ||
1037 | |||
1038 | ReadPatternEOF(handle, 0, 240, exp_len); | ||
1039 | ASSERT_FALSE(HasFatalFailure()); | ||
1040 | |||
1041 | // close but do not delete file | ||
1042 | storage_close_file(handle); | ||
1043 | } | ||
1044 | |||
1045 | TEST_P(StorageServiceTest, CleanUpPersistent1M) { | ||
1046 | int rc; | ||
1047 | const char *fname = "test_persistent_1M_file"; | ||
1048 | rc = storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1049 | rc = (rc == -ENOENT) ? 0 : rc; | ||
1050 | ASSERT_EQ(0, rc); | ||
1051 | } | ||
1052 | |||
1053 | TEST_P(StorageServiceTest, WriteReadLong) { | ||
1054 | int rc; | ||
1055 | file_handle_t handle; | ||
1056 | size_t wc = 10000; | ||
1057 | const char *fname = "test_write_read_long"; | ||
1058 | |||
1059 | rc = storage_open_file(session_, &handle, fname, | ||
1060 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1061 | STORAGE_OP_COMPLETE); | ||
1062 | ASSERT_EQ(0, rc); | ||
1063 | |||
1064 | test_buf_ = new uint32_t[wc]; | ||
1065 | fill_pattern32(test_buf_, wc * sizeof(uint32_t), 0); | ||
1066 | rc = storage_write(handle, 0, test_buf_, wc * sizeof(uint32_t), STORAGE_OP_COMPLETE); | ||
1067 | ASSERT_EQ((int)(wc * sizeof(uint32_t)), rc); | ||
1068 | |||
1069 | rc = storage_read(handle, 0, test_buf_, wc * sizeof(uint32_t)); | ||
1070 | ASSERT_EQ((int)(wc * sizeof(uint32_t)), rc); | ||
1071 | ASSERT_TRUE(check_pattern32(test_buf_, wc * sizeof(uint32_t), 0)); | ||
1072 | |||
1073 | // cleanup | ||
1074 | storage_close_file(handle); | ||
1075 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1076 | } | ||
1077 | |||
1078 | // Negative tests | ||
1079 | |||
1080 | TEST_P(StorageServiceTest, OpenInvalidFileName) { | ||
1081 | int rc; | ||
1082 | file_handle_t handle; | ||
1083 | const char *fname1 = ""; | ||
1084 | const char *fname2 = "ffff$ffff"; | ||
1085 | const char *fname3 = "ffff\\ffff"; | ||
1086 | char max_name[STORAGE_MAX_NAME_LENGTH_BYTES+1]; | ||
1087 | |||
1088 | rc = storage_open_file(session_, &handle, fname1, | ||
1089 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1090 | STORAGE_OP_COMPLETE); | ||
1091 | ASSERT_EQ(-EINVAL, rc); | ||
1092 | |||
1093 | rc = storage_open_file(session_, &handle, fname2, | ||
1094 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1095 | STORAGE_OP_COMPLETE); | ||
1096 | ASSERT_EQ(-EINVAL, rc); | ||
1097 | |||
1098 | rc = storage_open_file(session_, &handle, fname3, | ||
1099 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1100 | STORAGE_OP_COMPLETE); | ||
1101 | ASSERT_EQ(-EINVAL, rc); | ||
1102 | |||
1103 | /* max name */ | ||
1104 | memset(max_name, 'a', sizeof(max_name)); | ||
1105 | max_name[sizeof(max_name)-1] = 0; | ||
1106 | |||
1107 | rc = storage_open_file(session_, &handle, max_name, | ||
1108 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1109 | STORAGE_OP_COMPLETE); | ||
1110 | ASSERT_EQ(-EINVAL, rc); | ||
1111 | |||
1112 | max_name[sizeof(max_name)-2] = 0; | ||
1113 | rc = storage_open_file(session_, &handle, max_name, | ||
1114 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1115 | STORAGE_OP_COMPLETE); | ||
1116 | ASSERT_EQ(0, rc); | ||
1117 | |||
1118 | storage_close_file(handle); | ||
1119 | storage_delete_file(session_, max_name, STORAGE_OP_COMPLETE); | ||
1120 | } | ||
1121 | |||
1122 | |||
1123 | TEST_P(StorageServiceTest, BadFileHnadle) { | ||
1124 | int rc; | ||
1125 | file_handle_t handle; | ||
1126 | file_handle_t handle1; | ||
1127 | const char *fname = "test_invalid_file_handle"; | ||
1128 | |||
1129 | rc = storage_open_file(session_, &handle, fname, | ||
1130 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1131 | STORAGE_OP_COMPLETE); | ||
1132 | ASSERT_EQ(0, rc); | ||
1133 | |||
1134 | handle1 = handle + 1; | ||
1135 | |||
1136 | // write to invalid file handle | ||
1137 | uint32_t val = 0xDEDBEEF; | ||
1138 | rc = storage_write(handle1, 0, &val, sizeof(val), STORAGE_OP_COMPLETE); | ||
1139 | ASSERT_EQ(-EINVAL, rc); | ||
1140 | |||
1141 | // read from invalid handle | ||
1142 | rc = storage_read(handle1, 0, &val, sizeof(val)); | ||
1143 | ASSERT_EQ(-EINVAL, rc); | ||
1144 | |||
1145 | // set size | ||
1146 | rc = storage_set_file_size(handle1, 0, STORAGE_OP_COMPLETE); | ||
1147 | ASSERT_EQ(-EINVAL, rc); | ||
1148 | |||
1149 | // get size | ||
1150 | storage_off_t fsize = (storage_off_t)(-1); | ||
1151 | rc = storage_get_file_size(handle1, &fsize); | ||
1152 | ASSERT_EQ(-EINVAL, rc); | ||
1153 | |||
1154 | // close (there is no way to check errors here) | ||
1155 | storage_close_file(handle1); | ||
1156 | |||
1157 | storage_close_file(handle); | ||
1158 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1159 | } | ||
1160 | |||
1161 | |||
1162 | TEST_P(StorageServiceTest, ClosedFileHnadle) { | ||
1163 | int rc; | ||
1164 | file_handle_t handle1; | ||
1165 | file_handle_t handle2; | ||
1166 | const char *fname1 = "test_invalid_file_handle1"; | ||
1167 | const char *fname2 = "test_invalid_file_handle2"; | ||
1168 | |||
1169 | rc = storage_open_file(session_, &handle1, fname1, | ||
1170 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1171 | STORAGE_OP_COMPLETE); | ||
1172 | ASSERT_EQ(0, rc); | ||
1173 | |||
1174 | rc = storage_open_file(session_, &handle2, fname2, | ||
1175 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1176 | STORAGE_OP_COMPLETE); | ||
1177 | ASSERT_EQ(0, rc); | ||
1178 | |||
1179 | // close first file handle | ||
1180 | storage_close_file(handle1); | ||
1181 | |||
1182 | // write to invalid file handle | ||
1183 | uint32_t val = 0xDEDBEEF; | ||
1184 | rc = storage_write(handle1, 0, &val, sizeof(val), STORAGE_OP_COMPLETE); | ||
1185 | ASSERT_EQ(-EINVAL, rc); | ||
1186 | |||
1187 | // read from invalid handle | ||
1188 | rc = storage_read(handle1, 0, &val, sizeof(val)); | ||
1189 | ASSERT_EQ(-EINVAL, rc); | ||
1190 | |||
1191 | // set size | ||
1192 | rc = storage_set_file_size(handle1, 0, STORAGE_OP_COMPLETE); | ||
1193 | ASSERT_EQ(-EINVAL, rc); | ||
1194 | |||
1195 | // get size | ||
1196 | storage_off_t fsize = (storage_off_t)(-1); | ||
1197 | rc = storage_get_file_size(handle1, &fsize); | ||
1198 | ASSERT_EQ(-EINVAL, rc); | ||
1199 | |||
1200 | // close (there is no way to check errors here) | ||
1201 | storage_close_file(handle1); | ||
1202 | |||
1203 | // clean up | ||
1204 | storage_close_file(handle2); | ||
1205 | storage_delete_file(session_, fname1, STORAGE_OP_COMPLETE); | ||
1206 | storage_delete_file(session_, fname2, STORAGE_OP_COMPLETE); | ||
1207 | } | ||
1208 | |||
1209 | // Transactions | ||
1210 | |||
1211 | TEST_P(StorageServiceTest, TransactDiscardInactive) { | ||
1212 | int rc; | ||
1213 | |||
1214 | // discard current transaction (there should not be any) | ||
1215 | rc = storage_end_transaction(session_, false); | ||
1216 | ASSERT_EQ(0, rc); | ||
1217 | |||
1218 | // try it again | ||
1219 | rc = storage_end_transaction(session_, false); | ||
1220 | ASSERT_EQ(0, rc); | ||
1221 | } | ||
1222 | |||
1223 | TEST_P(StorageServiceTest, TransactCommitInactive) { | ||
1224 | int rc; | ||
1225 | |||
1226 | // try to commit current transaction | ||
1227 | rc = storage_end_transaction(session_, true); | ||
1228 | ASSERT_EQ(0, rc); | ||
1229 | |||
1230 | // try it again | ||
1231 | rc = storage_end_transaction(session_, true); | ||
1232 | ASSERT_EQ(0, rc); | ||
1233 | } | ||
1234 | |||
1235 | TEST_P(StorageServiceTest, TransactDiscardWrite) { | ||
1236 | |||
1237 | int rc; | ||
1238 | file_handle_t handle; | ||
1239 | size_t blk = 2048; | ||
1240 | size_t exp_len = 32 * 1024; | ||
1241 | storage_off_t fsize = (storage_off_t)(-1); | ||
1242 | const char *fname = "test_transact_discard_write"; | ||
1243 | |||
1244 | // open create truncate file (with commit) | ||
1245 | rc = storage_open_file(session_, &handle, fname, | ||
1246 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1247 | STORAGE_OP_COMPLETE); | ||
1248 | ASSERT_EQ(0, rc); | ||
1249 | |||
1250 | // check file size | ||
1251 | rc = storage_get_file_size(handle, &fsize); | ||
1252 | ASSERT_EQ(0, rc); | ||
1253 | ASSERT_EQ((storage_off_t)0, fsize); | ||
1254 | |||
1255 | // write (without commit) | ||
1256 | WritePattern(handle, 0, exp_len, blk, false); | ||
1257 | ASSERT_FALSE(HasFatalFailure()); | ||
1258 | |||
1259 | // check file size | ||
1260 | rc = storage_get_file_size(handle, &fsize); | ||
1261 | ASSERT_EQ(0, rc); | ||
1262 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1263 | |||
1264 | // abort current transaction | ||
1265 | rc = storage_end_transaction(session_, false); | ||
1266 | ASSERT_EQ(0, rc); | ||
1267 | |||
1268 | // check file size | ||
1269 | rc = storage_get_file_size(handle, &fsize); | ||
1270 | ASSERT_EQ(0, rc); | ||
1271 | ASSERT_EQ((storage_off_t)0, fsize); | ||
1272 | |||
1273 | // cleanup | ||
1274 | storage_close_file( handle); | ||
1275 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1276 | } | ||
1277 | |||
1278 | |||
1279 | TEST_P(StorageServiceTest, TransactDiscardWriteAppend) { | ||
1280 | |||
1281 | int rc; | ||
1282 | file_handle_t handle; | ||
1283 | size_t blk = 2048; | ||
1284 | size_t exp_len = 32 * 1024; | ||
1285 | storage_off_t fsize = (storage_off_t)(-1); | ||
1286 | const char *fname = "test_transact_write_append"; | ||
1287 | |||
1288 | // open create truncate file (with commit) | ||
1289 | rc = storage_open_file(session_, &handle, fname, | ||
1290 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1291 | STORAGE_OP_COMPLETE); | ||
1292 | ASSERT_EQ(0, rc); | ||
1293 | |||
1294 | // write data with commit | ||
1295 | WritePattern(handle, 0, exp_len/2, blk, true); | ||
1296 | ASSERT_FALSE(HasFatalFailure()); | ||
1297 | |||
1298 | // write data without commit | ||
1299 | WritePattern(handle, exp_len/2, exp_len/2, blk, false); | ||
1300 | ASSERT_FALSE(HasFatalFailure()); | ||
1301 | |||
1302 | // check file size (should be exp_len) | ||
1303 | rc = storage_get_file_size(handle, &fsize); | ||
1304 | ASSERT_EQ(0, rc); | ||
1305 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1306 | |||
1307 | // discard transaction | ||
1308 | rc = storage_end_transaction(session_, false); | ||
1309 | ASSERT_EQ(0, rc); | ||
1310 | |||
1311 | // check file size, it should be exp_len/2 | ||
1312 | rc = storage_get_file_size(handle, &fsize); | ||
1313 | ASSERT_EQ(0, rc); | ||
1314 | ASSERT_EQ((storage_off_t)exp_len/2, fsize); | ||
1315 | |||
1316 | // check file data | ||
1317 | ReadPatternEOF(handle, 0, blk, exp_len/2); | ||
1318 | ASSERT_FALSE(HasFatalFailure()); | ||
1319 | |||
1320 | // cleanup | ||
1321 | storage_close_file(handle); | ||
1322 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1323 | } | ||
1324 | |||
1325 | TEST_P(StorageServiceTest, TransactDiscardWriteRead) { | ||
1326 | |||
1327 | int rc; | ||
1328 | file_handle_t handle; | ||
1329 | size_t blk = 2048; | ||
1330 | storage_off_t fsize = (storage_off_t)(-1); | ||
1331 | const char *fname = "test_transact_discard_write_read"; | ||
1332 | |||
1333 | // open create truncate file (with commit) | ||
1334 | rc = storage_open_file(session_, &handle, fname, | ||
1335 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1336 | STORAGE_OP_COMPLETE); | ||
1337 | ASSERT_EQ(0, rc); | ||
1338 | |||
1339 | // check file size | ||
1340 | rc = storage_get_file_size(handle, &fsize); | ||
1341 | ASSERT_EQ(0, rc); | ||
1342 | ASSERT_EQ((storage_off_t)0, fsize); | ||
1343 | |||
1344 | // Fill with zeroes (with commit) | ||
1345 | for (uint i = 0; i < 32; i++) { | ||
1346 | WriteZeroChunk(handle, i * blk, blk, true); | ||
1347 | ASSERT_FALSE(HasFatalFailure()); | ||
1348 | } | ||
1349 | |||
1350 | // check that test chunk is filled with zeroes | ||
1351 | ReadChunk(handle, blk, blk, blk, 0, 0); | ||
1352 | ASSERT_FALSE(HasFatalFailure()); | ||
1353 | |||
1354 | // write test pattern (without commit) | ||
1355 | WritePattern(handle, blk, blk, blk, false); | ||
1356 | ASSERT_FALSE(HasFatalFailure()); | ||
1357 | |||
1358 | // read it back an check pattern | ||
1359 | ReadChunk(handle, blk, blk, 0, blk, 0); | ||
1360 | ASSERT_FALSE(HasFatalFailure()); | ||
1361 | |||
1362 | // abort current transaction | ||
1363 | rc = storage_end_transaction(session_, false); | ||
1364 | ASSERT_EQ(0, rc); | ||
1365 | |||
1366 | // read same chunk back (should be filled with zeros) | ||
1367 | ReadChunk(handle, blk, blk, blk, 0, 0); | ||
1368 | ASSERT_FALSE(HasFatalFailure()); | ||
1369 | |||
1370 | // cleanup | ||
1371 | storage_close_file(handle); | ||
1372 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1373 | } | ||
1374 | |||
1375 | TEST_P(StorageServiceTest, TransactDiscardWriteMany) { | ||
1376 | int rc; | ||
1377 | file_handle_t handle1; | ||
1378 | file_handle_t handle2; | ||
1379 | size_t blk = 2048; | ||
1380 | size_t exp_len1 = 32 * 1024; | ||
1381 | size_t exp_len2 = 31 * 1024; | ||
1382 | storage_off_t fsize = (storage_off_t)(-1); | ||
1383 | const char *fname1 = "test_transact_discard_write_file1"; | ||
1384 | const char *fname2 = "test_transact_discard_write_file2"; | ||
1385 | |||
1386 | // open create truncate (with commit) | ||
1387 | rc = storage_open_file(session_, &handle1, fname1, | ||
1388 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1389 | STORAGE_OP_COMPLETE); | ||
1390 | ASSERT_EQ(0, rc); | ||
1391 | |||
1392 | // open create truncate (with commit) | ||
1393 | rc = storage_open_file(session_, &handle2, fname2, | ||
1394 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1395 | STORAGE_OP_COMPLETE); | ||
1396 | ASSERT_EQ(0, rc); | ||
1397 | |||
1398 | // file1: fill file with pattern (without commit) | ||
1399 | WritePattern(handle1, 0, exp_len1, blk, false); | ||
1400 | ASSERT_FALSE(HasFatalFailure()); | ||
1401 | |||
1402 | // file2: fill file with pattern (without commit) | ||
1403 | WritePattern(handle2, 0, exp_len2, blk, false); | ||
1404 | ASSERT_FALSE(HasFatalFailure()); | ||
1405 | |||
1406 | // check file size, it should be exp_len1 | ||
1407 | rc = storage_get_file_size(handle1, &fsize); | ||
1408 | ASSERT_EQ(0, rc); | ||
1409 | ASSERT_EQ((storage_off_t)exp_len1, fsize); | ||
1410 | |||
1411 | // check file size, it should be exp_len2 | ||
1412 | rc = storage_get_file_size(handle2, &fsize); | ||
1413 | ASSERT_EQ(0, rc); | ||
1414 | ASSERT_EQ((storage_off_t)exp_len2, fsize); | ||
1415 | |||
1416 | // commit transaction | ||
1417 | rc = storage_end_transaction(session_, false); | ||
1418 | ASSERT_EQ(0, rc); | ||
1419 | |||
1420 | // check file size, it should be exp_len1 | ||
1421 | rc = storage_get_file_size(handle1, &fsize); | ||
1422 | ASSERT_EQ(0, rc); | ||
1423 | ASSERT_EQ((storage_off_t)0, fsize); | ||
1424 | |||
1425 | // check file size, it should be exp_len2 | ||
1426 | rc = storage_get_file_size(handle2, &fsize); | ||
1427 | ASSERT_EQ(0, rc); | ||
1428 | ASSERT_EQ((storage_off_t)0, fsize); | ||
1429 | |||
1430 | // check data | ||
1431 | ReadPatternEOF(handle1, 0, blk, 0); | ||
1432 | ASSERT_FALSE(HasFatalFailure()); | ||
1433 | |||
1434 | ReadPatternEOF(handle2, 0, blk, 0); | ||
1435 | ASSERT_FALSE(HasFatalFailure()); | ||
1436 | |||
1437 | // cleanup | ||
1438 | storage_close_file(handle1); | ||
1439 | storage_delete_file(session_, fname1, STORAGE_OP_COMPLETE); | ||
1440 | storage_close_file(handle2); | ||
1441 | storage_delete_file(session_, fname2, STORAGE_OP_COMPLETE); | ||
1442 | } | ||
1443 | |||
1444 | TEST_P(StorageServiceTest, TransactDiscardTruncate) { | ||
1445 | int rc; | ||
1446 | file_handle_t handle; | ||
1447 | size_t blk = 2048; | ||
1448 | size_t exp_len = 32 * 1024; | ||
1449 | storage_off_t fsize = (storage_off_t)(-1); | ||
1450 | const char *fname = "test_transact_discard_truncate"; | ||
1451 | |||
1452 | // open create truncate file (with commit) | ||
1453 | rc = storage_open_file(session_, &handle, fname, | ||
1454 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1455 | STORAGE_OP_COMPLETE); | ||
1456 | ASSERT_EQ(0, rc); | ||
1457 | |||
1458 | // write data (with commit) | ||
1459 | WritePattern(handle, 0, exp_len, blk, true); | ||
1460 | ASSERT_FALSE(HasFatalFailure()); | ||
1461 | |||
1462 | // check file size | ||
1463 | rc = storage_get_file_size(handle, &fsize); | ||
1464 | ASSERT_EQ(0, rc); | ||
1465 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1466 | |||
1467 | // close file | ||
1468 | storage_close_file(handle); | ||
1469 | |||
1470 | // open truncate file (without commit) | ||
1471 | rc = storage_open_file(session_, &handle, fname, STORAGE_FILE_OPEN_TRUNCATE, 0); | ||
1472 | ASSERT_EQ(0, rc); | ||
1473 | |||
1474 | // check file size | ||
1475 | rc = storage_get_file_size(handle, &fsize); | ||
1476 | ASSERT_EQ(0, rc); | ||
1477 | ASSERT_EQ((storage_off_t)0, fsize); | ||
1478 | |||
1479 | // abort current transaction | ||
1480 | rc = storage_end_transaction(session_, false); | ||
1481 | ASSERT_EQ(0, rc); | ||
1482 | |||
1483 | // check file size (should be an oruginal size) | ||
1484 | rc = storage_get_file_size(handle, &fsize); | ||
1485 | ASSERT_EQ(0, rc); | ||
1486 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1487 | |||
1488 | // cleanup | ||
1489 | storage_close_file(handle); | ||
1490 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1491 | } | ||
1492 | |||
1493 | TEST_P(StorageServiceTest, TransactDiscardSetSize) { | ||
1494 | int rc; | ||
1495 | file_handle_t handle; | ||
1496 | size_t blk = 2048; | ||
1497 | size_t exp_len = 32 * 1024; | ||
1498 | storage_off_t fsize = (storage_off_t)(-1); | ||
1499 | const char *fname = "test_transact_discard_set_size"; | ||
1500 | |||
1501 | // open create truncate file (with commit) | ||
1502 | rc = storage_open_file(session_, &handle, fname, | ||
1503 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1504 | STORAGE_OP_COMPLETE); | ||
1505 | ASSERT_EQ(0, rc); | ||
1506 | |||
1507 | // write data (with commit) | ||
1508 | WritePattern(handle, 0, exp_len, blk, true); | ||
1509 | ASSERT_FALSE(HasFatalFailure()); | ||
1510 | |||
1511 | // check file size | ||
1512 | rc = storage_get_file_size(handle, &fsize); | ||
1513 | ASSERT_EQ(0, rc); | ||
1514 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1515 | |||
1516 | // set file size to half of original (no commit) | ||
1517 | rc = storage_set_file_size(handle, (storage_off_t)exp_len/2, 0); | ||
1518 | ASSERT_EQ(0, rc); | ||
1519 | |||
1520 | // check file size | ||
1521 | rc = storage_get_file_size(handle, &fsize); | ||
1522 | ASSERT_EQ(0, rc); | ||
1523 | ASSERT_EQ((storage_off_t)exp_len/2, fsize); | ||
1524 | |||
1525 | // set file size to 1/3 of original (no commit) | ||
1526 | rc = storage_set_file_size(handle, (storage_off_t)exp_len/3, 0); | ||
1527 | ASSERT_EQ(0, rc); | ||
1528 | |||
1529 | // check file size | ||
1530 | rc = storage_get_file_size(handle, &fsize); | ||
1531 | ASSERT_EQ(0, rc); | ||
1532 | ASSERT_EQ((storage_off_t)exp_len/3, fsize); | ||
1533 | |||
1534 | // abort current transaction | ||
1535 | rc = storage_end_transaction(session_, false); | ||
1536 | ASSERT_EQ(0, rc); | ||
1537 | |||
1538 | // check file size (should be an original size) | ||
1539 | rc = storage_get_file_size(handle, &fsize); | ||
1540 | ASSERT_EQ(0, rc); | ||
1541 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1542 | |||
1543 | // cleanup | ||
1544 | storage_close_file(handle); | ||
1545 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1546 | } | ||
1547 | |||
1548 | TEST_P(StorageServiceTest, TransactDiscardDelete) { | ||
1549 | int rc; | ||
1550 | file_handle_t handle; | ||
1551 | size_t blk = 2048; | ||
1552 | size_t exp_len = 32 * 1024; | ||
1553 | storage_off_t fsize = (storage_off_t)(-1); | ||
1554 | const char *fname = "test_transact_discard_delete"; | ||
1555 | |||
1556 | // open create truncate file (with commit) | ||
1557 | rc = storage_open_file(session_, &handle, fname, | ||
1558 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1559 | STORAGE_OP_COMPLETE); | ||
1560 | ASSERT_EQ(0, rc); | ||
1561 | |||
1562 | // write data (with commit) | ||
1563 | WritePattern(handle, 0, exp_len, blk, true); | ||
1564 | ASSERT_FALSE(HasFatalFailure()); | ||
1565 | |||
1566 | // close it | ||
1567 | storage_close_file(handle); | ||
1568 | |||
1569 | // delete file (without commit) | ||
1570 | rc = storage_delete_file(session_, fname, 0); | ||
1571 | ASSERT_EQ(0, rc); | ||
1572 | |||
1573 | // try to open it (should fail) | ||
1574 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
1575 | ASSERT_EQ(-ENOENT, rc); | ||
1576 | |||
1577 | // abort current transaction | ||
1578 | rc = storage_end_transaction(session_, false); | ||
1579 | ASSERT_EQ(0, rc); | ||
1580 | |||
1581 | // try to open it | ||
1582 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
1583 | ASSERT_EQ(0, rc); | ||
1584 | |||
1585 | // check file size (should be an original size) | ||
1586 | rc = storage_get_file_size(handle, &fsize); | ||
1587 | ASSERT_EQ(0, rc); | ||
1588 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1589 | |||
1590 | // cleanup | ||
1591 | storage_close_file(handle); | ||
1592 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1593 | } | ||
1594 | |||
1595 | TEST_P(StorageServiceTest, TransactDiscardDelete2) { | ||
1596 | int rc; | ||
1597 | file_handle_t handle; | ||
1598 | size_t blk = 2048; | ||
1599 | size_t exp_len = 32 * 1024; | ||
1600 | storage_off_t fsize = (storage_off_t)(-1); | ||
1601 | const char *fname = "test_transact_discard_delete"; | ||
1602 | |||
1603 | // open create truncate file (with commit) | ||
1604 | rc = storage_open_file(session_, &handle, fname, | ||
1605 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1606 | STORAGE_OP_COMPLETE); | ||
1607 | ASSERT_EQ(0, rc); | ||
1608 | |||
1609 | // write data (with commit) | ||
1610 | WritePattern(handle, 0, exp_len, blk, true); | ||
1611 | ASSERT_FALSE(HasFatalFailure()); | ||
1612 | |||
1613 | // delete file (without commit) | ||
1614 | rc = storage_delete_file(session_, fname, 0); | ||
1615 | ASSERT_EQ(0, rc); | ||
1616 | storage_close_file(handle); | ||
1617 | |||
1618 | // try to open it (should fail) | ||
1619 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
1620 | ASSERT_EQ(-ENOENT, rc); | ||
1621 | |||
1622 | // abort current transaction | ||
1623 | rc = storage_end_transaction(session_, false); | ||
1624 | ASSERT_EQ(0, rc); | ||
1625 | |||
1626 | // try to open it | ||
1627 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
1628 | ASSERT_EQ(0, rc); | ||
1629 | |||
1630 | // check file size (should be an original size) | ||
1631 | rc = storage_get_file_size(handle, &fsize); | ||
1632 | ASSERT_EQ(0, rc); | ||
1633 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1634 | |||
1635 | // cleanup | ||
1636 | storage_close_file(handle); | ||
1637 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1638 | } | ||
1639 | |||
1640 | |||
1641 | TEST_P(StorageServiceTest, TransactDiscardCreate) { | ||
1642 | int rc; | ||
1643 | file_handle_t handle; | ||
1644 | const char *fname = "test_transact_discard_create_excl"; | ||
1645 | |||
1646 | // delete test file just in case | ||
1647 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1648 | |||
1649 | // create file (without commit) | ||
1650 | rc = storage_open_file(session_, &handle, fname, | ||
1651 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
1652 | 0); | ||
1653 | ASSERT_EQ(0, rc); | ||
1654 | |||
1655 | // abort current transaction | ||
1656 | rc = storage_end_transaction(session_, false); | ||
1657 | ASSERT_EQ(0, rc); | ||
1658 | |||
1659 | // cleanup | ||
1660 | storage_close_file(handle); | ||
1661 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1662 | } | ||
1663 | |||
1664 | TEST_P(StorageServiceTest, TransactCommitWrites) { | ||
1665 | |||
1666 | int rc; | ||
1667 | file_handle_t handle; | ||
1668 | file_handle_t handle_aux; | ||
1669 | size_t blk = 2048; | ||
1670 | size_t exp_len = 32 * 1024; | ||
1671 | storage_off_t fsize = (storage_off_t)(-1); | ||
1672 | const char *fname = "test_transact_commit_writes"; | ||
1673 | |||
1674 | // open second session | ||
1675 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
1676 | ASSERT_EQ(0, rc); | ||
1677 | |||
1678 | // open create truncate file (with commit) | ||
1679 | rc = storage_open_file(session_, &handle, fname, | ||
1680 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1681 | STORAGE_OP_COMPLETE); | ||
1682 | ASSERT_EQ(0, rc); | ||
1683 | |||
1684 | // open the same file in aux session | ||
1685 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
1686 | ASSERT_EQ(0, rc); | ||
1687 | |||
1688 | // check file size, it should be 0 | ||
1689 | rc = storage_get_file_size(handle_aux, &fsize); | ||
1690 | ASSERT_EQ(0, rc); | ||
1691 | ASSERT_EQ((storage_off_t)0, fsize); | ||
1692 | |||
1693 | // write data in primary session (without commit) | ||
1694 | WritePattern(handle, 0, exp_len/2, blk, false); | ||
1695 | ASSERT_FALSE(HasFatalFailure()); | ||
1696 | |||
1697 | // write more data in primary session (without commit) | ||
1698 | WritePattern(handle, exp_len/2, exp_len/2, blk, false); | ||
1699 | ASSERT_FALSE(HasFatalFailure()); | ||
1700 | |||
1701 | // check file size in aux session, it should still be 0 | ||
1702 | rc = storage_get_file_size(handle_aux, &fsize); | ||
1703 | ASSERT_EQ(0, rc); | ||
1704 | ASSERT_EQ((storage_off_t)0, fsize); | ||
1705 | |||
1706 | // commit current transaction | ||
1707 | rc = storage_end_transaction(session_, true); | ||
1708 | ASSERT_EQ(0, rc); | ||
1709 | |||
1710 | // check file size of aux session, should fail | ||
1711 | rc = storage_get_file_size(handle_aux, &fsize); | ||
1712 | ASSERT_EQ(-EBUSY, rc); | ||
1713 | |||
1714 | // abort transaction in aux session to recover | ||
1715 | rc = storage_end_transaction(aux_session_, false); | ||
1716 | ASSERT_EQ(0, rc); | ||
1717 | |||
1718 | // check file size in aux session, it should be exp_len | ||
1719 | rc = storage_get_file_size(handle_aux, &fsize); | ||
1720 | ASSERT_EQ(0, rc); | ||
1721 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1722 | |||
1723 | // check file size in primary session, it should be exp_len | ||
1724 | rc = storage_get_file_size(handle, &fsize); | ||
1725 | ASSERT_EQ(0, rc); | ||
1726 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1727 | |||
1728 | // check data in primary session | ||
1729 | ReadPatternEOF(handle, 0, blk, exp_len); | ||
1730 | ASSERT_FALSE(HasFatalFailure()); | ||
1731 | |||
1732 | // check data in aux session | ||
1733 | ReadPatternEOF(handle_aux, 0, blk, exp_len); | ||
1734 | ASSERT_FALSE(HasFatalFailure()); | ||
1735 | |||
1736 | // cleanup | ||
1737 | storage_close_file(handle); | ||
1738 | storage_close_file(handle_aux); | ||
1739 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1740 | } | ||
1741 | |||
1742 | |||
1743 | TEST_P(StorageServiceTest, TransactCommitWrites2) { | ||
1744 | |||
1745 | int rc; | ||
1746 | file_handle_t handle; | ||
1747 | file_handle_t handle_aux; | ||
1748 | size_t blk = 2048; | ||
1749 | storage_off_t fsize = (storage_off_t)(-1); | ||
1750 | const char *fname = "test_transact_commit_writes2"; | ||
1751 | |||
1752 | // open second session | ||
1753 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
1754 | ASSERT_EQ(0, rc); | ||
1755 | |||
1756 | // open create truncate file (with commit) | ||
1757 | rc = storage_open_file(session_, &handle, fname, | ||
1758 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1759 | STORAGE_OP_COMPLETE); | ||
1760 | ASSERT_EQ(0, rc); | ||
1761 | |||
1762 | // open the same file in separate session | ||
1763 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
1764 | ASSERT_EQ(0, rc); | ||
1765 | |||
1766 | // check file size | ||
1767 | rc = storage_get_file_size(handle, &fsize); | ||
1768 | ASSERT_EQ(0, rc); | ||
1769 | ASSERT_EQ((storage_off_t)0, fsize); | ||
1770 | |||
1771 | rc = storage_get_file_size(handle_aux, &fsize); | ||
1772 | ASSERT_EQ(0, rc); | ||
1773 | ASSERT_EQ((storage_off_t)0, fsize); | ||
1774 | |||
1775 | // discard transaction in aux_session | ||
1776 | rc = storage_end_transaction(aux_session_, false); | ||
1777 | ASSERT_EQ(0, rc); | ||
1778 | |||
1779 | // Fill with zeroes (with commit) | ||
1780 | for (uint i = 0; i < 8; i++) { | ||
1781 | WriteZeroChunk(handle, i * blk, blk, true); | ||
1782 | ASSERT_FALSE(HasFatalFailure()); | ||
1783 | } | ||
1784 | |||
1785 | // check that test chunks are filled with zeroes | ||
1786 | ReadChunk(handle, blk, blk, blk, 0, 0); | ||
1787 | ASSERT_FALSE(HasFatalFailure()); | ||
1788 | |||
1789 | ReadChunk(handle, 2 * blk, blk, blk, 0, 0); | ||
1790 | ASSERT_FALSE(HasFatalFailure()); | ||
1791 | |||
1792 | // write test pattern (without commit) | ||
1793 | WritePattern(handle, blk, blk, blk, false); | ||
1794 | ASSERT_FALSE(HasFatalFailure()); | ||
1795 | |||
1796 | // write test pattern (without commit) | ||
1797 | WritePattern(handle, 2 * blk, blk, blk, false); | ||
1798 | ASSERT_FALSE(HasFatalFailure()); | ||
1799 | |||
1800 | // read it back and check pattern | ||
1801 | ReadChunk(handle, blk, blk, 0, blk, 0); | ||
1802 | ASSERT_FALSE(HasFatalFailure()); | ||
1803 | |||
1804 | ReadChunk(handle, 2 * blk, blk, 0, blk, 0); | ||
1805 | ASSERT_FALSE(HasFatalFailure()); | ||
1806 | |||
1807 | // In aux session it still should be empty | ||
1808 | ReadChunk(handle_aux, blk, blk, blk, 0, 0); | ||
1809 | ASSERT_FALSE(HasFatalFailure()); | ||
1810 | |||
1811 | ReadChunk(handle_aux, 2 * blk, blk, blk, 0, 0); | ||
1812 | ASSERT_FALSE(HasFatalFailure()); | ||
1813 | |||
1814 | // commit current transaction | ||
1815 | rc = storage_end_transaction(session_, true); | ||
1816 | ASSERT_EQ(0, rc); | ||
1817 | |||
1818 | // read same chunks back in primary session | ||
1819 | ReadChunk(handle, blk, blk, 0, blk, 0); | ||
1820 | ASSERT_FALSE(HasFatalFailure()); | ||
1821 | |||
1822 | ReadChunk(handle, 2 * blk, blk, 0, blk, 0); | ||
1823 | ASSERT_FALSE(HasFatalFailure()); | ||
1824 | |||
1825 | // read same chunks back in aux session (should fail) | ||
1826 | uint32_t val; | ||
1827 | rc = storage_read(handle_aux, blk, &val, sizeof(val)); | ||
1828 | ASSERT_EQ(-EBUSY, rc); | ||
1829 | |||
1830 | rc = storage_read(handle_aux, 2 * blk, &val, sizeof(val)); | ||
1831 | ASSERT_EQ(-EBUSY, rc); | ||
1832 | |||
1833 | // abort transaction in aux session | ||
1834 | rc = storage_end_transaction(aux_session_, false); | ||
1835 | ASSERT_EQ(0, rc); | ||
1836 | |||
1837 | // read same chunk again in aux session | ||
1838 | ReadChunk(handle_aux, blk, blk, 0, blk, 0); | ||
1839 | ASSERT_FALSE(HasFatalFailure()); | ||
1840 | |||
1841 | ReadChunk(handle_aux, 2 * blk, blk, 0, blk, 0); | ||
1842 | ASSERT_FALSE(HasFatalFailure()); | ||
1843 | |||
1844 | |||
1845 | // cleanup | ||
1846 | storage_close_file(handle); | ||
1847 | storage_close_file(handle_aux); | ||
1848 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1849 | } | ||
1850 | |||
1851 | TEST_P(StorageServiceTest, TransactCommitSetSize) { | ||
1852 | int rc; | ||
1853 | file_handle_t handle; | ||
1854 | file_handle_t handle_aux; | ||
1855 | size_t blk = 2048; | ||
1856 | size_t exp_len = 32 * 1024; | ||
1857 | storage_off_t fsize = (storage_off_t)(-1); | ||
1858 | const char *fname = "test_transact_commit_set_size"; | ||
1859 | |||
1860 | // open second session | ||
1861 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
1862 | ASSERT_EQ(0, rc); | ||
1863 | |||
1864 | // open create truncate file (with commit) | ||
1865 | rc = storage_open_file(session_, &handle, fname, | ||
1866 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1867 | STORAGE_OP_COMPLETE); | ||
1868 | ASSERT_EQ(0, rc); | ||
1869 | |||
1870 | // open the same file in separate session | ||
1871 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
1872 | ASSERT_EQ(0, rc); | ||
1873 | |||
1874 | // write data (with commit) | ||
1875 | WritePattern(handle, 0, exp_len, blk, true); | ||
1876 | ASSERT_FALSE(HasFatalFailure()); | ||
1877 | |||
1878 | // check file size | ||
1879 | rc = storage_get_file_size(handle, &fsize); | ||
1880 | ASSERT_EQ(0, rc); | ||
1881 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1882 | |||
1883 | // same in aux session | ||
1884 | rc = storage_get_file_size(handle_aux, &fsize); | ||
1885 | ASSERT_EQ(0, rc); | ||
1886 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1887 | |||
1888 | // set file size to half of original (no commit) | ||
1889 | rc = storage_set_file_size(handle, (storage_off_t)exp_len/2, 0); | ||
1890 | ASSERT_EQ(0, rc); | ||
1891 | |||
1892 | // check file size | ||
1893 | rc = storage_get_file_size(handle, &fsize); | ||
1894 | ASSERT_EQ(0, rc); | ||
1895 | ASSERT_EQ((storage_off_t)exp_len/2, fsize); | ||
1896 | |||
1897 | rc = storage_get_file_size(handle_aux, &fsize); | ||
1898 | ASSERT_EQ(0, rc); | ||
1899 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1900 | |||
1901 | // set file size to 1/3 of original (no commit) | ||
1902 | rc = storage_set_file_size(handle, (storage_off_t)exp_len/3, 0); | ||
1903 | ASSERT_EQ(0, rc); | ||
1904 | |||
1905 | // check file size | ||
1906 | rc = storage_get_file_size(handle, &fsize); | ||
1907 | ASSERT_EQ(0, rc); | ||
1908 | ASSERT_EQ((storage_off_t)exp_len/3, fsize); | ||
1909 | |||
1910 | rc = storage_get_file_size(handle_aux, &fsize); | ||
1911 | ASSERT_EQ(0, rc); | ||
1912 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
1913 | |||
1914 | // commit current transaction | ||
1915 | rc = storage_end_transaction(session_, true); | ||
1916 | ASSERT_EQ(0, rc); | ||
1917 | |||
1918 | // check file size (should be 1/3 of an original size) | ||
1919 | rc = storage_get_file_size(handle, &fsize); | ||
1920 | ASSERT_EQ(0, rc); | ||
1921 | ASSERT_EQ((storage_off_t)exp_len/3, fsize); | ||
1922 | |||
1923 | // check file size from aux session | ||
1924 | rc = storage_get_file_size(handle_aux, &fsize); | ||
1925 | ASSERT_EQ(-EBUSY, rc); | ||
1926 | |||
1927 | // abort transaction in aux_session | ||
1928 | rc = storage_end_transaction(aux_session_, false); | ||
1929 | ASSERT_EQ(0, rc); | ||
1930 | |||
1931 | // check again | ||
1932 | rc = storage_get_file_size(handle_aux, &fsize); | ||
1933 | ASSERT_EQ(0, rc); | ||
1934 | ASSERT_EQ((storage_off_t)exp_len/3, fsize); | ||
1935 | |||
1936 | // cleanup | ||
1937 | storage_close_file(handle); | ||
1938 | storage_close_file(handle_aux); | ||
1939 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
1940 | } | ||
1941 | |||
1942 | |||
1943 | TEST_P(StorageServiceTest, TransactCommitDelete) { | ||
1944 | int rc; | ||
1945 | file_handle_t handle; | ||
1946 | file_handle_t handle_aux; | ||
1947 | size_t blk = 2048; | ||
1948 | size_t exp_len = 32 * 1024; | ||
1949 | const char *fname = "test_transact_commit_delete"; | ||
1950 | |||
1951 | // open second session | ||
1952 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
1953 | ASSERT_EQ(0, rc); | ||
1954 | |||
1955 | // open create truncate file (with commit) | ||
1956 | rc = storage_open_file(session_, &handle, fname, | ||
1957 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
1958 | STORAGE_OP_COMPLETE); | ||
1959 | ASSERT_EQ(0, rc); | ||
1960 | |||
1961 | // write data (with commit) | ||
1962 | WritePattern(handle, 0, exp_len, blk, true); | ||
1963 | ASSERT_FALSE(HasFatalFailure()); | ||
1964 | |||
1965 | // close it | ||
1966 | storage_close_file(handle); | ||
1967 | |||
1968 | // open the same file in separate session | ||
1969 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
1970 | ASSERT_EQ(0, rc); | ||
1971 | storage_close_file(handle_aux); | ||
1972 | |||
1973 | // delete file (without commit) | ||
1974 | rc = storage_delete_file(session_, fname, 0); | ||
1975 | ASSERT_EQ(0, rc); | ||
1976 | |||
1977 | // try to open it (should fail) | ||
1978 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
1979 | ASSERT_EQ(-ENOENT, rc); | ||
1980 | |||
1981 | // open the same file in separate session (should be fine) | ||
1982 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
1983 | ASSERT_EQ(0, rc); | ||
1984 | storage_close_file(handle_aux); | ||
1985 | |||
1986 | // commit current transaction | ||
1987 | rc = storage_end_transaction(session_, true); | ||
1988 | ASSERT_EQ(0, rc); | ||
1989 | |||
1990 | // try to open it in primary session (still fails) | ||
1991 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
1992 | ASSERT_EQ(-ENOENT, rc); | ||
1993 | |||
1994 | // open the same file in aux session (should also fail) | ||
1995 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
1996 | ASSERT_EQ(-ENOENT, rc); | ||
1997 | } | ||
1998 | |||
1999 | |||
2000 | TEST_P(StorageServiceTest, TransactCommitTruncate) { | ||
2001 | int rc; | ||
2002 | file_handle_t handle; | ||
2003 | file_handle_t handle_aux; | ||
2004 | size_t blk = 2048; | ||
2005 | size_t exp_len = 32 * 1024; | ||
2006 | storage_off_t fsize = (storage_off_t)(-1); | ||
2007 | const char *fname = "test_transact_commit_truncate"; | ||
2008 | |||
2009 | // open second session | ||
2010 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2011 | ASSERT_EQ(0, rc); | ||
2012 | |||
2013 | // open create truncate file (with commit) | ||
2014 | rc = storage_open_file(session_, &handle, fname, | ||
2015 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2016 | STORAGE_OP_COMPLETE); | ||
2017 | ASSERT_EQ(0, rc); | ||
2018 | |||
2019 | // write data (with commit) | ||
2020 | WritePattern(handle, 0, exp_len, blk, true); | ||
2021 | ASSERT_FALSE(HasFatalFailure()); | ||
2022 | |||
2023 | // check file size | ||
2024 | rc = storage_get_file_size(handle, &fsize); | ||
2025 | ASSERT_EQ(0, rc); | ||
2026 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
2027 | |||
2028 | // close file | ||
2029 | storage_close_file(handle); | ||
2030 | |||
2031 | // check from different session | ||
2032 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
2033 | ASSERT_EQ(0, rc); | ||
2034 | |||
2035 | rc = storage_get_file_size(handle_aux, &fsize); | ||
2036 | ASSERT_EQ(0, rc); | ||
2037 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
2038 | |||
2039 | // open truncate file (without commit) | ||
2040 | rc = storage_open_file(session_, &handle, fname, STORAGE_FILE_OPEN_TRUNCATE, 0); | ||
2041 | ASSERT_EQ(0, rc); | ||
2042 | |||
2043 | // check file size | ||
2044 | rc = storage_get_file_size(handle, &fsize); | ||
2045 | ASSERT_EQ(0, rc); | ||
2046 | ASSERT_EQ((storage_off_t)0, fsize); | ||
2047 | |||
2048 | rc = storage_get_file_size(handle_aux, &fsize); | ||
2049 | ASSERT_EQ(0, rc); | ||
2050 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
2051 | |||
2052 | // commit current transaction | ||
2053 | rc = storage_end_transaction(session_, true); | ||
2054 | ASSERT_EQ(0, rc); | ||
2055 | |||
2056 | // check file size (should be 0) | ||
2057 | rc = storage_get_file_size(handle, &fsize); | ||
2058 | ASSERT_EQ(0, rc); | ||
2059 | ASSERT_EQ((storage_off_t)0, fsize); | ||
2060 | |||
2061 | // check file size in aux session (should be -EBUSY) | ||
2062 | rc = storage_get_file_size(handle_aux, &fsize); | ||
2063 | ASSERT_EQ(-EBUSY, rc); | ||
2064 | |||
2065 | // abort transaction in aux session | ||
2066 | rc = storage_end_transaction(aux_session_, false); | ||
2067 | ASSERT_EQ(0, rc); | ||
2068 | |||
2069 | // check again | ||
2070 | rc = storage_get_file_size(handle_aux, &fsize); | ||
2071 | ASSERT_EQ(0, rc); | ||
2072 | ASSERT_EQ((storage_off_t)0, fsize); | ||
2073 | |||
2074 | // cleanup | ||
2075 | storage_close_file(handle); | ||
2076 | storage_close_file(handle_aux); | ||
2077 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
2078 | } | ||
2079 | |||
2080 | TEST_P(StorageServiceTest, TransactCommitCreate) { | ||
2081 | int rc; | ||
2082 | file_handle_t handle; | ||
2083 | file_handle_t handle_aux; | ||
2084 | storage_off_t fsize = (storage_off_t)(-1); | ||
2085 | const char *fname = "test_transact_commit_create"; | ||
2086 | |||
2087 | // open second session | ||
2088 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2089 | ASSERT_EQ(0, rc); | ||
2090 | |||
2091 | // delete test file just in case | ||
2092 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
2093 | |||
2094 | // check from aux session | ||
2095 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
2096 | ASSERT_EQ(-ENOENT, rc); | ||
2097 | |||
2098 | // create file (without commit) | ||
2099 | rc = storage_open_file(session_, &handle, fname, | ||
2100 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
2101 | 0); | ||
2102 | ASSERT_EQ(0, rc); | ||
2103 | |||
2104 | // check file size | ||
2105 | rc = storage_get_file_size(handle, &fsize); | ||
2106 | ASSERT_EQ(0, rc); | ||
2107 | ASSERT_EQ((storage_off_t)0, fsize); | ||
2108 | |||
2109 | // close file | ||
2110 | storage_close_file(handle); | ||
2111 | |||
2112 | // check from aux session (should fail) | ||
2113 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
2114 | ASSERT_EQ(-ENOENT, rc); | ||
2115 | |||
2116 | // commit current transaction | ||
2117 | rc = storage_end_transaction(session_, true); | ||
2118 | ASSERT_EQ(0, rc); | ||
2119 | |||
2120 | // check open from normal session | ||
2121 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
2122 | ASSERT_EQ(0, rc); | ||
2123 | |||
2124 | // check open from aux session (should succeed) | ||
2125 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
2126 | ASSERT_EQ(0, rc); | ||
2127 | |||
2128 | // cleanup | ||
2129 | storage_close_file(handle); | ||
2130 | storage_close_file(handle_aux); | ||
2131 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
2132 | } | ||
2133 | |||
2134 | TEST_P(StorageServiceTest, TransactCommitCreateMany) { | ||
2135 | int rc; | ||
2136 | file_handle_t handle1; | ||
2137 | file_handle_t handle2; | ||
2138 | file_handle_t handle1_aux; | ||
2139 | file_handle_t handle2_aux; | ||
2140 | storage_off_t fsize = (storage_off_t)(-1); | ||
2141 | const char *fname1 = "test_transact_commit_create1"; | ||
2142 | const char *fname2 = "test_transact_commit_create2"; | ||
2143 | |||
2144 | // open second session | ||
2145 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2146 | ASSERT_EQ(0, rc); | ||
2147 | |||
2148 | // delete test file just in case | ||
2149 | storage_delete_file(session_, fname1, STORAGE_OP_COMPLETE); | ||
2150 | storage_delete_file(session_, fname2, STORAGE_OP_COMPLETE); | ||
2151 | |||
2152 | // create file (without commit) | ||
2153 | rc = storage_open_file(session_, &handle1, fname1, | ||
2154 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
2155 | 0); | ||
2156 | ASSERT_EQ(0, rc); | ||
2157 | |||
2158 | // create file (without commit) | ||
2159 | rc = storage_open_file(session_, &handle2, fname2, | ||
2160 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
2161 | 0); | ||
2162 | ASSERT_EQ(0, rc); | ||
2163 | |||
2164 | // check file sizes | ||
2165 | rc = storage_get_file_size(handle1, &fsize); | ||
2166 | ASSERT_EQ(0, rc); | ||
2167 | ASSERT_EQ((storage_off_t)0, fsize); | ||
2168 | |||
2169 | rc = storage_get_file_size(handle1, &fsize); | ||
2170 | ASSERT_EQ(0, rc); | ||
2171 | ASSERT_EQ((storage_off_t)0, fsize); | ||
2172 | |||
2173 | // close files | ||
2174 | storage_close_file(handle1); | ||
2175 | storage_close_file(handle2); | ||
2176 | |||
2177 | // open files from aux session | ||
2178 | rc = storage_open_file(aux_session_, &handle1_aux, fname1, 0, 0); | ||
2179 | ASSERT_EQ(-ENOENT, rc); | ||
2180 | |||
2181 | rc = storage_open_file(aux_session_, &handle2_aux, fname2, 0, 0); | ||
2182 | ASSERT_EQ(-ENOENT, rc); | ||
2183 | |||
2184 | // commit current transaction | ||
2185 | rc = storage_end_transaction(session_, true); | ||
2186 | ASSERT_EQ(0, rc); | ||
2187 | |||
2188 | // open from primary session | ||
2189 | rc = storage_open_file(session_, &handle1, fname1, 0, 0); | ||
2190 | ASSERT_EQ(0, rc); | ||
2191 | |||
2192 | rc = storage_open_file(session_, &handle2, fname2, 0, 0); | ||
2193 | ASSERT_EQ(0, rc); | ||
2194 | |||
2195 | // open from aux session | ||
2196 | rc = storage_open_file(aux_session_, &handle1_aux, fname1, 0, 0); | ||
2197 | ASSERT_EQ(0, rc); | ||
2198 | |||
2199 | rc = storage_open_file(aux_session_, &handle2_aux, fname2, 0, 0); | ||
2200 | ASSERT_EQ(0, rc); | ||
2201 | |||
2202 | // cleanup | ||
2203 | storage_close_file(handle1); | ||
2204 | storage_close_file(handle1_aux); | ||
2205 | storage_delete_file(session_, fname1, STORAGE_OP_COMPLETE); | ||
2206 | storage_close_file(handle2); | ||
2207 | storage_close_file(handle2_aux); | ||
2208 | storage_delete_file(session_, fname2, STORAGE_OP_COMPLETE); | ||
2209 | } | ||
2210 | |||
2211 | |||
2212 | TEST_P(StorageServiceTest, TransactCommitWriteMany) { | ||
2213 | int rc; | ||
2214 | file_handle_t handle1; | ||
2215 | file_handle_t handle2; | ||
2216 | file_handle_t handle1_aux; | ||
2217 | file_handle_t handle2_aux; | ||
2218 | size_t blk = 2048; | ||
2219 | size_t exp_len1 = 32 * 1024; | ||
2220 | size_t exp_len2 = 31 * 1024; | ||
2221 | storage_off_t fsize = (storage_off_t)(-1); | ||
2222 | const char *fname1 = "test_transact_commit_write_file1"; | ||
2223 | const char *fname2 = "test_transact_commit_write_file2"; | ||
2224 | |||
2225 | // open second session | ||
2226 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2227 | ASSERT_EQ(0, rc); | ||
2228 | |||
2229 | // open create truncate (with commit) | ||
2230 | rc = storage_open_file(session_, &handle1, fname1, | ||
2231 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2232 | STORAGE_OP_COMPLETE); | ||
2233 | ASSERT_EQ(0, rc); | ||
2234 | |||
2235 | // open create truncate (with commit) | ||
2236 | rc = storage_open_file(session_, &handle2, fname2, | ||
2237 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2238 | STORAGE_OP_COMPLETE); | ||
2239 | ASSERT_EQ(0, rc); | ||
2240 | |||
2241 | // open same files from aux session | ||
2242 | rc = storage_open_file(aux_session_, &handle1_aux, fname1, 0, 0); | ||
2243 | ASSERT_EQ(0, rc); | ||
2244 | |||
2245 | rc = storage_open_file(aux_session_, &handle2_aux, fname2, 0, 0); | ||
2246 | ASSERT_EQ(0, rc); | ||
2247 | |||
2248 | // file1: fill file with pattern (without commit) | ||
2249 | WritePattern(handle1, 0, exp_len1, blk, false); | ||
2250 | ASSERT_FALSE(HasFatalFailure()); | ||
2251 | |||
2252 | // file2: fill file with pattern (without commit) | ||
2253 | WritePattern(handle2, 0, exp_len2, blk, false); | ||
2254 | ASSERT_FALSE(HasFatalFailure()); | ||
2255 | |||
2256 | // check file size, it should be exp_len1 | ||
2257 | rc = storage_get_file_size(handle1, &fsize); | ||
2258 | ASSERT_EQ(0, rc); | ||
2259 | ASSERT_EQ((storage_off_t)exp_len1, fsize); | ||
2260 | |||
2261 | // check file size, it should be exp_len2 | ||
2262 | rc = storage_get_file_size(handle2, &fsize); | ||
2263 | ASSERT_EQ(0, rc); | ||
2264 | ASSERT_EQ((storage_off_t)exp_len2, fsize); | ||
2265 | |||
2266 | // check file sizes from aux session (should be 0) | ||
2267 | rc = storage_get_file_size(handle1_aux, &fsize); | ||
2268 | ASSERT_EQ(0, rc); | ||
2269 | ASSERT_EQ((storage_off_t)0, fsize); | ||
2270 | |||
2271 | rc = storage_get_file_size(handle2_aux, &fsize); | ||
2272 | ASSERT_EQ(0, rc); | ||
2273 | ASSERT_EQ((storage_off_t)0, fsize); | ||
2274 | |||
2275 | // commit transaction | ||
2276 | rc = storage_end_transaction(session_, true); | ||
2277 | ASSERT_EQ(0, rc); | ||
2278 | |||
2279 | // check file size, it should be exp_len1 | ||
2280 | rc = storage_get_file_size(handle1, &fsize); | ||
2281 | ASSERT_EQ(0, rc); | ||
2282 | ASSERT_EQ((storage_off_t)exp_len1, fsize); | ||
2283 | |||
2284 | // check file size, it should be exp_len2 | ||
2285 | rc = storage_get_file_size(handle2, &fsize); | ||
2286 | ASSERT_EQ(0, rc); | ||
2287 | ASSERT_EQ((storage_off_t)exp_len2, fsize); | ||
2288 | |||
2289 | // check from aux session (should be -EBUSY) | ||
2290 | rc = storage_get_file_size(handle1_aux, &fsize); | ||
2291 | ASSERT_EQ(-EBUSY, rc); | ||
2292 | |||
2293 | // abort transaction in aux session | ||
2294 | rc = storage_end_transaction(aux_session_, false); | ||
2295 | ASSERT_EQ(0, rc); | ||
2296 | |||
2297 | // and check again | ||
2298 | rc = storage_get_file_size(handle1_aux, &fsize); | ||
2299 | ASSERT_EQ(0, rc); | ||
2300 | ASSERT_EQ((storage_off_t)exp_len1, fsize); | ||
2301 | |||
2302 | rc = storage_get_file_size(handle2_aux, &fsize); | ||
2303 | ASSERT_EQ(0, rc); | ||
2304 | ASSERT_EQ((storage_off_t)exp_len2, fsize); | ||
2305 | |||
2306 | // check data | ||
2307 | ReadPatternEOF(handle1, 0, blk, exp_len1); | ||
2308 | ASSERT_FALSE(HasFatalFailure()); | ||
2309 | |||
2310 | ReadPatternEOF(handle2, 0, blk, exp_len2); | ||
2311 | ASSERT_FALSE(HasFatalFailure()); | ||
2312 | |||
2313 | ReadPatternEOF(handle1_aux, 0, blk, exp_len1); | ||
2314 | ASSERT_FALSE(HasFatalFailure()); | ||
2315 | |||
2316 | ReadPatternEOF(handle2_aux, 0, blk, exp_len2); | ||
2317 | ASSERT_FALSE(HasFatalFailure()); | ||
2318 | |||
2319 | // cleanup | ||
2320 | storage_close_file(handle1); | ||
2321 | storage_close_file(handle1_aux); | ||
2322 | storage_delete_file(session_, fname1, STORAGE_OP_COMPLETE); | ||
2323 | storage_close_file(handle2); | ||
2324 | storage_close_file(handle2_aux); | ||
2325 | storage_delete_file(session_, fname2, STORAGE_OP_COMPLETE); | ||
2326 | } | ||
2327 | |||
2328 | |||
2329 | TEST_P(StorageServiceTest, TransactCommitDeleteCreate) { | ||
2330 | int rc; | ||
2331 | file_handle_t handle; | ||
2332 | file_handle_t handle_aux; | ||
2333 | size_t blk = 2048; | ||
2334 | size_t exp_len = 32 * 1024; | ||
2335 | storage_off_t fsize = (storage_off_t)(-1); | ||
2336 | const char *fname = "test_transact_delete_create"; | ||
2337 | |||
2338 | // open second session | ||
2339 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2340 | ASSERT_EQ(0, rc); | ||
2341 | |||
2342 | // open create truncate file (with commit) | ||
2343 | rc = storage_open_file(session_, &handle, fname, | ||
2344 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2345 | STORAGE_OP_COMPLETE); | ||
2346 | ASSERT_EQ(0, rc); | ||
2347 | |||
2348 | // write data (with commit) | ||
2349 | WritePattern(handle, 0, exp_len, blk, true); | ||
2350 | ASSERT_FALSE(HasFatalFailure()); | ||
2351 | |||
2352 | // close it | ||
2353 | storage_close_file(handle); | ||
2354 | |||
2355 | // delete file (without commit) | ||
2356 | rc = storage_delete_file(session_, fname, 0); | ||
2357 | ASSERT_EQ(0, rc); | ||
2358 | |||
2359 | // try to open it (should fail) | ||
2360 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
2361 | ASSERT_EQ(-ENOENT, rc); | ||
2362 | |||
2363 | // try to open it in aux session (should succeed) | ||
2364 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
2365 | ASSERT_EQ(0, rc); | ||
2366 | |||
2367 | // create file with the same name (no commit) | ||
2368 | rc = storage_open_file(session_, &handle, fname, | ||
2369 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_CREATE_EXCLUSIVE, | ||
2370 | 0); | ||
2371 | ASSERT_EQ(0, rc); | ||
2372 | |||
2373 | // write half of data (with commit) | ||
2374 | WritePattern(handle, 0, exp_len/2, blk, true); | ||
2375 | ASSERT_FALSE(HasFatalFailure()); | ||
2376 | |||
2377 | // check file size (should be half) | ||
2378 | rc = storage_get_file_size(handle, &fsize); | ||
2379 | ASSERT_EQ(0, rc); | ||
2380 | ASSERT_EQ((storage_off_t)exp_len/2, fsize); | ||
2381 | |||
2382 | // commit transaction | ||
2383 | rc = storage_end_transaction(session_, true); | ||
2384 | ASSERT_EQ(0, rc); | ||
2385 | |||
2386 | // check data from primary session | ||
2387 | ReadPatternEOF(handle, 0, blk, exp_len/2); | ||
2388 | ASSERT_FALSE(HasFatalFailure()); | ||
2389 | |||
2390 | // check from aux session (should fail) | ||
2391 | rc = storage_get_file_size(handle_aux, &fsize); | ||
2392 | ASSERT_EQ(-EINVAL, rc); | ||
2393 | |||
2394 | // abort trunsaction in aux session | ||
2395 | rc = storage_end_transaction(aux_session_, false); | ||
2396 | ASSERT_EQ(0, rc); | ||
2397 | |||
2398 | // and try again (should still fail) | ||
2399 | rc = storage_get_file_size(handle_aux, &fsize); | ||
2400 | ASSERT_EQ(-EINVAL, rc); | ||
2401 | |||
2402 | // close file and reopen it again | ||
2403 | storage_close_file(handle_aux); | ||
2404 | rc = storage_open_file(aux_session_, &handle_aux, fname, 0, 0); | ||
2405 | ASSERT_EQ(0, rc); | ||
2406 | |||
2407 | // try it again (should succeed) | ||
2408 | rc = storage_get_file_size(handle_aux, &fsize); | ||
2409 | ASSERT_EQ(0, rc); | ||
2410 | ASSERT_EQ((storage_off_t)exp_len/2, fsize); | ||
2411 | |||
2412 | // check data | ||
2413 | ReadPatternEOF(handle_aux, 0, blk, exp_len/2); | ||
2414 | ASSERT_FALSE(HasFatalFailure()); | ||
2415 | |||
2416 | // cleanup | ||
2417 | storage_close_file(handle); | ||
2418 | storage_close_file(handle_aux); | ||
2419 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
2420 | } | ||
2421 | |||
2422 | TEST_P(StorageServiceTest, TransactRewriteExistingTruncate) { | ||
2423 | int rc; | ||
2424 | file_handle_t handle; | ||
2425 | size_t blk = 2048; | ||
2426 | const char *fname = "test_transact_rewrite_existing_truncate"; | ||
2427 | |||
2428 | // open create truncate file (with commit) | ||
2429 | rc = storage_open_file(session_, &handle, fname, | ||
2430 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2431 | STORAGE_OP_COMPLETE); | ||
2432 | ASSERT_EQ(0, rc); | ||
2433 | |||
2434 | // close it | ||
2435 | storage_close_file(handle); | ||
2436 | |||
2437 | // up | ||
2438 | for (uint i = 1; i < 32; i++) { | ||
2439 | // open truncate (no commit) | ||
2440 | rc = storage_open_file(session_, &handle, fname, STORAGE_FILE_OPEN_TRUNCATE, 0); | ||
2441 | ASSERT_EQ(0, rc); | ||
2442 | |||
2443 | // write data (with commit) | ||
2444 | WritePattern(handle, 0, i * blk, blk, true); | ||
2445 | ASSERT_FALSE(HasFatalFailure()); | ||
2446 | |||
2447 | // close | ||
2448 | storage_close_file(handle); | ||
2449 | } | ||
2450 | |||
2451 | // down | ||
2452 | for (uint i = 1; i < 32; i++) { | ||
2453 | // open truncate (no commit) | ||
2454 | rc = storage_open_file(session_, &handle, fname, STORAGE_FILE_OPEN_TRUNCATE, 0); | ||
2455 | ASSERT_EQ(0, rc); | ||
2456 | |||
2457 | // write data (with commit) | ||
2458 | WritePattern(handle, 0, (32 - i) * blk, blk, true); | ||
2459 | ASSERT_FALSE(HasFatalFailure()); | ||
2460 | |||
2461 | // close | ||
2462 | storage_close_file(handle); | ||
2463 | } | ||
2464 | |||
2465 | // cleanup | ||
2466 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
2467 | } | ||
2468 | |||
2469 | |||
2470 | TEST_P(StorageServiceTest, TransactRewriteExistingSetSize) { | ||
2471 | int rc; | ||
2472 | file_handle_t handle; | ||
2473 | size_t blk = 2048; | ||
2474 | const char *fname = "test_transact_rewrite_existing_set_size"; | ||
2475 | |||
2476 | // open create truncate file (with commit) | ||
2477 | rc = storage_open_file(session_, &handle, fname, | ||
2478 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2479 | STORAGE_OP_COMPLETE); | ||
2480 | ASSERT_EQ(0, rc); | ||
2481 | |||
2482 | // close it | ||
2483 | storage_close_file(handle); | ||
2484 | |||
2485 | // up | ||
2486 | for (uint i = 1; i < 32; i++) { | ||
2487 | // open truncate (no commit) | ||
2488 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
2489 | ASSERT_EQ(0, rc); | ||
2490 | |||
2491 | // write data (with commit) | ||
2492 | WritePattern(handle, 0, i * blk, blk, false); | ||
2493 | ASSERT_FALSE(HasFatalFailure()); | ||
2494 | |||
2495 | // update size (with commit) | ||
2496 | rc = storage_set_file_size(handle, i * blk, STORAGE_OP_COMPLETE); | ||
2497 | ASSERT_EQ(0, rc); | ||
2498 | |||
2499 | // close | ||
2500 | storage_close_file(handle); | ||
2501 | } | ||
2502 | |||
2503 | // down | ||
2504 | for (uint i = 1; i < 32; i++) { | ||
2505 | // open trancate (no commit) | ||
2506 | rc = storage_open_file(session_, &handle, fname, 0, 0); | ||
2507 | ASSERT_EQ(0, rc); | ||
2508 | |||
2509 | // write data (with commit) | ||
2510 | WritePattern(handle, 0, (32 - i) * blk, blk, false); | ||
2511 | ASSERT_FALSE(HasFatalFailure()); | ||
2512 | |||
2513 | // update size (with commit) | ||
2514 | rc = storage_set_file_size(handle, (32 - i) * blk, STORAGE_OP_COMPLETE); | ||
2515 | ASSERT_EQ(0, rc); | ||
2516 | |||
2517 | // close | ||
2518 | storage_close_file(handle); | ||
2519 | } | ||
2520 | |||
2521 | // cleanup | ||
2522 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
2523 | } | ||
2524 | |||
2525 | |||
2526 | TEST_P(StorageServiceTest, TransactResumeAfterNonFatalError) { | ||
2527 | |||
2528 | int rc; | ||
2529 | file_handle_t handle; | ||
2530 | file_handle_t handle1; | ||
2531 | size_t blk = 2048; | ||
2532 | size_t exp_len = 32 * 1024; | ||
2533 | storage_off_t fsize = (storage_off_t)(-1); | ||
2534 | const char *fname = "test_transact_resume_writes"; | ||
2535 | |||
2536 | // open create truncate file (with commit) | ||
2537 | rc = storage_open_file(session_, &handle, fname, | ||
2538 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2539 | STORAGE_OP_COMPLETE); | ||
2540 | ASSERT_EQ(0, rc); | ||
2541 | |||
2542 | // write (without commit) | ||
2543 | WritePattern(handle, 0, exp_len/2, blk, false); | ||
2544 | ASSERT_FALSE(HasFatalFailure()); | ||
2545 | |||
2546 | // issue some commands that should fail with non-fatal errors | ||
2547 | |||
2548 | // write past end of file | ||
2549 | uint32_t val = 0xDEDBEEF; | ||
2550 | rc = storage_write(handle, exp_len/2 + 1, &val, sizeof(val), 0); | ||
2551 | ASSERT_EQ(-EINVAL, rc); | ||
2552 | |||
2553 | // read past end of file | ||
2554 | rc = storage_read(handle, exp_len/2 + 1, &val, sizeof(val)); | ||
2555 | ASSERT_EQ(-EINVAL, rc); | ||
2556 | |||
2557 | // try to extend file past end of file | ||
2558 | rc = storage_set_file_size(handle, exp_len/2 + 1, 0); | ||
2559 | ASSERT_EQ(-EINVAL, rc); | ||
2560 | |||
2561 | // open non existing file | ||
2562 | rc = storage_open_file(session_, &handle1, "foo", | ||
2563 | STORAGE_FILE_OPEN_TRUNCATE, STORAGE_OP_COMPLETE); | ||
2564 | ASSERT_EQ(-ENOENT, rc); | ||
2565 | |||
2566 | // delete non-existing file | ||
2567 | rc = storage_delete_file(session_, "foo", STORAGE_OP_COMPLETE); | ||
2568 | ASSERT_EQ(-ENOENT, rc); | ||
2569 | |||
2570 | // then resume writinga (without commit) | ||
2571 | WritePattern(handle, exp_len/2, exp_len/2, blk, false); | ||
2572 | ASSERT_FALSE(HasFatalFailure()); | ||
2573 | |||
2574 | // commit current transaction | ||
2575 | rc = storage_end_transaction(session_, true); | ||
2576 | ASSERT_EQ(0, rc); | ||
2577 | |||
2578 | // check file size, it should be exp_len | ||
2579 | rc = storage_get_file_size(handle, &fsize); | ||
2580 | ASSERT_EQ(0, rc); | ||
2581 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
2582 | |||
2583 | // check data | ||
2584 | ReadPatternEOF(handle, 0, blk, exp_len); | ||
2585 | ASSERT_FALSE(HasFatalFailure()); | ||
2586 | |||
2587 | // cleanup | ||
2588 | storage_close_file(handle); | ||
2589 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
2590 | } | ||
2591 | |||
2592 | |||
2593 | // Transaction Collisions | ||
2594 | |||
2595 | TEST_P(StorageServiceTest, Transact2_WriteNC) { | ||
2596 | int rc; | ||
2597 | file_handle_t handle1; | ||
2598 | file_handle_t handle2; | ||
2599 | size_t blk = 2048; | ||
2600 | const char *fname1 = "test_transact_f1"; | ||
2601 | const char *fname2 = "test_transact_f2"; | ||
2602 | |||
2603 | // open second session | ||
2604 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2605 | ASSERT_EQ(0, rc); | ||
2606 | |||
2607 | rc = storage_open_file(session_, &handle1, fname1, | ||
2608 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2609 | STORAGE_OP_COMPLETE); | ||
2610 | ASSERT_EQ(0, rc); | ||
2611 | |||
2612 | rc = storage_open_file(aux_session_, &handle2, fname2, | ||
2613 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2614 | STORAGE_OP_COMPLETE); | ||
2615 | ASSERT_EQ(0, rc); | ||
2616 | |||
2617 | // session 1 | ||
2618 | WritePattern(handle1, 0, blk, blk, true); | ||
2619 | ASSERT_FALSE(HasFatalFailure()); | ||
2620 | |||
2621 | // read it back | ||
2622 | ReadPatternEOF(handle1, 0, blk, blk); | ||
2623 | ASSERT_FALSE(HasFatalFailure()); | ||
2624 | |||
2625 | // session 2 | ||
2626 | WritePattern(handle2, 0, blk, blk, true); | ||
2627 | ASSERT_FALSE(HasFatalFailure()); | ||
2628 | |||
2629 | // read it back | ||
2630 | ReadPatternEOF(handle2, 0, blk, blk); | ||
2631 | ASSERT_FALSE(HasFatalFailure()); | ||
2632 | |||
2633 | // cleanup | ||
2634 | storage_close_file(handle1); | ||
2635 | storage_close_file(handle2); | ||
2636 | |||
2637 | storage_delete_file(session_, fname1, STORAGE_OP_COMPLETE); | ||
2638 | storage_delete_file(aux_session_, fname2, STORAGE_OP_COMPLETE); | ||
2639 | } | ||
2640 | |||
2641 | |||
2642 | TEST_P(StorageServiceTest, Transact2_DeleteNC) { | ||
2643 | int rc; | ||
2644 | file_handle_t handle1; | ||
2645 | file_handle_t handle2; | ||
2646 | size_t blk = 2048; | ||
2647 | const char *fname1 = "test_transact_delete_f1"; | ||
2648 | const char *fname2 = "test_transact_delete_f2"; | ||
2649 | |||
2650 | // open second session | ||
2651 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2652 | ASSERT_EQ(0, rc); | ||
2653 | |||
2654 | rc = storage_open_file(session_, &handle1, fname1, | ||
2655 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2656 | STORAGE_OP_COMPLETE); | ||
2657 | ASSERT_EQ(0, rc); | ||
2658 | |||
2659 | rc = storage_open_file(aux_session_, &handle2, fname2, | ||
2660 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2661 | STORAGE_OP_COMPLETE); | ||
2662 | ASSERT_EQ(0, rc); | ||
2663 | |||
2664 | // session 1 | ||
2665 | WritePattern(handle1, 0, blk, blk, true); | ||
2666 | ASSERT_FALSE(HasFatalFailure()); | ||
2667 | |||
2668 | // read it back | ||
2669 | ReadPatternEOF(handle1, 0, blk, blk); | ||
2670 | ASSERT_FALSE(HasFatalFailure()); | ||
2671 | |||
2672 | // session 2 | ||
2673 | WritePattern(handle2, 0, blk, blk, true); | ||
2674 | ASSERT_FALSE(HasFatalFailure()); | ||
2675 | |||
2676 | // read it back | ||
2677 | ReadPatternEOF(handle2, 0, blk, blk); | ||
2678 | ASSERT_FALSE(HasFatalFailure()); | ||
2679 | |||
2680 | // close files and delete them | ||
2681 | storage_close_file(handle1); | ||
2682 | storage_delete_file(session_, fname1, 0); | ||
2683 | |||
2684 | storage_close_file(handle2); | ||
2685 | storage_delete_file(aux_session_, fname2, 0); | ||
2686 | |||
2687 | // commit | ||
2688 | rc = storage_end_transaction(session_, true); | ||
2689 | ASSERT_EQ(0, rc); | ||
2690 | |||
2691 | rc = storage_end_transaction(aux_session_, true); | ||
2692 | ASSERT_EQ(0, rc); | ||
2693 | } | ||
2694 | |||
2695 | |||
2696 | TEST_P(StorageServiceTest, Transact2_Write_Read) { | ||
2697 | int rc; | ||
2698 | file_handle_t handle1; | ||
2699 | file_handle_t handle2; | ||
2700 | size_t blk = 2048; | ||
2701 | size_t exp_len = 32 * 1024; | ||
2702 | storage_off_t fsize = (storage_off_t)(-1); | ||
2703 | const char *fname = "test_transact_writeRead"; | ||
2704 | |||
2705 | // open second session | ||
2706 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2707 | ASSERT_EQ(0, rc); | ||
2708 | |||
2709 | // S1: open create truncate file | ||
2710 | rc = storage_open_file(session_, &handle1, fname, | ||
2711 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2712 | STORAGE_OP_COMPLETE); | ||
2713 | ASSERT_EQ(0, rc); | ||
2714 | |||
2715 | // S2: open the same file | ||
2716 | rc = storage_open_file(aux_session_, &handle2, fname, | ||
2717 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2718 | STORAGE_OP_COMPLETE); | ||
2719 | ASSERT_EQ(0, rc); | ||
2720 | |||
2721 | // S1: write (no commit) | ||
2722 | WritePattern(handle1, 0, exp_len, blk, false); | ||
2723 | ASSERT_FALSE(HasFatalFailure()); | ||
2724 | |||
2725 | // S1: read it back | ||
2726 | ReadPatternEOF(handle1, 0, blk, exp_len); | ||
2727 | ASSERT_FALSE(HasFatalFailure()); | ||
2728 | |||
2729 | // S2: check file size, it should be 0 | ||
2730 | rc = storage_get_file_size(handle2, &fsize); | ||
2731 | ASSERT_EQ(0, rc); | ||
2732 | ASSERT_EQ((storage_off_t)0, fsize); | ||
2733 | |||
2734 | // S2: read it back (should no data) | ||
2735 | ReadPatternEOF(handle2, 0, blk, 0); | ||
2736 | ASSERT_FALSE(HasFatalFailure()); | ||
2737 | |||
2738 | // S1: commit | ||
2739 | rc = storage_end_transaction(session_, true); | ||
2740 | ASSERT_EQ(0, rc); | ||
2741 | |||
2742 | // S2: check file size, it should fail | ||
2743 | rc = storage_get_file_size(handle2, &fsize); | ||
2744 | ASSERT_EQ(-EBUSY, rc); | ||
2745 | |||
2746 | // S2: abort transaction | ||
2747 | rc = storage_end_transaction(aux_session_, false); | ||
2748 | ASSERT_EQ(0, rc); | ||
2749 | |||
2750 | // S2: check file size again, it should be exp_len | ||
2751 | rc = storage_get_file_size(handle2, &fsize); | ||
2752 | ASSERT_EQ(0, rc); | ||
2753 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
2754 | |||
2755 | // S2: read it again (should be exp_len) | ||
2756 | ReadPatternEOF(handle2, 0, blk, exp_len); | ||
2757 | ASSERT_FALSE(HasFatalFailure()); | ||
2758 | |||
2759 | // cleanup | ||
2760 | storage_close_file(handle1); | ||
2761 | storage_close_file(handle2); | ||
2762 | |||
2763 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
2764 | } | ||
2765 | |||
2766 | |||
2767 | TEST_P(StorageServiceTest, Transact2_Write_Write_Commit_Commit) { | ||
2768 | int rc; | ||
2769 | file_handle_t handle1; | ||
2770 | file_handle_t handle2; | ||
2771 | file_handle_t handle3; | ||
2772 | size_t blk = 2048; | ||
2773 | size_t exp_len = 32 * 1024; | ||
2774 | storage_off_t fsize = (storage_off_t)(-1); | ||
2775 | const char *fname = "test_transact_write_write_commit_commit"; | ||
2776 | |||
2777 | // open second session | ||
2778 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2779 | ASSERT_EQ(0, rc); | ||
2780 | |||
2781 | // S1: open create truncate file | ||
2782 | rc = storage_open_file(session_, &handle1, fname, | ||
2783 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2784 | STORAGE_OP_COMPLETE); | ||
2785 | ASSERT_EQ(0, rc); | ||
2786 | |||
2787 | // S2: open the same file | ||
2788 | rc = storage_open_file(aux_session_, &handle2, fname, | ||
2789 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2790 | STORAGE_OP_COMPLETE); | ||
2791 | ASSERT_EQ(0, rc); | ||
2792 | |||
2793 | // S1: write (no commit) | ||
2794 | WritePattern(handle1, 0, exp_len, blk, false); | ||
2795 | ASSERT_FALSE(HasFatalFailure()); | ||
2796 | |||
2797 | // S2: write (no commit) | ||
2798 | WritePattern(handle2, 0, exp_len/2, blk, false); | ||
2799 | ASSERT_FALSE(HasFatalFailure()); | ||
2800 | |||
2801 | // S1: commit | ||
2802 | rc = storage_end_transaction(session_, true); | ||
2803 | ASSERT_EQ(0, rc); | ||
2804 | |||
2805 | // S2: read/write/get/set size/delete (all should fail) | ||
2806 | uint32_t val = 0; | ||
2807 | rc = storage_read(handle2, 0, &val, sizeof(val)); | ||
2808 | ASSERT_EQ(-EBUSY, rc); | ||
2809 | |||
2810 | rc = storage_write(handle2, 0, &val, sizeof(val), 0); | ||
2811 | ASSERT_EQ(-EBUSY, rc); | ||
2812 | |||
2813 | rc = storage_get_file_size(handle2, &fsize); | ||
2814 | ASSERT_EQ(-EBUSY, rc); | ||
2815 | |||
2816 | rc = storage_set_file_size(handle2, fsize, 0); | ||
2817 | ASSERT_EQ(-EBUSY, rc); | ||
2818 | |||
2819 | rc = storage_delete_file(aux_session_, fname, 0); | ||
2820 | ASSERT_EQ(-EBUSY, rc); | ||
2821 | |||
2822 | rc = storage_open_file(aux_session_, &handle3, fname, | ||
2823 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, 0); | ||
2824 | ASSERT_EQ(-EBUSY, rc); | ||
2825 | |||
2826 | // S2: commit (should fail, and failed state should be cleared) | ||
2827 | rc = storage_end_transaction(aux_session_, true); | ||
2828 | ASSERT_EQ(-EBUSY, rc); | ||
2829 | |||
2830 | // S2: check file size, it should be exp_len | ||
2831 | rc = storage_get_file_size(handle2, &fsize); | ||
2832 | ASSERT_EQ(0, rc); | ||
2833 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
2834 | |||
2835 | // S2: read it again (should be exp_len) | ||
2836 | ReadPatternEOF(handle2, 0, blk, exp_len); | ||
2837 | ASSERT_FALSE(HasFatalFailure()); | ||
2838 | |||
2839 | // cleanup | ||
2840 | storage_close_file(handle1); | ||
2841 | storage_close_file(handle2); | ||
2842 | |||
2843 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
2844 | } | ||
2845 | |||
2846 | |||
2847 | TEST_P(StorageServiceTest, Transact2_Write_Write_Commit_Discard) { | ||
2848 | int rc; | ||
2849 | file_handle_t handle1; | ||
2850 | file_handle_t handle2; | ||
2851 | file_handle_t handle3; | ||
2852 | size_t blk = 2048; | ||
2853 | size_t exp_len = 32 * 1024; | ||
2854 | storage_off_t fsize = (storage_off_t)(-1); | ||
2855 | const char *fname = "test_transact_write_write_commit_discard"; | ||
2856 | |||
2857 | // open second session | ||
2858 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2859 | ASSERT_EQ(0, rc); | ||
2860 | |||
2861 | // S1: open create truncate file | ||
2862 | rc = storage_open_file(session_, &handle1, fname, | ||
2863 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2864 | STORAGE_OP_COMPLETE); | ||
2865 | ASSERT_EQ(0, rc); | ||
2866 | |||
2867 | // S2: open the same file | ||
2868 | rc = storage_open_file(aux_session_, &handle2, fname, | ||
2869 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2870 | STORAGE_OP_COMPLETE); | ||
2871 | ASSERT_EQ(0, rc); | ||
2872 | |||
2873 | // S1: write (no commit) | ||
2874 | WritePattern(handle1, 0, exp_len, blk, false); | ||
2875 | ASSERT_FALSE(HasFatalFailure()); | ||
2876 | |||
2877 | // S2: write (no commit) | ||
2878 | WritePattern(handle2, 0, exp_len/2, blk, false); | ||
2879 | ASSERT_FALSE(HasFatalFailure()); | ||
2880 | |||
2881 | // S1: commit | ||
2882 | rc = storage_end_transaction(session_, true); | ||
2883 | ASSERT_EQ(0, rc); | ||
2884 | |||
2885 | // S2: read/write/get/set size/delete (all should fail) | ||
2886 | uint32_t val = 0; | ||
2887 | rc = storage_read(handle2, 0, &val, sizeof(val)); | ||
2888 | ASSERT_EQ(-EBUSY, rc); | ||
2889 | |||
2890 | rc = storage_write(handle2, 0, &val, sizeof(val), 0); | ||
2891 | ASSERT_EQ(-EBUSY, rc); | ||
2892 | |||
2893 | rc = storage_get_file_size(handle2, &fsize); | ||
2894 | ASSERT_EQ(-EBUSY, rc); | ||
2895 | |||
2896 | rc = storage_set_file_size(handle2, fsize, 0); | ||
2897 | ASSERT_EQ(-EBUSY, rc); | ||
2898 | |||
2899 | rc = storage_delete_file(aux_session_, fname, 0); | ||
2900 | ASSERT_EQ(-EBUSY, rc); | ||
2901 | |||
2902 | rc = storage_open_file(aux_session_, &handle3, fname, | ||
2903 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, 0); | ||
2904 | ASSERT_EQ(-EBUSY, rc); | ||
2905 | |||
2906 | // S2: discard (should fail, and failed state should be cleared) | ||
2907 | rc = storage_end_transaction(aux_session_, false); | ||
2908 | ASSERT_EQ(0, rc); | ||
2909 | |||
2910 | // S2: check file size, it should be exp_len | ||
2911 | rc = storage_get_file_size(handle2, &fsize); | ||
2912 | ASSERT_EQ(0, rc); | ||
2913 | ASSERT_EQ((storage_off_t)exp_len, fsize); | ||
2914 | |||
2915 | // S2: read it again (should be exp_len) | ||
2916 | ReadPatternEOF(handle2, 0, blk, exp_len); | ||
2917 | ASSERT_FALSE(HasFatalFailure()); | ||
2918 | |||
2919 | // cleanup | ||
2920 | storage_close_file(handle1); | ||
2921 | storage_close_file(handle2); | ||
2922 | |||
2923 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
2924 | } | ||
2925 | |||
2926 | TEST_P(StorageServiceTest, Transact2_Write_Write_Discard_Commit) { | ||
2927 | int rc; | ||
2928 | file_handle_t handle1; | ||
2929 | file_handle_t handle2; | ||
2930 | size_t blk = 2048; | ||
2931 | size_t exp_len = 32 * 1024; | ||
2932 | storage_off_t fsize = (storage_off_t)(-1); | ||
2933 | const char *fname = "test_transact_write_write_discard_commit"; | ||
2934 | |||
2935 | // open second session | ||
2936 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2937 | ASSERT_EQ(0, rc); | ||
2938 | |||
2939 | // S1: open create truncate file | ||
2940 | rc = storage_open_file(session_, &handle1, fname, | ||
2941 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2942 | STORAGE_OP_COMPLETE); | ||
2943 | ASSERT_EQ(0, rc); | ||
2944 | |||
2945 | // S2: open the same file | ||
2946 | rc = storage_open_file(aux_session_, &handle2, fname, | ||
2947 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
2948 | STORAGE_OP_COMPLETE); | ||
2949 | ASSERT_EQ(0, rc); | ||
2950 | |||
2951 | // S1: write (no commit) | ||
2952 | WritePattern(handle1, 0, exp_len, blk, false); | ||
2953 | ASSERT_FALSE(HasFatalFailure()); | ||
2954 | |||
2955 | // S2: write (no commit) | ||
2956 | WritePattern(handle2, 0, exp_len/2, blk, false); | ||
2957 | ASSERT_FALSE(HasFatalFailure()); | ||
2958 | |||
2959 | // S1: discard | ||
2960 | rc = storage_end_transaction(session_, false); | ||
2961 | ASSERT_EQ(0, rc); | ||
2962 | |||
2963 | // S2: commit (should succeed) | ||
2964 | rc = storage_end_transaction(aux_session_, true); | ||
2965 | ASSERT_EQ(0, rc); | ||
2966 | |||
2967 | // S2: check file size, it should be exp_len | ||
2968 | rc = storage_get_file_size(handle2, &fsize); | ||
2969 | ASSERT_EQ(0, rc); | ||
2970 | ASSERT_EQ((storage_off_t)exp_len/2, fsize); | ||
2971 | |||
2972 | // S2: read it again (should be exp_len) | ||
2973 | ReadPatternEOF(handle2, 0, blk, exp_len/2); | ||
2974 | ASSERT_FALSE(HasFatalFailure()); | ||
2975 | |||
2976 | // cleanup | ||
2977 | storage_close_file(handle1); | ||
2978 | storage_close_file(handle2); | ||
2979 | |||
2980 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
2981 | } | ||
2982 | |||
2983 | |||
2984 | TEST_P(StorageServiceTest, Transact2_Write_Write_Discard_Discard) { | ||
2985 | int rc; | ||
2986 | file_handle_t handle1; | ||
2987 | file_handle_t handle2; | ||
2988 | size_t blk = 2048; | ||
2989 | size_t exp_len = 32 * 1024; | ||
2990 | storage_off_t fsize = (storage_off_t)(-1); | ||
2991 | const char *fname = "test_transact_write_write_discard_Discard"; | ||
2992 | |||
2993 | // open second session | ||
2994 | rc = storage_open_session(TRUSTY_DEVICE_NAME, &aux_session_, port_); | ||
2995 | ASSERT_EQ(0, rc); | ||
2996 | |||
2997 | // S1: open create truncate file | ||
2998 | rc = storage_open_file(session_, &handle1, fname, | ||
2999 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
3000 | STORAGE_OP_COMPLETE); | ||
3001 | ASSERT_EQ(0, rc); | ||
3002 | |||
3003 | // S2: open the same file | ||
3004 | rc = storage_open_file(aux_session_, &handle2, fname, | ||
3005 | STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, | ||
3006 | STORAGE_OP_COMPLETE); | ||
3007 | ASSERT_EQ(0, rc); | ||
3008 | |||
3009 | // S1: write (no commit) | ||
3010 | WritePattern(handle1, 0, exp_len, blk, false); | ||
3011 | ASSERT_FALSE(HasFatalFailure()); | ||
3012 | |||
3013 | // S2: write (no commit) | ||
3014 | WritePattern(handle2, 0, exp_len/2, blk, false); | ||
3015 | ASSERT_FALSE(HasFatalFailure()); | ||
3016 | |||
3017 | // S1: discard | ||
3018 | rc = storage_end_transaction(session_, false); | ||
3019 | ASSERT_EQ(0, rc); | ||
3020 | |||
3021 | // S2: discard | ||
3022 | rc = storage_end_transaction(aux_session_, false); | ||
3023 | ASSERT_EQ(0, rc); | ||
3024 | |||
3025 | // S2: check file size, it should be 0 | ||
3026 | rc = storage_get_file_size(handle2, &fsize); | ||
3027 | ASSERT_EQ(0, rc); | ||
3028 | ASSERT_EQ((storage_off_t)0, fsize); | ||
3029 | |||
3030 | // S2: read it again (should be 0) | ||
3031 | ReadPatternEOF(handle2, 0, blk, 0); | ||
3032 | ASSERT_FALSE(HasFatalFailure()); | ||
3033 | |||
3034 | // cleanup | ||
3035 | storage_close_file(handle1); | ||
3036 | storage_close_file(handle2); | ||
3037 | |||
3038 | storage_delete_file(session_, fname, STORAGE_OP_COMPLETE); | ||
3039 | } | ||
3040 | |||