Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6727285 authored by Erwin Jansen's avatar Erwin Jansen Committed by Henri Chataing
Browse files

Rootcanal: do not starve the reader in unittest

On an M1 the writer thread can write faster than the reader can read.
This results in the reader never exiting the loop, causing the test to
hang.

We now lower the rate of writing to make sure the readers can always
keep up.

Bug: 251187705
Test: Unit tests now succeed on M1
Bug: 245578454
Ignore-AOSP-First: cherry-pick from AOSP
Merged-In: Ia675c3b3b0613b2b00a588a803473a3d997bf0ee
Change-Id: Ia675c3b3b0613b2b00a588a803473a3d997bf0ee
(cherry picked from commit c1a2deb6)
parent 894d0e79
Loading
Loading
Loading
Loading
+30 −18
Original line number Diff line number Diff line
@@ -32,8 +32,8 @@
#include <mutex>               // for mutex
#include <ratio>               // for ratio
#include <string>              // for string
#include <tuple>               // for tuple
#include <thread>
#include <tuple>  // for tuple

#include "osi/include/osi.h"  // for OSI_NO_INTR

@@ -125,6 +125,8 @@ class AsyncManagerSocketTest : public ::testing::Test {
  void SetUp() override {
    memset(server_buffer_, 0, kBufferSize);
    memset(client_buffer_, 0, kBufferSize);
    socket_fd_ = -1;
    connection_fd_ = -1;

    socket_fd_ = StartServer();

@@ -139,7 +141,9 @@ class AsyncManagerSocketTest : public ::testing::Test {
  void TearDown() override {
    async_manager_.StopWatchingFileDescriptor(socket_fd_);
    close(socket_fd_);
    ASSERT_EQ(std::string_view(server_buffer_, kBufferSize), std::string_view(client_buffer_, kBufferSize));
    close(connection_fd_);
    ASSERT_EQ(std::string_view(server_buffer_, kBufferSize),
              std::string_view(client_buffer_, kBufferSize));
  }

  int ConnectClient() {
@@ -193,6 +197,8 @@ TEST_F(AsyncManagerSocketTest, TestOneConnection) {
}

TEST_F(AsyncManagerSocketTest, CanUnsubscribeInCallback) {
  using namespace std::chrono_literals;

  int socket_cli_fd = ConnectClient();
  WriteFromClient(socket_cli_fd);
  AwaitServerResponse(socket_cli_fd);
@@ -211,37 +217,40 @@ TEST_F(AsyncManagerSocketTest, CanUnsubscribeInCallback) {

  while (!stopped) {
    write(socket_cli_fd, data.data(), data.size());
    std::this_thread::sleep_for(5ms);
  }

  SUCCEED();
  close(socket_cli_fd);
}


TEST_F(AsyncManagerSocketTest, CanUnsubscribeTaskFromWithinTask) {
  Event running;
  using namespace std::chrono_literals;
  async_manager_.ExecAsyncPeriodically(1, 1ms, 2ms, [&running, this]() {
     EXPECT_TRUE(async_manager_.CancelAsyncTask(1)) << "We were scheduled, so cancel should return true";
     EXPECT_FALSE(async_manager_.CancelAsyncTask(1)) << "We were not scheduled, so cancel should return false";
    EXPECT_TRUE(async_manager_.CancelAsyncTask(1))
        << "We were scheduled, so cancel should return true";
    EXPECT_FALSE(async_manager_.CancelAsyncTask(1))
        << "We were not scheduled, so cancel should return false";
    running.set(true);
  });

  EXPECT_TRUE(running.wait_for(10ms));
}


TEST_F(AsyncManagerSocketTest, UnsubScribeWaitsUntilCompletion) {
  using namespace std::chrono_literals;
  Event running;
  bool cancel_done = false;
  bool task_complete = false;
  async_manager_.ExecAsyncPeriodically(1, 1ms, 2ms, [&running, &cancel_done, &task_complete]() {
  async_manager_.ExecAsyncPeriodically(
      1, 1ms, 2ms, [&running, &cancel_done, &task_complete]() {
        // Let the other thread now we are in the callback..
        running.set(true);
        // Wee bit of a hack that relies on timing..
        std::this_thread::sleep_for(20ms);
      EXPECT_FALSE(cancel_done) << "Task cancellation did not wait for us to complete!";
        EXPECT_FALSE(cancel_done)
            << "Task cancellation did not wait for us to complete!";
        task_complete = true;
      });

@@ -249,11 +258,14 @@ TEST_F(AsyncManagerSocketTest, UnsubScribeWaitsUntilCompletion) {
  auto start = std::chrono::system_clock::now();

  // There is a 20ms wait.. so we know that this should take some time.
  EXPECT_TRUE(async_manager_.CancelAsyncTask(1)) << "We were scheduled, so cancel should return true";
  EXPECT_TRUE(async_manager_.CancelAsyncTask(1))
      << "We were scheduled, so cancel should return true";
  cancel_done = true;
  EXPECT_TRUE(task_complete) << "We managed to cancel a task while it was not yet finished.";
  EXPECT_TRUE(task_complete)
      << "We managed to cancel a task while it was not yet finished.";
  auto end = std::chrono::system_clock::now();
  auto passed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
  auto passed_ms =
      std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
  EXPECT_GT(passed_ms.count(), 10);
}