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 22 kB image not shown  

Quelle  TestVector.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 <utility>

#include "mozilla/IntegerRange.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Vector.h"

using mozilla::IntegerRange;
using mozilla::MakeUnique;
using mozilla::UniquePtr;
using mozilla::Vector;
using mozilla::detail::VectorTesting;

struct mozilla::detail::VectorTesting {
  static void testReserved();
  static void testConstRange();
  static void testEmplaceBack();
  static void testReverse();
  static void testExtractRawBuffer();
  static void testExtractOrCopyRawBuffer();
  static void testReplaceRawBuffer();
  static void testInsert();
  static void testErase();
  static void testShrinkStorageToFit();
  static void testAppend();
};

void mozilla::detail::VectorTesting::testReserved() {
#ifdef DEBUG
  Vector<bool> bv;
  MOZ_RELEASE_ASSERT(bv.reserved() == 0);

  MOZ_RELEASE_ASSERT(bv.append(true));
  MOZ_RELEASE_ASSERT(bv.reserved() == 1);

  Vector<bool> otherbv;
  MOZ_RELEASE_ASSERT(otherbv.append(false));
  MOZ_RELEASE_ASSERT(otherbv.append(true));
  MOZ_RELEASE_ASSERT(bv.appendAll(otherbv));
  MOZ_RELEASE_ASSERT(bv.reserved() == 3);

  MOZ_RELEASE_ASSERT(bv.reserve(5));
  MOZ_RELEASE_ASSERT(bv.reserved() == 5);

  MOZ_RELEASE_ASSERT(bv.reserve(1));
  MOZ_RELEASE_ASSERT(bv.reserved() == 5);

  Vector<bool> bv2(std::move(bv));
  MOZ_RELEASE_ASSERT(bv.reserved() == 0);
  MOZ_RELEASE_ASSERT(bv2.reserved() == 5);

  bv2.clearAndFree();
  MOZ_RELEASE_ASSERT(bv2.reserved() == 0);

  Vector<int, 42> iv;
  MOZ_RELEASE_ASSERT(iv.reserved() == 0);

  MOZ_RELEASE_ASSERT(iv.append(17));
  MOZ_RELEASE_ASSERT(iv.reserved() == 1);

  Vector<int, 42> otheriv;
  MOZ_RELEASE_ASSERT(otheriv.append(42));
  MOZ_RELEASE_ASSERT(otheriv.append(37));
  MOZ_RELEASE_ASSERT(iv.appendAll(otheriv));
  MOZ_RELEASE_ASSERT(iv.reserved() == 3);

  MOZ_RELEASE_ASSERT(iv.reserve(5));
  MOZ_RELEASE_ASSERT(iv.reserved() == 5);

  MOZ_RELEASE_ASSERT(iv.reserve(1));
  MOZ_RELEASE_ASSERT(iv.reserved() == 5);

  MOZ_RELEASE_ASSERT(iv.reserve(55));
  MOZ_RELEASE_ASSERT(iv.reserved() == 55);

  Vector<int, 42> iv2(std::move(iv));
  MOZ_RELEASE_ASSERT(iv.reserved() == 0);
  MOZ_RELEASE_ASSERT(iv2.reserved() == 55);

  iv2.clearAndFree();
  MOZ_RELEASE_ASSERT(iv2.reserved() == 0);
#endif
}

void mozilla::detail::VectorTesting::testConstRange() {
#ifdef DEBUG
  Vector<int> vec;

  for (int i = 0; i < 10; i++) {
    MOZ_RELEASE_ASSERT(vec.append(i));
  }

  const auto& vecRef = vec;

  Vector<int>::ConstRange range = vecRef.all();
  for (int i = 0; i < 10; i++) {
    MOZ_RELEASE_ASSERT(!range.empty());
    MOZ_RELEASE_ASSERT(range.front() == i);
    range.popFront();
  }
#endif
}

namespace {

struct S {
  size_t j;
  UniquePtr<size_t> k;

  static size_t constructCount;
  static size_t moveCount;
  static size_t destructCount;

  static void resetCounts() {
    constructCount = 0;
    moveCount = 0;
    destructCount = 0;
  }

  S(size_t j, size_t k) : j(j), k(MakeUnique<size_t>(k)) { constructCount++; }

