Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  bit_vector_test.cc

  Sprache: C
 

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include <cstdint>
#include <memory>
#include <random>
#include <vector>

#include "allocator.h"
#include "base/stl_util.h"
#include "bit_vector-inl.h"
#include "gtest/gtest.h"
#include "transform_iterator.h"

namespace art {

template <typename StorageType, StorageType kWord0, StorageType kWord1>
void TestBitVectorViewSetBitAndClearBit() {
  static constexpr StorageType kStorage[2] = { kWord0, kWord1 };
  static constexpr size_t kSizeInBits = 2 * BitSizeOf<StorageType>();
  static constexpr BitVectorView<const StorageType> kBvv(kStorage, kSizeInBits);
  auto get_bit_from_params = [](size_t index) constexpr {
    StorageType word = (index < BitSizeOf<StorageType>()) ? kWord0 : kWord1;
    size_t shift = index % BitSizeOf<StorageType>();
    return (word & (static_cast<StorageType>(1u) << shift)) != 0u;
  };
  auto verify_is_bit_set = [get_bit_from_params]() constexpr {
    for (size_t index = 0; index != kSizeInBits; ++index) {
      // If the `CHECK_EQ()` fails, the `static_assert` evaluation fails at compile time.
      CHECK_EQ(get_bit_from_params(index), kBvv.IsBitSet(index)) << index;
    }
    return true;
  };
  static_assert(verify_is_bit_set());

  auto verify_size = []() constexpr {
    for (size_t size = 0; size != kSizeInBits; ++size) {
      // If the `CHECK_EQ()` fails, the `static_assert` evaluation fails at compile time.
      CHECK_EQ(size, BitVectorView(kStorage, size).SizeInBits());
      size_t words = RoundUp(size, BitSizeOf<StorageType>()) / BitSizeOf<StorageType>();
      CHECK_EQ(words, BitVectorView(kStorage, size).SizeInWords());
    }
    return true;
  };
  static_assert(verify_size());

  StorageType storage[2] = {0u, 0u};
  size_t size_in_bits = 2 * BitSizeOf<StorageType>();
  BitVectorView<StorageType> bvv(storage, size_in_bits);
  for (size_t index = 0; index != size_in_bits; ++index) {
    ASSERT_FALSE(bvv.IsBitSet(index));
  }
  // Set one bit at a time, then clear it.
  for (size_t bit_to_set = 0; bit_to_set != size_in_bits; ++bit_to_set) {
    bvv.SetBit(bit_to_set);
    for (size_t index = 0; index != size_in_bits; ++index) {
      ASSERT_EQ(index == bit_to_set, bvv.IsBitSet(index));
    }
    ASSERT_TRUE(bvv.IsAnyBitSet());
    bvv.ClearBit(bit_to_set);
    for (size_t index = 0; index != size_in_bits; ++index) {
      ASSERT_FALSE(bvv.IsBitSet(index));
    }
    ASSERT_FALSE(bvv.IsAnyBitSet());
  }
  // Set bits for `kWord0` and `kWord1`.
  for (size_t index = 0; index != size_in_bits; ++index) {
    if (get_bit_from_params(index)) {
      bvv.SetBit(index);
    }
  }
  ASSERT_EQ(kWord0, storage[0]);
  ASSERT_EQ(kWord1, storage[1]);
  // Clear all bits that are already clear.
  for (size_t index = 0; index != size_in_bits; ++index) {
    if (!get_bit_from_params(index)) {
      bvv.ClearBit(index);
    }
  }
  ASSERT_EQ(kWord0, storage[0]);
  ASSERT_EQ(kWord1, storage[1]);
  // Clear all bits that are set.
  for (size_t index = 0; index != size_in_bits; ++index) {
    if (get_bit_from_params(index)) {
      bvv.ClearBit(index);
    }
  }
  ASSERT_EQ(0u, storage[0]);
  ASSERT_EQ(0u, storage[1]);
}

TEST(BitVectorView, Uint32T) {
  TestBitVectorViewSetBitAndClearBit<uint32_t, 0x12345678u, 0x87654321u>();
}

TEST(BitVectorView, Uint64T) {
  TestBitVectorViewSetBitAndClearBit<uint64_t,
                                     UINT64_C(0x1234567890abcdef),
                                     UINT64_C(0xfedcba0987654321)>();
}

TEST(BitVectorView, SizeT) {
  // Note: The constants below are truncated on 32-bit architectures.
  TestBitVectorViewSetBitAndClearBit<size_t,
                                     static_cast<size_t>(UINT64_C(0xfedcba0987654321)),
                                     static_cast<size_t>(UINT64_C(0x1234567890abcdef))>();
}

TEST(BitVectorView, ConversionToConstStorage) {
  uint32_t storage[] = {1u, 2u, 3u};
  size_t size = 2 * BitSizeOf<uint32_t>() + MinimumBitsToStore(storage[2]);
  BitVectorView<uint32_t> bvv(storage, size);
  auto is_bit_set = [](BitVectorView<const uint32_t> cbvv, size_t index) {
    return cbvv.IsBitSet(index);
  };
  for (size_t index = 0; index != size; ++index) {
    ASSERT_EQ(bvv.IsBitSet(index), is_bit_set(bvv, index));
  }
}

TEST(BitVectorView, DefaultConstructor) {
  BitVectorView<> bvv;
  ASSERT_EQ(0u, bvv.SizeInBits());
  ASSERT_EQ(0u, bvv.SizeInWords());
}

TEST(BitVectorView, ClearAllBits) {
  uint32_t storage[] = {1u, 2u, 0xffffffffu};
  size_t size = 2 * BitSizeOf<uint32_t>() + 1u;
  BitVectorView<uint32_t> bvv(storage, size);  // Construction allowed with bogus trailing bits.
  ASSERT_EQ(1u, storage[0]);
  ASSERT_EQ(2u, storage[1]);
  ASSERT_EQ(0xffffffffu, storage[2]);
  bvv.ClearAllBits();
  ASSERT_EQ(0u, storage[0]);
  ASSERT_EQ(0u, storage[1]);
  ASSERT_EQ(0u, storage[2]);
}

TEST(BitVectorView, SetInitialBits) {
  uint32_t storage[] = {1u, 2u, 0xffffffffu};
  size_t size = 2 * BitSizeOf<uint32_t>() + 1u;
  BitVectorView<uint32_t> bvv(storage, size);  // Construction allowed with bogus trailing bits.
  ASSERT_EQ(1u, storage[0]);
  ASSERT_EQ(2u, storage[1]);
  ASSERT_EQ(0xffffffffu, storage[2]);
  bvv.SetInitialBits(40u);
  ASSERT_EQ(0xffffffffu, storage[0]);
  ASSERT_EQ(0xffu, storage[1]);
  ASSERT_EQ(0u, storage[2]);
  bvv.SetInitialBits(0u);
  ASSERT_EQ(0u, storage[0]);
  ASSERT_EQ(0u, storage[1]);
  ASSERT_EQ(0u, storage[2]);
  bvv.SetInitialBits(17u);
  ASSERT_EQ(0x1ffffu, storage[0]);
  ASSERT_EQ(0u, storage[1]);
  ASSERT_EQ(0u, storage[2]);
  bvv.SetInitialBits(64u);
  ASSERT_EQ(0xffffffffu, storage[0]);
  ASSERT_EQ(0xffffffffu, storage[1]);
  ASSERT_EQ(0u, storage[2]);
  bvv.SetInitialBits(65u);
  ASSERT_EQ(0xffffffffu, storage[0]);
  ASSERT_EQ(0xffffffffu, storage[1]);
  ASSERT_EQ(1u, storage[2]);
}

template <typename StorageType, StorageType kWord0, StorageType kWord1>
void TestBitVectorViewIndexes() {
  StorageType storage[] = {kWord0, kWord1};
  size_t size = 2u * BitSizeOf<StorageType>();
  BitVectorView bvv(storage, size);

  std::vector<size_t> indexes1;
  for (size_t index = 0; index != size; ++index) {
    if (bvv.IsBitSet(index)) {
      indexes1.push_back(index);
    }
  }

  std::vector<size_t> indexes2;
  for (size_t index : bvv.Indexes()) {
    indexes2.push_back(index);
  }
  ASSERT_EQ(indexes1, indexes2);

  std::vector<size_t> indexes3;
  for (auto it = bvv.Indexes().begin(); !it.Done(); ++it) {
    indexes3.push_back(*it);
  }
  ASSERT_EQ(indexes1, indexes3);

  StorageType empty_storage[] = {0u, 0u, 0u};
  BitVectorView empty(empty_storage, 3 * BitSizeOf<StorageType>() - 1u);
  for (size_t index : empty.Indexes()) {
    FAIL() << index;
  }
  ASSERT_TRUE(empty.Indexes().begin().Done());
}

TEST(BitVectorView, IndexesUint32T) {
  TestBitVectorViewIndexes<uint32_t, 0x12345678u, 0x87654321u>();
}

TEST(BitVectorView, IndexesUint64T) {
  TestBitVectorViewIndexes<uint64_t,
                           UINT64_C(0x1234567890abcdef),
                           UINT64_C(0xfedcba0987654321)>();
}

TEST(BitVectorView, IndexesSizeT) {
  // Note: The constants below are truncated on 32-bit architectures.
  TestBitVectorViewIndexes<size_t,
                           static_cast<size_t>(UINT64_C(0xfedcba0987654321)),
                           static_cast<size_t>(UINT64_C(0x1234567890abcdef))>();
}

template <typename StorageType>
void TestBitVectorViewUnion() {
  // Truncated if the constants do not fit in `StorageType`.
  static constexpr StorageType kInitWord0 = static_cast<StorageType>(UINT64_C(0xfedcba0987654321));
  static constexpr StorageType kInitWord1 = static_cast<StorageType>(UINT64_C(0x1234567890abcdef));
  StorageType storage[] = { kInitWord0, kInitWord1 };
  size_t size = 2u * BitSizeOf<StorageType>();
  BitVectorView<StorageType> bvv(storage, size);

  StorageType equal_storage[] = { kInitWord0, kInitWord1 };
  BitVectorView<StorageType> equal_bvv(equal_storage, size);
  ASSERT_FALSE(bvv.Union(equal_bvv));
  ASSERT_EQ(kInitWord0, storage[0]);
  ASSERT_EQ(kInitWord1, storage[1]);

  StorageType mask = static_cast<StorageType>(UINT64_C(0x5555555555555555));
  StorageType subset_storage[] = { kInitWord0 & mask, kInitWord1 & mask };
  BitVectorView<StorageType> subset_bvv(subset_storage, size);
  ASSERT_FALSE(bvv.Union(subset_bvv));
  ASSERT_EQ(kInitWord0, storage[0]);
  ASSERT_EQ(kInitWord1, storage[1]);

  static constexpr StorageType kOtherWord0 = kInitWord1;
  static constexpr StorageType kOtherWord1 = kInitWord0;
  StorageType other_storage[] = { kOtherWord0, kOtherWord1 };
  BitVectorView<StorageType> other_bvv(other_storage, size);
  ASSERT_TRUE(bvv.Union(other_bvv));
  ASSERT_EQ(kInitWord0 | kOtherWord0, storage[0]);
  ASSERT_EQ(kInitWord1 | kOtherWord1, storage[1]);
}

TEST(BitVectorView, UnionUint32T) {
  TestBitVectorViewUnion<uint32_t>();
}

TEST(BitVectorView, UnionUint64T) {
  TestBitVectorViewUnion<uint64_t>();
}

TEST(BitVectorView, UnionSizeT) {
  // Note: The constants below are truncated on 32-bit architectures.
  TestBitVectorViewUnion<size_t>();
}

template <typename StorageType>
void TestBitVectorViewUnionIfNotIn() {
  // Truncated if the constants do not fit in `StorageType`.
  static constexpr StorageType kInitWord0 = static_cast<StorageType>(UINT64_C(0xfedcba0987654321));
  static constexpr StorageType kInitWord1 = static_cast<StorageType>(UINT64_C(0x1234567890abcdef));
  StorageType storage[] = { kInitWord0, kInitWord1 };
  size_t size = 2u * BitSizeOf<StorageType>();
  BitVectorView<StorageType> bvv(storage, size);
  StorageType equal_storage[] = { kInitWord0, kInitWord1 };
  BitVectorView<StorageType> equal_bvv(equal_storage, size);
  StorageType mask = static_cast<StorageType>(UINT64_C(0x5555555555555555));
  StorageType subset_storage[] = { kInitWord0 & mask, kInitWord1 & mask };
  BitVectorView<StorageType> subset_bvv(subset_storage, size);
  StorageType empty_storage[] = { 0u, 0u };
  BitVectorView<StorageType> empty_bvv(empty_storage, size);
  static constexpr StorageType kOtherWord0 = kInitWord1;
  static constexpr StorageType kOtherWord1 = kInitWord0;
  StorageType other_storage[] = { kOtherWord0, kOtherWord1 };
  BitVectorView<StorageType> other_bvv(other_storage, size);
  StorageType mask_storage[] = { mask, mask };
  BitVectorView<StorageType> mask_bvv(mask_storage, size);

  // Test cases where we add bits and the `not_in` is relevant.
  ASSERT_TRUE(bvv.UnionIfNotIn(other_bvv, mask_bvv));
  ASSERT_EQ(kInitWord0 | (kOtherWord0 & ~mask), storage[0]);
  ASSERT_EQ(kInitWord1 | (kOtherWord1 & ~mask), storage[1]);
  storage[0] = kInitWord0;  // Reset `bvv` storage.
  storage[1] = kInitWord1;
  ASSERT_TRUE(bvv.UnionIfNotIn(mask_bvv, other_bvv));
  ASSERT_EQ(kInitWord0 | (mask & ~kOtherWord0), storage[0]);
  ASSERT_EQ(kInitWord1 | (mask & ~kOtherWord1), storage[1]);
  storage[0] = kInitWord0;  // Reset `bvv` storage.
  storage[1] = kInitWord1;

  // Test cases where we add bits but the `not_in` is irrelevant because it's a subset of `bvv`.
  for (BitVectorView<StorageType> not_in : { equal_bvv, subset_bvv, empty_bvv }) {
    ASSERT_TRUE(bvv.UnionIfNotIn(other_bvv, not_in));
    ASSERT_EQ(kInitWord0 | kOtherWord0, storage[0]);
    ASSERT_EQ(kInitWord1 | kOtherWord1, storage[1]);
    storage[0] = kInitWord0;  // Reset `bvv` storage.
    storage[1] = kInitWord1;
    ASSERT_TRUE(bvv.UnionIfNotIn(mask_bvv, not_in));
    ASSERT_EQ(kInitWord0 | mask, storage[0]);
    ASSERT_EQ(kInitWord1 | mask, storage[1]);
    storage[0] = kInitWord0;  // Reset `bvv` storage.
    storage[1] = kInitWord1;
  }

  // Test various cases where we add no bits.
  for (BitVectorView<StorageType> union_with : { equal_bvv, subset_bvv, empty_bvv }) {
    for (BitVectorView<StorageType> not_in :
             { equal_bvv, subset_bvv, empty_bvv, other_bvv, mask_bvv }) {
      ASSERT_FALSE(bvv.UnionIfNotIn(union_with, not_in));
      ASSERT_EQ(kInitWord0, storage[0]);
      ASSERT_EQ(kInitWord1, storage[1]);
    }
  }
  ASSERT_FALSE(bvv.UnionIfNotIn(other_bvv, other_bvv));
  ASSERT_EQ(kInitWord0, storage[0]);
  ASSERT_EQ(kInitWord1, storage[1]);
  ASSERT_FALSE(bvv.UnionIfNotIn(mask_bvv, mask_bvv));
  ASSERT_EQ(kInitWord0, storage[0]);
  ASSERT_EQ(kInitWord1, storage[1]);
}

TEST(BitVectorView, UnionIfNotInUint32T) {
  TestBitVectorViewUnionIfNotIn<uint32_t>();
}

TEST(BitVectorView, UnionIfNotInUint64T) {
  TestBitVectorViewUnionIfNotIn<uint64_t>();
}

TEST(BitVectorView, UnionIfNotInSizeT) {
  // Note: The constants below are truncated on 32-bit architectures.
  TestBitVectorViewUnionIfNotIn<size_t>();
}

TEST(BitVector, Test) {
  const size_t kBits = 32;

  BitVector bv(kBits, false, Allocator::GetCallocAllocator());
  EXPECT_EQ(1U, bv.GetStorageSize());
  EXPECT_EQ(sizeof(uint32_t), bv.GetSizeOf());
  EXPECT_FALSE(bv.IsExpandable());

  EXPECT_EQ(0U, bv.NumSetBits());
  EXPECT_EQ(0U, bv.NumSetBits(1));
  EXPECT_EQ(0U, bv.NumSetBits(kBits));
  for (size_t i = 0; i < kBits; i++) {
    EXPECT_FALSE(bv.IsBitSet(i));
  }
  EXPECT_EQ(0U, bv.GetRawStorageWord(0));
  EXPECT_EQ(0U, *bv.GetRawStorage());

  EXPECT_TRUE(bv.Indexes().begin().Done());
  EXPECT_TRUE(bv.Indexes().begin() == bv.Indexes().end());

  bv.SetBit(0);
  bv.SetBit(kBits - 1);
  EXPECT_EQ(2U, bv.NumSetBits());
  EXPECT_EQ(1U, bv.NumSetBits(1));
  EXPECT_EQ(2U, bv.NumSetBits(kBits));
  EXPECT_TRUE(bv.IsBitSet(0));
  for (size_t i = 1; i < kBits - 1; i++) {
    EXPECT_FALSE(bv.IsBitSet(i));
  }
  EXPECT_TRUE(bv.IsBitSet(kBits - 1));
  EXPECT_EQ(0x80000001U, bv.GetRawStorageWord(0));
  EXPECT_EQ(0x80000001U, *bv.GetRawStorage());

  BitVectorIndexIterator<const uint32_t> iterator = bv.Indexes().begin();
  EXPECT_TRUE(iterator != bv.Indexes().end());
  EXPECT_EQ(0u, *iterator);
  ++iterator;
  EXPECT_TRUE(iterator != bv.Indexes().end());
  EXPECT_EQ(kBits - 1u, *iterator);
  ++iterator;
  EXPECT_TRUE(iterator == bv.Indexes().end());
}

struct MessyAllocator : public Allocator {
 public:
  MessyAllocator() : malloc_(Allocator::GetCallocAllocator()) {}
  ~MessyAllocator() {}

