blob: 2c8fc7af334e8bbcd535193bb4266580b507bee3 [file] [log] [blame]
// Copyright 2024 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 <cstdint>
#include "pw_compilation_testing/negative_compilation.h"
#include "pw_containers/intrusive_forward_list.h"
#include "pw_containers/intrusive_list.h"
#include "pw_containers/intrusive_map.h"
#include "pw_containers/intrusive_multimap.h"
#include "pw_containers/intrusive_multiset.h"
#include "pw_containers/intrusive_set.h"
#include "pw_unit_test/framework.h"
namespace {
using pw::IntrusiveForwardList;
using pw::IntrusiveMap;
using pw::IntrusiveMultiMap;
using pw::IntrusiveMultiSet;
using pw::IntrusiveSet;
using pw::containers::future::IntrusiveList;
struct ForwardListItem1 : public IntrusiveForwardList<ForwardListItem1>::Item {
};
struct ForwardListItem2 : public IntrusiveForwardList<ForwardListItem2>::Item {
};
struct ListItem1 : public IntrusiveList<ListItem1>::Item {};
struct ListItem2 : public IntrusiveList<ListItem2>::Item {};
struct MapPair1 : public IntrusiveMap<uint32_t, MapPair1>::Pair {
explicit MapPair1(uint32_t id) : IntrusiveMap<uint32_t, MapPair1>::Pair(id) {}
};
struct MapPair2 : public IntrusiveMap<uint32_t, MapPair2>::Pair {
explicit MapPair2(uint32_t id) : IntrusiveMap<uint32_t, MapPair2>::Pair(id) {}
};
struct MultiMapPair1 : public IntrusiveMultiMap<uint32_t, MultiMapPair1>::Pair {
explicit MultiMapPair1(uint32_t id)
: IntrusiveMultiMap<uint32_t, MultiMapPair1>::Pair(id) {}
};
struct MultiMapPair2 : public IntrusiveMultiMap<uint32_t, MultiMapPair2>::Pair {
explicit MultiMapPair2(uint32_t id)
: IntrusiveMultiMap<uint32_t, MultiMapPair2>::Pair(id) {}
};
struct SetItem1 : public IntrusiveSet<SetItem1>::Item {
bool operator<(const SetItem1& rhs) const { return this < &rhs; }
};
struct SetItem2 : public IntrusiveSet<SetItem2>::Item {
bool operator<(const SetItem2& rhs) const { return this < &rhs; }
};
struct MultiSetItem1 : public IntrusiveMultiSet<MultiSetItem1>::Item {
bool operator<(const MultiSetItem1& rhs) const { return this < &rhs; }
};
struct MultiSetItem2 : public IntrusiveMultiSet<MultiSetItem2>::Item {
bool operator<(const MultiSetItem2& rhs) const { return this < &rhs; }
};
class Base {
public:
explicit constexpr Base(const char* name) : name_(name) {}
constexpr const char* name() const { return name_; }
private:
const char* name_;
};
class Derived : public Base,
public ForwardListItem1,
public ForwardListItem2,
public ListItem1,
public ListItem2,
public MapPair1,
public MapPair2,
public MultiMapPair1,
public MultiMapPair2,
public SetItem1,
public SetItem2,
public MultiSetItem1,
public MultiSetItem2 {
public:
Derived(const char* name, uint32_t id)
: Base(name),
MapPair1(id),
MapPair2(id),
MultiMapPair1(id),
MultiMapPair2(id) {}
};
TEST(IntrusiveItemTest, AddToEachContainerSequentially) {
Derived item("a", 1);
IntrusiveForwardList<ForwardListItem1> forward_list1;
IntrusiveForwardList<ForwardListItem2> forward_list2;
IntrusiveList<ListItem1> list1;
IntrusiveList<ListItem2> list2;
IntrusiveMap<uint32_t, MapPair1> map1;
IntrusiveMap<uint32_t, MapPair2> map2;
IntrusiveMultiMap<uint32_t, MultiMapPair1> multimap1;
IntrusiveMultiMap<uint32_t, MultiMapPair2> multimap2;
IntrusiveSet<SetItem1> set1;
IntrusiveSet<SetItem2> set2;
IntrusiveMultiSet<MultiSetItem1> multiset1;
IntrusiveMultiSet<MultiSetItem2> multiset2;
forward_list1.push_front(item);
forward_list1.clear();
forward_list2.push_front(item);
forward_list2.clear();
list1.push_back(item);
list1.clear();
list2.push_back(item);
list2.clear();
map1.insert(item);
map1.clear();
map2.insert(item);
map2.clear();
multimap1.insert(item);
multimap1.clear();
multimap2.insert(item);
multimap2.clear();
set1.insert(item);
set1.clear();
set2.insert(item);
set2.clear();
multiset1.insert(item);
multiset1.clear();
multiset2.insert(item);
multiset2.clear();
}
TEST(IntrusiveItemTest, AddToEachContainerSimultaneousy) {
Derived item("a", 1);
IntrusiveForwardList<ForwardListItem1> forward_list1;
IntrusiveForwardList<ForwardListItem2> forward_list2;
IntrusiveList<ListItem1> list1;
IntrusiveList<ListItem2> list2;
IntrusiveMap<uint32_t, MapPair1> map1;
IntrusiveMap<uint32_t, MapPair2> map2;
IntrusiveMultiMap<uint32_t, MultiMapPair1> multimap1;
IntrusiveMultiMap<uint32_t, MultiMapPair2> multimap2;
IntrusiveSet<SetItem1> set1;
IntrusiveSet<SetItem2> set2;
IntrusiveMultiSet<MultiSetItem1> multiset1;
IntrusiveMultiSet<MultiSetItem2> multiset2;
forward_list1.push_front(item);
list1.push_back(item);
map1.insert(item);
multimap1.insert(item);
set1.insert(item);
multiset1.insert(item);
forward_list1.clear();
list1.clear();
map1.clear();
multimap1.clear();
set1.clear();
multiset1.clear();
forward_list2.push_front(item);
list2.push_back(item);
map2.insert(item);
multimap2.insert(item);
set2.insert(item);
multiset2.insert(item);
forward_list2.clear();
list2.clear();
map2.clear();
multimap2.clear();
set2.clear();
multiset2.clear();
}
#if PW_NC_TEST(ForwardListValueTypeHasMultipleBases)
PW_NC_EXPECT_CLANG(
"member 'ItemType' found in multiple base classes of different types");
PW_NC_EXPECT_GCC("lookup of 'ItemType' in '{anonymous}::Derived' is ambiguous");
[[maybe_unused]] IntrusiveForwardList<Derived> bad_fwd_list;
#elif PW_NC_TEST(ListValueTypeHasMultipleBases)
PW_NC_EXPECT_CLANG(
"member 'ItemType' found in multiple base classes of different types");
PW_NC_EXPECT_GCC("lookup of 'ItemType' in '{anonymous}::Derived' is ambiguous");
[[maybe_unused]] IntrusiveList<Derived> bad_list;
#elif PW_NC_TEST(MapValueTypeHasMultipleBases)
PW_NC_EXPECT_CLANG(
"member 'key' found in multiple base classes of different types");
PW_NC_EXPECT_GCC("request for member 'key' is ambiguous");
[[maybe_unused]] IntrusiveMap<uint32_t, Derived> bad_map;
#elif PW_NC_TEST(MultiMapValueTypeHasMultipleBases)
PW_NC_EXPECT_CLANG(
"member 'key' found in multiple base classes of different types");
PW_NC_EXPECT_GCC("request for member 'key' is ambiguous");
[[maybe_unused]] IntrusiveMultiMap<uint32_t, Derived> bad_multimap;
#elif PW_NC_TEST(SetValueTypeHasMultipleBases)
PW_NC_EXPECT_CLANG(
"member 'ItemType' found in multiple base classes of different types");
PW_NC_EXPECT_GCC("lookup of 'ItemType' in '{anonymous}::Derived' is ambiguous");
[[maybe_unused]] IntrusiveSet<Derived> bad_set([](const Derived& lhs,
const Derived& rhs) {
return &lhs < &rhs;
});
#elif PW_NC_TEST(MultiSetValueTypeHasMultipleBases)
PW_NC_EXPECT_CLANG(
"member 'ItemType' found in multiple base classes of different types");
PW_NC_EXPECT_GCC("lookup of 'ItemType' in '{anonymous}::Derived' is ambiguous");
[[maybe_unused]] IntrusiveMultiSet<Derived> bad_multiset(
[](const Derived& lhs, const Derived& rhs) { return &lhs < &rhs; });
#endif // PW_NC_TEST
} // namespace