Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/xpcom/tests/gtest/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 11 kB image not shown  

Quelle  TestNsRefPtr.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "mozilla/RefPtr.h"
#include "nsCOMPtr.h"
#include "nsISupports.h"
#include "nsQueryObject.h"
#include "mozilla/Unused.h"

#include "gtest/gtest.h"

namespace TestNsRefPtr {

#define NS_FOO_IID                                   \
  {                                                  \
    0x6f7652e0, 0xee43, 0x11d1, {                    \
      0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 \
    }                                                \
  }

class Foo : public nsISupports {
 public:
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_FOO_IID)

 public:
  Foo();
  // virtual dtor because Bar uses our Release()
  virtual ~Foo();

  NS_IMETHOD_(MozExternalRefCountType) AddRef() override;
  NS_IMETHOD_(MozExternalRefCountType) Release() override;
  NS_IMETHOD QueryInterface(const nsIID&, void**) override;
  void MemberFunction(intint*, int&);
  virtual void VirtualMemberFunction(intint*, int&);
  virtual void VirtualConstMemberFunction(intint*, int&) const;

  void NonconstMethod() {}
  void ConstMethod() const {}

  int refcount_;

  static int total_constructions_;
  static int total_destructions_;
  static int total_addrefs_;
  static int total_queries_;
};

NS_DEFINE_STATIC_IID_ACCESSOR(Foo, NS_FOO_IID)

int Foo::total_constructions_;
int Foo::total_destructions_;
int Foo::total_addrefs_;
int Foo::total_queries_;

Foo::Foo() : refcount_(0) { ++total_constructions_; }

Foo::~Foo() { ++total_destructions_; }

MozExternalRefCountType Foo::AddRef() {
  ++refcount_;
  ++total_addrefs_;
  return refcount_;
}

MozExternalRefCountType Foo::Release() {
  int newcount = --refcount_;
  if (newcount == 0) {
    delete this;
  }

  return newcount;
}

nsresult Foo::QueryInterface(const nsIID& aIID, void** aResult) {
  ++total_queries_;

  nsISupports* rawPtr = 0;
  nsresult status = NS_OK;

  if (aIID.Equals(NS_GET_IID(Foo)))
    rawPtr = this;
  else {
    nsID iid_of_ISupports = NS_ISUPPORTS_IID;
    if (aIID.Equals(iid_of_ISupports))
      rawPtr = static_cast<nsISupports*>(this);
    else
      status = NS_ERROR_NO_INTERFACE;
  }

  NS_IF_ADDREF(rawPtr);
  *aResult = rawPtr;

  return status;
}

void Foo::MemberFunction(int aArg1, int* aArgPtr, int& aArgRef) {}

void Foo::VirtualMemberFunction(int aArg1, int* aArgPtr, int& aArgRef) {}

void Foo::VirtualConstMemberFunction(int aArg1, int* aArgPtr,
                                     int& aArgRef) const {}

static nsresult CreateFoo(void** result)
// a typical factory function (that calls AddRef)
{
  auto* foop = new Foo;

  foop->AddRef();
  *result = foop;

  return NS_OK;
}

static void set_a_Foo(RefPtr<Foo>* result) {
  assert(result);

  RefPtr<Foo> foop(do_QueryObject(new Foo));
  *result = foop;
}

static RefPtr<Foo> return_a_Foo() {
  RefPtr<Foo> foop(do_QueryObject(new Foo));
  return foop;
}

#define NS_BAR_IID                                   \
  {                                                  \
    0x6f7652e1, 0xee43, 0x11d1, {                    \
      0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 \
    }                                                \
  }

class Bar : public Foo {
 public:
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_BAR_IID)

 public:
  Bar();
  ~Bar() override;

  NS_IMETHOD QueryInterface(const nsIID&, void**) override;

  void VirtualMemberFunction(intint*, int&) override;
  void VirtualConstMemberFunction(intint*, int&) const override;

  static int total_constructions_;
  static int total_destructions_;
  static int total_queries_;
};

NS_DEFINE_STATIC_IID_ACCESSOR(Bar, NS_BAR_IID)

int Bar::total_constructions_;
int Bar::total_destructions_;
int Bar::total_queries_;

Bar::Bar() { ++total_constructions_; }

Bar::~Bar() { ++total_destructions_; }

nsresult Bar::QueryInterface(const nsID& aIID, void** aResult) {
  ++total_queries_;

  nsISupports* rawPtr = 0;
  nsresult status = NS_OK;

  if (aIID.Equals(NS_GET_IID(Bar)))
    rawPtr = this;
  else if (aIID.Equals(NS_GET_IID(Foo)))
    rawPtr = static_cast<Foo*>(this);
  else {
    nsID iid_of_ISupports = NS_ISUPPORTS_IID;
    if (aIID.Equals(iid_of_ISupports))
      rawPtr = static_cast<nsISupports*>(this);
    else
      status = NS_ERROR_NO_INTERFACE;
  }

  NS_IF_ADDREF(rawPtr);
  *aResult = rawPtr;

  return status;
}

