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