1 /** @file 2 3 Catch based unit tests for IOBuffer 4 5 @section license License 6 7 Licensed to the Apache Software Foundation (ASF) under one 8 or more contributor license agreements. See the NOTICE file 9 distributed with this work for additional information 10 regarding copyright ownership. The ASF licenses this file 11 to you under the Apache License, Version 2.0 (the 12 "License"); you may not use this file except in compliance 13 with the License. You may obtain a copy of the License at 14 15 http://www.apache.org/licenses/LICENSE-2.0 16 17 Unless required by applicable law or agreed to in writing, software 18 distributed under the License is distributed on an "AS IS" BASIS, 19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 See the License for the specific language governing permissions and 21 limitations under the License. 22 */ 23 24 #define CATCH_CONFIG_MAIN 25 #include "catch.hpp" 26 27 #include "tscore/I_Layout.h" 28 29 #include "I_EventSystem.h" 30 #include "RecordsConfig.h" 31 #if defined(darwin) 32 #include "P_IOBuffer.h" 33 #endif 34 35 #include "diags.i" 36 37 #define TEST_THREADS 1 38 39 TEST_CASE("MIOBuffer", "[iocore]") 40 { 41 SECTION("new_MIOBuffer 100 times") 42 { 43 int64_t read_avail_len1 = 0; 44 int64_t read_avail_len2 = 0; 45 46 for (unsigned i = 0; i < 100; ++i) { 47 MIOBuffer *b1 = new_MIOBuffer(BUFFER_SIZE_INDEX_512); 48 int64_t len1 = b1->write_avail(); 49 IOBufferReader *b1reader = b1->alloc_reader(); 50 b1->fill(len1); 51 read_avail_len1 += b1reader->read_avail(); 52 53 MIOBuffer *b2 = new_MIOBuffer(BUFFER_SIZE_INDEX_4K); 54 int64_t len2 = b2->write_avail(); 55 IOBufferReader *b2reader = b2->alloc_reader(); 56 b2->fill(len2); 57 read_avail_len2 += b2reader->read_avail(); 58 59 free_MIOBuffer(b2); 60 free_MIOBuffer(b1); 61 } 62 63 CHECK(read_avail_len1 == 100 * BUFFER_SIZE_FOR_INDEX(BUFFER_SIZE_INDEX_512)); 64 CHECK(read_avail_len2 == 100 * BUFFER_SIZE_FOR_INDEX(BUFFER_SIZE_INDEX_4K)); 65 } 66 67 SECTION("write") 68 { 69 MIOBuffer *miob = new_MIOBuffer(BUFFER_SIZE_INDEX_4K); 70 IOBufferReader *miob_r = miob->alloc_reader(); 71 const IOBufferBlock *block = miob->first_write_block(); 72 73 SECTION("initial state") 74 { 75 CHECK(miob->size_index == BUFFER_SIZE_INDEX_4K); 76 CHECK(miob->water_mark == 0); 77 CHECK(miob->first_write_block() != nullptr); 78 CHECK(miob->block_size() == 4096); 79 CHECK(miob->block_write_avail() == 4096); 80 CHECK(miob->current_write_avail() == 4096); 81 CHECK(miob->write_avail() == 4096); 82 83 CHECK(miob->max_read_avail() == 0); 84 CHECK(miob_r->read_avail() == 0); 85 } 86 87 SECTION("write(const void *rbuf, int64_t nbytes)") 88 { 89 SECTION("1K") 90 { 91 uint8_t buf[1024]; 92 memset(buf, 0xAA, sizeof(buf)); 93 94 int64_t written = miob->write(buf, sizeof(buf)); 95 96 REQUIRE(written == sizeof(buf)); 97 98 CHECK(miob->block_size() == 4096); 99 CHECK(miob->block_write_avail() == 3072); 100 CHECK(miob->current_write_avail() == 3072); 101 CHECK(miob->write_avail() == 3072); 102 103 CHECK(miob->first_write_block() == block); 104 105 CHECK(miob->max_read_avail() == sizeof(buf)); 106 CHECK(miob_r->read_avail() == sizeof(buf)); 107 } 108 109 SECTION("4K") 110 { 111 uint8_t buf[4096]; 112 memset(buf, 0xAA, sizeof(buf)); 113 114 int64_t written = miob->write(buf, sizeof(buf)); 115 116 REQUIRE(written == sizeof(buf)); 117 118 CHECK(miob->block_size() == 4096); 119 CHECK(miob->block_write_avail() == 0); 120 CHECK(miob->current_write_avail() == 0); 121 CHECK(miob->write_avail() == 0); 122 123 CHECK(miob->first_write_block() == block); 124 125 CHECK(miob->max_read_avail() == sizeof(buf)); 126 CHECK(miob_r->read_avail() == sizeof(buf)); 127 } 128 129 SECTION("5K") 130 { 131 uint8_t buf[5120]; 132 memset(buf, 0xAA, sizeof(buf)); 133 134 int64_t written = miob->write(buf, sizeof(buf)); 135 136 REQUIRE(written == sizeof(buf)); 137 138 CHECK(miob->block_size() == 4096); 139 CHECK(miob->block_write_avail() == 3072); 140 CHECK(miob->current_write_avail() == 3072); 141 CHECK(miob->write_avail() == 3072); 142 143 CHECK(miob->first_write_block() != block); 144 145 CHECK(miob->max_read_avail() == sizeof(buf)); 146 CHECK(miob_r->read_avail() == sizeof(buf)); 147 } 148 149 SECTION("8K") 150 { 151 uint8_t buf[8192]; 152 memset(buf, 0xAA, sizeof(buf)); 153 154 int64_t written = miob->write(buf, sizeof(buf)); 155 156 REQUIRE(written == sizeof(buf)); 157 158 CHECK(miob->block_size() == 4096); 159 CHECK(miob->block_write_avail() == 0); 160 CHECK(miob->current_write_avail() == 0); 161 CHECK(miob->write_avail() == 0); 162 163 CHECK(miob->first_write_block() != block); 164 165 CHECK(miob->max_read_avail() == sizeof(buf)); 166 CHECK(miob_r->read_avail() == sizeof(buf)); 167 } 168 } 169 170 free_MIOBuffer(miob); 171 } 172 173 SECTION("write_avail") 174 { 175 MIOBuffer *miob = new_MIOBuffer(BUFFER_SIZE_INDEX_4K); 176 IOBufferReader *miob_r = miob->alloc_reader(); 177 uint8_t buf[8192]; 178 memset(buf, 0xAA, sizeof(buf)); 179 180 // initial state 181 CHECK(miob->block_size() == 4096); 182 CHECK(miob->current_write_avail() == 4096); 183 CHECK(miob->write_avail() == 4096); 184 185 SECTION("water_mark == 0 (default)") 186 { 187 REQUIRE(miob->water_mark == 0); 188 189 // fill half of the current buffer 190 miob->write(buf, 2048); 191 CHECK(miob->max_read_avail() == 2048); 192 CHECK(miob->current_write_avail() == 2048); 193 CHECK(miob->high_water() == true); 194 CHECK(miob->current_low_water() == false); 195 CHECK(miob->write_avail() == 2048); ///< should have no side effect 196 197 // fill all of the current buffer 198 miob->write(buf, 2048); 199 CHECK(miob->max_read_avail() == 4096); 200 CHECK(miob->current_write_avail() == 0); 201 CHECK(miob->high_water() == true); 202 CHECK(miob->current_low_water() == true); 203 CHECK(miob->write_avail() == 0); ///< should have no side effect 204 205 // consume half of the data 206 miob_r->consume(2048); 207 CHECK(miob->max_read_avail() == 2048); 208 CHECK(miob->current_write_avail() == 0); 209 CHECK(miob->high_water() == true); 210 CHECK(miob->current_low_water() == true); 211 CHECK(miob->write_avail() == 0); ///< should have no side effect 212 213 // consume all of the data 214 miob_r->consume(2048); 215 CHECK(miob->max_read_avail() == 0); 216 CHECK(miob->current_write_avail() == 0); 217 CHECK(miob->high_water() == false); 218 CHECK(miob->current_low_water() == true); 219 CHECK(miob->write_avail() == 4096); ///< should have a side effect: add a new block 220 221 CHECK(miob->max_read_avail() == 0); 222 CHECK(miob->current_write_avail() == 4096); 223 CHECK(miob->high_water() == false); 224 CHECK(miob->current_low_water() == false); 225 CHECK(miob->write_avail() == 4096); ///< should have no side effect 226 } 227 228 SECTION("water_mark == half of block size") 229 { 230 miob->water_mark = 2048; 231 REQUIRE(miob->water_mark * 2 == miob->block_size()); 232 233 // fill half of the current buffer 234 miob->write(buf, 2048); 235 CHECK(miob->max_read_avail() == 2048); 236 CHECK(miob->current_write_avail() == 2048); 237 CHECK(miob->high_water() == false); 238 CHECK(miob->current_low_water() == true); 239 CHECK(miob->write_avail() == 6144); ///< should have a side effect: add a new block 240 241 CHECK(miob->max_read_avail() == 2048); 242 CHECK(miob->current_write_avail() == 6144); 243 CHECK(miob->high_water() == false); 244 CHECK(miob->current_low_water() == false); 245 CHECK(miob->write_avail() == 6144); ///< should have no side effect 246 247 // fill all of the current buffer 248 miob->write(buf, 6144); 249 CHECK(miob->max_read_avail() == 8192); 250 CHECK(miob->current_write_avail() == 0); 251 CHECK(miob->high_water() == true); 252 CHECK(miob->current_low_water() == true); 253 CHECK(miob->write_avail() == 0); ///< should have no side effect 254 255 // consume half of the data 256 miob_r->consume(4096); 257 CHECK(miob->max_read_avail() == 4096); 258 CHECK(miob->current_write_avail() == 0); 259 CHECK(miob->high_water() == true); 260 CHECK(miob->current_low_water() == true); 261 CHECK(miob->write_avail() == 0); ///< should have no side effect 262 263 // consume all of the data 264 miob_r->consume(4096); 265 CHECK(miob->max_read_avail() == 0); 266 CHECK(miob->current_write_avail() == 0); 267 CHECK(miob->high_water() == false); 268 CHECK(miob->current_low_water() == true); 269 CHECK(miob->write_avail() == 4096); ///< should have a side effect: add a new block 270 271 CHECK(miob->max_read_avail() == 0); 272 CHECK(miob->current_write_avail() == 4096); 273 CHECK(miob->high_water() == false); 274 CHECK(miob->current_low_water() == false); 275 CHECK(miob->write_avail() == 4096); ///< should have no side effect 276 } 277 278 SECTION("water_mark == block_size()") 279 { 280 miob->water_mark = 4096; 281 REQUIRE(miob->water_mark == miob->block_size()); 282 283 // fill half of the current buffer 284 miob->write(buf, 2048); 285 CHECK(miob->max_read_avail() == 2048); 286 CHECK(miob->current_write_avail() == 2048); 287 CHECK(miob->high_water() == false); 288 CHECK(miob->current_low_water() == true); 289 CHECK(miob->write_avail() == 6144); ///< should have a side effect: add a new block 290 291 CHECK(miob->max_read_avail() == 2048); 292 CHECK(miob->current_write_avail() == 6144); 293 CHECK(miob->high_water() == false); 294 CHECK(miob->current_low_water() == false); 295 CHECK(miob->write_avail() == 6144); ///< should have no side effect 296 297 // fill all of the current buffer 298 miob->write(buf, 6144); 299 CHECK(miob->max_read_avail() == 8192); 300 CHECK(miob->current_write_avail() == 0); 301 CHECK(miob->high_water() == true); 302 CHECK(miob->current_low_water() == true); 303 CHECK(miob->write_avail() == 0); ///< should have no side effect 304 305 // consume half of the data 306 miob_r->consume(4096); 307 CHECK(miob->max_read_avail() == 4096); 308 CHECK(miob->current_write_avail() == 0); 309 CHECK(miob->high_water() == false); 310 CHECK(miob->current_low_water() == true); 311 CHECK(miob->write_avail() == 4096); ///< should have a side effect: add a new block 312 IOBufferBlock *tail = miob->_writer->next.get(); 313 CHECK(tail != nullptr); 314 315 CHECK(miob->max_read_avail() == 4096); 316 CHECK(miob->current_write_avail() == 4096); 317 CHECK(miob->high_water() == false); 318 CHECK(miob->current_low_water() == true); 319 CHECK(miob->write_avail() == 4096); ///< should have no side effect 320 CHECK(tail == miob->_writer->next.get()); ///< the tail block should not be changed 321 322 // consume all of the data 323 miob_r->consume(4096); 324 CHECK(miob->max_read_avail() == 0); 325 CHECK(miob->current_write_avail() == 4096); 326 CHECK(miob->high_water() == false); 327 CHECK(miob->current_low_water() == true); 328 CHECK(miob->write_avail() == 4096); ///< should have no side effect 329 CHECK(tail == miob->_writer->next.get()); ///< the tail block should not be changed 330 } 331 332 free_MIOBuffer(miob); 333 } 334 } 335 336 struct EventProcessorListener : Catch::TestEventListenerBase { 337 using TestEventListenerBase::TestEventListenerBase; 338 339 void testRunStartingEventProcessorListener340 testRunStarting(Catch::TestRunInfo const &testRunInfo) override 341 { 342 Layout::create(); 343 init_diags("", nullptr); 344 RecProcessInit(RECM_STAND_ALONE); 345 346 LibRecordsConfigInit(); 347 348 ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION); 349 eventProcessor.start(TEST_THREADS); 350 351 EThread *main_thread = new EThread; 352 main_thread->set_specific(); 353 } 354 }; 355 356 CATCH_REGISTER_LISTENER(EventProcessorListener); 357