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