// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <lib/zx/event.h>
#include <lib/zx/job.h>

#include <zxtest/zxtest.h>

// Tests in this file rely that the default job is the root job.

static void retrieve_mem_event(zx_system_event_type_t event_type) {
  zx::event mem_event;

  ASSERT_EQ(zx_system_get_event(ZX_HANDLE_INVALID, event_type, mem_event.reset_and_get_address()),
            ZX_ERR_BAD_HANDLE, "cannot get with invalid root job");

  ASSERT_EQ(zx_system_get_event(zx_process_self(), event_type, mem_event.reset_and_get_address()),
            ZX_ERR_WRONG_TYPE, "cannot get without a job handle");

  zx::job tmp_job;
  ASSERT_EQ(zx::job::create(*zx::job::default_job(), 0u, &tmp_job), ZX_OK, "helper sub job");

  ASSERT_EQ(zx_system_get_event(tmp_job.get(), event_type, mem_event.reset_and_get_address()),
            ZX_ERR_ACCESS_DENIED, "cannot get without correct root job");

  zx::unowned_job root_job(zx_job_default());
  if (!root_job->is_valid()) {
    printf("no root job. skipping part of test\n");
  } else {
    ASSERT_EQ(zx_system_get_event(root_job->get(), ~0u, mem_event.reset_and_get_address()),
              ZX_ERR_INVALID_ARGS, "incorrect kind value does not retrieve");

    ASSERT_EQ(zx_system_get_event(root_job->get(), event_type, mem_event.reset_and_get_address()),
              ZX_OK, "can get if root provided");

    // Confirm we at least got an event.
    zx_info_handle_basic_t info;
    ASSERT_EQ(zx_object_get_info(mem_event.get(), ZX_INFO_HANDLE_BASIC, &info, sizeof(info),
                                 nullptr, nullptr),
              ZX_OK, "object_get_info");
    EXPECT_NE(info.koid, 0, "no koid");
    EXPECT_EQ(info.type, ZX_OBJ_TYPE_EVENT, "incorrect type");
    EXPECT_EQ(info.rights, ZX_DEFAULT_SYSTEM_EVENT_LOW_MEMORY_RIGHTS, "incorrect rights");
  }
}

static void signal_mem_event_from_userspace(zx_system_event_type_t event_type) {
  zx::unowned_job root_job(zx_job_default());
  if (!root_job->is_valid()) {
    printf("no root job. skipping test\n");
  } else {
    zx::event mem_event;
    ASSERT_EQ(zx_system_get_event(root_job->get(), event_type, mem_event.reset_and_get_address()),
              ZX_OK);

    ASSERT_EQ(mem_event.signal(0, 1), ZX_ERR_ACCESS_DENIED, "shouldn't be able to signal");
  }
}

TEST(SystemEvent, RetrieveOom) { retrieve_mem_event(ZX_SYSTEM_EVENT_OUT_OF_MEMORY); }

TEST(SystemEvent, CannotSignalOomFromUserspace) {
  signal_mem_event_from_userspace(ZX_SYSTEM_EVENT_OUT_OF_MEMORY);
}

TEST(SystemEvent, RetrieveImminentOom) {
  retrieve_mem_event(ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY);
}

TEST(SystemEvent, CannotSignalImminentOomFromUserspace) {
  signal_mem_event_from_userspace(ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY);
}

TEST(SystemEvent, RetrieveMempressureCritical) {
  retrieve_mem_event(ZX_SYSTEM_EVENT_MEMORY_PRESSURE_CRITICAL);
}

TEST(SystemEvent, CannotSignalMempressureCriticalFromUserspace) {
  signal_mem_event_from_userspace(ZX_SYSTEM_EVENT_MEMORY_PRESSURE_CRITICAL);
}

TEST(SystemEvent, RetreiveMempressureWarning) {
  retrieve_mem_event(ZX_SYSTEM_EVENT_MEMORY_PRESSURE_WARNING);
}

TEST(SystemEvent, CannotSignalMempressureWarningFromUserspace) {
  signal_mem_event_from_userspace(ZX_SYSTEM_EVENT_MEMORY_PRESSURE_WARNING);
}

TEST(SystemEvent, RetrieveMempressureNormal) {
  retrieve_mem_event(ZX_SYSTEM_EVENT_MEMORY_PRESSURE_NORMAL);
}

TEST(SystemEvent, CannotSignalMempressureNormalFromUserspace) {
  signal_mem_event_from_userspace(ZX_SYSTEM_EVENT_MEMORY_PRESSURE_NORMAL);
}

TEST(SystemEvent, ExactlyOneMemoryEventSignaled) {
  zx::unowned_job root_job(zx_job_default());
  if (!root_job->is_valid()) {
    printf("no root job. skipping part of test\n");
    return;
  }

  const int kNumEvents = 5;
  zx::event mem_events[kNumEvents];
  zx_wait_item_t wait_items[kNumEvents];
  zx_system_event_type_t types[kNumEvents] = {
      ZX_SYSTEM_EVENT_OUT_OF_MEMORY, ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY,
      ZX_SYSTEM_EVENT_MEMORY_PRESSURE_CRITICAL, ZX_SYSTEM_EVENT_MEMORY_PRESSURE_WARNING,
      ZX_SYSTEM_EVENT_MEMORY_PRESSURE_NORMAL};

  for (int i = 0; i < kNumEvents; i++) {
    ASSERT_EQ(zx_system_get_event(root_job->get(), types[i], mem_events[i].reset_and_get_address()),
              ZX_OK, "can get if root provided");
    wait_items[i].handle = mem_events[i].get();
    wait_items[i].waitfor = ZX_EVENT_SIGNALED;
    wait_items[i].pending = 0;
  }

  // This wait should return immediately.
  ASSERT_EQ(zx_object_wait_many(wait_items, kNumEvents, ZX_TIME_INFINITE), ZX_OK,
            "wait on memory events");

  int events_signaled = 0;
  for (auto& wait_item : wait_items) {
    if (wait_item.pending) {
      events_signaled++;
    }
  }

  ASSERT_EQ(events_signaled, 1, "exactly one memory event signaled");
}
