/** * Copyright (C) 2015 MongoDB Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects for * all of the code used other than as permitted herein. If you modify file(s) * with this exception, you may extend this exception to your version of the * file(s), but you are not obligated to do so. If you do not wish to do so, * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. */ #define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault #include "mongo/platform/basic.h" #include #include "mongo/unittest/unittest.h" #include "mongo/util/assert_util.h" #include "mongo/util/decorable.h" #include "mongo/util/decoration_container.h" #include "mongo/util/decoration_registry.h" #include "mongo/util/log.h" namespace mongo { namespace { static int numConstructedAs; static int numDestructedAs; class A { public: A() : value(0) { ++numConstructedAs; } ~A() { ++numDestructedAs; } int value; }; class ThrowA { public: ThrowA() : value(0) { uasserted(ErrorCodes::Unauthorized, "Throwing in a constructor"); } int value; }; TEST(DecorableTest, DecorableType) { class MyDecorable : public Decorable {}; const auto dd1 = MyDecorable::declareDecoration(); const auto dd2 = MyDecorable::declareDecoration(); const auto dd3 = MyDecorable::declareDecoration(); numConstructedAs = 0; numDestructedAs = 0; { MyDecorable decorable1; ASSERT_EQ(2, numConstructedAs); ASSERT_EQ(0, numDestructedAs); MyDecorable decorable2; ASSERT_EQ(4, numConstructedAs); ASSERT_EQ(0, numDestructedAs); ASSERT_EQ(0, dd1(decorable1).value); ASSERT_EQ(0, dd2(decorable1).value); ASSERT_EQ(0, dd1(decorable2).value); ASSERT_EQ(0, dd2(decorable2).value); ASSERT_EQ(0, dd3(decorable2)); dd1(decorable1).value = 1; dd2(decorable1).value = 2; dd1(decorable2).value = 3; dd2(decorable2).value = 4; dd3(decorable2) = 5; ASSERT_EQ(1, dd1(decorable1).value); ASSERT_EQ(2, dd2(decorable1).value); ASSERT_EQ(3, dd1(decorable2).value); ASSERT_EQ(4, dd2(decorable2).value); ASSERT_EQ(5, dd3(decorable2)); } ASSERT_EQ(4, numDestructedAs); } TEST(DecorableTest, SimpleDecoration) { numConstructedAs = 0; numDestructedAs = 0; DecorationRegistry registry; const auto dd1 = registry.declareDecoration(); const auto dd2 = registry.declareDecoration(); const auto dd3 = registry.declareDecoration(); { DecorationContainer decorable1(®istry); ASSERT_EQ(2, numConstructedAs); ASSERT_EQ(0, numDestructedAs); DecorationContainer decorable2(®istry); ASSERT_EQ(4, numConstructedAs); ASSERT_EQ(0, numDestructedAs); ASSERT_EQ(0, decorable1.getDecoration(dd1).value); ASSERT_EQ(0, decorable1.getDecoration(dd2).value); ASSERT_EQ(0, decorable2.getDecoration(dd1).value); ASSERT_EQ(0, decorable2.getDecoration(dd2).value); ASSERT_EQ(0, decorable2.getDecoration(dd3)); decorable1.getDecoration(dd1).value = 1; decorable1.getDecoration(dd2).value = 2; decorable2.getDecoration(dd1).value = 3; decorable2.getDecoration(dd2).value = 4; decorable2.getDecoration(dd3) = 5; ASSERT_EQ(1, decorable1.getDecoration(dd1).value); ASSERT_EQ(2, decorable1.getDecoration(dd2).value); ASSERT_EQ(3, decorable2.getDecoration(dd1).value); ASSERT_EQ(4, decorable2.getDecoration(dd2).value); ASSERT_EQ(5, decorable2.getDecoration(dd3)); } ASSERT_EQ(4, numDestructedAs); } TEST(DecorableTest, ThrowingConstructor) { numConstructedAs = 0; numDestructedAs = 0; DecorationRegistry registry; registry.declareDecoration(); registry.declareDecoration(); registry.declareDecoration(); try { DecorationContainer d(®istry); } catch (const UserException& ex) { ASSERT_EQ(ErrorCodes::Unauthorized, ex.getCode()); } ASSERT_EQ(1, numConstructedAs); ASSERT_EQ(1, numDestructedAs); } TEST(DecorableTest, Alignment) { DecorationRegistry registry; const auto firstChar = registry.declareDecoration(); const auto firstInt = registry.declareDecoration(); const auto secondChar = registry.declareDecoration(); const auto secondInt = registry.declareDecoration(); DecorationContainer d(®istry); ASSERT_EQ(0U, reinterpret_cast(&d.getDecoration(firstChar)) % std::alignment_of::value); ASSERT_EQ(0U, reinterpret_cast(&d.getDecoration(secondChar)) % std::alignment_of::value); ASSERT_EQ(0U, reinterpret_cast(&d.getDecoration(firstInt)) % std::alignment_of::value); ASSERT_EQ(0U, reinterpret_cast(&d.getDecoration(secondInt)) % std::alignment_of::value); } } // namespace } // namespace mongo