  S(S&& rhs) : j(rhs.j), k(std::move(rhs.k)) {
    rhs.j = 0;
    rhs.k.reset(0);
    moveCount++;
  }

  ~S() { destructCount++; }

  S& operator=(S&& rhs) {
    j = rhs.j;
    rhs.j = 0;
    k = std::move(rhs.k);
    rhs.k.reset();
    moveCount++;
    return *this;
  }

  bool operator==(const S& rhs) const { return j == rhs.j && *k == *rhs.k; }

  S(const S&) = delete;
  S& operator=(const S&) = delete;
};

size_t S::constructCount = 0;
size_t S::moveCount = 0;
size_t S::destructCount = 0;

}  // namespace

void mozilla::detail::VectorTesting::testEmplaceBack() {
  S::resetCounts();

  Vector<S> vec;
  MOZ_RELEASE_ASSERT(vec.reserve(20));

  for (size_t i = 0; i < 10; i++) {
    S s(i, i * i);
    MOZ_RELEASE_ASSERT(vec.append(std::move(s)));
  }

  MOZ_RELEASE_ASSERT(vec.length() == 10);
  MOZ_RELEASE_ASSERT(S::constructCount == 10);
  MOZ_RELEASE_ASSERT(S::moveCount == 10);

  for (size_t i = 10; i < 20; i++) {
    MOZ_RELEASE_ASSERT(vec.emplaceBack(i, i * i));
  }

  MOZ_RELEASE_ASSERT(vec.length() == 20);
  MOZ_RELEASE_ASSERT(S::constructCount == 20);
  MOZ_RELEASE_ASSERT(S::moveCount == 10);

  for (size_t i = 0; i < 20; i++) {
    MOZ_RELEASE_ASSERT(vec[i].j == i);
    MOZ_RELEASE_ASSERT(*vec[i].k == i * i);
  }
}

void mozilla::detail::VectorTesting::testReverse() {
  // Use UniquePtr to make sure that reverse() can handler move-only types.
  Vector<UniquePtr<uint8_t>, 0> vec;

  // Reverse an odd number of elements.

  for (uint8_t i = 0; i < 5; i++) {
    auto p = MakeUnique<uint8_t>(i);
    MOZ_RELEASE_ASSERT(p);
    MOZ_RELEASE_ASSERT(vec.append(std::move(p)));
  }

  vec.reverse();

  MOZ_RELEASE_ASSERT(*vec[0] == 4);
  MOZ_RELEASE_ASSERT(*vec[1] == 3);
  MOZ_RELEASE_ASSERT(*vec[2] == 2);
  MOZ_RELEASE_ASSERT(*vec[3] == 1);
  MOZ_RELEASE_ASSERT(*vec[4] == 0);

  // Reverse an even number of elements.

  vec.popBack();
  vec.reverse();

  MOZ_RELEASE_ASSERT(*vec[0] == 1);
  MOZ_RELEASE_ASSERT(*vec[1] == 2);
  MOZ_RELEASE_ASSERT(*vec[2] == 3);
  MOZ_RELEASE_ASSERT(*vec[3] == 4);

  // Reverse an empty vector.

  vec.clear();
  MOZ_RELEASE_ASSERT(vec.length() == 0);
  vec.reverse();
  MOZ_RELEASE_ASSERT(vec.length() == 0);

  // Reverse a vector using only inline storage.

  Vector<UniquePtr<uint8_t>, 5> vec2;
  for (uint8_t i = 0; i < 5; i++) {
    auto p = MakeUnique<uint8_t>(i);
    MOZ_RELEASE_ASSERT(p);
    MOZ_RELEASE_ASSERT(vec2.append(std::move(p)));
  }

  vec2.reverse();

  MOZ_RELEASE_ASSERT(*vec2[0] == 4);
  MOZ_RELEASE_ASSERT(*vec2[1] == 3);
  MOZ_RELEASE_ASSERT(*vec2[2] == 2);
  MOZ_RELEASE_ASSERT(*vec2[3] == 1);
  MOZ_RELEASE_ASSERT(*vec2[4] == 0);
}

