blob: 7b3737db78e7aefb53b5c525cf3b9a09a788b584 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "data_structs.h"
#include <sstream>
#include <vector>
#include <gtest/gtest.h>
#include "src/lib/testing/predicates/status.h"
namespace network {
namespace testing {
using IndexedSlab = network::internal::IndexedSlab<uint64_t>;
using RingQueue = network::internal::RingQueue<uint64_t>;
TEST(DataStructsTest, RingQueue) {
constexpr uint32_t kCapacity = 16;
zx::result queue_creation = RingQueue::Create(kCapacity);
ASSERT_OK(queue_creation.status_value());
std::unique_ptr queue = std::move(queue_creation.value());
ASSERT_EQ(queue->count(), 0u);
queue->Push(1);
queue->Push(2);
queue->Push(3);
ASSERT_EQ(queue->Peek(), 1u);
ASSERT_EQ(queue->count(), 3u);
ASSERT_EQ(queue->Pop(), 1u);
ASSERT_EQ(queue->Pop(), 2u);
ASSERT_EQ(queue->Pop(), 3u);
ASSERT_DEATH_IF_SUPPORTED(queue->Pop(), "ASSERT FAILED");
}
TEST(DataStructsTest, RingQueueOverCapacity) {
constexpr uint32_t kCapacity = 2;
zx::result queue_creation = RingQueue::Create(kCapacity);
ASSERT_OK(queue_creation.status_value());
std::unique_ptr queue = std::move(queue_creation.value());
queue->Push(1);
queue->Push(2);
ASSERT_DEATH_IF_SUPPORTED(queue->Push(3), "ASSERT FAILED");
}
TEST(DataStructsTest, IndexedSlab) {
constexpr uint32_t kCapacity = 16;
zx::result slab_creation = IndexedSlab::Create(kCapacity);
ASSERT_OK(slab_creation.status_value());
std::unique_ptr slab = std::move(slab_creation.value());
ASSERT_EQ(slab->available(), kCapacity);
uint32_t a = slab->Push(1);
uint32_t b = slab->Push(2);
uint32_t c = slab->Push(3);
ASSERT_EQ(slab->available(), kCapacity - 3);
ASSERT_EQ(slab->Get(a), 1u);
ASSERT_EQ(slab->Get(b), 2u);
ASSERT_EQ(slab->Get(c), 3u);
slab->Free(a);
slab->Free(b);
slab->Free(c);
ASSERT_EQ(slab->available(), kCapacity);
}
TEST(DataStructsTest, IndexedSlabOverCapacity) {
constexpr uint32_t kCapacity = 2;
zx::result slab_creation = IndexedSlab::Create(kCapacity);
ASSERT_OK(slab_creation.status_value());
std::unique_ptr slab = std::move(slab_creation.value());
slab->Push(1);
slab->Push(2);
ASSERT_DEATH_IF_SUPPORTED(slab->Push(3), "ASSERT FAILED");
}
TEST(DataStructsTest, IndexedSlabDoubleFree) {
constexpr uint32_t kCapacity = 2;
zx::result slab_creation = IndexedSlab::Create(kCapacity);
ASSERT_OK(slab_creation.status_value());
std::unique_ptr slab = std::move(slab_creation.value());
slab->Push(1);
uint32_t b = slab->Push(2);
slab->Free(b);
ASSERT_EQ(slab->available(), kCapacity - 1);
ASSERT_DEATH_IF_SUPPORTED(slab->Free(b), "ASSERT FAILED");
}
void VerifyIterator(IndexedSlab& slab, const std::vector<uint64_t>& expect) {
std::stringstream context_stream;
for (auto e = expect.begin(); e != expect.end(); e++) {
if (e != expect.begin()) {
context_stream << ", ";
}
context_stream << *e;
}
auto context = context_stream.str();
auto i = slab.begin();
for (auto& e : expect) {
ASSERT_EQ(slab.Get(*i), e) << ": " << context.c_str();
++i;
}
ASSERT_EQ(i, slab.end()) << ": " << context.c_str();
}
TEST(DataStructsTest, IndexedSlabIterator) {
constexpr uint32_t kCapacity = 4;
zx::result slab_creation = IndexedSlab::Create(kCapacity);
ASSERT_OK(slab_creation.status_value());
std::unique_ptr slab = std::move(slab_creation.value());
// If we're empty, the iterator should be empty:
ASSERT_EQ(slab->begin(), slab->end());
uint32_t i1 = slab->Push(1);
VerifyIterator(*slab, {1});
uint32_t i2 = slab->Push(2);
uint32_t i3 = slab->Push(3);
slab->Push(4);
VerifyIterator(*slab, {1, 2, 3, 4});
slab->Free(i2);
slab->Free(i3);
VerifyIterator(*slab, {1, 4});
slab->Push(2);
VerifyIterator(*slab, {1, 2, 4});
slab->Free(i1);
VerifyIterator(*slab, {2, 4});
}
} // namespace testing
} // namespace network