/*-------------------------------------------------------------------------
 * drawElements C++ Base Library
 * -----------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * 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.
 *
 *//*!
 * \file
 * \brief Unique pointer.
 *//*--------------------------------------------------------------------*/

#include "deUniquePtr.hpp"

#include <exception>

namespace de
{

namespace
{

class Object
{
public:
	Object (bool& exists)
		: m_exists(exists)
	{
		m_exists = true;
	}

	~Object (void)
	{
		m_exists = false;
	}

private:
	bool& m_exists;
};

struct CustomDeleter
{
	CustomDeleter (bool* called) : m_called(called) {}

	void operator() (Object* ptr)
	{
		DE_TEST_ASSERT(!*m_called);
		delete ptr;
		*m_called = true;
	}

	bool* m_called;
};

MovePtr<Object> createObject (bool& exists)
{
	UniquePtr<Object> objectPtr(new Object(exists));
	return objectPtr.move();
}

} // anonymous

void UniquePtr_selfTest (void)
{
	// Basic test.
	{
		bool exists = false;
		{
			UniquePtr<Object> ptr(new Object(exists));
			DE_TEST_ASSERT(exists);
			DE_TEST_ASSERT(ptr.get() != DE_NULL);
		}
		DE_TEST_ASSERT(!exists);
	}

	// Exception test.
	{
		bool exists = false;
		try
		{
			UniquePtr<Object> ptr(new Object(exists));
			DE_TEST_ASSERT(exists);
			DE_TEST_ASSERT(ptr.get() != DE_NULL);
			throw std::exception();
		}
		catch (const std::exception&)
		{
			DE_TEST_ASSERT(!exists);
		}
		DE_TEST_ASSERT(!exists);
	}

	// Expression test.
	{
		bool exists = false;
		bool test	= (UniquePtr<Object>(new Object(exists))).get() != DE_NULL && exists;
		DE_TEST_ASSERT(!exists);
		DE_TEST_ASSERT(test);
	}

	// Custom deleter.
	{
		bool exists = false;
		bool deleterCalled = false;
		{
			UniquePtr<Object, CustomDeleter> ptr(new Object(exists), CustomDeleter(&deleterCalled));
			DE_TEST_ASSERT(exists);
			DE_TEST_ASSERT(!deleterCalled);
			DE_TEST_ASSERT(ptr.get() != DE_NULL);
		}
		DE_TEST_ASSERT(!exists);
		DE_TEST_ASSERT(deleterCalled);
	}

	// MovePtr -> MovePtr moving
	{
		bool exists = false;
		MovePtr<Object> ptr(new Object(exists));
		DE_TEST_ASSERT(exists);
		{
			MovePtr<Object> ptr2 = ptr;
			DE_TEST_ASSERT(exists);
			// Ownership moved to ptr2, should be deleted when ptr2 goes out of scope.
		}
		DE_TEST_ASSERT(!exists);
	}

	// UniquePtr -> MovePtr moving
	{
		bool exists = false;
		UniquePtr<Object> ptr(new Object(exists));
		DE_TEST_ASSERT(exists);
		{
			MovePtr<Object> ptr2 = ptr.move();
			DE_TEST_ASSERT(exists);
			// Ownership moved to ptr2, should be deleted when ptr2 goes out of scope.
		}
		DE_TEST_ASSERT(!exists);
	}

	// MovePtr -> UniquePtr moving
	{
		bool exists = false;
		{
			UniquePtr<Object> ptr(createObject(exists));
			DE_TEST_ASSERT(exists);
		}
		DE_TEST_ASSERT(!exists);
	}

	// MovePtr assignment
	{
		bool exists1 = false;
		bool exists2 = false;
		MovePtr<Object> ptr1(new Object(exists1));
		MovePtr<Object> ptr2(new Object(exists2));
		ptr1 = ptr2;
		DE_TEST_ASSERT(!exists1);
		DE_TEST_ASSERT(exists2);
	}

	// MovePtr stealing
	{
		bool exists = false;
		Object* raw = DE_NULL;
		{
			MovePtr<Object> ptr1(new Object(exists));
			raw = ptr1.release();
			DE_TEST_ASSERT(raw != DE_NULL);
			DE_TEST_ASSERT(ptr1.get() == DE_NULL);
			DE_TEST_ASSERT(exists);
		}
		DE_TEST_ASSERT(exists);
		delete raw;
		DE_TEST_ASSERT(!exists);
	}

	// Null MovePtr and assigning to it.
	{
		bool exists = false;
		{
			MovePtr<Object> ptr1;
			DE_TEST_ASSERT(ptr1.get() == DE_NULL);
			MovePtr<Object> ptr2(new Object(exists));
			ptr1 = ptr2;
			DE_TEST_ASSERT(exists);
			DE_TEST_ASSERT(ptr1.get() != DE_NULL);
			DE_TEST_ASSERT(ptr2.get() == DE_NULL);
		}
		DE_TEST_ASSERT(!exists);
	}

#if 0
	// UniquePtr assignment or copy construction should not compile. This
	// piece of code is intentionally commented out. To manually test that
	// copying a UniquePtr is statically forbidden, uncomment and try to
	// compile.
	{
		bool exists = false;
		UniquePtr<Object> ptr(new Object(exists));
		{
			UniquePtr<Object> ptr2(ptr);
			DE_TEST_ASSERT(exists);
		}
		DE_TEST_ASSERT(!exists);
	}
#endif
}

} // de
