Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/ipc/gtest/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 10 kB image not shown  

Quelle  TestDataPipe.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "chrome/common/ipc_message.h"
#include "gtest/gtest.h"

#include "mozilla/gtest/MozAssertions.h"
#include "mozilla/ipc/DataPipe.h"
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
#include "nsNetUtil.h"
#include "nsStreamUtils.h"

namespace mozilla::ipc {

namespace {

struct InputStreamCallback : public nsIInputStreamCallback {
 public:
  NS_DECL_THREADSAFE_ISUPPORTS

  explicit InputStreamCallback(
      std::function<nsresult(nsIAsyncInputStream*)> aFunc = nullptr)
      : mFunc(std::move(aFunc)) {}

  NS_IMETHOD OnInputStreamReady(nsIAsyncInputStream* aStream) override {
    MOZ_ALWAYS_FALSE(mCalled.exchange(true));
    return mFunc ? mFunc(aStream) : NS_OK;
  }

  bool Called() const { return mCalled; }

 private:
  virtual ~InputStreamCallback() = default;

  std::atomic<bool> mCalled = false;
  std::function<nsresult(nsIAsyncInputStream*)> mFunc;
};

NS_IMPL_ISUPPORTS(InputStreamCallback, nsIInputStreamCallback)

struct OutputStreamCallback : public nsIOutputStreamCallback {
 public:
  NS_DECL_THREADSAFE_ISUPPORTS

  explicit OutputStreamCallback(
      std::function<nsresult(nsIAsyncOutputStream*)> aFunc = nullptr)
      : mFunc(std::move(aFunc)) {}

  NS_IMETHOD OnOutputStreamReady(nsIAsyncOutputStream* aStream) override {
    MOZ_ALWAYS_FALSE(mCalled.exchange(true));
    return mFunc ? mFunc(aStream) : NS_OK;
  }

  bool Called() const { return mCalled; }

 private:
  virtual ~OutputStreamCallback() = default;

