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

Quelle  TestNotNull.cpp   Sprache: C

 
/* -*- 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 <type_traits>

#include "mozilla/NotNull.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"

using mozilla::MakeNotNull;
using mozilla::NotNull;
using mozilla::UniquePtr;
using mozilla::WrapNotNull;

#define CHECK MOZ_RELEASE_ASSERT

class Blah {
 public:
  Blah() : mX(0) {}
  void blah() {};
  int mX;
};

// A simple smart pointer that implicity converts to and from T*.
template <typename T>
class MyPtr {
  T* mRawPtr;

 public:
  MyPtr() : mRawPtr(nullptr) {}
  MOZ_IMPLICIT MyPtr(T* aRawPtr) : mRawPtr(aRawPtr) {}

  T* get() const { return mRawPtr; }
  operator T*() const { return get(); }

  T* operator->() const { return get(); }
};

// A simple class that works with RefPtr. It keeps track of the maximum
// refcount value for testing purposes.
class MyRefType {
  int mExpectedMaxRefCnt;
  int mMaxRefCnt;
  int mRefCnt;

 public:
  explicit MyRefType(int aExpectedMaxRefCnt)
      : mExpectedMaxRefCnt(aExpectedMaxRefCnt), mMaxRefCnt(0), mRefCnt(0) {}

  ~MyRefType() { CHECK(mMaxRefCnt == mExpectedMaxRefCnt); }

  uint32_t AddRef() {
    mRefCnt++;
    if (mRefCnt > mMaxRefCnt) {
      mMaxRefCnt = mRefCnt;
    }
    return mRefCnt;
  }

  uint32_t Release() {
    CHECK(mRefCnt > 0);
    mRefCnt--;
    if (mRefCnt == 0) {
      delete this;
      return 0;
    }
    return mRefCnt;
  }
};

void f_i(int* aPtr) {}
void f_my(MyPtr<int> aPtr) {}

void f_nni(NotNull<int*> aPtr) {}
void f_nnmy(NotNull<MyPtr<int>> aPtr) {}

void TestNotNullWithMyPtr() {
  int i4 = 4;
  int i5 = 5;

  MyPtr<int> my4 = &i4;
  MyPtr<int> my5 = &i5;

  NotNull<int*> nni4 = WrapNotNull(&i4);
  NotNull<int*> nni5 = WrapNotNull(&i5);
  NotNull<MyPtr<int>> nnmy4 = WrapNotNull(my4);

  // WrapNotNull(nullptr);                       // no wrapping from nullptr
  // WrapNotNull(0);                             // no wrapping from zero

  // NotNull<int*> construction combinations
  // NotNull<int*> nni4a;                        // no default
  // NotNull<int*> nni4a(nullptr);               // no nullptr
  // NotNull<int*> nni4a(0);                     // no zero
  // NotNull<int*> nni4a(&i4);                   // no int*
  // NotNull<int*> nni4a(my4);                   // no MyPtr<int>
  NotNull<int*> nni4b(WrapNotNull(&i4));  // WrapNotNull(int*)
  NotNull<int*> nni4c(WrapNotNull(my4));  // WrapNotNull(MyPtr<int>)
  NotNull<int*> nni4d(nni4);              // NotNull<int*>
  NotNull<int*> nni4e(nnmy4);             // NotNull<MyPtr<int>>
  CHECK(*nni4b == 4);
  CHECK(*nni4c == 4);
  CHECK(*nni4d == 4);
  CHECK(*nni4e == 4);

  // NotNull<MyPtr<int>> construction combinations
  // NotNull<MyPtr<int>> nnmy4a;                 // no default
  // NotNull<MyPtr<int>> nnmy4a(nullptr);        // no nullptr
  // NotNull<MyPtr<int>> nnmy4a(0);              // no zero
  // NotNull<MyPtr<int>> nnmy4a(&i4);            // no int*
  // NotNull<MyPtr<int>> nnmy4a(my4);            // no MyPtr<int>
  NotNull<MyPtr<int>> nnmy4b(WrapNotNull(&i4));  // WrapNotNull(int*)
  NotNull<MyPtr<int>> nnmy4c(WrapNotNull(my4));  // WrapNotNull(MyPtr<int>)
  NotNull<MyPtr<int>> nnmy4d(nni4);              // NotNull<int*>
  NotNull<MyPtr<int>> nnmy4e(nnmy4);             // NotNull<MyPtr<int>>
  CHECK(*nnmy4b == 4);
  CHECK(*nnmy4c == 4);
  CHECK(*nnmy4d == 4);
  CHECK(*nnmy4e == 4);

  // NotNull<int*> assignment combinations
  // nni4b = nullptr;                            // no nullptr
  // nni4b = 0;                                  // no zero
  // nni4a = &i4;                                // no int*
  // nni4a = my4;                                // no MyPtr<int>
  nni4b = WrapNotNull(&i4);  // WrapNotNull(int*)
  nni4c = WrapNotNull(my4);  // WrapNotNull(MyPtr<int>)
  nni4d = nni4;              // NotNull<int*>
  nni4e = nnmy4;             // NotNull<MyPtr<int>>
  CHECK(*nni4b == 4);
  CHECK(*nni4c == 4);
  CHECK(*nni4d == 4);
  CHECK(*nni4e == 4);

  // NotNull<MyPtr<int>> assignment combinations
  // nnmy4a = nullptr;                           // no nullptr
  // nnmy4a = 0;                                 // no zero
  // nnmy4a = &i4;                               // no int*
  // nnmy4a = my4;                               // no MyPtr<int>
  nnmy4b = WrapNotNull(&i4);  // WrapNotNull(int*)
  nnmy4c = WrapNotNull(my4);  // WrapNotNull(MyPtr<int>)
  nnmy4d = nni4;              // NotNull<int*>
  nnmy4e = nnmy4;             // NotNull<MyPtr<int>>
  CHECK(*nnmy4b == 4);
  CHECK(*nnmy4c == 4);
  CHECK(*nnmy4d == 4);
  CHECK(*nnmy4e == 4);

  NotNull<MyPtr<int>> nnmy5 = WrapNotNull(&i5);
  CHECK(*nnmy5 == 5);
  CHECK(nnmy5 == &i5);    // NotNull<MyPtr<int>> == int*
  CHECK(nnmy5 == my5);    // NotNull<MyPtr<int>> == MyPtr<int>
  CHECK(nnmy5 == nni5);   // NotNull<MyPtr<int>> == NotNull<int*>
  CHECK(nnmy5 == nnmy5);  // NotNull<MyPtr<int>> == NotNull<MyPtr<int>>
  CHECK(&i5 == nnmy5);    // int*                == NotNull<MyPtr<int>>
  CHECK(my5 == nnmy5);    // MyPtr<int>          == NotNull<MyPtr<int>>
  CHECK(nni5 == nnmy5);   // NotNull<int*>       == NotNull<MyPtr<int>>
  CHECK(nnmy5 == nnmy5);  // NotNull<MyPtr<int>> == NotNull<MyPtr<int>>
  // CHECK(nni5 == nullptr);  // no comparisons with nullptr
  // CHECK(nullptr == nni5);  // no comparisons with nullptr
  // CHECK(nni5 == 0);        // no comparisons with zero
  // CHECK(0 == nni5);        // no comparisons with zero

  CHECK(*nnmy5 == 5);
  CHECK(nnmy5 != &i4);    // NotNull<MyPtr<int>> != int*
  CHECK(nnmy5 != my4);    // NotNull<MyPtr<int>> != MyPtr<int>
  CHECK(nnmy5 != nni4);   // NotNull<MyPtr<int>> != NotNull<int*>
  CHECK(nnmy5 != nnmy4);  // NotNull<MyPtr<int>> != NotNull<MyPtr<int>>
  CHECK(&i4 != nnmy5);    // int*                != NotNull<MyPtr<int>>
  CHECK(my4 != nnmy5);    // MyPtr<int>          != NotNull<MyPtr<int>>
  CHECK(nni4 != nnmy5);   // NotNull<int*>       != NotNull<MyPtr<int>>
  CHECK(nnmy4 != nnmy5);  // NotNull<MyPtr<int>> != NotNull<MyPtr<int>>
  // CHECK(nni4 != nullptr);  // no comparisons with nullptr
  // CHECK(nullptr != nni4);  // no comparisons with nullptr
  // CHECK(nni4 != 0);        // no comparisons with zero
  // CHECK(0 != nni4);        // no comparisons with zero

  // int* parameter
  f_i(&i4);         // identity int*                        --> int*
  f_i(my4);         // implicit MyPtr<int>                  --> int*
  f_i(my4.get());   // explicit MyPtr<int>                  --> int*
  f_i(nni4);        // implicit NotNull<int*>               --> int*
  f_i(nni4.get());  // explicit NotNull<int*>               --> int*
  // f_i(nnmy4);         // no implicit NotNull<MyPtr<int>>      --> int*
  f_i(nnmy4.get());        // explicit NotNull<MyPtr<int>>         --> int*
  f_i(nnmy4.get().get());  // doubly-explicit NotNull<MyPtr<int>> --> int*

  // MyPtr<int> parameter
  f_my(&i4);        // implicit int*                         --> MyPtr<int>
  f_my(my4);        // identity MyPtr<int>                   --> MyPtr<int>
  f_my(my4.get());  // explicit MyPtr<int>                   --> MyPtr<int>
  // f_my(nni4);         // no implicit NotNull<int*>             --> MyPtr<int>
  f_my(nni4.get());   // explicit NotNull<int*>                --> MyPtr<int>
  f_my(nnmy4);        // implicit NotNull<MyPtr<int>>          --> MyPtr<int>
  f_my(nnmy4.get());  // explicit NotNull<MyPtr<int>>          --> MyPtr<int>
  f_my(
      nnmy4.get().get());  // doubly-explicit NotNull<MyPtr<int>> --> MyPtr<int>

  // NotNull<int*> parameter
  f_nni(nni4);   // identity NotNull<int*>       --> NotNull<int*>
  f_nni(nnmy4);  // implicit NotNull<MyPtr<int>> --> NotNull<int*>

  // NotNull<MyPtr<int>> parameter
  f_nnmy(nni4);   // implicit NotNull<int*>       --> NotNull<MyPtr<int>>
  f_nnmy(nnmy4);  // identity NotNull<MyPtr<int>> --> NotNull<MyPtr<int>>

  // CHECK(nni4);        // disallow boolean conversion / unary expression usage
  // CHECK(nnmy4);       // ditto

  // '->' dereferencing.
  Blah blah;
  MyPtr<Blah> myblah = &blah;
  NotNull<Blah*> nnblah = WrapNotNull(&blah);
  NotNull<MyPtr<Blah>> nnmyblah = WrapNotNull(myblah);
  (&blah)->blah();   // int*
  myblah->blah();    // MyPtr<int>
  nnblah->blah();    // NotNull<int*>
  nnmyblah->blah();  // NotNull<MyPtr<int>>

  (&blah)->mX = 1;
  CHECK((&blah)->mX == 1);
  myblah->mX = 2;
  CHECK(myblah->mX == 2);
  nnblah->mX = 3;
  CHECK(nnblah->mX == 3);
  nnmyblah->mX = 4;
  CHECK(nnmyblah->mX == 4);

  // '*' dereferencing (lvalues and rvalues)
  *(&i4) = 7;  // int*
  CHECK(*(&i4) == 7);
  *my4 = 6;  // MyPtr<int>
  CHECK(*my4 == 6);
  *nni4 = 5;  // NotNull<int*>
  CHECK(*nni4 == 5);
  *nnmy4 = 4;  // NotNull<MyPtr<int>>
  CHECK(*nnmy4 == 4);

  // Non-null arrays.
  static const int N = 20;
  int a[N];
  NotNull<int*> nna = WrapNotNull(a);
  for (int i = 0; i < N; i++) {
    nna[i] = i;
  }
  for (int i = 0; i < N; i++) {
    nna[i] *= 2;
  }
  for (int i = 0; i < N; i++) {
    CHECK(nna[i] == i * 2);
  }
}

void f_ref(NotNull<MyRefType*> aR) { NotNull<RefPtr<MyRefType>> r = aR; }

void TestNotNullWithRefPtr() {
  // This MyRefType object will have a maximum refcount of 5.
  NotNull<RefPtr<MyRefType>> r1 = WrapNotNull(new MyRefType(5));

  // At this point the refcount is 1.

  NotNull<RefPtr<MyRefType>> r2 = r1;

  // At this point the refcount is 2.

  NotNull<MyRefType*> r3 = r2;
  (void)r3;

  // At this point the refcount is still 2.

  RefPtr<MyRefType> r4 = r2;
  mozilla::Unused << r4;

  // At this point the refcount is 3.

  RefPtr<MyRefType> r5 = r3.get();
  mozilla::Unused << r5;

  // At this point the refcount is 4.

  // No change to the refcount occurs because of the argument passing. Within
  // f_ref() the refcount temporarily hits 5, due to the local RefPtr.
  f_ref(r2);

  // At this point the refcount is 4.

  NotNull<RefPtr<MyRefType>> r6 = std::move(r2);
  mozilla::Unused << r6;

  CHECK(r2.get());
  CHECK(r6.get());

  // At this point the refcount is 5 again, since NotNull is not movable.

  // At function's end all RefPtrs are destroyed and the refcount drops to 0
  // and the MyRefType is destroyed.
}

// Create a derived object and store its base pointer.
struct Base {
  virtual ~Base() = default;
  virtual bool IsDerived() const { return false; }
};
struct Derived : Base {
  bool IsDerived() const override { return true; }
};

void TestMakeNotNull() {
  // Raw pointer.
  auto nni = MakeNotNull<int*>(11);
  static_assert(std::is_same_v<NotNull<int*>, decltype(nni)>,
                "MakeNotNull should return NotNull");
  CHECK(*nni == 11);
  delete nni;

  // Raw pointer to const.
  auto nnci = MakeNotNull<const int*>(12);
  static_assert(std::is_same_v<NotNull<const int*>, decltype(nnci)>,
                "MakeNotNull should return NotNull");
  CHECK(*nnci == 12);
  delete nnci;

  auto nnd = MakeNotNull<Derived*>();
  static_assert(std::is_same_v<NotNull<Derived*>, decltype(nnd)>,
                "MakeNotNull should return NotNull");
  CHECK(nnd->IsDerived());
  delete nnd;
  NotNull<Base*> nnb = MakeNotNull<Derived*>();
  static_assert(std::is_same_v<NotNull<Base*>, decltype(nnb)>,
                "MakeNotNull should be assignable to NotNull");
  // Check that we have really built a Derived object.
  CHECK(nnb->IsDerived());
  delete nnb;

  // Allow smart pointers.
  auto nnmi = MakeNotNull<MyPtr<int>>(23);
  static_assert(std::is_same_v<NotNull<MyPtr<int>>, decltype(nnmi)>,
                "MakeNotNull> should return NotNull>");
  CHECK(*nnmi == 23);
  delete nnmi.get().get();

  auto nnui = MakeNotNull<UniquePtr<int>>(24);
  static_assert(
      std::is_same_v<NotNull<UniquePtr<int>>, decltype(nnui)>,
      "MakeNotNull> should return NotNull>");
  CHECK(*nnui == 24);

  // Expect only 1 RefCnt (from construction).
  auto nnr = MakeNotNull<RefPtr<MyRefType>>(1);
  static_assert(std::is_same_v<NotNull<RefPtr<MyRefType>>, decltype(nnr)>,
                "MakeNotNull> should return "
                "NotNull>");
  mozilla::Unused << nnr;
}

mozilla::MovingNotNull<UniquePtr<int>> CreateNotNullUniquePtr() {
  return mozilla::WrapMovingNotNull(mozilla::MakeUnique<int>(42));
}

void TestMovingNotNull() {
  UniquePtr<int> x1 = CreateNotNullUniquePtr();
  CHECK(x1);
  CHECK(42 == *x1);

  NotNull<UniquePtr<int>> x2 = CreateNotNullUniquePtr();
  CHECK(42 == *x2);

  NotNull<UniquePtr<Base>> x3 =
      mozilla::WrapMovingNotNull(mozilla::MakeUnique<Derived>());

  // Must not compile:
  // auto y = CreateNotNullUniquePtr();
}

int main() {
  TestNotNullWithMyPtr();
  TestNotNullWithRefPtr();
  TestMakeNotNull();
  TestMovingNotNull();

  return 0;
}

95%


¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© 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.