| 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 | */ |
| 50 | template<template<typename> class ArrayType, typename KeyType, typename ElementType> |
| 51 | void 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 | |