void Bar::VirtualMemberFunction(int aArg1, int* aArgPtr, int& aArgRef) {}
void Bar::VirtualConstMemberFunction(int aArg1, int* aArgPtr,
                                     int& aArgRef) const {}

}  // namespace TestNsRefPtr

using namespace TestNsRefPtr;

TEST(nsRefPtr, AddRefAndRelease)
{
  Foo::total_constructions_ = 0;
  Foo::total_destructions_ = 0;

  {
    RefPtr<Foo> foop(do_QueryObject(new Foo));
    ASSERT_EQ(Foo::total_constructions_, 1);
    ASSERT_EQ(Foo::total_destructions_, 0);
    ASSERT_EQ(foop->refcount_, 1);

    foop = do_QueryObject(new Foo);
    ASSERT_EQ(Foo::total_constructions_, 2);
    ASSERT_EQ(Foo::total_destructions_, 1);

    // [Shouldn't compile] Is it a compile time error to try to |AddRef| by
    // hand?
    // foop->AddRef();

    // [Shouldn't compile] Is it a compile time error to try to |Release| be
    // hand?
    // foop->Release();

    // [Shouldn't compile] Is it a compile time error to try to |delete| an
    // |nsCOMPtr|?
    // delete foop;

    static_cast<Foo*>(foop)->AddRef();
    ASSERT_EQ(foop->refcount_, 2);

    static_cast<Foo*>(foop)->Release();
    ASSERT_EQ(foop->refcount_, 1);
  }

  ASSERT_EQ(Foo::total_destructions_, 2);

  {
    RefPtr<Foo> fooP(do_QueryObject(new Foo));
    ASSERT_EQ(Foo::total_constructions_, 3);
    ASSERT_EQ(Foo::total_destructions_, 2);
    ASSERT_EQ(fooP->refcount_, 1);

    Foo::total_addrefs_ = 0;
    RefPtr<Foo> fooP2 = std::move(fooP);
    mozilla::Unused << fooP2;
    ASSERT_EQ(Foo::total_addrefs_, 0);
  }
}

TEST(nsRefPtr, VirtualDestructor)
{
  Bar::total_destructions_ = 0;

  {
    RefPtr<Foo> foop(do_QueryObject(new Bar));
    mozilla::Unused << foop;
  }

  ASSERT_EQ(Bar::total_destructions_, 1);
}

TEST(nsRefPtr, Equality)
{
  Foo::total_constructions_ = 0;
  Foo::total_destructions_ = 0;

  {
    RefPtr<Foo> foo1p(do_QueryObject(new Foo));
    RefPtr<Foo> foo2p(do_QueryObject(new Foo));

    ASSERT_EQ(Foo::total_constructions_, 2);
    ASSERT_EQ(Foo::total_destructions_, 0);

    ASSERT_NE(foo1p, foo2p);

    ASSERT_NE(foo1p, nullptr);
    ASSERT_NE(nullptr, foo1p);
    ASSERT_FALSE(foo1p == nullptr);
    ASSERT_FALSE(nullptr == foo1p);

    ASSERT_NE(foo1p, foo2p.get());

    foo1p = foo2p;

    ASSERT_EQ(Foo::total_constructions_, 2);
    ASSERT_EQ(Foo::total_destructions_, 1);
    ASSERT_EQ(foo1p, foo2p);

    ASSERT_EQ(foo2p, foo2p.get());

    ASSERT_EQ(RefPtr<Foo>(foo2p.get()), foo2p);

    ASSERT_TRUE(foo1p);
  }

  ASSERT_EQ(Foo::total_constructions_, 2);
  ASSERT_EQ(Foo::total_destructions_, 2);
}

TEST(nsRefPtr, AddRefHelpers)
{
  Foo::total_addrefs_ = 0;

  {
    auto* raw_foo1p = new Foo;
    raw_foo1p->AddRef();

    auto* raw_foo2p = new Foo;
    raw_foo2p->AddRef();

    ASSERT_EQ(Foo::total_addrefs_, 2);

    RefPtr<Foo> foo1p(dont_AddRef(raw_foo1p));

    ASSERT_EQ(Foo::total_addrefs_, 2);

    RefPtr<Foo> foo2p;
    foo2p = dont_AddRef(raw_foo2p);

    ASSERT_EQ(Foo::total_addrefs_, 2);
  }

  {
    // Test that various assignment helpers compile.
    RefPtr<Foo> foop;
    CreateFoo(RefPtrGetterAddRefs<Foo>(foop));
    CreateFoo(getter_AddRefs(foop));
    set_a_Foo(address_of(foop));
    foop = return_a_Foo();
  }
}

