blob: 281f18c492b39015de3c4e095c1fdaf9ffcb353d [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 "gtest/gtest.h"
#include "utility/ScopedDeleter.hpp"
namespace quickstep {
namespace {
// Various dummy classes that set an external bool to let us know when a
// destructor is invoked.
class Base {
public:
explicit Base(bool *base_deleted)
: base_deleted_(base_deleted) {
}
virtual ~Base() {
*base_deleted_ = true;
}
private:
bool *base_deleted_;
};
class DerivedA : public Base {
public:
DerivedA(bool *base_deleted, bool *derived_a_deleted)
: Base(base_deleted),
derived_a_deleted_(derived_a_deleted) {
}
virtual ~DerivedA() {
*derived_a_deleted_ = true;
}
private:
bool *derived_a_deleted_;
};
class DerivedB : public Base {
public:
DerivedB(bool *base_deleted, bool *derived_b_deleted)
: Base(base_deleted),
derived_b_deleted_(derived_b_deleted) {
}
virtual ~DerivedB() {
*derived_b_deleted_ = true;
}
private:
bool *derived_b_deleted_;
};
class Other {
public:
explicit Other(bool *other_deleted)
: other_deleted_(other_deleted) {
}
~Other() {
*other_deleted_ = true;
}
private:
bool *other_deleted_;
};
} // namespace
TEST(ScopedDeleterTest, DeletionTest) {
// Setup flags that record whether objects are deleted.
bool base_1_deleted, base_2_deleted,
derived_a_1_base_deleted, derived_a_1_derived_deleted,
derived_a_2_base_deleted, derived_a_2_derived_deleted,
derived_b_1_base_deleted, derived_b_1_derived_deleted,
derived_b_2_base_deleted, derived_b_2_derived_deleted,
other_1_deleted, other_2_deleted;
base_1_deleted = base_2_deleted
= derived_a_1_base_deleted = derived_a_1_derived_deleted
= derived_a_2_base_deleted = derived_a_2_derived_deleted
= derived_b_1_base_deleted = derived_b_1_derived_deleted
= derived_b_2_base_deleted = derived_b_2_derived_deleted
= other_1_deleted = other_2_deleted
= false;
// Create objects and throw them into the ScopedDeleter.
ScopedDeleter deleter;
deleter.addObject(new Base(&base_1_deleted));
deleter.addObject(new Base(&base_2_deleted));
// Add one instance of DerivedA as itself, and one as a Base class pointer.
deleter.addObject(new DerivedA(&derived_a_1_base_deleted,
&derived_a_1_derived_deleted));
Base *derived_a_2 = new DerivedA(&derived_a_2_base_deleted,
&derived_a_2_derived_deleted);
deleter.addObject(derived_a_2);
// Do the same for the other derived class.
deleter.addObject(new DerivedB(&derived_b_1_base_deleted,
&derived_b_1_derived_deleted));
Base *derived_b_2 = new DerivedB(&derived_b_2_base_deleted,
&derived_b_2_derived_deleted);
deleter.addObject(derived_b_2);
// Also throw in a couple of objects that aren't part of the same inheritance
// heirarchy.
deleter.addObject(new Other(&other_1_deleted));
deleter.addObject(new Other(&other_2_deleted));
// Add some heap-allocated built-in types (we don't directly check whether
// these are deleted, but running under valgrind should report no leaks).
deleter.addObject(new int);
deleter.addObject(new float);
// Have the deleter delete everything and verify that destructors were
// invoked.
deleter.deleteAll();
EXPECT_TRUE(base_1_deleted);
EXPECT_TRUE(base_2_deleted);
EXPECT_TRUE(derived_a_1_base_deleted);
EXPECT_TRUE(derived_a_1_derived_deleted);
EXPECT_TRUE(derived_a_2_base_deleted);
EXPECT_TRUE(derived_a_2_derived_deleted);
EXPECT_TRUE(derived_b_1_base_deleted);
EXPECT_TRUE(derived_b_1_derived_deleted);
EXPECT_TRUE(derived_b_2_base_deleted);
EXPECT_TRUE(derived_b_2_derived_deleted);
EXPECT_TRUE(other_1_deleted);
EXPECT_TRUE(other_2_deleted);
// Should not cause double-frees:
deleter.deleteAll();
}
} // namespace quickstep