/*
 *  Copyright 2026 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "pc/scoped_operations_batcher.h"

#include <memory>
#include <utility>
#include <vector>

#include "absl/functional/any_invocable.h"
#include "api/rtc_error.h"
#include "rtc_base/thread.h"
#include "test/gtest.h"

namespace webrtc {
namespace {

TEST(ScopedOperationsBatcherTest, ExecutesTasksOnTargetThread) {
  auto target_thread = Thread::Create();
  target_thread->Start();

  bool task_executed = false;
  bool target_checked = false;

  {
    ScopedOperationsBatcher batcher(target_thread.get());
    batcher.Add([&] {
      task_executed = true;
      target_checked = target_thread->IsCurrent();
    });
  }

  EXPECT_TRUE(task_executed);
  EXPECT_TRUE(target_checked);
}

TEST(ScopedOperationsBatcherTest, ExecutesReturnedTasksOnCallingThread) {
  // Use current thread as the calling (signaling) thread. This test runs
  // without an explicit RunLoop, because the returned tasks are executed
  // synchronously within the caller's context of `Run()` or
  // `~ScopedOperationsBatcher()`.
  auto signaling_thread = Thread::Current();

  auto target_thread = Thread::Create();
  target_thread->Start();

  bool return_task_executed = false;
  Thread* return_task_thread = nullptr;
  bool task_executed = false;
  Thread* task_thread = nullptr;

  {
    ScopedOperationsBatcher batcher(target_thread.get());
    ScopedOperationsBatcher::BatchTaskWithFinalizer task =
        [&]() -> RTCErrorOr<ScopedOperationsBatcher::FinalizerTask> {
      task_executed = true;
      task_thread = Thread::Current();
      return ScopedOperationsBatcher::FinalizerTask([&]() {
        return_task_executed = true;
        return_task_thread = Thread::Current();
      });
    };
    batcher.AddWithFinalizer(std::move(task));
  }

  EXPECT_TRUE(task_executed);
  EXPECT_EQ(task_thread, target_thread.get());
  EXPECT_TRUE(return_task_executed);
  EXPECT_EQ(return_task_thread, signaling_thread);
}

TEST(ScopedOperationsBatcherTest, YieldsToOtherTasks) {
  auto target_thread = Thread::Create();
  target_thread->Start();

  std::vector<int> execution_order;

  {
    ScopedOperationsBatcher batcher(target_thread.get());
    batcher.Add([&] { execution_order.push_back(1); });
    batcher.Add([&] {
      execution_order.push_back(2);
      // Post a task that should interrupt the batch since we now yield to any
      // pending task.
      target_thread->PostTask([&] { execution_order.push_back(3); });
    });
    batcher.Add([&] { execution_order.push_back(4); });
    batcher.Add([&] { execution_order.push_back(5); });
  }

  // Expect the task (3) to execute immediately after the task
  // that posted it (2). The operations remaining in the batch (4, 5)
  // should resume after the thread has processed the new task.
  EXPECT_EQ(execution_order, std::vector<int>({1, 2, 3, 4, 5}));
}

TEST(ScopedOperationsBatcherTest, StopsExecutionOnError) {
  auto target_thread = Thread::Create();
  target_thread->Start();

  bool task1_executed = false;
  bool task2_executed = false;
  bool task3_executed = false;
  // There's no finalizer for task2.
  bool finalizer1_executed = false;
  bool finalizer3_executed = false;

  RTCError error = RTCError::OK();
  {
    ScopedOperationsBatcher batcher(target_thread.get());
    // Task 1.
    batcher.AddWithFinalizer(
        [&]() -> RTCErrorOr<ScopedOperationsBatcher::FinalizerTask> {
          task1_executed = true;
          return ScopedOperationsBatcher::FinalizerTask(
              [&] { finalizer1_executed = true; });
        });
    // Task 2.
    batcher.AddWithFinalizer(
        [&]() -> RTCErrorOr<ScopedOperationsBatcher::FinalizerTask> {
          task2_executed = true;
          return RTCError(RTCErrorType::INVALID_STATE, "Failed");
        });
    // Task 3.
    batcher.AddWithFinalizer(
        [&]() -> RTCErrorOr<ScopedOperationsBatcher::FinalizerTask> {
          task3_executed = true;
          return ScopedOperationsBatcher::FinalizerTask(
              [&] { finalizer3_executed = true; });
        });

    error = batcher.Run();
  }

  EXPECT_FALSE(error.ok());
  EXPECT_EQ(error.type(), RTCErrorType::INVALID_STATE);
  EXPECT_STREQ(error.message(), "Failed");

  EXPECT_TRUE(task1_executed);
  EXPECT_TRUE(finalizer1_executed);
  EXPECT_TRUE(task2_executed);
  EXPECT_FALSE(task3_executed);
  EXPECT_FALSE(finalizer3_executed);
}

}  // namespace
}  // namespace webrtc
