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