  std::atomic<bool> mCalled = false;
  std::function<nsresult(nsIAsyncOutputStream*)> mFunc;
};

NS_IMPL_ISUPPORTS(OutputStreamCallback, nsIOutputStreamCallback)

// Populate an array with the given number of bytes.  Data is lorem ipsum
// random text, but deterministic across multiple calls.
void CreateData(uint32_t aNumBytes, nsCString& aDataOut) {
  static const char data[] =
      "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec egestas "
      "purus eu condimentum iaculis. In accumsan leo eget odio porttitor, non "
      "rhoncus nulla vestibulum. Etiam lacinia consectetur nisl nec "
      "sollicitudin. Sed fringilla accumsan diam, pulvinar varius massa. Duis "
      "mollis dignissim felis, eget tempus nisi tristique ut. Fusce euismod, "
      "lectus non lacinia tempor, tellus diam suscipit quam, eget hendrerit "
      "lacus nunc fringilla ante. Sed ultrices massa vitae risus molestie, ut "
      "finibus quam laoreet nullam.";
  static const uint32_t dataLength = sizeof(data) - 1;

  aDataOut.SetCapacity(aNumBytes);

  while (aNumBytes > 0) {
    uint32_t amount = std::min(dataLength, aNumBytes);
    aDataOut.Append(data, amount);
    aNumBytes -= amount;
  }
}

// Synchronously consume the given input stream and validate the resulting data
// against the given string of expected values.
void ConsumeAndValidateStream(nsIInputStream* aStream,
                              const nsACString& aExpectedData) {
  nsAutoCString outputData;
  nsresult rv = NS_ConsumeStream(aStream, UINT32_MAX, outputData);
  ASSERT_NS_SUCCEEDED(rv);
  ASSERT_EQ(aExpectedData.Length(), outputData.Length());
  ASSERT_TRUE(aExpectedData.Equals(outputData));
}

}  // namespace

TEST(DataPipe, SegmentedReadWrite)
{
  RefPtr<DataPipeReceiver> reader;
  RefPtr<DataPipeSender> writer;

  nsresult rv =
      NewDataPipe(1024, getter_AddRefs(writer), getter_AddRefs(reader));
  ASSERT_NS_SUCCEEDED(rv);

  nsCString inputData1;
  CreateData(512, inputData1);

  uint32_t numWritten = 0;
  rv = writer->Write(inputData1.BeginReading(), inputData1.Length(),
                     &numWritten);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_EQ(numWritten, 512u);

  uint64_t available = 0;
  rv = reader->Available(&available);
  EXPECT_EQ(available, 512u);
  ConsumeAndValidateStream(reader, inputData1);

  nsCString inputData2;
  CreateData(1024, inputData2);

  rv = writer->Write(inputData2.BeginReading(), inputData2.Length(),
                     &numWritten);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_EQ(numWritten, 1024u);

  rv = reader->Available(&available);
  EXPECT_EQ(available, 1024u);
  ConsumeAndValidateStream(reader, inputData2);
}

TEST(DataPipe, SegmentedPartialRead)
{
  RefPtr<DataPipeReceiver> reader;
  RefPtr<DataPipeSender> writer;

  nsresult rv =
      NewDataPipe(1024, getter_AddRefs(writer), getter_AddRefs(reader));
  ASSERT_NS_SUCCEEDED(rv);

  nsCString inputData1;
  CreateData(512, inputData1);

  uint32_t numWritten = 0;
  rv = writer->Write(inputData1.BeginReading(), inputData1.Length(),
                     &numWritten);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_EQ(numWritten, 512u);

  uint64_t available = 0;
  rv = reader->Available(&available);
  EXPECT_EQ(available, 512u);
  ConsumeAndValidateStream(reader, inputData1);

  nsCString inputData2;
  CreateData(1024, inputData2);

  rv = writer->Write(inputData2.BeginReading(), inputData2.Length(),
                     &numWritten);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_EQ(numWritten, 1024u);

  rv = reader->Available(&available);
  EXPECT_EQ(available, 1024u);

  nsAutoCString outputData;
  rv = NS_ReadInputStreamToString(reader, outputData, 768);
  ASSERT_NS_SUCCEEDED(rv);
  ASSERT_EQ(768u, outputData.Length());
  ASSERT_TRUE(Substring(inputData2, 0, 768).Equals(outputData));

  rv = reader->Available(&available);
  EXPECT_EQ(available, 256u);

  nsAutoCString outputData2;
  rv = NS_ReadInputStreamToString(reader, outputData2, 256);
  ASSERT_NS_SUCCEEDED(rv);
  ASSERT_EQ(256u, outputData2.Length());
  ASSERT_TRUE(Substring(inputData2, 768).Equals(outputData2));
}

TEST(DataPipe, Write_AsyncWait)
{
  RefPtr<DataPipeReceiver> reader;
  RefPtr<DataPipeSender> writer;

  const uint32_t segmentSize = 1024;

  nsresult rv =
      NewDataPipe(segmentSize, getter_AddRefs(writer), getter_AddRefs(reader));
  ASSERT_NS_SUCCEEDED(rv);

  nsCString inputData;
  CreateData(segmentSize, inputData);

  uint32_t numWritten = 0;
  rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_EQ(numWritten, segmentSize);

  rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
  ASSERT_EQ(NS_BASE_STREAM_WOULD_BLOCK, rv);

  RefPtr<OutputStreamCallback> cb = new OutputStreamCallback();

  rv = writer->AsyncWait(cb, 0, 0, GetCurrentSerialEventTarget());
  ASSERT_NS_SUCCEEDED(rv);

  NS_ProcessPendingEvents(nullptr);

  ASSERT_FALSE(cb->Called());

  ConsumeAndValidateStream(reader, inputData);

  ASSERT_FALSE(cb->Called());

  NS_ProcessPendingEvents(nullptr);

  ASSERT_TRUE(cb->Called());
}

TEST(DataPipe, Read_AsyncWait)
{
  RefPtr<DataPipeReceiver> reader;
  RefPtr<DataPipeSender> writer;

  const uint32_t segmentSize = 1024;

  nsresult rv =
      NewDataPipe(segmentSize, getter_AddRefs(writer), getter_AddRefs(reader));
  ASSERT_NS_SUCCEEDED(rv);

  nsCString inputData;
  CreateData(segmentSize, inputData);

  RefPtr<InputStreamCallback> cb = new InputStreamCallback();

  rv = reader->AsyncWait(cb, 0, 0, GetCurrentSerialEventTarget());
  ASSERT_NS_SUCCEEDED(rv);

  NS_ProcessPendingEvents(nullptr);

  ASSERT_FALSE(cb->Called());

  uint32_t numWritten = 0;
  rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
  ASSERT_NS_SUCCEEDED(rv);

  ASSERT_FALSE(cb->Called());

  NS_ProcessPendingEvents(nullptr);

  ASSERT_TRUE(cb->Called());

  ConsumeAndValidateStream(reader, inputData);
}

TEST(DataPipe, Write_AsyncWait_Cancel)
{
  RefPtr<DataPipeReceiver> reader;
  RefPtr<DataPipeSender> writer;

  const uint32_t segmentSize = 1024;

  nsresult rv =
      NewDataPipe(segmentSize, getter_AddRefs(writer), getter_AddRefs(reader));
  ASSERT_NS_SUCCEEDED(rv);

  nsCString inputData;
  CreateData(segmentSize, inputData);

  uint32_t numWritten = 0;
  rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
  ASSERT_NS_SUCCEEDED(rv);
  EXPECT_EQ(numWritten, segmentSize);

  rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
  ASSERT_EQ(NS_BASE_STREAM_WOULD_BLOCK, rv);

  RefPtr<OutputStreamCallback> cb = new OutputStreamCallback();

  // Register a callback and immediately cancel it.
  rv = writer->AsyncWait(cb, 0, 0, GetCurrentSerialEventTarget());
  ASSERT_NS_SUCCEEDED(rv);
  rv = writer->AsyncWait(nullptr, 0, 0, nullptr);
  ASSERT_NS_SUCCEEDED(rv);

  // Even after consuming the stream and processing pending events, the callback
  // shouldn't be called as it was cancelled.
  ConsumeAndValidateStream(reader, inputData);
  NS_ProcessPendingEvents(nullptr);
  ASSERT_FALSE(cb->Called());
}

TEST(DataPipe, Read_AsyncWait_Cancel)
{
  RefPtr<DataPipeReceiver> reader;
  RefPtr<DataPipeSender> writer;

  const uint32_t segmentSize = 1024;

  nsresult rv =
      NewDataPipe(segmentSize, getter_AddRefs(writer), getter_AddRefs(reader));
  ASSERT_NS_SUCCEEDED(rv);

  nsCString inputData;
  CreateData(segmentSize, inputData);

  RefPtr<InputStreamCallback> cb = new InputStreamCallback();

  // Register a callback and immediately cancel it.
  rv = reader->AsyncWait(cb, 0, 0, GetCurrentSerialEventTarget());
  ASSERT_NS_SUCCEEDED(rv);

  rv = reader->AsyncWait(nullptr, 0, 0, nullptr);
  ASSERT_NS_SUCCEEDED(rv);

  // Write data into the pipe to make the callback become ready.
  uint32_t numWritten = 0;
  rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
  ASSERT_NS_SUCCEEDED(rv);

  // Even after processing pending events, the callback shouldn't be called as
  // it was cancelled.
  NS_ProcessPendingEvents(nullptr);
  ASSERT_FALSE(cb->Called());

  ConsumeAndValidateStream(reader, inputData);
}

TEST(DataPipe, SerializeReader)
{
  RefPtr<DataPipeReceiver> reader;
  RefPtr<DataPipeSender> writer;
  nsresult rv =
      NewDataPipe(1024, getter_AddRefs(writer), getter_AddRefs(reader));
  ASSERT_NS_SUCCEEDED(rv);

  IPC::Message msg(MSG_ROUTING_NONE, 0);
  IPC::MessageWriter msgWriter(msg);
  IPC::WriteParam(&msgWriter, reader);

  uint64_t available = 0;
  rv = reader->Available(&available);
  ASSERT_NS_FAILED(rv);

  nsCString inputData;
  CreateData(512, inputData);

  uint32_t numWritten = 0;
  rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
  ASSERT_NS_SUCCEEDED(rv);

  RefPtr<DataPipeReceiver> reader2;
  IPC::MessageReader msgReader(msg);
  ASSERT_TRUE(IPC::ReadParam(&msgReader, &reader2));
  ASSERT_TRUE(reader2);

  rv = reader2->Available(&available);
  ASSERT_NS_SUCCEEDED(rv);
  ASSERT_EQ(available, 512u);
  ConsumeAndValidateStream(reader2, inputData);
}

}  // namespace mozilla::ipc

96%


¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.