void mozilla::detail::VectorTesting::testExtractRawBuffer() {
  S::resetCounts();

  Vector<S, 5> vec;
  MOZ_RELEASE_ASSERT(vec.reserve(5));
  for (size_t i = 0; i < 5; i++) {
    vec.infallibleEmplaceBack(i, i * i);
  }
  MOZ_RELEASE_ASSERT(vec.length() == 5);
  MOZ_ASSERT(vec.reserved() == 5);
  MOZ_RELEASE_ASSERT(S::constructCount == 5);
  MOZ_RELEASE_ASSERT(S::moveCount == 0);
  MOZ_RELEASE_ASSERT(S::destructCount == 0);

  S* buf = vec.extractRawBuffer();
  MOZ_RELEASE_ASSERT(!buf);
  MOZ_RELEASE_ASSERT(vec.length() == 5);
  MOZ_ASSERT(vec.reserved() == 5);
  MOZ_RELEASE_ASSERT(S::constructCount == 5);
  MOZ_RELEASE_ASSERT(S::moveCount == 0);
  MOZ_RELEASE_ASSERT(S::destructCount == 0);

  MOZ_RELEASE_ASSERT(vec.reserve(10));
  for (size_t i = 5; i < 10; i++) {
    vec.infallibleEmplaceBack(i, i * i);
  }
  MOZ_RELEASE_ASSERT(vec.length() == 10);
  MOZ_ASSERT(vec.reserved() == 10);
  MOZ_RELEASE_ASSERT(S::constructCount == 10);
  MOZ_RELEASE_ASSERT(S::moveCount == 5);
  MOZ_RELEASE_ASSERT(S::destructCount == 5);

  buf = vec.extractRawBuffer();
  MOZ_RELEASE_ASSERT(buf);
  MOZ_RELEASE_ASSERT(vec.length() == 0);
  MOZ_ASSERT(vec.reserved() == 0);
  MOZ_RELEASE_ASSERT(S::constructCount == 10);
  MOZ_RELEASE_ASSERT(S::moveCount == 5);
  MOZ_RELEASE_ASSERT(S::destructCount == 5);

  for (size_t i = 0; i < 10; i++) {
    MOZ_RELEASE_ASSERT(buf[i].j == i);
    MOZ_RELEASE_ASSERT(*buf[i].k == i * i);
  }

  free(buf);
}

void mozilla::detail::VectorTesting::testExtractOrCopyRawBuffer() {
  S::resetCounts();

  Vector<S, 5> vec;
  MOZ_RELEASE_ASSERT(vec.reserve(5));
  for (size_t i = 0; i < 5; i++) {
    vec.infallibleEmplaceBack(i, i * i);
  }
  MOZ_RELEASE_ASSERT(vec.length() == 5);
  MOZ_ASSERT(vec.reserved() == 5);
  MOZ_RELEASE_ASSERT(S::constructCount == 5);
  MOZ_RELEASE_ASSERT(S::moveCount == 0);
  MOZ_RELEASE_ASSERT(S::destructCount == 0);

  S* buf = vec.extractOrCopyRawBuffer();
  MOZ_RELEASE_ASSERT(buf);
  MOZ_RELEASE_ASSERT(vec.length() == 0);
  MOZ_ASSERT(vec.reserved() == 0);
  MOZ_RELEASE_ASSERT(S::constructCount == 5);
  MOZ_RELEASE_ASSERT(S::moveCount == 5);
  MOZ_RELEASE_ASSERT(S::destructCount == 5);

  for (size_t i = 0; i < 5; i++) {
    MOZ_RELEASE_ASSERT(buf[i].j == i);
    MOZ_RELEASE_ASSERT(*buf[i].k == i * i);
  }

  S::resetCounts();

  MOZ_RELEASE_ASSERT(vec.reserve(10));
  for (size_t i = 0; i < 10; i++) {
    vec.infallibleEmplaceBack(i, i * i);
  }
  MOZ_RELEASE_ASSERT(vec.length() == 10);
  MOZ_ASSERT(vec.reserved() == 10);
  MOZ_RELEASE_ASSERT(S::constructCount == 10);
  MOZ_RELEASE_ASSERT(S::moveCount == 0);
  MOZ_RELEASE_ASSERT(S::destructCount == 0);

  buf = vec.extractOrCopyRawBuffer();
  MOZ_RELEASE_ASSERT(buf);
  MOZ_RELEASE_ASSERT(vec.length() == 0);
  MOZ_ASSERT(vec.reserved() == 0);
  MOZ_RELEASE_ASSERT(S::constructCount == 10);
  MOZ_RELEASE_ASSERT(S::moveCount == 0);
  MOZ_RELEASE_ASSERT(S::destructCount == 0);

  for (size_t i = 0; i < 10; i++) {
    MOZ_RELEASE_ASSERT(buf[i].j == i);
    MOZ_RELEASE_ASSERT(*buf[i].k == i * i);
  }

  free(buf);
}

