blob: 5ed9e814d7c988d2e43611d1e06ace741407d8d5 [file] [log] [blame]
/*
* 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_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_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_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_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 DestructorCalledAfterGC()
{
bool destructorCalled = false;
auto p = gcnew native_unique_ptr<UniqueDestructNativeTestClass>(std::make_unique<UniqueDestructNativeTestClass>(1, destructorCalled));
// p eligible for GC
Utils::GCCollectAndWait();
Assert::IsTrue(destructorCalled);
}
[TestMethod]
void DestructorCalledAfterNativeUniquePtrIsDestructed()
{
bool destructorCalled = false;
auto n = std::make_unique<UniqueDestructNativeTestClass>(1, destructorCalled);
auto p = gcnew native_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_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_unique_ptr<UniqueDestructNativeTestClass>(std::make_unique<UniqueDestructNativeTestClass>(1, destructorCalled));
p->get()->GCCollectAndAssertDestructorCalledEquals(true, destructorCalled);
}
[TestMethod]
void GCCollectsAfterExecutingOnNativeClass()
{
bool destructorCalled = false;
auto p = gcnew native_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);
}
};
}