| 325 | } |
| 326 | |
| 327 | void SC::AsyncStreamsTest::writableStream() |
| 328 | { |
| 329 | constexpr size_t numberOfBuffers = 2; |
| 330 | AsyncBufferView bufferViews[numberOfBuffers]; // Empty BufferViews (to be filled with ReadOnly ones) |
| 331 | AsyncBuffersPool pool; |
| 332 | pool.setBuffers(bufferViews); |
| 333 | |
| 334 | struct TestWritableStream : public AsyncWritableStream |
| 335 | { |
| 336 | size_t numAsyncWrites = 0; |
| 337 | String concatenated; |
| 338 | |
| 339 | AsyncBufferView::ID bufferID; |
| 340 | |
| 341 | virtual Result asyncWrite(AsyncBufferView::ID incomingBufferID, Function<void(AsyncBufferView::ID)> cb) override |
| 342 | { |
| 343 | (void)cb; |
| 344 | numAsyncWrites++; |
| 345 | Span<const char> data; |
| 346 | SC_TRY(getBuffersPool().getReadableData(incomingBufferID, data)); |
| 347 | StringView sv(data, false, StringEncoding::Ascii); |
| 348 | SC_TRY(StringBuilder::createForAppendingTo(concatenated).append(sv)); |
| 349 | bufferID = incomingBufferID; |
| 350 | return Result(true); |
| 351 | } |
| 352 | }; |
| 353 | TestWritableStream writable; |
| 354 | AsyncWritableStream::Request writeRequestsQueue[numberOfBuffers + 1]; // Only N-1 slots will be used |
| 355 | writable.setWriteQueue(writeRequestsQueue); |
| 356 | SC_TEST_EXPECT(writable.init(pool)); |
| 357 | (void)writable.eventError.addListener([this](Result res) { SC_TEST_EXPECT(res); }); |
| 358 | |
| 359 | int numDrain = 0; |
| 360 | (void)writable.eventDrain.addListener([&numDrain] { numDrain++; }); |
| 361 | |
| 362 | // When passing String(...) the writable takes ownership of the String destroying it after the write |
| 363 | SC_TEST_EXPECT(writable.write(String("1"))); // Executes asyncWrites and queue slot is freed immediately |
| 364 | SC_TEST_EXPECT(writable.numAsyncWrites == 1); |
| 365 | SC_TEST_EXPECT(writable.write("2")); // queued, uses first write slot |
| 366 | SC_TEST_EXPECT(writable.write(String("3"))); // queued, uses second write slot |
| 367 | SC_TEST_EXPECT(not writable.write("4")); // no more write queue slots |
| 368 | SC_TEST_EXPECT(writable.numAsyncWrites == 1); |
| 369 | writable.finishedWriting(writable.bufferID, {}, Result(true)); // writes 2 |
| 370 | SC_TEST_EXPECT(writable.concatenated == "12"); |
| 371 | SC_TEST_EXPECT(numDrain == 0); |
| 372 | SC_TEST_EXPECT(writable.numAsyncWrites == 2); |
| 373 | SC_TEST_EXPECT(writable.write("4")); |
| 374 | SC_TEST_EXPECT(writable.numAsyncWrites == 2); |
| 375 | SC_TEST_EXPECT(not writable.write(String("5"))); |
| 376 | writable.finishedWriting(writable.bufferID, {}, Result(true)); // writes 3 |
| 377 | SC_TEST_EXPECT(writable.concatenated == "123"); |
| 378 | SC_TEST_EXPECT(numDrain == 0); |
| 379 | writable.finishedWriting(writable.bufferID, {}, Result(true)); // writes 4 |
| 380 | SC_TEST_EXPECT(writable.concatenated == "1234"); |
| 381 | SC_TEST_EXPECT(numDrain == 0); |
| 382 | writable.finishedWriting(writable.bufferID, {}, Result(true)); // writes nothing |
| 383 | SC_TEST_EXPECT(writable.concatenated == "1234"); |
| 384 | SC_TEST_EXPECT(numDrain == 1); |