void mozilla::detail::VectorTesting::testReplaceRawBuffer() {
  S::resetCounts();

  S* s = nullptr;

  {
    Vector<S> v;
    MOZ_RELEASE_ASSERT(v.reserve(4));
    v.infallibleEmplaceBack(1, 2);
    v.infallibleEmplaceBack(3, 4);
    MOZ_RELEASE_ASSERT(S::constructCount == 2);
    s = v.extractRawBuffer();
  }

  MOZ_RELEASE_ASSERT(S::constructCount == 2);
  MOZ_RELEASE_ASSERT(S::moveCount == 0);
  MOZ_RELEASE_ASSERT(S::destructCount == 0);

  {
    Vector<S, 10> v;
    v.replaceRawBuffer(s, 2);
    MOZ_ASSERT(v.reserved() == 2);
    MOZ_RELEASE_ASSERT(v.length() == 2);
    MOZ_RELEASE_ASSERT(v.capacity() == 10);
    MOZ_RELEASE_ASSERT(v[0].j == 1);
    MOZ_RELEASE_ASSERT(v[1].j == 3);
    MOZ_RELEASE_ASSERT(S::destructCount == 2);
  }

  MOZ_RELEASE_ASSERT(S::constructCount == 2);
  MOZ_RELEASE_ASSERT(S::moveCount == 2);
  MOZ_RELEASE_ASSERT(S::destructCount == 4);

  S::resetCounts();

  {
    Vector<S, 2> v;
    MOZ_RELEASE_ASSERT(v.reserve(4));
    v.infallibleEmplaceBack(9, 10);
    MOZ_RELEASE_ASSERT(S::constructCount == 1);
    s = v.extractRawBuffer();
    MOZ_RELEASE_ASSERT(S::constructCount == 1);
    MOZ_RELEASE_ASSERT(S::moveCount == 0);
  }

  MOZ_RELEASE_ASSERT(S::destructCount == 0);

  {
    Vector<S> v;
    v.replaceRawBuffer(s, 1, 4);
    MOZ_ASSERT(v.reserved() == 4);
    MOZ_RELEASE_ASSERT(v.length() == 1);
    MOZ_RELEASE_ASSERT(v.capacity() == 4);
    MOZ_RELEASE_ASSERT(v[0].j == 9);
    for (size_t i = 0; i < 5; i++) MOZ_RELEASE_ASSERT(v.emplaceBack(i, i));
    MOZ_ASSERT(v.reserved() == 6);
    MOZ_RELEASE_ASSERT(v.length() == 6);
    MOZ_RELEASE_ASSERT(S::constructCount == 6);
    MOZ_RELEASE_ASSERT(S::moveCount == 4);
    MOZ_RELEASE_ASSERT(S::destructCount == 4);
  }

  MOZ_RELEASE_ASSERT(S::destructCount == 10);
}