  void* Alloc(size_t s) override {
    void* res = malloc_->Alloc(s);
    memset(res, 0xfe, s);
    return res;
  }

  void Free(void* v) override {
    malloc_->Free(v);
  }

 private:
  Allocator* malloc_;
};

TEST(BitVector, MessyAllocator) {
  MessyAllocator alloc;
  BitVector bv(32false, &alloc);
  bv.ClearAllBits();
  EXPECT_EQ(bv.NumSetBits(), 0u);
  EXPECT_EQ(bv.GetHighestBitSet(), -1);
}

TEST(BitVector, NoopAllocator) {
  const uint32_t kWords = 2;

  uint32_t bits[kWords];
  memset(bits, 0sizeof(bits));

  BitVector bv(false, Allocator::GetNoopAllocator(), kWords, bits);
  EXPECT_EQ(kWords, bv.GetStorageSize());
  EXPECT_EQ(kWords * sizeof(uint32_t), bv.GetSizeOf());
  EXPECT_EQ(bits, bv.GetRawStorage());
  EXPECT_EQ(0U, bv.NumSetBits());

  bv.SetBit(8);
  EXPECT_EQ(1U, bv.NumSetBits());
  EXPECT_EQ(0x00000100U, bv.GetRawStorageWord(0));
  EXPECT_EQ(0x00000000U, bv.GetRawStorageWord(1));
  EXPECT_EQ(1U, bv.NumSetBits());

  bv.SetBit(16);
  EXPECT_EQ(2U, bv.NumSetBits());
  EXPECT_EQ(0x00010100U, bv.GetRawStorageWord(0));
  EXPECT_EQ(0x00000000U, bv.GetRawStorageWord(1));
  EXPECT_EQ(2U, bv.NumSetBits());

  bv.SetBit(32);
  EXPECT_EQ(3U, bv.NumSetBits());
  EXPECT_EQ(0x00010100U, bv.GetRawStorageWord(0));
  EXPECT_EQ(0x00000001U, bv.GetRawStorageWord(1));
  EXPECT_EQ(3U, bv.NumSetBits());

  bv.SetBit(48);
  EXPECT_EQ(4U, bv.NumSetBits());
  EXPECT_EQ(0x00010100U, bv.GetRawStorageWord(0));
  EXPECT_EQ(0x00010001U, bv.GetRawStorageWord(1));
  EXPECT_EQ(4U, bv.NumSetBits());

  EXPECT_EQ(0U, bv.NumSetBits(1));

  EXPECT_EQ(0U, bv.NumSetBits(8));
  EXPECT_EQ(1U, bv.NumSetBits(9));
  EXPECT_EQ(1U, bv.NumSetBits(10));

  EXPECT_EQ(1U, bv.NumSetBits(16));
  EXPECT_EQ(2U, bv.NumSetBits(17));
  EXPECT_EQ(2U, bv.NumSetBits(18));

  EXPECT_EQ(2U, bv.NumSetBits(32));
  EXPECT_EQ(3U, bv.NumSetBits(33));
  EXPECT_EQ(3U, bv.NumSetBits(34));

  EXPECT_EQ(3U, bv.NumSetBits(48));
  EXPECT_EQ(4U, bv.NumSetBits(49));
  EXPECT_EQ(4U, bv.NumSetBits(50));

  EXPECT_EQ(4U, bv.NumSetBits(64));
}

TEST(BitVector, SetInitialBits) {
  const uint32_t kWords = 2;

  uint32_t bits[kWords];
  memset(bits, 0sizeof(bits));

  BitVector bv(false, Allocator::GetNoopAllocator(), kWords, bits);
  bv.SetInitialBits(0u);
  EXPECT_EQ(0u, bv.NumSetBits());
  bv.SetInitialBits(1u);
  EXPECT_EQ(1u, bv.NumSetBits());
  bv.SetInitialBits(32u);
  EXPECT_EQ(32u, bv.NumSetBits());
  bv.SetInitialBits(63u);
  EXPECT_EQ(63u, bv.NumSetBits());
  bv.SetInitialBits(64u);
  EXPECT_EQ(64u, bv.NumSetBits());
}

TEST(BitVector, UnionIfNotIn) {
  {
    BitVector first(2true, Allocator::GetCallocAllocator());
    BitVector second(5true, Allocator::GetCallocAllocator());
    BitVector third(5true, Allocator::GetCallocAllocator());

    second.SetBit(64);
    third.SetBit(64);
    bool changed = first.UnionIfNotIn(&second, &third);
    EXPECT_EQ(0u, first.NumSetBits());
    EXPECT_FALSE(changed);
  }

  {
    BitVector first(2true, Allocator::GetCallocAllocator());
    BitVector second(5true, Allocator::GetCallocAllocator());
    BitVector third(5true, Allocator::GetCallocAllocator());

    second.SetBit(64);
    bool changed = first.UnionIfNotIn(&second, &third);
    EXPECT_EQ(1u, first.NumSetBits());
    EXPECT_TRUE(changed);
    EXPECT_TRUE(first.IsBitSet(64));
  }
}

TEST(BitVector, Subset) {
  {
    BitVector first(2true, Allocator::GetCallocAllocator());
    BitVector second(5true, Allocator::GetCallocAllocator());

    EXPECT_TRUE(first.IsSubsetOf(&second));
    second.SetBit(4);
    EXPECT_TRUE(first.IsSubsetOf(&second));
  }

  {
    BitVector first(5true, Allocator::GetCallocAllocator());
    BitVector second(5true, Allocator::GetCallocAllocator());

    first.SetBit(5);
    EXPECT_FALSE(first.IsSubsetOf(&second));
    second.SetBit(4);
    EXPECT_FALSE(first.IsSubsetOf(&second));
  }

  {
    BitVector first(5true, Allocator::GetCallocAllocator());
    BitVector second(5true, Allocator::GetCallocAllocator());

    first.SetBit(16);
    first.SetBit(32);
    first.SetBit(48);
    second.SetBit(16);
    second.SetBit(32);
    second.SetBit(48);

    EXPECT_TRUE(first.IsSubsetOf(&second));
    second.SetBit(8);
    EXPECT_TRUE(first.IsSubsetOf(&second));
    second.SetBit(40);
    EXPECT_TRUE(first.IsSubsetOf(&second));
    second.SetBit(52);
    EXPECT_TRUE(first.IsSubsetOf(&second));

    first.SetBit(9);
    EXPECT_FALSE(first.IsSubsetOf(&second));
  }
}

TEST(BitVector, CopyTo) {
  {
    // Test copying an empty BitVector. Padding should fill `buf` with zeroes.
    BitVector bv(0true, Allocator::GetCallocAllocator());
    uint32_t buf;

    bv.CopyTo(&buf, sizeof(buf));
    EXPECT_EQ(0u, bv.GetSizeOf());
    EXPECT_EQ(0u, buf);
  }

  {
    // Test copying when `bv.storage_` and `buf` are of equal lengths.
    BitVector bv(0true, Allocator::GetCallocAllocator());
    uint32_t buf;

    bv.SetBit(0);
    bv.SetBit(17);
    bv.SetBit(26);
    EXPECT_EQ(sizeof(buf), bv.GetSizeOf());

    bv.CopyTo(&buf, sizeof(buf));
    EXPECT_EQ(0x04020001u, buf);
  }

  {
    // Test copying when the `bv.storage_` is longer than `buf`. As long as
    // `buf` is long enough to hold all set bits, copying should succeed.
    BitVector bv(0true, Allocator::GetCallocAllocator());
    uint8_t buf[5];

    bv.SetBit(18);
    bv.SetBit(39);
    EXPECT_LT(sizeof(buf), bv.GetSizeOf());

    bv.CopyTo(buf, sizeof(buf));
    EXPECT_EQ(0x00u, buf[0]);
    EXPECT_EQ(0x00u, buf[1]);
    EXPECT_EQ(0x04u, buf[2]);
    EXPECT_EQ(0x00u, buf[3]);
    EXPECT_EQ(0x80u, buf[4]);
  }

  {
    // Test zero padding when `bv.storage_` is shorter than `buf`.
    BitVector bv(0true, Allocator::GetCallocAllocator());
    uint32_t buf[2];

    bv.SetBit(18);
    bv.SetBit(31);
    EXPECT_GT(sizeof(buf), bv.GetSizeOf());

    bv.CopyTo(buf, sizeof(buf));
    EXPECT_EQ(0x80040000U, buf[0]);
    EXPECT_EQ(0x00000000U, buf[1]);
  }
}

TEST(BitVector, GetLowestBitCleared) {
  uint32_t storage_size = 3;
  {
    uint32_t storage[] = {0u, 0u, 0u};
    BitVector bv(false, Allocator::GetNoopAllocator(), storage_size, storage);
    EXPECT_EQ(0u, bv.GetLowestBitCleared());
  }

  {
    uint32_t storage[] = {UINT32_MAX, UINT32_MAX, UINT32_MAX};
    BitVector bv(false, Allocator::GetNoopAllocator(), storage_size, storage);
    EXPECT_EQ(-1, bv.GetLowestBitCleared());
  }

  {
    uint32_t storage[] = {UINT32_MAX, 0u, 0u};
    BitVector bv(false, Allocator::GetNoopAllocator(), storage_size, storage);
    EXPECT_EQ(32, bv.GetLowestBitCleared());
  }

  {
    uint32_t storage[] = {0x1, 0u, 0u};
    BitVector bv(false, Allocator::GetNoopAllocator(), storage_size, storage);
    EXPECT_EQ(1, bv.GetLowestBitCleared());
  }

  {
    uint32_t storage[] = {0x5, 0u, 0u};
    BitVector bv(false, Allocator::GetNoopAllocator(), storage_size, storage);
    EXPECT_EQ(1, bv.GetLowestBitCleared());
  }

  {
    uint32_t storage[] = {UINT32_MAX, 0x5, 0u};
    BitVector bv(false, Allocator::GetNoopAllocator(), storage_size, storage);
    EXPECT_EQ(33, bv.GetLowestBitCleared());
  }
}

TEST(BitVector, TransformIterator) {
  BitVector bv(16false, Allocator::GetCallocAllocator());
  bv.SetBit(4);
  bv.SetBit(8);

  auto indexs = bv.Indexes();
  for (int32_t negative :
       MakeTransformRange(indexs, [](uint32_t idx) { return -1 * static_cast<int32_t>(idx); })) {
    EXPECT_TRUE(negative == -4 || negative == -8);
  }
}

class SingleAllocator : public Allocator {
 public:
  SingleAllocator() : alloc_count_(0), free_count_(0) {}
  ~SingleAllocator() {
    EXPECT_EQ(alloc_count_, 1u);
    EXPECT_EQ(free_count_, 1u);
  }

