/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 "begin_native.hpp"
#include <memory>
#include <functional>
#include "end_native.hpp"
#include <native_conditional_unique_ptr.hpp>
#include "Utils.hpp"

using namespace System;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;

using namespace Apache::Geode::Client;

namespace cliunittests
{

  class NativeTestClass {
  public:
    int i;
    NativeTestClass(int i) : i(i) {};
  };

  class UniqueDestructNativeTestClass {
  public:
    int i;
    UniqueDestructNativeTestClass(int i, bool& destructorCalled) : i(i), destructorCalled(destructorCalled) {};
    ~UniqueDestructNativeTestClass() { destructorCalled = true; }
    void GCCollectAndAssertDestructorCalledEquals(bool expected, const bool& destructorCalled)
    {
      Utils::GCCollectAndWait();
      Assert::AreEqual(expected, destructorCalled);
    }
 

  private:
    bool& destructorCalled;
  };


	[TestClass]
	public ref class native_conditional_unique_ptrTests
	{
	private:
		TestContext^ testContextInstance;

	public: 
		/// <summary>
		///Gets or sets the test context which provides
		///information about and functionality for the current test run.
		///</summary>
		property Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ TestContext
		{
			Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ get()
			{
				return testContextInstance;
			}
			System::Void set(Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ value)
			{
				testContextInstance = value;
			}
		};

		#pragma region Additional test attributes
		//
		//You can use the following additional attributes as you write your tests:
		//
		//Use ClassInitialize to run code before running the first test in the class
		//[ClassInitialize()]
		//static void MyClassInitialize(TestContext^ testContext) {};
		//
		//Use ClassCleanup to run code after all tests in a class have run
		//[ClassCleanup()]
		//static void MyClassCleanup() {};
		//
		//Use TestInitialize to run code before running each test
		//[TestInitialize()]
		//void MyTestInitialize() {};
		//
		//Use TestCleanup to run code after each test has run
		//[TestCleanup()]
		//void MyTestCleanup() {};
		//
		#pragma endregion 

		[TestMethod]
		void NullptrInstance()
		{
      auto p = gcnew native_conditional_unique_ptr<NativeTestClass>(std::unique_ptr<NativeTestClass>(__nullptr));
      
      Assert::IsNotNull(p);
      Assert::IsTrue(__nullptr == p->get());
		};

    [TestMethod]
		void NullptrInstanceUnowned()
		{
      auto p = gcnew native_conditional_unique_ptr<NativeTestClass>(__nullptr);
      
      Assert::IsNotNull(p);
      Assert::IsTrue(__nullptr == p->get());
		};

    [TestMethod]
		void AnInstance()
		{
      auto n = std::make_unique<NativeTestClass>(1);
      auto p = gcnew native_conditional_unique_ptr<NativeTestClass>(std::move(n));

      Assert::IsTrue(__nullptr == n);
      Assert::IsNotNull(p);
      Assert::IsFalse(__nullptr == p->get());
      Assert::AreEqual(1, p->get()->i);
		};

    [TestMethod]
		void AnInstanceUnowned()
		{
      auto n = new NativeTestClass(1);
      try
      {
        auto p = gcnew native_conditional_unique_ptr<NativeTestClass>(n);

        Assert::IsNotNull(p);
        Assert::IsFalse(__nullptr == p->get());
        Assert::AreEqual(1, p->get()->i);
      }
      finally
      {
        delete n;
      }
		};


    [TestMethod]
    void DestructorCalledAfterGC()
    {
      bool destructorCalled = false;
      auto p = gcnew native_conditional_unique_ptr<UniqueDestructNativeTestClass>(std::make_unique<UniqueDestructNativeTestClass>(1, destructorCalled));

      // p eligible for GC
      Utils::GCCollectAndWait();

      Assert::IsTrue(destructorCalled);
    }

    [TestMethod]
    void DestructorNotCalledAfterGC()
    {
      bool destructorCalled = false;
      auto n = new UniqueDestructNativeTestClass(1, destructorCalled);
      try
      {
        auto p = gcnew native_conditional_unique_ptr<UniqueDestructNativeTestClass>(n);
        auto w = gcnew WeakReference(p);

        // p eligible for GC
        Utils::GCCollectAndWait();

        Assert::IsFalse(w->IsAlive);
        Assert::IsFalse(destructorCalled);
      }
      finally
      {
        delete n;
        Assert::IsTrue(destructorCalled);
      }
    }

    [TestMethod]
    void DestructorCalledAfterNativeUniquePtrIsDestructed()
    {
      bool destructorCalled = false;
      auto n = std::make_unique<UniqueDestructNativeTestClass>(1, destructorCalled);
      auto p = gcnew native_conditional_unique_ptr<UniqueDestructNativeTestClass>(std::move(n));

      // p eligible for GC
      Utils::GCCollectAndWait();

      // n does not have a ref on our native pointer, so native not deleted
      Assert::IsTrue(destructorCalled);
    }


    [TestMethod]
    void DestructorCalledAfterAllReferencesReleased()
    {
      bool destructorCalled = false;
      auto p = gcnew native_conditional_unique_ptr<UniqueDestructNativeTestClass>(std::make_unique<UniqueDestructNativeTestClass>(1, destructorCalled));
      auto q = p;

      // only p eligible for collection
      Utils::GCCollectAndWait();

      Assert::IsFalse(destructorCalled);
     
      // keeps q ineligible for collection
      GC::KeepAlive(q);

      // q eligible for collection
      Utils::GCCollectAndWait();

      Assert::IsTrue(destructorCalled);
    }

    [TestMethod]
    void GCCollectsWhileExecutingOnNativeClass()
    {
      bool destructorCalled = false;
      auto p = gcnew native_conditional_unique_ptr<UniqueDestructNativeTestClass>(std::make_unique<UniqueDestructNativeTestClass>(1, destructorCalled));

      p->get()->GCCollectAndAssertDestructorCalledEquals(true, destructorCalled);
    }

    [TestMethod]
    void GCCollectsAfterExecutingOnNativeClass()
    {
      bool destructorCalled = false;
      auto p = gcnew native_conditional_unique_ptr<UniqueDestructNativeTestClass>(std::make_unique<UniqueDestructNativeTestClass>(1, destructorCalled));

      p->get()->GCCollectAndAssertDestructorCalledEquals(false, destructorCalled);
      // keeps p ineligible for collection
      GC::KeepAlive(p);

      // p eligible for collection
      Utils::GCCollectAndWait();
      Assert::IsTrue(destructorCalled);
    }

  };
}
