/*
 * Copyright (c) 2021 Nordic Semiconductor ASA.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/ztest.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/device_runtime.h>

#include "test_driver.h"

static const struct device *dev;
static struct k_thread get_runner_td;
K_THREAD_STACK_DEFINE(get_runner_stack, 1024);

static void get_runner(void *arg1, void *arg2, void *arg3)
{
	int ret;
	bool ongoing;

	ARG_UNUSED(arg1);
	ARG_UNUSED(arg2);
	ARG_UNUSED(arg3);

	/* make sure we test blocking path (suspend is ongoing) */
	ongoing = test_driver_pm_ongoing(dev);
	zassert_equal(ongoing, true);

	/* usage: 0, +1, resume: yes */
	ret = pm_device_runtime_get(dev);
	zassert_equal(ret, 0);
}

void test_api_setup(void *data)
{
	int ret;
	enum pm_device_state state;

	/* check API always returns 0 when runtime PM is disabled */
	ret = pm_device_runtime_get(dev);
	zassert_equal(ret, 0);
	ret = pm_device_runtime_put(dev);
	zassert_equal(ret, 0);
	ret = pm_device_runtime_put_async(dev);
	zassert_equal(ret, 0);

	/* enable runtime PM */
	ret = pm_device_runtime_enable(dev);
	zassert_equal(ret, 0);

	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);

	/* enabling again should succeed (no-op) */
	ret = pm_device_runtime_enable(dev);
	zassert_equal(ret, 0);
}

static void test_api_teardown(void *data)
{
	int ret;
	enum pm_device_state state;

	/* let test driver finish async PM (in case it was left pending due to
	 * a failure)
	 */
	if (test_driver_pm_ongoing(dev)) {
		test_driver_pm_done(dev);
	}

	/* disable runtime PM, make sure device is left into active state */
	ret = pm_device_runtime_disable(dev);
	zassert_equal(ret, 0);

	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_ACTIVE);
}

/**
 * @brief Test the behavior of the device runtime PM API.
 *
 * Scenarios tested:
 *
 * - get + put
 * - get + asynchronous put until suspended
 * - get + asynchronous put + get (while suspend still ongoing)
 */
ZTEST(device_runtime_api, test_api)
{
	int ret;
	enum pm_device_state state;

	/* device is initially suspended */
	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);

	/*** get + put ***/

	/* usage: 0, +1, resume: yes */
	ret = pm_device_runtime_get(dev);
	zassert_equal(ret, 0);

	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_ACTIVE);

	/* usage: 1, +1, resume: no */
	ret = pm_device_runtime_get(dev);
	zassert_equal(ret, 0);

	/* usage: 2, -1, suspend: no */
	ret = pm_device_runtime_put(dev);
	zassert_equal(ret, 0);

	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_ACTIVE);

	/* usage: 1, -1, suspend: yes */
	ret = pm_device_runtime_put(dev);
	zassert_equal(ret, 0);

	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);

	/* usage: 0, -1, suspend: no (unbalanced call) */
	ret = pm_device_runtime_put(dev);
	zassert_equal(ret, -EALREADY);

	/*** get + asynchronous put until suspended ***/

	/* usage: 0, +1, resume: yes */
	ret = pm_device_runtime_get(dev);
	zassert_equal(ret, 0);

	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_ACTIVE);

	test_driver_pm_async(dev);

	/* usage: 1, -1, suspend: yes (queued) */
	ret = pm_device_runtime_put_async(dev);
	zassert_equal(ret, 0);

	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);

	/* usage: 0, -1, suspend: no (unbalanced call) */
	ret = pm_device_runtime_put(dev);
	zassert_equal(ret, -EALREADY);

	/* usage: 0, -1, suspend: no (unbalanced call) */
	ret = pm_device_runtime_put_async(dev);
	zassert_equal(ret, -EALREADY);

	/* unblock test driver and let it finish */
	test_driver_pm_done(dev);
	k_yield();

	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);

	/*** get + asynchronous put + get (while suspend still ongoing) ***/

	/* usage: 0, +1, resume: yes */
	ret = pm_device_runtime_get(dev);
	zassert_equal(ret, 0);

	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_ACTIVE);

	test_driver_pm_async(dev);

	/* usage: 1, -1, suspend: yes (queued) */
	ret = pm_device_runtime_put_async(dev);
	zassert_equal(ret, 0);

	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);

	/* let suspension start */
	k_yield();

	/* create and start get_runner thread
	 * get_runner thread is used to test synchronous path while asynchronous
	 * is ongoing. It is important to set its priority >= to the system work
	 * queue to make sure sync path run by the thread is forced to wait.
	 */
	k_thread_create(&get_runner_td, get_runner_stack,
			K_THREAD_STACK_SIZEOF(get_runner_stack), get_runner,
			NULL, NULL, NULL, CONFIG_SYSTEM_WORKQUEUE_PRIORITY, 0,
			K_NO_WAIT);
	k_yield();

	/* let driver suspend to finish and wait until get_runner finishes
	 * resuming the driver
	 */
	test_driver_pm_done(dev);
	k_thread_join(&get_runner_td, K_FOREVER);

	(void)pm_device_state_get(dev, &state);
	zassert_equal(state, PM_DEVICE_STATE_ACTIVE);

	/* Put operation should fail due the state be locked. */
	ret = pm_device_runtime_disable(dev);
	zassert_equal(ret, 0);

	pm_device_state_lock(dev);

	/* This operation should not succeed.  */
	ret = pm_device_runtime_enable(dev);
	zassert_equal(ret, -EPERM);

	/* After unlock the state, enable runtime should work. */
	pm_device_state_unlock(dev);

	ret = pm_device_runtime_enable(dev);
	zassert_equal(ret, 0);
}

static int pm_unsupported_init(const struct device *dev)
{
	return 0;
}

DEVICE_DEFINE(pm_unsupported_device, "PM Unsupported", pm_unsupported_init,
	      NULL, NULL, NULL, APPLICATION, 0, NULL);

ZTEST(device_runtime_api, test_unsupported)
{
	const struct device *const dev = DEVICE_GET(pm_unsupported_device);

	zassert_false(pm_device_runtime_is_enabled(dev), "");
	zassert_equal(pm_device_runtime_enable(dev), -ENOTSUP, "");
	zassert_equal(pm_device_runtime_disable(dev), -ENOTSUP, "");
	zassert_equal(pm_device_runtime_get(dev), -ENOTSUP, "");
	zassert_equal(pm_device_runtime_put(dev), -ENOTSUP, "");
}

void *device_runtime_api_setup(void)
{
	dev = device_get_binding("test_driver");
	zassert_not_null(dev, NULL);
	return NULL;
}

ZTEST_SUITE(device_runtime_api, NULL, device_runtime_api_setup,
			test_api_setup, test_api_teardown, NULL);
