1
2 /**
3 * Copyright (C) 2018-present MongoDB, Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the Server Side Public License, version 1,
7 * as published by MongoDB, Inc.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * Server Side Public License for more details.
13 *
14 * You should have received a copy of the Server Side Public License
15 * along with this program. If not, see
16 * <http://www.mongodb.com/licensing/server-side-public-license>.
17 *
18 * As a special exception, the copyright holders give permission to link the
19 * code of portions of this program with the OpenSSL library under certain
20 * conditions as described in each individual source file and distribute
21 * linked combinations including the program with the OpenSSL library. You
22 * must comply with the Server Side Public License in all respects for
23 * all of the code used other than as permitted herein. If you modify file(s)
24 * with this exception, you may extend this exception to your version of the
25 * file(s), but you are not obligated to do so. If you do not wish to do so,
26 * delete this exception statement from your version. If you delete this
27 * exception statement from all source files in the program, then also delete
28 * it in the license file.
29 */
30
31 #include "mongo/base/data_builder.h"
32 #include "mongo/base/data_type_terminated.h"
33
34 #include "mongo/platform/endian.h"
35 #include "mongo/unittest/unittest.h"
36
37 namespace mongo {
38
39 namespace {
40 /**
41 * Helper type for writeAndAdvance in tests
42 */
43 template <std::size_t bytes>
44 struct NByteStruct {
45 NByteStruct() = default;
46 char buf[bytes] = {};
47 };
48
49 } // namespace
50
TEST(DataBuilder,Basic)51 TEST(DataBuilder, Basic) {
52 DataBuilder db(1);
53
54 ASSERT_EQUALS(true, db.writeAndAdvance<uint16_t>(1).isOK());
55 ASSERT_EQUALS(true, db.writeAndAdvance<LittleEndian<uint32_t>>(2).isOK());
56 ASSERT_EQUALS(true, db.writeAndAdvance<BigEndian<uint64_t>>(3).isOK());
57
58 ASSERT_EQUALS(18u, db.capacity());
59 ASSERT_EQUALS(14u, db.size());
60
61 db.resize(14u);
62 ASSERT_EQUALS(14u, db.capacity());
63 ASSERT_EQUALS(14u, db.size());
64
65 db.reserve(2u);
66 ASSERT_EQUALS(21u, db.capacity());
67 ASSERT_EQUALS(14u, db.size());
68
69 ConstDataRangeCursor cdrc = db.getCursor();
70
71 ASSERT_EQUALS(static_cast<uint16_t>(1), cdrc.readAndAdvance<uint16_t>().getValue());
72 ASSERT_EQUALS(static_cast<uint32_t>(2),
73 cdrc.readAndAdvance<LittleEndian<uint32_t>>().getValue());
74 ASSERT_EQUALS(static_cast<uint64_t>(3), cdrc.readAndAdvance<BigEndian<uint64_t>>().getValue());
75 ASSERT_EQUALS(false, cdrc.readAndAdvance<char>().isOK());
76 }
77
TEST(DataBuilder,ResizeDown)78 TEST(DataBuilder, ResizeDown) {
79 DataBuilder db(1);
80
81 ASSERT_EQUALS(true, db.writeAndAdvance<uint16_t>(1).isOK());
82 ASSERT_EQUALS(true, db.writeAndAdvance<uint64_t>(2).isOK());
83
84 db.resize(2u);
85 ASSERT_EQUALS(2u, db.capacity());
86 ASSERT_EQUALS(2u, db.size());
87
88 ConstDataRangeCursor cdrc = db.getCursor();
89
90 ASSERT_EQUALS(static_cast<uint16_t>(1), cdrc.readAndAdvance<uint16_t>().getValue());
91 ASSERT_EQUALS(false, cdrc.readAndAdvance<char>().isOK());
92 }
93
TEST(DataBuilder,ResizeUp)94 TEST(DataBuilder, ResizeUp) {
95 DataBuilder db(1);
96
97 ASSERT_EQUALS(true, db.writeAndAdvance<uint16_t>(1).isOK());
98 ASSERT_EQUALS(true, db.writeAndAdvance<uint64_t>(2).isOK());
99
100 db.resize(64u);
101 ASSERT_EQUALS(64u, db.capacity());
102 ASSERT_EQUALS(10u, db.size());
103
104 ConstDataRangeCursor cdrc = db.getCursor();
105
106 ASSERT_EQUALS(static_cast<uint16_t>(1), cdrc.readAndAdvance<uint16_t>().getValue());
107 ASSERT_EQUALS(static_cast<uint64_t>(2), cdrc.readAndAdvance<uint64_t>().getValue());
108 ASSERT_EQUALS(false, cdrc.readAndAdvance<char>().isOK());
109 }
110
TEST(DataBuilder,Reserve)111 TEST(DataBuilder, Reserve) {
112 DataBuilder db;
113
114 ASSERT_EQUALS(0u, db.capacity());
115 ASSERT_EQUALS(0u, db.size());
116
117 // first step up is to 64
118 db.reserve(10);
119 ASSERT_EQUALS(64u, db.capacity());
120 ASSERT_EQUALS(0u, db.size());
121
122 // reserving less than we have doesn't change anything
123 db.reserve(1);
124 ASSERT_EQUALS(64u, db.capacity());
125 ASSERT_EQUALS(0u, db.size());
126
127 // next actual step up goes up by x1.5
128 db.reserve(65);
129 ASSERT_EQUALS(96u, db.capacity());
130 ASSERT_EQUALS(0u, db.size());
131
132 ASSERT_EQUALS(true, db.writeAndAdvance(NByteStruct<90>()).isOK());
133 ASSERT_EQUALS(96u, db.capacity());
134 ASSERT_EQUALS(90u, db.size());
135
136 // partially satisfiable reserve works
137 db.reserve(7);
138 ASSERT_EQUALS(144u, db.capacity());
139 ASSERT_EQUALS(90u, db.size());
140 }
141
TEST(DataBuilder,Clear)142 TEST(DataBuilder, Clear) {
143 DataBuilder db(1);
144
145 ASSERT_EQUALS(true, db.writeAndAdvance<uint16_t>(1).isOK());
146
147 db.clear();
148 ASSERT_EQUALS(2u, db.capacity());
149 ASSERT_EQUALS(0u, db.size());
150
151 ConstDataRangeCursor cdrc = db.getCursor();
152 ASSERT_EQUALS(false, cdrc.readAndAdvance<char>().isOK());
153 }
154
TEST(DataBuilder,Move)155 TEST(DataBuilder, Move) {
156 DataBuilder db(1);
157
158 ASSERT_EQUALS(true, db.writeAndAdvance<uint16_t>(1).isOK());
159
160 auto db2 = DataBuilder(std::move(db));
161
162 ConstDataRangeCursor cdrc = db2.getCursor();
163
164 ASSERT_EQUALS(static_cast<uint16_t>(1), cdrc.readAndAdvance<uint16_t>().getValue());
165 ASSERT_EQUALS(2u, db2.capacity());
166 ASSERT_EQUALS(2u, db2.size());
167
168 ASSERT_EQUALS(0u, db.capacity());
169 ASSERT_EQUALS(0u, db.size());
170 ASSERT(!db.getCursor().data());
171 }
172
TEST(DataBuilder,TerminatedStringDatas)173 TEST(DataBuilder, TerminatedStringDatas) {
174 DataBuilder db{10};
175 StringData sample{"abcdefgh"};
176
177 auto status2 = db.writeAndAdvance<Terminated<'\0', StringData>>(sample);
178 ASSERT_EQUALS(true, status2.isOK());
179
180 auto status3 = db.writeAndAdvance<Terminated<'\0', StringData>>(sample);
181 ASSERT_EQUALS(true, status3.isOK());
182 }
183
184 } // namespace mongo
185