void mozilla::detail::VectorTesting::testInsert() {
  S::resetCounts();

  Vector<S, 8> vec;
  MOZ_RELEASE_ASSERT(vec.reserve(8));
  for (size_t i = 0; i < 7; i++) {
    vec.infallibleEmplaceBack(i, i * i);
  }

  MOZ_RELEASE_ASSERT(vec.length() == 7);
  MOZ_ASSERT(vec.reserved() == 8);
  MOZ_RELEASE_ASSERT(S::constructCount == 7);
  MOZ_RELEASE_ASSERT(S::moveCount == 0);
  MOZ_RELEASE_ASSERT(S::destructCount == 0);

  S s(42, 43);
  MOZ_RELEASE_ASSERT(vec.insert(vec.begin() + 4, std::move(s)));

  for (size_t i = 0; i < vec.length(); i++) {
    const S& s = vec[i];
    MOZ_RELEASE_ASSERT(s.k);
    if (i < 4) {
      MOZ_RELEASE_ASSERT(s.j == i && *s.k == i * i);
    } else if (i == 4) {
      MOZ_RELEASE_ASSERT(s.j == 42 && *s.k == 43);
    } else {
      MOZ_RELEASE_ASSERT(s.j == i - 1 && *s.k == (i - 1) * (i - 1));
    }
  }

  MOZ_RELEASE_ASSERT(vec.length() == 8);
  MOZ_ASSERT(vec.reserved() == 8);
  MOZ_RELEASE_ASSERT(S::constructCount == 8);
  MOZ_RELEASE_ASSERT(S::moveCount == 1 /* move in insert() call */ +
                                         1 /* move the back() element */ +
                                         3 /* elements to shift */);
  MOZ_RELEASE_ASSERT(S::destructCount == 1);
}

void mozilla::detail::VectorTesting::testErase() {
  S::resetCounts();

  Vector<S, 8> vec;
  MOZ_RELEASE_ASSERT(vec.reserve(8));
  for (size_t i = 0; i < 7; i++) {
    vec.infallibleEmplaceBack(i, i * i);
  }

  // vec: [0, 1, 2, 3, 4, 5, 6]
  MOZ_RELEASE_ASSERT(vec.length() == 7);
  MOZ_ASSERT(vec.reserved() == 8);
  MOZ_RELEASE_ASSERT(S::constructCount == 7);
  MOZ_RELEASE_ASSERT(S::moveCount == 0);
  MOZ_RELEASE_ASSERT(S::destructCount == 0);
  S::resetCounts();

  vec.erase(&vec[4]);
  // vec: [0, 1, 2, 3, 5, 6]
  MOZ_RELEASE_ASSERT(vec.length() == 6);
  MOZ_ASSERT(vec.reserved() == 8);
  MOZ_RELEASE_ASSERT(S::constructCount == 0);
  // 5 and 6 should have been moved into 4 and 5.
  MOZ_RELEASE_ASSERT(S::moveCount == 2);
  MOZ_RELEASE_ASSERT(S::destructCount == 1);
  MOZ_RELEASE_ASSERT(vec[4] == S(5, 5 * 5));
  MOZ_RELEASE_ASSERT(vec[5] == S(6, 6 * 6));
  S::resetCounts();

  vec.erase(&vec[3], &vec[5]);
  // vec: [0, 1, 2, 6]
  MOZ_RELEASE_ASSERT(vec.length() == 4);
  MOZ_ASSERT(vec.reserved() == 8);
  MOZ_RELEASE_ASSERT(S::constructCount == 0);
  // 6 should have been moved into 3.
  MOZ_RELEASE_ASSERT(S::moveCount == 1);
  MOZ_RELEASE_ASSERT(S::destructCount == 2);
  MOZ_RELEASE_ASSERT(vec[3] == S(6, 6 * 6));

  S s2(2, 2 * 2);
  S::resetCounts();

  vec.eraseIfEqual(s2);
  // vec: [0, 1, 6]
  MOZ_RELEASE_ASSERT(vec.length() == 3);
  MOZ_ASSERT(vec.reserved() == 8);
  MOZ_RELEASE_ASSERT(S::constructCount == 0);
  // 6 should have been moved into 2.
  MOZ_RELEASE_ASSERT(S::moveCount == 1);
  MOZ_RELEASE_ASSERT(S::destructCount == 1);
  MOZ_RELEASE_ASSERT(vec[2] == S(6, 6 * 6));
  S::resetCounts();

  // Predicate to find one element.
  vec.eraseIf([](const S& s) { return s.j == 1; });
  // vec: [0, 6]
  MOZ_RELEASE_ASSERT(vec.length() == 2);
  MOZ_ASSERT(vec.reserved() == 8);
  MOZ_RELEASE_ASSERT(S::constructCount == 0);
  // 6 should have been moved into 1.
  MOZ_RELEASE_ASSERT(S::moveCount == 1);
  MOZ_RELEASE_ASSERT(S::destructCount == 1);
  MOZ_RELEASE_ASSERT(vec[1] == S(6, 6 * 6));
  S::resetCounts();

  // Generic predicate that flags everything.
  vec.eraseIf([](auto&&) { return true; });
  // vec: []
  MOZ_RELEASE_ASSERT(vec.length() == 0);
  MOZ_ASSERT(vec.reserved() == 8);
  MOZ_RELEASE_ASSERT(S::constructCount == 0);
  MOZ_RELEASE_ASSERT(S::moveCount == 0);
  MOZ_RELEASE_ASSERT(S::destructCount == 2);

  for (size_t i = 0; i < 7; i++) {
    vec.infallibleEmplaceBack(i, i * i);
  }
  // vec: [0, 1, 2, 3, 4, 5, 6]
  MOZ_RELEASE_ASSERT(vec.length() == 7);
  S::resetCounts();

  // Predicate that flags all even numbers.
  vec.eraseIf([](const S& s) { return s.j % 2 == 0; });
  // vec: [1 (was 0), 3 (was 1), 5 (was 2)]
  MOZ_RELEASE_ASSERT(vec.length() == 3);
  MOZ_ASSERT(vec.reserved() == 8);
  MOZ_RELEASE_ASSERT(S::constructCount == 0);
  MOZ_RELEASE_ASSERT(S::moveCount == 3);
  MOZ_RELEASE_ASSERT(S::destructCount == 4);
}

