// Copyright 2022 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "pw_async/dispatcher_basic.h"

#include "gtest/gtest.h"
#include "public/pw_async/dispatcher_basic.h"
#include "pw_log/log.h"
#include "pw_sync/thread_notification.h"
#include "pw_thread/thread.h"
#include "pw_thread_stl/options.h"

using namespace std::chrono_literals;

namespace pw::async {

// Lambdas can only capture one ptr worth of memory without allocating, so we
// group the data we want to share between tasks and their containing tests
// inside one struct.
struct TestPrimitives {
  int count = 0;
  sync::ThreadNotification notification;
};

TEST(DispatcherBasic, PostTasks) {
  BasicDispatcher dispatcher;
  thread::Thread work_thread(thread::stl::Options(), dispatcher);

  TestPrimitives tp;
  auto inc_count = [&tp]([[maybe_unused]] Context& c) { ++tp.count; };

  Task task(inc_count);
  dispatcher.PostTask(task);

  Task task2(inc_count);
  dispatcher.PostTask(task2);

  Task task3([&tp]([[maybe_unused]] Context& c) {
    ++tp.count;
    tp.notification.release();
  });
  dispatcher.PostTask(task3);

  tp.notification.acquire();
  dispatcher.RequestStop();
  work_thread.join();

  ASSERT_TRUE(tp.count == 3);
}

struct TaskPair {
  Task task_a;
  Task task_b;
  int count = 0;
  sync::ThreadNotification notification;
};

TEST(DispatcherBasic, ChainedTasks) {
  BasicDispatcher dispatcher;
  thread::Thread work_thread(thread::stl::Options(), dispatcher);

  TaskPair tp;

  Task task0([&tp](Context& c) {
    ++tp.count;

    c.dispatcher->PostTask(tp.task_a);
  });

  tp.task_a.SetFunction([&tp](Context& c) {
    ++tp.count;

    c.dispatcher->PostTask(tp.task_b);
  });

  tp.task_b.SetFunction([&tp]([[maybe_unused]] Context& c) {
    ++tp.count;
    tp.notification.release();
  });

  dispatcher.PostTask(task0);

  tp.notification.acquire();
  dispatcher.RequestStop();
  work_thread.join();

  ASSERT_TRUE(tp.count == 3);
}

// Test RequestStop() from inside task.
TEST(DispatcherBasic, RequestStopInsideTask) {
  BasicDispatcher dispatcher;
  thread::Thread work_thread(thread::stl::Options(), dispatcher);

  TestPrimitives tp;
  auto inc_count = [&tp]([[maybe_unused]] Context& c) { ++tp.count; };

  // These tasks are never executed and cleaned up in RequestStop().
  Task task0(inc_count), task1(inc_count);
  dispatcher.PostDelayedTask(task0, 20ms);
  dispatcher.PostDelayedTask(task1, 21ms);

  Task stop_task([&tp]([[maybe_unused]] Context& c) {
    ++tp.count;
    c.dispatcher->RequestStop();
    tp.notification.release();
  });
  dispatcher.PostTask(stop_task);

  tp.notification.acquire();
  work_thread.join();

  ASSERT_TRUE(tp.count == 1);
}

}  // namespace pw::async
