<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and <NAME>
//
// 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
//
//     http://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 <common.cxx>
#include <util/delegate.hpp>

#include <string>

struct count_ctor
{
	size_t copy_count = 0;
	size_t move_count = 0;

	explicit count_ctor() {}

	count_ctor(const count_ctor& other) :
		copy_count(other.copy_count + 1),
		move_count(other.move_count)
	{}

	count_ctor(count_ctor&& other) :
		copy_count(other.copy_count),
		move_count(other.move_count + 1)
	{}
};

struct count_ctor_wrap
{
	count_ctor cc;
	explicit count_ctor_wrap() {};

	count_ctor foo(count_ctor arg) { return arg; }
};

struct user_closure
{
	int cap_val;

	explicit user_closure(int c) :
		cap_val(c)
	{}

	user_closure(const user_closure&) = default;
	user_closure(user_closure&&) = default;

	int operator() (int& arg)
	{
		arg += cap_val;
		return arg++;
	}

	int operator() ()
	{
		return cap_val;
	}
};

class user_class
{
public:
	using del_t = delegate<int(int)>;

	explicit user_class(int val) : val_(val) {}

	int foo(int a)
	{
		return a * val_;
	}

	int simple_ret()
	{
		return val_;
	}

	del_t get_del()
	{
		return{ this, &user_class::foo };
	}
private:
	int val_;
};

const std::string f1() { return "f1"; }
const std::string f2() { return "f2"; }

CASE("A delegate can be compared to nullptr")
{
	delegate<const std::string()> d{ f1 };
	EXPECT_NOT(d == nullptr);
	EXPECT(d != nullptr);

	delegate<const std::string()> d2;
	EXPECT(d2 == nullptr);
	EXPECT_NOT(d2 != nullptr);

	auto func = [](delegate<int()> del) { return static_cast<bool>(del); };
	bool valid = func(nullptr);
	EXPECT(valid == false);
}

CASE("A delegate can be copy assigned with a different closure type")
{
	using func_t = std::function<int(void)>;
	using del_t = delegate<int(void), spec::inplace, sizeof(func_t)>;

	struct copy_closure
	{
		int cap_val;
		explicit copy_closure(int c) : cap_val(c) {}

		copy_closure(const copy_closure&) = default;
		copy_closure(copy_closure&&) = default;

		int operator() () { return cap_val; }
	};

	int cap_val = 3;
	auto lam = [cap_val]() { return cap_val; };

	del_t del_a = func_t{ lam };
	del_t del_b = copy_closure{ -1 };

	del_b = del_a;
	int ret_val = del_b();
	EXPECT(ret_val == cap_val);
}

CASE("A delegate can swap values with another delegate")
{
	delegate<int()> d2 = [] { return 53; };
	delegate<int()> d3 = [] { return 35; };

	EXPECT(d2() == 53);
	EXPECT(d3() == 35);

	std::swap(d2, d3);

	EXPECT(d2() == 35);
	EXPECT(d3() == 53);
}

CASE("A delegate returns correct value (1)")
{
	std::vector<std::string> v = { "Something", "Something else" };
	delegate<size_t()> d = [v] { return v.size(); };

	size_t v_size = v.size();
	size_t d_vector_size = d();

	EXPECT(v_size == 2u);
	EXPECT(v_size == d_vector_size);
}