void mozilla::detail::VectorTesting::testShrinkStorageToFit() {
  // Vectors not using inline storage realloc capacity to exact length.
  {
    Vector<int, 0> v1;
    MOZ_RELEASE_ASSERT(v1.reserve(10));
    v1.infallibleAppend(1);
    MOZ_ASSERT(v1.reserved() == 10);
    MOZ_RELEASE_ASSERT(v1.length() == 1);
    MOZ_RELEASE_ASSERT(v1.capacity() >= 10);
    v1.shrinkStorageToFit();
    MOZ_ASSERT(v1.reserved() == 1);
    MOZ_RELEASE_ASSERT(v1.length() == 1);
    MOZ_RELEASE_ASSERT(v1.capacity() == 1);
  }

  // Vectors using inline storage do nothing.
  {
    Vector<int, 2> v2;
    MOZ_RELEASE_ASSERT(v2.reserve(2));
    v2.infallibleAppend(1);
    MOZ_ASSERT(v2.reserved() == 2);
    MOZ_RELEASE_ASSERT(v2.length() == 1);
    MOZ_RELEASE_ASSERT(v2.capacity() == 2);
    v2.shrinkStorageToFit();
    MOZ_ASSERT(v2.reserved() == 2);
    MOZ_RELEASE_ASSERT(v2.length() == 1);
    MOZ_RELEASE_ASSERT(v2.capacity() == 2);
  }

  // shrinkStorageToFit uses inline storage if possible.
  {
    Vector<int, 2> v;
    MOZ_RELEASE_ASSERT(v.reserve(4));
    v.infallibleAppend(1);
    MOZ_ASSERT(v.reserved() == 4);
    MOZ_RELEASE_ASSERT(v.length() == 1);
    MOZ_RELEASE_ASSERT(v.capacity() >= 4);
    v.shrinkStorageToFit();
    MOZ_ASSERT(v.reserved() == 1);
    MOZ_RELEASE_ASSERT(v.length() == 1);
    MOZ_RELEASE_ASSERT(v.capacity() == 2);
  }

  // Non-pod shrinking to non-inline storage.
  {
    static size_t sConstructCounter = 0;
    static size_t sCopyCounter = 0;
    static size_t sMoveCounter = 0;
    static size_t sDestroyCounter = 0;
    struct NonPod {
      int mSomething = 10;

      NonPod() { sConstructCounter++; }

      NonPod(const NonPod& aOther) : mSomething(aOther.mSomething) {
        sCopyCounter++;
      }
      NonPod(NonPod&& aOther) : mSomething(aOther.mSomething) {
        sMoveCounter++;
      }
      ~NonPod() { sDestroyCounter++; }
    };

    Vector<NonPod, 5> v;
    MOZ_RELEASE_ASSERT(v.reserve(10));
    for (size_t i = 0; i < 8; ++i) {
      v.infallibleEmplaceBack();
    }
    MOZ_RELEASE_ASSERT(sConstructCounter == 8);
    MOZ_RELEASE_ASSERT(sCopyCounter == 0);
    MOZ_RELEASE_ASSERT(sMoveCounter == 0);
    MOZ_RELEASE_ASSERT(sDestroyCounter == 0);
    MOZ_RELEASE_ASSERT(v.length() == 8);
    MOZ_ASSERT(v.reserved() == 10);
    MOZ_RELEASE_ASSERT(v.capacity() >= 10);
    MOZ_RELEASE_ASSERT(v.shrinkStorageToFit());

    MOZ_RELEASE_ASSERT(sConstructCounter == 8);
    MOZ_RELEASE_ASSERT(sCopyCounter == 0);
    MOZ_RELEASE_ASSERT(sMoveCounter == 8);
    MOZ_RELEASE_ASSERT(sDestroyCounter == 8);
    MOZ_RELEASE_ASSERT(v.length() == 8);
    MOZ_ASSERT(v.reserved() == 8);
    MOZ_RELEASE_ASSERT(v.capacity() == 8);
  }

  // Non-POD shrinking to inline storage.
  {
    static size_t sConstructCounter = 0;
    static size_t sCopyCounter = 0;
    static size_t sMoveCounter = 0;
    static size_t sDestroyCounter = 0;
    struct NonPod {
      int mSomething = 10;

      NonPod() { sConstructCounter++; }

      NonPod(const NonPod& aOther) : mSomething(aOther.mSomething) {
        sCopyCounter++;
      }
      NonPod(NonPod&& aOther) : mSomething(aOther.mSomething) {
        sMoveCounter++;
      }
      ~NonPod() { sDestroyCounter++; }
    };

    Vector<NonPod, 5> v;
    MOZ_RELEASE_ASSERT(v.reserve(10));
    for (size_t i = 0; i < 3; ++i) {
      v.infallibleEmplaceBack();
    }
    MOZ_RELEASE_ASSERT(sConstructCounter == 3);
    MOZ_RELEASE_ASSERT(sCopyCounter == 0);
    MOZ_RELEASE_ASSERT(sMoveCounter == 0);
    MOZ_RELEASE_ASSERT(sDestroyCounter == 0);
    MOZ_RELEASE_ASSERT(v.length() == 3);
    MOZ_ASSERT(v.reserved() == 10);
    MOZ_RELEASE_ASSERT(v.capacity() >= 10);
    MOZ_RELEASE_ASSERT(v.shrinkStorageToFit());

    MOZ_RELEASE_ASSERT(sConstructCounter == 3);
    MOZ_RELEASE_ASSERT(sCopyCounter == 0);
    MOZ_RELEASE_ASSERT(sMoveCounter == 3);
    MOZ_RELEASE_ASSERT(sDestroyCounter == 3);
    MOZ_RELEASE_ASSERT(v.length() == 3);
    MOZ_ASSERT(v.reserved() == 3);
    MOZ_RELEASE_ASSERT(v.capacity() == 5);
  }
}

