/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include "gtest/gtest.h" #include "mozilla/DbgMacro.h" #include "mozilla/Unused.h" using namespace mozilla; #define TEST_MOZ_DBG_TYPE_IS(type_, expression_...) \ static_assert(IsSame::value, \ "MOZ_DBG should return the indicated type") #define TEST_MOZ_DBG_TYPE_SAME(expression_...) \ static_assert( \ IsSame::value, \ "MOZ_DBG should return the same type") struct Number { explicit Number(int aValue) : mValue(aValue) {} Number(const Number& aOther) : mValue(aOther.mValue) {} Number(Number&& aOther) : mValue(aOther.mValue) { aOther.mValue = 0; } Number& operator=(const Number& aOther) { mValue = aOther.mValue; return *this; } Number& operator=(Number&& aOther) { mValue = aOther.mValue; aOther.mValue = 0; return *this; } ~Number() { mValue = -999; } int mValue; MOZ_DEFINE_DBG(Number, mValue) }; struct MoveOnly { explicit MoveOnly(int aValue) : mValue(aValue) {} MoveOnly(const MoveOnly& aOther) = delete; MoveOnly(MoveOnly&& aOther) : mValue(aOther.mValue) { aOther.mValue = 0; } MoveOnly& operator=(MoveOnly& aOther) { mValue = aOther.mValue; return *this; } MoveOnly& operator=(MoveOnly&& aOther) { mValue = aOther.mValue; aOther.mValue = 0; return *this; } int mValue; MOZ_DEFINE_DBG(MoveOnly) }; void StaticAssertions() { int x = 123; Number y(123); Number z(234); MoveOnly w(456); // Static assertions. // lvalues TEST_MOZ_DBG_TYPE_SAME(x); // int& TEST_MOZ_DBG_TYPE_SAME(y); // Number& TEST_MOZ_DBG_TYPE_SAME(x = 234); // int& TEST_MOZ_DBG_TYPE_SAME(y = z); // Number& TEST_MOZ_DBG_TYPE_SAME(w); // MoveOnly& // prvalues (which MOZ_DBG turns into xvalues by creating objects for them) TEST_MOZ_DBG_TYPE_IS(int&&, 123); TEST_MOZ_DBG_TYPE_IS(int&&, 1 + 2); TEST_MOZ_DBG_TYPE_IS(int*&&, &x); TEST_MOZ_DBG_TYPE_IS(int&&, x++); TEST_MOZ_DBG_TYPE_IS(Number&&, Number(123)); TEST_MOZ_DBG_TYPE_IS(MoveOnly&&, MoveOnly(123)); // xvalues TEST_MOZ_DBG_TYPE_SAME(std::move(y)); // int&& TEST_MOZ_DBG_TYPE_SAME(std::move(y)); // Number&& TEST_MOZ_DBG_TYPE_SAME(std::move(w)); // MoveOnly& Unused << x; Unused << y; Unused << z; } TEST(MozDbg, ObjectValues) { // Test that moves and assignments all operate correctly with MOZ_DBG wrapped // around various parts of the expression. Number a(1); Number b(4); ASSERT_EQ(a.mValue, 1); MOZ_DBG(a.mValue); ASSERT_EQ(a.mValue, 1); MOZ_DBG(a.mValue + 1); ASSERT_EQ(a.mValue, 1); MOZ_DBG(a.mValue = 2); ASSERT_EQ(a.mValue, 2); MOZ_DBG(a).mValue = 3; ASSERT_EQ(a.mValue, 3); MOZ_DBG(a = b); ASSERT_EQ(a.mValue, 4); ASSERT_EQ(b.mValue, 4); b.mValue = 5; MOZ_DBG(a) = b; ASSERT_EQ(a.mValue, 5); ASSERT_EQ(b.mValue, 5); b.mValue = 6; MOZ_DBG(a = std::move(b)); ASSERT_EQ(a.mValue, 6); ASSERT_EQ(b.mValue, 0); b.mValue = 7; MOZ_DBG(a) = std::move(b); ASSERT_EQ(a.mValue, 7); ASSERT_EQ(b.mValue, 0); b.mValue = 8; a = std::move(MOZ_DBG(b)); ASSERT_EQ(a.mValue, 8); ASSERT_EQ(b.mValue, 0); a = MOZ_DBG(Number(9)); ASSERT_EQ(a.mValue, 9); MoveOnly c(1); MoveOnly d(2); c = std::move(MOZ_DBG(d)); ASSERT_EQ(c.mValue, 2); ASSERT_EQ(d.mValue, 0); c.mValue = 3; d.mValue = 4; c = MOZ_DBG(std::move(d)); ASSERT_EQ(c.mValue, 4); ASSERT_EQ(d.mValue, 0); c.mValue = 5; d.mValue = 6; MOZ_DBG(c = std::move(d)); ASSERT_EQ(c.mValue, 6); ASSERT_EQ(d.mValue, 0); c = MOZ_DBG(MoveOnly(7)); ASSERT_EQ(c.mValue, 7); }