142 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
This file is part of Telegram Desktop,
 | 
						|
the official desktop version of Telegram messaging app, see https://telegram.org
 | 
						|
 | 
						|
Telegram Desktop is free software: you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation, either version 3 of the License, or
 | 
						|
(at your option) any later version.
 | 
						|
 | 
						|
It is distributed in the hope that it will be useful,
 | 
						|
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
						|
GNU General Public License for more details.
 | 
						|
 | 
						|
In addition, as a special exception, the copyright holders give permission
 | 
						|
to link the code of portions of this program with the OpenSSL library.
 | 
						|
 | 
						|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | 
						|
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 | 
						|
*/
 | 
						|
#include "catch.hpp"
 | 
						|
 | 
						|
#include "base/flags.h"
 | 
						|
 | 
						|
namespace MethodNamespace {
 | 
						|
 | 
						|
template <typename Enum>
 | 
						|
void TestFlags(Enum a, Enum b, Enum c) {
 | 
						|
	auto abc = a | b;
 | 
						|
	abc |= c;
 | 
						|
	auto test = abc != a;
 | 
						|
	CHECK(abc != a);
 | 
						|
	CHECK(abc != (a | b));
 | 
						|
	CHECK((abc & a) == a);
 | 
						|
	CHECK((abc & b) == b);
 | 
						|
	CHECK((abc & c) == c);
 | 
						|
	CHECK((abc & ~a) == (b | c));
 | 
						|
	CHECK((abc & ~(b | c)) == a);
 | 
						|
	CHECK((abc ^ a) == (abc & ~a));
 | 
						|
 | 
						|
	auto another = a | b;
 | 
						|
	another |= c;
 | 
						|
	CHECK(abc == another);
 | 
						|
	another &= ~b;
 | 
						|
	CHECK(another == (a | c));
 | 
						|
	another ^= a;
 | 
						|
	CHECK(another == c);
 | 
						|
	another = 0;
 | 
						|
	another = nullptr;
 | 
						|
	auto is_zero = ((another & abc) == 0);
 | 
						|
	CHECK(is_zero);
 | 
						|
	CHECK(!(another & abc));
 | 
						|
	auto more = a | another;
 | 
						|
	auto just = a | 0;
 | 
						|
	CHECK(more == just);
 | 
						|
	CHECK(just);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace MethodNamespace
 | 
						|
 | 
						|
namespace FlagsNamespace {
 | 
						|
 | 
						|
enum class Flag : int {
 | 
						|
	one = (1 << 0),
 | 
						|
	two = (1 << 1),
 | 
						|
	three = (1 << 2),
 | 
						|
};
 | 
						|
inline constexpr auto is_flag_type(Flag) { return true; }
 | 
						|
 | 
						|
class Class {
 | 
						|
public:
 | 
						|
	enum class Public : long {
 | 
						|
		one = (1 << 2),
 | 
						|
		two = (1 << 1),
 | 
						|
		three = (1 << 0),
 | 
						|
	};
 | 
						|
	friend inline constexpr auto is_flag_type(Public) { return true; }
 | 
						|
 | 
						|
	static void TestPrivate();
 | 
						|
 | 
						|
private:
 | 
						|
	enum class Private : long {
 | 
						|
		one = (1 << 0),
 | 
						|
		two = (1 << 1),
 | 
						|
		three = (1 << 2),
 | 
						|
	};
 | 
						|
	friend inline constexpr auto is_flag_type(Private) { return true; }
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
void Class::TestPrivate() {
 | 
						|
	MethodNamespace::TestFlags(Private::one, Private::two, Private::three);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace FlagsNamespace
 | 
						|
 | 
						|
namespace ExtendedNamespace {
 | 
						|
 | 
						|
enum class Flag : int {
 | 
						|
	one = (1 << 3),
 | 
						|
	two = (1 << 4),
 | 
						|
	three = (1 << 5),
 | 
						|
};
 | 
						|
 | 
						|
} // namespace ExtendedNamespace
 | 
						|
 | 
						|
namespace base {
 | 
						|
 | 
						|
template<>
 | 
						|
struct extended_flags<ExtendedNamespace::Flag> {
 | 
						|
	using type = FlagsNamespace::Flag;
 | 
						|
};
 | 
						|
 | 
						|
} // namespace base
 | 
						|
 | 
						|
TEST_CASE("flags operators on scoped enums", "[flags]") {
 | 
						|
	SECTION("testing non-member flags") {
 | 
						|
		MethodNamespace::TestFlags(
 | 
						|
			FlagsNamespace::Flag::one,
 | 
						|
			FlagsNamespace::Flag::two,
 | 
						|
			FlagsNamespace::Flag::three);
 | 
						|
	}
 | 
						|
	SECTION("testing public member flags") {
 | 
						|
		MethodNamespace::TestFlags(
 | 
						|
			FlagsNamespace::Class::Public::one,
 | 
						|
			FlagsNamespace::Class::Public::two,
 | 
						|
			FlagsNamespace::Class::Public::three);
 | 
						|
	}
 | 
						|
	SECTION("testing private member flags") {
 | 
						|
		FlagsNamespace::Class::TestPrivate();
 | 
						|
	}
 | 
						|
	SECTION("testing extended flags") {
 | 
						|
		MethodNamespace::TestFlags(
 | 
						|
			ExtendedNamespace::Flag::one,
 | 
						|
			ExtendedNamespace::Flag::two,
 | 
						|
			ExtendedNamespace::Flag::three);
 | 
						|
 | 
						|
		auto onetwo = FlagsNamespace::Flag::one | ExtendedNamespace::Flag::two;
 | 
						|
		auto twoone = ExtendedNamespace::Flag::two | FlagsNamespace::Flag::one;
 | 
						|
		CHECK(onetwo == twoone);
 | 
						|
	}
 | 
						|
}
 |