CASE("A delegate returns correct value (2)")
{
	std::vector<std::string> v2;
	delegate<size_t()> d2 = [v2] { return v2.size(); };
<commit_msg>Add unit test for empty generic lambda delegate issue<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and <NAME>
//
// 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
//
//     http://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 <common.cxx>
#include <util/delegate.hpp>

#include <string>

struct count_ctor
{
	size_t copy_count = 0;
	size_t move_count = 0;

	explicit count_ctor() {}

	count_ctor(const count_ctor& other) :
		copy_count(other.copy_count + 1),
		move_count(other.move_count)
	{}

	count_ctor(count_ctor&& other) :
		copy_count(other.copy_count),
		move_count(other.move_count + 1)
	{}
};

struct count_ctor_wrap
{
	count_ctor cc;
	explicit count_ctor_wrap() {};

	count_ctor foo(count_ctor arg) { return arg; }
};

struct user_closure
{
	int cap_val;

	explicit user_closure(int c) :
		cap_val(c)
	{}

	user_closure(const user_closure&) = default;
	user_closure(user_closure&&) = default;

	int operator() (int& arg)
	{
		arg += cap_val;
		return arg++;
	}

	int operator() ()
	{
		return cap_val;
	}
};

class user_class
{
public:
	using del_t = delegate<int(int)>;

	explicit user_class(int val) : val_(val) {}

	int foo(int a)
	{
		return a * val_;
	}

	int simple_ret()
	{
		return val_;
	}

	del_t get_del()
	{
		return{ this, &user_class::foo };
	}
private:
	int val_;
};

const std::string f1() { return "f1"; }
const std::string f2() { return "f2"; }

CASE("A delegate can be compared to nullptr")
{
	delegate<const std::string()> d{ f1 };
	EXPECT_NOT(d == nullptr);
	EXPECT(d != nullptr);

	delegate<const std::string()> d2;
	EXPECT(d2 == nullptr);
	EXPECT_NOT(d2 != nullptr);

	auto func = [](delegate<int()> del) { return static_cast<bool>(del); };
	bool valid = func(nullptr);
	EXPECT(valid == false);
}

CASE("A delegate can be copy assigned with a different closure type")
{
	using func_t = std::function<int(void)>;
	using del_t = delegate<int(void), spec::inplace, sizeof(func_t)>;

	struct copy_closure
	{
		int cap_val;
		explicit copy_closure(int c) : cap_val(c) {}

		copy_closure(const copy_closure&) = default;
		copy_closure(copy_closure&&) = default;

		int operator() () { return cap_val; }
	};

	int cap_val = 3;
	auto lam = [cap_val]() { return cap_val; };

	del_t del_a = func_t{ lam };
	del_t del_b = copy_closure{ -1 };

	del_b = del_a;
	int ret_val = del_b();
	EXPECT(ret_val == cap_val);
}

CASE("A delegate can swap values with another delegate")
{
	delegate<int()> d2 = [] { return 53; };
	delegate<int()> d3 = [] { return 35; };

	EXPECT(d2() == 53);
	EXPECT(d3() == 35);

	std::swap(d2, d3);

	EXPECT(d2() == 35);
	EXPECT(d3() == 53);
}

CASE("A delegate can be constructed with a generic lambda")
{
	using del_t = delegate<void(int&)>;

	auto test = [&lest_env](del_t& del)
	{
		EXPECT(static_cast<bool>(del));

		int start_val = 3;
		int val = start_val;
		del(val);

		EXPECT(val == start_val + 1);
	};

	del_t del_a = [](auto& i) { ++i; };

	del_t del_b;
	del_b = del_a;

	test(del_a);
	test(del_b);
}

CASE("A delegate returns correct value (1)")
{
	std::vector<std::string> v = { "Something", "Something else" };
	delegate<size_t()> d = [v] { return v.size(); };

	size_t v_size = v.size();
	size_t d_vector_size = d();

	EXPECT(v_size == 2u);
	EXPECT(v_size == d_vector_size);
}

CASE("A delegate returns correct value (2)")
{
	std::vector<std::string> v2;
	delegate<size_t()> d2 = [v2] { return v2.size(); };

{'fraction_non_alphanumeric': 0.1508223024468512, 'fraction_numerical': 0.01444043321299639, 'mean_word_length': 4.119780971937029, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1655277', 'n_tokens_mistral': 2866, 'n_tokens_neox': 2735, 'n_words': 764}