void mozilla::detail::VectorTesting::testAppend() {
  // Test moving append/appendAll with a move-only type
  Vector<UniquePtr<int>> bv;
  for (const int val : IntegerRange<int>(0, 3)) {
    MOZ_RELEASE_ASSERT(bv.append(MakeUnique<int>(val)));
  }

  Vector<UniquePtr<int>> otherbv;
  for (const int val : IntegerRange<int>(3, 8)) {
    MOZ_RELEASE_ASSERT(otherbv.append(MakeUnique<int>(val)));
  }
  MOZ_RELEASE_ASSERT(bv.appendAll(std::move(otherbv)));

  MOZ_RELEASE_ASSERT(otherbv.length() == 0);
  MOZ_RELEASE_ASSERT(bv.length() == 8);
  for (const int val : IntegerRange<int>(0, 8)) {
    MOZ_RELEASE_ASSERT(*bv[val] == val);
  }
}

// Vector with no inline storage should occupy the absolute minimum space in
// non-debug builds.  (Debug adds a laundry list of other constraints, none
// directly relevant to shipping builds, that aren't worth precisely modeling.)
#ifndef DEBUG

template <typename T>
struct NoInlineStorageLayout {
  T* mBegin;
  size_t mLength;
  struct CRAndStorage {
    size_t mCapacity;
  } mTail;
};

