blob: 9b935001bcb0204f1ee73d64e46a55dc58ce5975 [file]
// Copyright 2025 The Pigweed Authors
//
// 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
//
// https://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 "pw_containers/internal/var_len_entry.h"
#include <array>
#include <cstddef>
#include <string_view>
#include "pw_bytes/array.h"
#include "pw_containers/var_len_entry_queue.h"
#include "pw_unit_test/constexpr.h"
#include "pw_unit_test/framework.h"
namespace {
using pw::containers::internal::VarLenEntry;
using namespace std::literals::string_view_literals;
PW_CONSTEXPR_TEST(VarLenEntry, DefaultConstructed, {
VarLenEntry<std::byte> entry;
PW_TEST_EXPECT_TRUE(entry.empty());
PW_TEST_EXPECT_EQ(entry.size(), 0u);
PW_TEST_EXPECT_EQ(entry.begin(), entry.end());
VarLenEntry<const std::byte> const_entry;
PW_TEST_EXPECT_TRUE(const_entry.empty());
PW_TEST_EXPECT_EQ(const_entry.size(), 0u);
PW_TEST_EXPECT_EQ(const_entry.begin(), const_entry.end());
});
PW_CONSTEXPR_TEST_IF_CLANG(VarLenEntry, Contiguous, {
std::byte buffer[10] = {};
pw::VarLenEntryQueue queue(buffer);
auto data = pw::bytes::String("ABCDE");
queue.push(data);
VarLenEntry<const std::byte> entry = queue.front();
PW_TEST_EXPECT_FALSE(entry.empty());
PW_TEST_EXPECT_EQ(entry.size(), sizeof(data));
PW_TEST_EXPECT_EQ(entry.front(), data[0]);
PW_TEST_EXPECT_EQ(entry.back(), data[sizeof(data) - 1]);
for (size_t i = 0; i < sizeof(data); ++i) {
PW_TEST_EXPECT_EQ(entry[i], data[i]);
PW_TEST_EXPECT_EQ(entry.at(i), data[i]);
}
auto [span1, span2] = entry.contiguous_data();
PW_TEST_EXPECT_EQ(span1.size(), sizeof(data));
PW_TEST_EXPECT_TRUE(span2.empty());
for (size_t i = 0; i < sizeof(data); ++i) {
PW_TEST_EXPECT_EQ(span1[i], data[i]);
}
std::byte copy_buffer[sizeof(data)] = {};
PW_TEST_EXPECT_EQ(entry.copy(copy_buffer, sizeof(copy_buffer)), sizeof(data));
for (size_t i = 0; i < sizeof(copy_buffer); ++i) {
PW_TEST_EXPECT_EQ(copy_buffer[i], data[i]);
}
std::byte small_copy_buffer[sizeof(data) - 2] = {};
PW_TEST_EXPECT_EQ(entry.copy(small_copy_buffer, sizeof(small_copy_buffer)),
sizeof(data));
for (size_t i = 0; i < sizeof(small_copy_buffer); ++i) {
PW_TEST_EXPECT_EQ(small_copy_buffer[i], data[i]);
}
});
PW_CONSTEXPR_TEST_IF_CLANG(VarLenEntry, Discontiguous, {
std::byte buffer[8] = {};
pw::VarLenEntryQueue queue(buffer);
auto overwritten = pw::bytes::String("12");
queue.push(overwritten);
auto data = pw::bytes::String("ABCDE");
queue.push_overwrite(data);
VarLenEntry<const std::byte> entry = queue.front();
PW_TEST_EXPECT_FALSE(entry.empty());
PW_TEST_EXPECT_EQ(entry.size(), sizeof(data));
PW_TEST_EXPECT_EQ(entry.front(), data[0]);
PW_TEST_EXPECT_EQ(entry.back(), data[sizeof(data) - 1]);
for (size_t i = 0; i < sizeof(data); ++i) {
PW_TEST_EXPECT_EQ(entry[i], data[i]);
PW_TEST_EXPECT_EQ(entry.at(i), data[i]);
}
auto [span1, span2] = entry.contiguous_data();
PW_TEST_EXPECT_FALSE(span1.empty());
PW_TEST_EXPECT_FALSE(span2.empty());
PW_TEST_EXPECT_EQ(span1.size() + span2.size(), sizeof(data));
std::byte copy_buffer[sizeof(data)] = {};
PW_TEST_EXPECT_EQ(entry.copy(copy_buffer, sizeof(copy_buffer)), sizeof(data));
for (size_t i = 0; i < sizeof(copy_buffer); ++i) {
PW_TEST_EXPECT_EQ(copy_buffer[i], data[i]);
}
std::byte small_copy_buffer[sizeof(data) - 2] = {};
PW_TEST_EXPECT_EQ(entry.copy(small_copy_buffer, sizeof(small_copy_buffer)),
sizeof(data));
for (size_t i = 0; i < sizeof(small_copy_buffer); ++i) {
PW_TEST_EXPECT_EQ(small_copy_buffer[i], data[i]);
}
});
PW_CONSTEXPR_TEST_IF_CLANG(VarLenEntry, ConstConversion, {
std::byte buffer[10] = {};
pw::VarLenEntryQueue queue(buffer);
auto data = pw::bytes::String("ABC");
queue.push(data);
VarLenEntry<std::byte> entry = queue.front();
VarLenEntry<const std::byte> const_entry = entry;
PW_TEST_EXPECT_EQ(const_entry.size(), sizeof(data));
for (size_t i = 0; i < sizeof(data); ++i) {
PW_TEST_EXPECT_EQ(const_entry[i], data[i]);
PW_TEST_EXPECT_EQ(const_entry.at(i), data[i]);
}
});
PW_CONSTEXPR_TEST_IF_CLANG(VarLenEntry, Equality, {
std::byte buffer[10] = {};
pw::VarLenEntryQueue queue(buffer);
auto data = pw::bytes::String("ABC");
queue.push(data);
queue.push(data);
VarLenEntry<const std::byte> entry1 = queue.front();
queue.pop();
VarLenEntry<const std::byte> entry2 = queue.front();
// These entries have the same content but are at different locations.
PW_TEST_EXPECT_NE(entry1, entry2);
// Create a copy of the iterator to get an equal entry.
auto it = queue.begin();
VarLenEntry<const std::byte> entry3 = *it;
PW_TEST_EXPECT_EQ(entry2, entry3);
});
PW_CONSTEXPR_TEST_IF_CLANG(VarLenEntry, Mutable, {
std::byte buffer[8] = {};
pw::VarLenEntryQueue queue(buffer);
auto data = pw::bytes::String("ABCDE");
queue.push(data);
VarLenEntry<std::byte> entry = queue.front();
entry[0] = std::byte{'Z'};
entry.at(1) = std::byte{'Y'};
entry.back() = std::byte{'X'};
std::byte copy_buffer[sizeof(data)] = {};
entry.copy(copy_buffer, sizeof(copy_buffer));
PW_TEST_EXPECT_EQ(copy_buffer[0], std::byte('Z'));
PW_TEST_EXPECT_EQ(copy_buffer[1], std::byte('Y'));
PW_TEST_EXPECT_EQ(copy_buffer[2], std::byte('C'));
PW_TEST_EXPECT_EQ(copy_buffer[3], std::byte('D'));
PW_TEST_EXPECT_EQ(copy_buffer[4], std::byte('X'));
});
} // namespace