Skip to content

Commit b591615

Browse files
committed
[ADT][Test]: multi-Pass safety, iterator_category for graph iterators
Check that using the same iterators for multiple passes produces the same result, as required by the C++ standard for forward iterators. Add a static_asserts for the iterator_category of Graph iterators (BreadthFirstIterator, DepthFirstIterator, PostOrderIterator).
1 parent 468b66a commit b591615

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

llvm/unittests/ADT/BreadthFirstIteratorTest.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
#include "TestGraph.h"
1111
#include "gtest/gtest.h"
1212

13+
#include <array>
14+
#include <iterator>
15+
#include <type_traits>
16+
17+
#include <cstddef>
18+
1319
using namespace llvm;
1420

1521
namespace llvm {
@@ -74,4 +80,29 @@ static_assert(
7480
std::is_convertible_v<decltype(*std::declval<bf_iterator<Graph<3>>>()),
7581
typename bf_iterator<Graph<3>>::reference>);
7682

83+
// bf_iterator should be (at-least) a forward-iterator
84+
static_assert(std::is_base_of_v<std::forward_iterator_tag,
85+
bf_iterator<Graph<4>>::iterator_category>);
86+
87+
TEST(BreadthFristIteratorTest, MultiPassSafeWithInternalSet) {
88+
Graph<4> G;
89+
G.AddEdge(0, 1);
90+
G.AddEdge(1, 2);
91+
G.AddEdge(1, 3);
92+
93+
std::array<decltype(G)::NodeType *, 4> NodesFirstPass, NodesSecondPass;
94+
95+
auto B = bf_begin(G), E = bf_end(G);
96+
97+
std::size_t I = 0;
98+
for (auto It = B; It != E; ++It)
99+
NodesFirstPass[I++] = *It;
100+
101+
I = 0;
102+
for (auto It = B; It != E; ++It)
103+
NodesSecondPass[I++] = *It;
104+
105+
EXPECT_EQ(NodesFirstPass, NodesSecondPass);
106+
}
107+
77108
} // end namespace llvm

llvm/unittests/ADT/DepthFirstIteratorTest.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
#include "TestGraph.h"
1111
#include "gtest/gtest.h"
1212

13+
#include <array>
14+
#include <iterator>
15+
#include <type_traits>
16+
17+
#include <cstddef>
18+
1319
using namespace llvm;
1420

1521
namespace llvm {
@@ -55,4 +61,33 @@ static_assert(
5561
std::is_convertible_v<decltype(*std::declval<df_iterator<Graph<3>>>()),
5662
typename df_iterator<Graph<3>>::reference>);
5763

64+
// df_iterator should be (at-least) a forward-iterator
65+
static_assert(std::is_base_of_v<std::forward_iterator_tag,
66+
df_iterator<Graph<4>>::iterator_category>);
67+
68+
// df_ext_iterator cannot provide multi-pass guarantee, therefore its only
69+
// an input-iterator
70+
static_assert(std::is_same_v<df_ext_iterator<Graph<4>>::iterator_category,
71+
std::input_iterator_tag>);
72+
73+
TEST(DepthFirstIteratorTest, MultiPassSafeWithInternalSet) {
74+
Graph<4> G;
75+
G.AddEdge(0, 1);
76+
G.AddEdge(1, 2);
77+
G.AddEdge(1, 3);
78+
79+
std::array<decltype(G)::NodeType *, 4> NodesFirstPass, NodesSecondPass;
80+
81+
auto B = df_begin(G), E = df_end(G);
82+
83+
std::size_t I = 0;
84+
for (auto It = B; It != E; ++It)
85+
NodesFirstPass[I++] = *It;
86+
87+
I = 0;
88+
for (auto It = B; It != E; ++It)
89+
NodesSecondPass[I++] = *It;
90+
91+
EXPECT_EQ(NodesFirstPass, NodesSecondPass);
92+
}
5893
}

llvm/unittests/ADT/PostOrderIteratorTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
#include "gtest/gtest.h"
1212
#include "TestGraph.h"
1313

14+
#include <array>
15+
#include <iterator>
16+
#include <type_traits>
17+
18+
#include <cstddef>
19+
1420
using namespace llvm;
1521

1622
namespace {
@@ -75,4 +81,34 @@ TEST(PostOrderIteratorTest, PostOrderAndReversePostOrderTraverrsal) {
7581
EXPECT_EQ(1, FromIterator[4]);
7682
EXPECT_EQ(4, FromIterator[5]);
7783
}
84+
85+
// po_iterator should be (at-least) a forward-iterator
86+
static_assert(std::is_base_of_v<std::forward_iterator_tag,
87+
po_iterator<Graph<4>>::iterator_category>);
88+
89+
// po_ext_iterator cannot provide multi-pass guarantee, therefore its only
90+
// an input-iterator
91+
static_assert(std::is_same_v<po_ext_iterator<Graph<4>>::iterator_category,
92+
std::input_iterator_tag>);
93+
94+
TEST(PostOrderIteratorTest, MultiPassSafeWithInternalSet) {
95+
Graph<4> G;
96+
G.AddEdge(0, 1);
97+
G.AddEdge(1, 2);
98+
G.AddEdge(1, 3);
99+
100+
std::array<decltype(G)::NodeType *, 4> NodesFirstPass, NodesSecondPass;
101+
102+
auto B = po_begin(G), E = po_end(G);
103+
104+
std::size_t I = 0;
105+
for (auto It = B; It != E; ++It)
106+
NodesFirstPass[I++] = *It;
107+
108+
I = 0;
109+
for (auto It = B; It != E; ++It)
110+
NodesSecondPass[I++] = *It;
111+
112+
EXPECT_EQ(NodesFirstPass, NodesSecondPass);
113+
}
78114
}

0 commit comments

Comments
 (0)