1 /*
2  * Copyright (C) 2018 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 <gtest/gtest.h>
18 
19 #include <memory>
20 #include "types.h"
21 
create_block(const std::string & string)22 static std::unique_ptr<IOVector::block_type> create_block(const std::string& string) {
23     return std::make_unique<IOVector::block_type>(string.begin(), string.end());
24 }
25 
create_block(char value,size_t len)26 static std::unique_ptr<IOVector::block_type> create_block(char value, size_t len) {
27     auto block = std::make_unique<IOVector::block_type>();
28     block->resize(len);
29     memset(&(*block)[0], value, len);
30     return block;
31 }
32 
33 template <typename T>
copy_block(T && block)34 static std::unique_ptr<IOVector::block_type> copy_block(T&& block) {
35     auto copy = std::make_unique<IOVector::block_type>();
36     copy->assign(block->begin(), block->end());
37     return copy;
38 }
39 
TEST(IOVector,empty)40 TEST(IOVector, empty) {
41     // Empty IOVector.
42     IOVector bc;
43     CHECK_EQ(0ULL, bc.coalesce().size());
44 }
45 
TEST(IOVector,single_block)46 TEST(IOVector, single_block) {
47     // A single block.
48     auto block = create_block('x', 100);
49     IOVector bc;
50     bc.append(copy_block(block));
51     ASSERT_EQ(100ULL, bc.size());
52     auto coalesced = bc.coalesce();
53     ASSERT_EQ(*block, coalesced);
54 }
55 
TEST(IOVector,single_block_split)56 TEST(IOVector, single_block_split) {
57     // One block split.
58     IOVector bc;
59     bc.append(create_block("foobar"));
60     IOVector foo = bc.take_front(3);
61     ASSERT_EQ(3ULL, foo.size());
62     ASSERT_EQ(3ULL, bc.size());
63     ASSERT_EQ(*create_block("foo"), foo.coalesce());
64     ASSERT_EQ(*create_block("bar"), bc.coalesce());
65 }
66 
TEST(IOVector,aligned_split)67 TEST(IOVector, aligned_split) {
68     IOVector bc;
69     bc.append(create_block("foo"));
70     bc.append(create_block("bar"));
71     bc.append(create_block("baz"));
72     ASSERT_EQ(9ULL, bc.size());
73 
74     IOVector foo = bc.take_front(3);
75     ASSERT_EQ(3ULL, foo.size());
76     ASSERT_EQ(*create_block("foo"), foo.coalesce());
77 
78     IOVector bar = bc.take_front(3);
79     ASSERT_EQ(3ULL, bar.size());
80     ASSERT_EQ(*create_block("bar"), bar.coalesce());
81 
82     IOVector baz = bc.take_front(3);
83     ASSERT_EQ(3ULL, baz.size());
84     ASSERT_EQ(*create_block("baz"), baz.coalesce());
85 
86     ASSERT_EQ(0ULL, bc.size());
87 }
88 
TEST(IOVector,misaligned_split)89 TEST(IOVector, misaligned_split) {
90     IOVector bc;
91     bc.append(create_block("foo"));
92     bc.append(create_block("bar"));
93     bc.append(create_block("baz"));
94     bc.append(create_block("qux"));
95     bc.append(create_block("quux"));
96 
97     // Aligned left, misaligned right, across multiple blocks.
98     IOVector foob = bc.take_front(4);
99     ASSERT_EQ(4ULL, foob.size());
100     ASSERT_EQ(*create_block("foob"), foob.coalesce());
101 
102     // Misaligned left, misaligned right, in one block.
103     IOVector a = bc.take_front(1);
104     ASSERT_EQ(1ULL, a.size());
105     ASSERT_EQ(*create_block("a"), a.coalesce());
106 
107     // Misaligned left, misaligned right, across two blocks.
108     IOVector rba = bc.take_front(3);
109     ASSERT_EQ(3ULL, rba.size());
110     ASSERT_EQ(*create_block("rba"), rba.coalesce());
111 
112     // Misaligned left, misaligned right, across three blocks.
113     IOVector zquxquu = bc.take_front(7);
114     ASSERT_EQ(7ULL, zquxquu.size());
115     ASSERT_EQ(*create_block("zquxquu"), zquxquu.coalesce());
116 
117     ASSERT_EQ(1ULL, bc.size());
118     ASSERT_EQ(*create_block("x"), bc.coalesce());
119 }
120