1/** \file
2 * \brief Generic tests for all array classes
3 *
4 * \author Stephan Beyer, Mirko Wagner, Tilo Wiedera
5 *
6 * \par License:
7 * This file is part of the Open Graph Drawing Framework (OGDF).
8 *
9 * \par
10 * Copyright (C)<br>
11 * See README.md in the OGDF root directory for details.
12 *
13 * \par
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * Version 2 or 3 as published by the Free Software Foundation;
17 * see the file LICENSE.txt included in the packaging of this file
18 * for details.
19 *
20 * \par
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * \par
27 * You should have received a copy of the GNU General Public
28 * License along with this program; if not, see
29 * http://www.gnu.org/copyleft/gpl.html
30 */
31
32#pragma once
33
34#include <ogdf/basic/graph_generators.h>
35#include <testing.h>
36
37/**
38 * Perform basic tests for a map of graph elements to values.
39 * @tparam ArrayType the type of array to be tested
40 * @tparam KeyType the type of key graph element
41 * @tparam ElementType the value type
42 *
43 * @param title the title of the top-level bandit::describe
44 * @param fillElement an arbitrary instance of \a ElementType
45 * @param secondElement a second instance of \a ElementType, must differ from \p fillElement
46 * @param chooseKey a function to choose an arbitrary key element from the graph
47 * @param getAllKeys a function to generate a list of all keys
48 * @param createKey a function to create a new key element in the graph
49 */
50template<template<typename> class ArrayType, typename KeyType, typename ElementType>
51void describeArray(
52 const std::string &title,
53 const ElementType &fillElement,
54 const ElementType &secondElement,
55 std::function<KeyType (const Graph&)> chooseKey,
56 std::function<void (const Graph&, List<KeyType>&)> getAllKeys,
57 std::function<KeyType (Graph&)> createKey)
58{
59 using MyArrayType = ArrayType<ElementType>;
60 using const_iterator = typename MyArrayType::const_iterator;
61 using iterator = typename MyArrayType::iterator;
62
63 describe(title.c_str(), [&]() {
64 std::unique_ptr<MyArrayType> array;
65 Graph graph;
66 randomGraph(graph, 42, 168);
67
68 before_each([&]() {
69 array.reset(new MyArrayType());
70 });
71
72 it("handles nested arrays well", [&]() {
73 Graph G;
74 G.newEdge(G.newNode(), G.newNode());
75
76 List<KeyType> keys;
77 getAllKeys(G, keys);
78
79 ArrayType<MyArrayType> nestedArray(G);
80 for (KeyType k : keys) {
81 nestedArray[k].init(G, fillElement);
82 }
83 });
84
85 describe("init", [&]() {
86 it("initializes w/o a graph", [&]() {
87 AssertThat(array->graphOf(), IsNull());
88 AssertThat(array->valid(), IsFalse());
89 array->init();
90 AssertThat(array->graphOf(), IsNull());
91 AssertThat(array->valid(), IsFalse());
92 });
93
94 it("initializes w a graph", [&]() {
95 array->init(graph);
96 AssertThat(array->graphOf(), Equals(&graph));
97 AssertThat(array->valid(), IsTrue());
98 });
99
100 it("initializes w a graph and filled", [&]() {
101 array->init(graph, fillElement);
102 AssertThat(array->graphOf(), Equals(&graph));
103 AssertThat(array->valid(), IsTrue());
104 AssertThat((*array)[chooseKey(graph)], Equals(fillElement));
105 });
106
107 it("is constructed w a graph", [&]() {
108 array.reset(new MyArrayType(graph));
109 AssertThat(array->graphOf(), Equals(&graph));
110 AssertThat(array->valid(), IsTrue());
111 });
112
113 it("is constructed w a graph and filled", [&]() {
114 array.reset(new MyArrayType(graph, fillElement));
115 AssertThat(array->graphOf(), Equals(&graph));
116 AssertThat(array->valid(), IsTrue());
117 AssertThat((*array)[chooseKey(graph)], Equals(fillElement));
118 });
119
120 it("supports copy-construction", [&]() {
121 array->init(graph, fillElement);
122 MyArrayType copiedArray(*array);
123 AssertThat(copiedArray.graphOf(), Equals(array->graphOf()));
124 AssertThat(array->valid(), IsTrue());
125 AssertThat((*array)[chooseKey(graph)], Equals(fillElement));
126 AssertThat(copiedArray.valid(), IsTrue());
127 AssertThat(copiedArray[chooseKey(graph)], Equals(fillElement));
128 });
129
130 it("implements the assignment-operator", [&]() {
131 array->init(graph, fillElement);
132 MyArrayType copiedArray = *array;
133 AssertThat(copiedArray.graphOf(), Equals(array->graphOf()));
134 AssertThat(copiedArray.valid(), IsTrue());
135 AssertThat(copiedArray[chooseKey(graph)], Equals(fillElement));
136 });
137
138 it("supports move-construction", [&]() {
139 array->init(graph, fillElement);
140 MyArrayType copiedArray = std::move(*array);
141 AssertThat(copiedArray.graphOf(), Equals(&graph));
142 AssertThat(array->graphOf(), IsNull());
143 AssertThat(array->valid(), IsFalse());
144 AssertThat(copiedArray.valid(), IsTrue());
145 AssertThat(copiedArray[chooseKey(graph)], Equals(fillElement));
146 });
147
148 it("moves an array using the assignment operator", [&]() {
149 array->init(graph, fillElement);
150 MyArrayType copiedArray;
151 copiedArray = (std::move(*array));
152 AssertThat(&(*copiedArray.graphOf()), Equals(&graph));
153 AssertThat(array->graphOf(), IsNull());
154 AssertThat(array->valid(), IsFalse());
155 AssertThat(copiedArray.valid(), IsTrue());
156 AssertThat(copiedArray[chooseKey(graph)], Equals(fillElement));
157 });
158
159 it("assigns the default value to a newly created key", [&]() {
160 array->init(graph, fillElement);
161 KeyType key = createKey(graph);
162 AssertThat((*array)[key], Equals(fillElement));
163 });
164 });
165
166 describe("access", [&]() {
167 it("distinguishes between a valid and an invalid array", [&]() {
168 AssertThat(array->valid(), IsFalse());
169 array->init(graph);
170 AssertThat(array->valid(), IsTrue());
171 });
172
173 it("knows its graph", [&]() {
174 array->init(graph);
175 AssertThat(array->graphOf(), Equals(&graph));
176 });
177
178 it("allows access with the subscript operator", [&]() {
179 array->init(graph, fillElement);
180 KeyType k = chooseKey(graph);
181 AssertThat((*array)[k], Equals(fillElement));
182 AssertThat((*array)[k] = secondElement, Equals(secondElement));
183
184 array->init(graph, fillElement);
185 const MyArrayType cAccessArray(*array);
186 AssertThat(cAccessArray[k], Equals(fillElement));
187 });
188
189 it("allows access with the () operator", [&]() {
190 array->init(graph, fillElement);
191 KeyType k = chooseKey(graph);
192 AssertThat((*array)(k), Equals(fillElement));
193 AssertThat((*array)(k) = secondElement, Equals(secondElement));
194
195 array->init(graph, fillElement);
196 const MyArrayType cAccessArray(*array);
197 AssertThat(cAccessArray(k), Equals(fillElement));
198 });
199 });
200
201 describe("iterators", [&]() {
202 before_each([&]() {
203 array->init(graph, fillElement);
204 });
205
206 it("iterates over the array", [&]() {
207 List<KeyType> list;
208 getAllKeys(graph, list);
209
210 const MyArrayType cArray(*array);
211 int counter = 0;
212 for(const_iterator it = cArray.begin(); it != cArray.end(); it++){
213 counter++;
214 }
215 AssertThat(counter, Equals(list.size()));
216
217 counter = 0;
218 for(iterator it = array->begin(); it != array->end(); it++){
219 counter++;
220 }
221 AssertThat(counter, Equals(list.size()));
222
223 counter = 0;
224 for(const_iterator it = cArray.cbegin(); it != cArray.cend(); it++){
225 counter++;
226 }
227 AssertThat(counter, Equals(list.size()));
228 });
229 });
230 });
231}
232