// Only one of these should be necessary, but test a few of them for good
// measure.
static_assert(sizeof(Vector<int, 0>) == sizeof(NoInlineStorageLayout<int>),
              "Vector of int without inline storage shouldn't occupy dead "
              "space for that absence of storage");

static_assert(sizeof(Vector<bool, 0>) == sizeof(NoInlineStorageLayout<bool>),
              "Vector of bool without inline storage shouldn't occupy dead "
              "space for that absence of storage");

static_assert(sizeof(Vector<S, 0>) == sizeof(NoInlineStorageLayout<S>),
              "Vector of S without inline storage shouldn't occupy dead "
              "space for that absence of storage");

#endif  // DEBUG

static void TestVectorBeginNonNull() {
  // Vector::begin() should never return nullptr, to accommodate callers that
  // (either for hygiene, or for semantic reasons) need a non-null pointer even
  // for zero elements.

  Vector<bool, 0> bvec0;
  MOZ_RELEASE_ASSERT(bvec0.length() == 0);
  MOZ_RELEASE_ASSERT(bvec0.begin() != nullptr);

  Vector<bool, 1> bvec1;
  MOZ_RELEASE_ASSERT(bvec1.length() == 0);
  MOZ_RELEASE_ASSERT(bvec1.begin() != nullptr);

  Vector<bool, 64> bvec64;
  MOZ_RELEASE_ASSERT(bvec64.length() == 0);
  MOZ_RELEASE_ASSERT(bvec64.begin() != nullptr);

  Vector<int, 0> ivec0;
  MOZ_RELEASE_ASSERT(ivec0.length() == 0);
  MOZ_RELEASE_ASSERT(ivec0.begin() != nullptr);

  Vector<int, 1> ivec1;
  MOZ_RELEASE_ASSERT(ivec1.length() == 0);
  MOZ_RELEASE_ASSERT(ivec1.begin() != nullptr);

  Vector<int, 64> ivec64;
  MOZ_RELEASE_ASSERT(ivec64.length() == 0);
  MOZ_RELEASE_ASSERT(ivec64.begin() != nullptr);

  Vector<long, 0> lvec0;
  MOZ_RELEASE_ASSERT(lvec0.length() == 0);
  MOZ_RELEASE_ASSERT(lvec0.begin() != nullptr);

  Vector<long, 1> lvec1;
  MOZ_RELEASE_ASSERT(lvec1.length() == 0);
  MOZ_RELEASE_ASSERT(lvec1.begin() != nullptr);

  Vector<long, 64> lvec64;
  MOZ_RELEASE_ASSERT(lvec64.length() == 0);
  MOZ_RELEASE_ASSERT(lvec64.begin() != nullptr);

  // Vector<T, N> doesn't guarantee N inline elements -- the actual count is
  // capped so that any Vector fits in a not-crazy amount of space -- so the
  // code below won't overflow stacks or anything crazy.
  struct VeryBig {
    int array[16 * 1024 * 1024];
  };

  Vector<VeryBig, 0> vbvec0;
  MOZ_RELEASE_ASSERT(vbvec0.length() == 0);
  MOZ_RELEASE_ASSERT(vbvec0.begin() != nullptr);

  Vector<VeryBig, 1> vbvec1;
  MOZ_RELEASE_ASSERT(vbvec1.length() == 0);
  MOZ_RELEASE_ASSERT(vbvec1.begin() != nullptr);

  Vector<VeryBig, 64> vbvec64;
  MOZ_RELEASE_ASSERT(vbvec64.length() == 0);
  MOZ_RELEASE_ASSERT(vbvec64.begin() != nullptr);
}

int main() {
  VectorTesting::testReserved();
  VectorTesting::testConstRange();
  VectorTesting::testEmplaceBack();
  VectorTesting::testReverse();
  VectorTesting::testExtractRawBuffer();
  VectorTesting::testExtractOrCopyRawBuffer();
  VectorTesting::testReplaceRawBuffer();
  VectorTesting::testInsert();
  VectorTesting::testErase();
  VectorTesting::testShrinkStorageToFit();
  VectorTesting::testAppend();
  TestVectorBeginNonNull();
}

72%


¤ Dauer der Verarbeitung: 0.11 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.