TEST(nsRefPtr, QueryInterface)
{
  Foo::total_queries_ = 0;
  Bar::total_queries_ = 0;

  {
    RefPtr<Foo> fooP;
    fooP = do_QueryObject(new Foo);
    ASSERT_EQ(Foo::total_queries_, 1);
  }

  {
    RefPtr<Foo> fooP;
    fooP = do_QueryObject(new Foo);
    ASSERT_EQ(Foo::total_queries_, 2);

    RefPtr<Foo> foo2P;
    foo2P = fooP;
    ASSERT_EQ(Foo::total_queries_, 2);
  }

  {
    RefPtr<Bar> barP(do_QueryObject(new Bar));
    ASSERT_EQ(Bar::total_queries_, 1);

    RefPtr<Foo> fooP(do_QueryObject(barP));
    ASSERT_TRUE(fooP);
    ASSERT_EQ(Foo::total_queries_, 2);
    ASSERT_EQ(Bar::total_queries_, 2);
  }
}

// -------------------------------------------------------------------------
// TODO(ER): The following tests should be moved to MFBT.

#define NS_INLINE_DECL_THREADSAFE_MUTABLE_REFCOUNTING(_class)    \
 public:                                                         \
  NS_METHOD_(MozExternalRefCountType) AddRef(voidconst {       \
    MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class)                   \
    MOZ_RELEASE_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
    nsrefcnt count = ++mRefCnt;                                  \
    return (nsrefcnt)count;                                      \
  }                                                              \
  NS_METHOD_(MozExternalRefCountType) Release(voidconst {      \
    MOZ_RELEASE_ASSERT(int32_t(mRefCnt) > 0, "dup release");     \
    nsrefcnt count = --mRefCnt;                                  \
    if (count == 0) {                                            \
      delete (this);                                             \
      return 0;                                                  \
    }                                                            \
    return count;                                                \
  }                                                              \
                                                                 \
 protected:                                                      \
  mutable ::mozilla::ThreadSafeAutoRefCnt mRefCnt;               \
                                                                 \
 public:

class ObjectForConstPtr {
 private:
  // Reference-counted classes cannot have public destructors.
  ~ObjectForConstPtr() = default;

 public:
  NS_INLINE_DECL_THREADSAFE_MUTABLE_REFCOUNTING(ObjectForConstPtr)
  void ConstMemberFunction(int aArg1, int* aArgPtr, int& aArgRef) const {}
};
#undef NS_INLINE_DECL_THREADSAFE_MUTABLE_REFCOUNTING

namespace TestNsRefPtr {
static void AnFooPtrPtrContext(Foo**) {}
static void AVoidPtrPtrContext(void**) {}
}  // namespace TestNsRefPtr

TEST(nsRefPtr, RefPtrCompilationTests)
{
  {
    RefPtr<Foo> fooP;

    AnFooPtrPtrContext(getter_AddRefs(fooP));
    AVoidPtrPtrContext(getter_AddRefs(fooP));
  }

  {
    RefPtr<Foo> fooP(new Foo);
    RefPtr<const Foo> constFooP = fooP;
    constFooP->ConstMethod();

    // [Shouldn't compile] Is it a compile time error to call a non-const method
    // on an |RefPtr<const T>|?
    // constFooP->NonconstMethod();

    // [Shouldn't compile] Is it a compile time error to construct an |RefPtr<T>
    // from an |RefPtr<const T>|?
    // RefPtr<Foo> otherFooP(constFooP);
  }

  {
    RefPtr<Foo> foop = new Foo;
    RefPtr<Foo> foop2 = new Bar;
    RefPtr<const ObjectForConstPtr> foop3 = new ObjectForConstPtr;
    int test = 1;
    void (Foo::*fPtr)(intint*, int&) = &Foo::MemberFunction;
    void (Foo::*fVPtr)(intint*, int&) = &Foo::VirtualMemberFunction;
    void (Foo::*fVCPtr)(intint*, int&) const =
        &Foo::VirtualConstMemberFunction;
    void (ObjectForConstPtr::*fCPtr2)(intint*, int&) const =
        &ObjectForConstPtr::ConstMemberFunction;

    (foop->*fPtr)(test, &test, test);
    (foop2->*fVPtr)(test, &test, test);
    (foop2->*fVCPtr)(test, &test, test);
    (foop3->*fCPtr2)(test, &test, test);
  }

  // Looks like everything ran.
  ASSERT_TRUE(true);
}

100%


¤ Dauer der Verarbeitung: 0.83 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.