  void* Alloc(size_t s) override {
    EXPECT_LT(s, 1024ull);
    EXPECT_EQ(alloc_count_, free_count_);
    ++alloc_count_;
    return bytes_.begin();
  }

  void Free(void*) override {
    ++free_count_;
  }

  uint32_t AllocCount() const {
    return alloc_count_;
  }
  uint32_t FreeCount() const {
    return free_count_;
  }

 private:
  std::array<uint8_t, 1024> bytes_;
  uint32_t alloc_count_;
  uint32_t free_count_;
};

TEST(BitVector, MovementFree) {
  SingleAllocator alloc;
  {
    BitVector bv(16false, &alloc);
    bv.SetBit(13);
    EXPECT_EQ(alloc.FreeCount(), 0u);
    EXPECT_EQ(alloc.AllocCount(), 1u);
    ASSERT_TRUE(bv.GetRawStorage() != nullptr);
    EXPECT_TRUE(bv.IsBitSet(13));
    {
      BitVector bv2(std::move(bv));
      // NOLINTNEXTLINE - checking underlying storage has been freed
      ASSERT_TRUE(bv.GetRawStorage() == nullptr);
      EXPECT_TRUE(bv2.IsBitSet(13));
      EXPECT_EQ(alloc.FreeCount(), 0u);
      EXPECT_EQ(alloc.AllocCount(), 1u);
    }
    EXPECT_EQ(alloc.FreeCount(), 1u);
    EXPECT_EQ(alloc.AllocCount(), 1u);
  }
  EXPECT_EQ(alloc.FreeCount(), 1u);
  EXPECT_EQ(alloc.AllocCount(), 1u);
}

}  // namespace art

Messung V0.5 in Prozent
C=90 H=95 G=92

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

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 und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik