/*
 * Copyright (c) 2016 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <logging/log.h>
LOG_MODULE_REGISTER(net_test, CONFIG_NET_MGMT_EVENT_LOG_LEVEL);

#include <zephyr.h>
#include <tc_util.h>
#include <errno.h>
#include <toolchain.h>
#include <linker/sections.h>

#include <net/dummy.h>
#include <net/net_mgmt.h>
#include <net/net_pkt.h>
#include <ztest.h>

#define TEST_INFO_STRING "mgmt event info"

#define TEST_MGMT_REQUEST		0x17AB1234
#define TEST_MGMT_EVENT			0x97AB1234
#define TEST_MGMT_EVENT_UNHANDLED	0x97AB4321
#define TEST_MGMT_EVENT_INFO_SIZE	\
	MAX(sizeof(TEST_INFO_STRING), sizeof(struct in6_addr))

/* Notifier infra */
static u32_t event2throw;
static u32_t throw_times;
static int throw_sleep;
static bool with_info;
static K_THREAD_STACK_DEFINE(thrower_stack, 512 + CONFIG_TEST_EXTRA_STACKSIZE);
static struct k_thread thrower_thread_data;
static struct k_sem thrower_lock;

/* Receiver infra */
static u32_t rx_event;
static u32_t rx_calls;
static size_t info_length_in_test;
static struct net_mgmt_event_callback rx_cb;
static char *info_string = TEST_INFO_STRING;

static struct in6_addr addr6 = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0,
				     0, 0, 0, 0, 0, 0, 0, 0x1 } } };

static char info_data[TEST_MGMT_EVENT_INFO_SIZE];

static int test_mgmt_request(u32_t mgmt_request,
			     struct net_if *iface, void *data, u32_t len)
{
	u32_t *test_data = data;

	ARG_UNUSED(iface);

	if (len == sizeof(u32_t)) {
		*test_data = 1U;

		return 0;
	}

	return -EIO;
}

NET_MGMT_REGISTER_REQUEST_HANDLER(TEST_MGMT_REQUEST, test_mgmt_request);

int fake_dev_init(struct device *dev)
{
	ARG_UNUSED(dev);

	return 0;
}

static void fake_iface_init(struct net_if *iface)
{
	static u8_t mac[8] = { 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d};

	net_if_set_link_addr(iface, mac, 8, NET_LINK_DUMMY);
}

static int fake_iface_send(struct device *dev, struct net_pkt *pkt)
{
	return 0;
}

static struct dummy_api fake_iface_api = {
	.iface_api.init = fake_iface_init,
	.send = fake_iface_send,
};

NET_DEVICE_INIT(net_event_test, "net_event_test",
		fake_dev_init, NULL, NULL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
		&fake_iface_api, DUMMY_L2, NET_L2_GET_CTX_TYPE(DUMMY_L2), 127);

void test_requesting_nm(void)
{
	u32_t data = 0U;

	TC_PRINT("- Request Net MGMT\n");

	zassert_false(net_mgmt(TEST_MGMT_REQUEST, NULL, &data, sizeof(data)),
		      "Requesting Net MGMT failed");
}

static void thrower_thread(void)
{
	while (1) {
		k_sem_take(&thrower_lock, K_FOREVER);

		TC_PRINT("\tThrowing event 0x%08X %u times\n",
			 event2throw, throw_times);

		for (; throw_times; throw_times--) {
			k_sleep(throw_sleep);

			if (with_info) {
				net_mgmt_event_notify_with_info(
					event2throw, net_if_get_default(),
					info_data,
					TEST_MGMT_EVENT_INFO_SIZE);
			} else {
				net_mgmt_event_notify(event2throw,
						      net_if_get_default());
			}

		}
	}
}

static void receiver_cb(struct net_mgmt_event_callback *cb,
			u32_t nm_event, struct net_if *iface)
{
	TC_PRINT("\t\tReceived event 0x%08X\n", nm_event);

	if (with_info && cb->info) {
		if (cb->info_length != info_length_in_test) {
			rx_calls = (u32_t) -1;
			return;
		}

		if (memcmp(info_data, cb->info, info_length_in_test)) {
			rx_calls = (u32_t) -1;
			return;
		}
	}

	rx_event = nm_event;
	rx_calls++;
}

static int sending_event(u32_t times, bool receiver, bool info)
{
	TC_PRINT("- Sending event %u times, %s a receiver, %s info\n",
		 times, receiver ? "with" : "without",
		 info ? "with" : "without");

	event2throw = TEST_MGMT_EVENT;
	throw_times = times;
	with_info = info;

	if (receiver) {
		net_mgmt_add_event_callback(&rx_cb);
	}

	k_sem_give(&thrower_lock);

	k_yield();

	if (receiver) {
		TC_PRINT("\tReceived 0x%08X %u times\n",
			 rx_event, rx_calls);

		zassert_equal(rx_event, event2throw, "rx_event check failed");
		zassert_equal(rx_calls, times, "rx_calls check failed");

		net_mgmt_del_event_callback(&rx_cb);
		rx_event = rx_calls = 0U;
	}

	return TC_PASS;
}

static int test_sending_event(u32_t times, bool receiver)
{
	return sending_event(times, receiver, false);
}

static int test_sending_event_info(u32_t times, bool receiver)
{
	return sending_event(times, receiver, true);
}

static int test_synchronous_event_listener(u32_t times, bool on_iface)
{
	u32_t event_mask;
	int ret;

	TC_PRINT("- Synchronous event listener %s\n",
		 on_iface ? "on interface" : "");

	event2throw = TEST_MGMT_EVENT | (on_iface ? NET_MGMT_IFACE_BIT : 0);
	throw_times = times;
	throw_sleep = K_MSEC(200);

	event_mask = event2throw;

	k_sem_give(&thrower_lock);

	if (on_iface) {
		ret = net_mgmt_event_wait_on_iface(net_if_get_default(),
						   event_mask, NULL, NULL,
						   NULL, K_SECONDS(1));
	} else {
		ret = net_mgmt_event_wait(event_mask, NULL, NULL, NULL, NULL,
					  K_SECONDS(1));
	}

	if (ret < 0) {
		if (ret == -ETIMEDOUT) {
			TC_ERROR("Call timed out\n");
		}

		return TC_FAIL;
	}

	return TC_PASS;
}

static void initialize_event_tests(void)
{
	event2throw = 0U;
	throw_times = 0U;
	throw_sleep = K_NO_WAIT;
	with_info = false;

	rx_event = 0U;
	rx_calls = 0U;

	k_sem_init(&thrower_lock, 0, UINT_MAX);

	info_length_in_test = TEST_MGMT_EVENT_INFO_SIZE;
	memcpy(info_data, info_string, strlen(info_string) + 1);

	net_mgmt_init_event_callback(&rx_cb, receiver_cb, TEST_MGMT_EVENT);

	k_thread_create(&thrower_thread_data, thrower_stack,
			K_THREAD_STACK_SIZEOF(thrower_stack),
			(k_thread_entry_t)thrower_thread,
			NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
}

static int test_core_event(u32_t event, bool (*func)(void))
{
	TC_PRINT("- Triggering core event: 0x%08X\n", event);

	info_length_in_test = sizeof(struct in6_addr);
	memcpy(info_data, &addr6, sizeof(addr6));

	net_mgmt_init_event_callback(&rx_cb, receiver_cb, event);

	net_mgmt_add_event_callback(&rx_cb);

	zassert_true(func(), "func() check failed");

	k_yield();

	zassert_true(rx_calls > 0 && rx_calls != -1, "rx_calls empty");
	zassert_equal(rx_event, event, "rx_event check failed, "
		      "0x%08x vs 0x%08x", rx_event, event);

	net_mgmt_del_event_callback(&rx_cb);
	rx_event = rx_calls = 0U;

	return TC_PASS;
}

static bool _iface_ip6_add(void)
{
	if (net_if_ipv6_addr_add(net_if_get_default(),
				 &addr6, NET_ADDR_MANUAL, 0)) {
		return true;
	}

	return false;
}

static bool _iface_ip6_del(void)
{
	if (net_if_ipv6_addr_rm(net_if_get_default(), &addr6)) {
		return true;
	}

	return false;
}

void test_mgmt(void)
{
	TC_PRINT("Starting Network Management API test\n");

	test_requesting_nm();

	initialize_event_tests();

	zassert_false(test_sending_event(1, false),
		      "test_sending_event failed");

	zassert_false(test_sending_event(2, false),
		      "test_sending_event failed");

	zassert_false(test_sending_event(1, true),
		      "test_sending_event failed");

	zassert_false(test_sending_event(2, true),
		      "test_sending_event failed");

	zassert_false(test_sending_event_info(1, false),
		      "test_sending_event failed");

	zassert_false(test_sending_event_info(2, false),
		      "test_sending_event failed");

	zassert_false(test_sending_event_info(1, true),
		      "test_sending_event failed");

	zassert_false(test_sending_event_info(2, true),
		      "test_sending_event failed");

	zassert_false(test_core_event(NET_EVENT_IPV6_ADDR_ADD, _iface_ip6_add),
		      "test_core_event failed");

	zassert_false(test_core_event(NET_EVENT_IPV6_ADDR_DEL, _iface_ip6_del),
		      "test_core_event failed");

	zassert_false(test_synchronous_event_listener(2, false),
		      "test_synchronous_event_listener failed");

	zassert_false(test_synchronous_event_listener(2, true),
		      "test_synchronous_event_listener failed");
}

void test_main(void)
{
	ztest_test_suite(test_mgmt_fn, ztest_unit_test(test_mgmt));
	ztest_run_test_suite(test_mgmt_fn);
}
