chromium/mojo/core/data_pipe_unittest.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "mojo/public/c/system/data_pipe.h"

#include <stddef.h>
#include <stdint.h>

#include <memory>

#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/numerics/safe_conversions.h"
#include "base/run_loop.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/test/mojo_test_base.h"
#include "mojo/public/c/system/functions.h"
#include "mojo/public/c/system/message_pipe.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace mojo {
namespace core {
namespace {

const uint32_t kSizeOfOptions =;

// In various places, we have to poll (since, e.g., we can't yet wait for a
// certain amount of data to be available). This is the maximum number of
// iterations (separated by a short sleep).
// TODO(vtl): Get rid of this.
const size_t kMaxPoll =;

// Used in Multiprocess test.
const size_t kMultiprocessCapacity =;
const char kMultiprocessTestData[] =;
const int kMultiprocessMaxIter =;

// Capacity that will cause data pipe creation to fail.
constexpr size_t kOversizedCapacity =;

// A timeout smaller than |TestTimeouts::tiny_timeout()|, as a |MojoDeadline|.
// Warning: This may lead to flakiness, but this is unavoidable if, e.g., you're
// trying to ensure that functions with timeouts are reasonably accurate. We
// want this to be as small as possible without causing too much flakiness.
base::TimeDelta EpsilonDeadline() {}

// TODO(rockot): There are many uses of ASSERT where EXPECT would be more
// appropriate. Fix this.

class DataPipeTest : public test::MojoTestBase {};

TEST_F(DataPipeTest, Basic) {}

// Tests creation of data pipes with various (valid) options.
TEST_F(DataPipeTest, CreateAndMaybeTransfer) {}

TEST_F(DataPipeTest, SimpleReadWrite) {}

// Note: The "basic" waiting tests test that the "wait states" are correct in
// various situations; they don't test that waiters are properly awoken on state
// changes. (For that, we need to use multiple threads.)
TEST_F(DataPipeTest, BasicProducerWaiting) {}

TEST_F(DataPipeTest, PeerClosedProducerWaiting) {}

TEST_F(DataPipeTest, PeerClosedConsumerWaiting) {}

TEST_F(DataPipeTest, BasicConsumerWaiting) {}

TEST_F(DataPipeTest, ConsumerNewDataReadable) {}

// Test with two-phase APIs and also closing the producer with an active
// consumer waiter.
TEST_F(DataPipeTest, ConsumerWaitingTwoPhase) {}

// Tests that data pipes aren't writable/readable during two-phase writes/reads.
TEST_F(DataPipeTest, BasicTwoPhaseWaiting) {}

void Seq(int32_t start, size_t count, int32_t* out) {}

TEST_F(DataPipeTest, AllOrNone) {}

// Tests that |ProducerWriteData()| and |ConsumerReadData()| writes and reads,
// respectively, as much as possible, even if it may have to "wrap around" the
// internal circular buffer. (Note that the two-phase write and read need not do
// this.)
TEST_F(DataPipeTest, WrapAround) {}

// Tests the behavior of writing (simple and two-phase), closing the producer,
// then reading (simple and two-phase).
TEST_F(DataPipeTest, WriteCloseProducerRead) {}

// Tests the behavior of interrupting a two-phase read and write by closing the
// consumer.
TEST_F(DataPipeTest, TwoPhaseWriteReadCloseConsumer) {}

// Tests the behavior of "interrupting" a two-phase write by closing both the
// producer and the consumer.
TEST_F(DataPipeTest, TwoPhaseWriteCloseBoth) {}

// Tests the behavior of writing, closing the producer, and then reading (with
// and without data remaining).
TEST_F(DataPipeTest, WriteCloseProducerReadNoData) {}

// Test that during a two phase read the memory stays valid even if more data
// comes in.
TEST_F(DataPipeTest, TwoPhaseReadMemoryStable) {}

// Test that two-phase reads/writes behave correctly when given invalid
// arguments.
TEST_F(DataPipeTest, TwoPhaseMoreInvalidArguments) {}

// Test that a producer can be sent over a MP.
TEST_F(DataPipeTest, SendProducer) {}

// Ensures that if a data pipe consumer whose producer has closed is passed over
// a message pipe, the deserialized dispatcher is also marked as having a closed
// peer.
TEST_F(DataPipeTest, ConsumerWithClosedProducerSent) {}

bool WriteAllData(MojoHandle producer,
                  const void* elements,
                  uint32_t num_bytes) {}

// If |expect_empty| is true, expect |consumer| to be empty after reading.
bool ReadAllData(MojoHandle consumer,
                 void* elements,
                 uint32_t num_bytes,
                 bool expect_empty) {}

TEST_F(DataPipeTest, CreateOversized) {}

#if BUILDFLAG(USE_BLINK)

constexpr size_t kNoSpuriousEvents_NumIterations =;

TEST_F(DataPipeTest, NoSpuriousEvents) {}

DEFINE_TEST_CLIENT_TEST_WITH_PIPE(NoSpuriousEventsHost, DataPipeTest, parent) {}

DEFINE_TEST_CLIENT_TEST_WITH_PIPE(NoSpuriousEventsClient,
                                  DataPipeTest,
                                  parent) {}

TEST_F(DataPipeTest, Multiprocess) {}

DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessClient, DataPipeTest, client_mp) {}

DEFINE_TEST_CLIENT_TEST_WITH_PIPE(WriteAndCloseProducer, DataPipeTest, h) {}

DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndCloseConsumer, DataPipeTest, h) {}

TEST_F(DataPipeTest, SendConsumerAndCloseProducer) {}

DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndWrite, DataPipeTest, h) {}

TEST_F(DataPipeTest, CreateInChild) {}

DEFINE_TEST_CLIENT_TEST_WITH_PIPE(DataPipeStatusChangeInTransitClient,
                                  DataPipeTest,
                                  parent) {}

TEST_F(DataPipeTest, StatusChangeInTransit) {}

DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateOversizedChild, DataPipeTest, h) {}

TEST_F(DataPipeTest, CreateOversizedInChild) {}

// Helper to fill a data pipe with data up to a given total size, using chunked
// two-phase writes. Automatically waits when the pipe is full and resumes as
// capacity allows.
class TestDataProducer {};

// Drains all data from a data pipe consumer endpoint. This combines read
// operations and trap usage (via watcher) in a way that is likely to trigger a
// regression path in the data pipe implementation if a certain type of bug is
// present. See comments in the implementation below.
class TestDataDrain {};

constexpr uint32_t kStressTestDataSize =;

DEFINE_TEST_CLIENT_TEST_WITH_PIPE(StressTestRacyTrapsClient, DataPipeTest, h) {}

// Temporarily disabled during experimentation with suppression of this fix for
// metrics collection only. Re-enable once the experiment is done.
// See https://crbug.com/41494387.
TEST_F(DataPipeTest, DISABLED_StressTestRacyTraps) {}

#endif  // BUILDFLAG(USE_BLINK)

}  // namespace
}  // namespace core
}  // namespace mojo