Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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 <iostream>
#include <type_traits>
#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(std::is_same_v<type_, decltype(MOZ_DBG(expression_))>, \
"MOZ_DBG should return the indicated type")
#define TEST_MOZ_DBG_TYPE_SAME(expression_...) \
static_assert( \
std::is_same_v<decltype((expression_)), decltype(MOZ_DBG(expression_))>, \
"MOZ_DBG should return the same type")
struct Number {
explicit Number(int aValue) : mValue(aValue) {}
Number(const Number& aOther) = default;
Number(Number&& aOther) : mValue(aOther.mValue) { aOther.mValue = 0; }
Number& operator=(const Number& aOther) = default;
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) = default;
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);
}