Skip to content

Commit 597976e

Browse files
feat: added tests for dial and minor changes
1 parent 15eaeab commit 597976e

3 files changed

Lines changed: 182 additions & 3 deletions

File tree

include/CXXGraph/Graph/Algorithm/Dial_impl.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const DialResult Graph<T>::dial(const Node<T> &source, int maxWeight) const {
4747
its bucket is stored so that vertex can be deleted
4848
in O(1) at time of updation. So
4949
dist[i].first = distance of ith vertex from src vertex
50-
dits[i].second = vertex i in bucket number */
50+
dist[i].second = vertex i in bucket number */
5151
auto V = nodeSet.size();
5252
std::unordered_map<shared<const Node<T>>,
5353
std::pair<long, shared<const Node<T>>>, nodeHash<T>>

include/CXXGraph/Utility/Typedef.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,13 @@ struct MstResult_struct {
145145
};
146146
typedef MstResult_struct MstResult;
147147

148-
/// Struct that contains the information about Dijsktra's Algorithm results
148+
/// Struct that contains the information about Dijkstra's Algorithm results
149149
struct DialResult_struct {
150150
bool success =
151151
false; // TRUE if the function does not return error, FALSE otherwise
152152
std::string errorMessage = ""; // message of error
153153
std::unordered_map<unsigned long long, long> minDistanceMap =
154-
{}; // result a map that contains the node id and the minumum distance
154+
{}; // result a map that contains the node id and the minimum distance
155155
// from source (valid only if success is TRUE)
156156
};
157157
typedef DialResult_struct DialResult;

test/DialTest.cpp

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ using shared = std::shared_ptr<T>;
1212
using std::make_shared;
1313
using std::make_unique;
1414

15+
/*
16+
* 3 Nodes
17+
* Node1 -> Node2 weight = 1
18+
* Node2 -> Node3 weight = 1
19+
* Node1 <-> Node3 weight = 6
20+
*/
1521
TEST(DialTest, test_1) {
1622
CXXGraph::Node<int> node1("1", 1);
1723
CXXGraph::Node<int> node2("2", 2);
@@ -34,6 +40,12 @@ TEST(DialTest, test_1) {
3440
ASSERT_EQ(res.minDistanceMap.at(node3.getId()), 2);
3541
}
3642

43+
/*
44+
* 3 Nodes
45+
* Node1 -> Node2 weight = 5
46+
* Node2 -> Node3 weight = 4
47+
* Node1 <-> Node3 weight = 6
48+
*/
3749
TEST(DialTest, test_2) {
3850
CXXGraph::Node<int> node1("1", 1);
3951
CXXGraph::Node<int> node2("2", 2);
@@ -57,6 +69,12 @@ TEST(DialTest, test_2) {
5769
ASSERT_EQ(res.minDistanceMap.at(node3.getId()), 6);
5870
}
5971

72+
/*
73+
* 3 Nodes
74+
* Node1 -> Node2 weight = 5
75+
* Node2 -> Node3 unweighted
76+
* Node1 <-> Node3 weight = 6
77+
*/
6078
TEST(DialTest, test_3) {
6179
CXXGraph::Node<int> node1("1", 1);
6280
CXXGraph::Node<int> node2("2", 2);
@@ -77,6 +95,11 @@ TEST(DialTest, test_3) {
7795
ASSERT_TRUE(res.minDistanceMap.empty());
7896
}
7997

98+
/*
99+
* 3 Nodes
100+
* Node2 -> Node3 unweighted
101+
* Node1 <-> Node3 weight = 6
102+
*/
80103
TEST(DialTest, test_4) {
81104
CXXGraph::Node<int> node1("1", 1);
82105
CXXGraph::Node<int> node2("2", 2);
@@ -96,6 +119,12 @@ TEST(DialTest, test_4) {
96119
ASSERT_EQ(res.minDistanceMap.at(node3.getId()), 6);
97120
}
98121

122+
/*
123+
* 4 Nodes
124+
* Node2 -> Node3 unweighted
125+
* Node1 <-> Node3 weight = 6
126+
* Only nodes which are a part of the edgeSet are a part of the graph (nodeSet)
127+
*/
99128
TEST(DialTest, test_5) {
100129
CXXGraph::Node<int> node1("1", 1);
101130
CXXGraph::Node<int> node2("2", 2);
@@ -112,3 +141,153 @@ TEST(DialTest, test_5) {
112141
ASSERT_EQ(res.errorMessage, CXXGraph::ERR_SOURCE_NODE_NOT_IN_GRAPH);
113142
ASSERT_TRUE(res.minDistanceMap.empty());
114143
}
144+
145+
/*
146+
* 3 Nodes, zero weight edges
147+
* Node1 -> Node2 weight = 0
148+
* Node2 -> Node3 weight = 0
149+
*/
150+
TEST(DialTest, test_6) {
151+
CXXGraph::Node<int> node1("1", 1);
152+
CXXGraph::Node<int> node2("2", 2);
153+
CXXGraph::Node<int> node3("3", 3);
154+
155+
CXXGraph::DirectedWeightedEdge<int> edge12(1, node1, node2, 0);
156+
CXXGraph::DirectedWeightedEdge<int> edge23(1, node2, node3, 0);
157+
158+
CXXGraph::T_EdgeSet<int> edgeSet;
159+
edgeSet.insert(make_shared<CXXGraph::DirectedWeightedEdge<int>>(edge12));
160+
edgeSet.insert(make_shared<CXXGraph::DirectedWeightedEdge<int>>(edge23));
161+
162+
CXXGraph::Graph<int> graph(edgeSet);
163+
164+
// Setting maxWeight = 0 causes an early exit
165+
// As a consequence all distances except source node are at infinity.
166+
auto res = graph.dial(node1, 1);
167+
ASSERT_TRUE(res.success);
168+
ASSERT_EQ(res.errorMessage, "");
169+
ASSERT_EQ(res.minDistanceMap.at(node1.getId()), 0);
170+
ASSERT_EQ(res.minDistanceMap.at(node2.getId()), 0);
171+
ASSERT_EQ(res.minDistanceMap.at(node3.getId()), 0);
172+
}
173+
174+
/*
175+
* 2 Nodes, multi edges, same end points, choose smaller edge
176+
* Node1 -> Node2 weight = 3
177+
* Node1 -> Node2 weight = 5
178+
*/
179+
TEST(DialTest, test_7) {
180+
CXXGraph::Node<int> node1("1", 1);
181+
CXXGraph::Node<int> node2("2", 2);
182+
183+
CXXGraph::DirectedWeightedEdge<int> edge12First(1, node1, node2, 3);
184+
CXXGraph::DirectedWeightedEdge<int> edge12Second(1, node1, node2, 5);
185+
186+
CXXGraph::T_EdgeSet<int> edgeSet;
187+
edgeSet.insert(make_shared<CXXGraph::DirectedWeightedEdge<int>>(edge12First));
188+
edgeSet.insert(make_shared<CXXGraph::DirectedWeightedEdge<int>>(edge12Second));
189+
190+
CXXGraph::Graph<int> graph(edgeSet);
191+
192+
auto res = graph.dial(node1, 5);
193+
ASSERT_TRUE(res.success);
194+
ASSERT_EQ(res.errorMessage, "");
195+
ASSERT_EQ(res.minDistanceMap.at(node1.getId()), 0);
196+
ASSERT_EQ(res.minDistanceMap.at(node2.getId()), 3);
197+
}
198+
199+
/*
200+
* 3 Nodes, multi edges with a cycle, cycle should not trap algorithm
201+
* Node1 -> Node2 weight = 3
202+
* Node2 -> Node3 weight = 5
203+
* Node3 -> Node1 weight = 8
204+
* Node1 -> Node3 weight = 2
205+
*/
206+
TEST(DialTest, test_8) {
207+
CXXGraph::Node<int> node1("1", 1);
208+
CXXGraph::Node<int> node2("2", 2);
209+
CXXGraph::Node<int> node3("3", 3);
210+
211+
CXXGraph::DirectedWeightedEdge<int> edge12(1, node1, node2, 3);
212+
CXXGraph::DirectedWeightedEdge<int> edge23(1, node2, node3, 5);
213+
CXXGraph::DirectedWeightedEdge<int> edge31(1, node3, node1, 8);
214+
CXXGraph::DirectedWeightedEdge<int> edge13(1, node1, node3, 2);
215+
216+
CXXGraph::T_EdgeSet<int> edgeSet;
217+
edgeSet.insert(make_shared<CXXGraph::DirectedWeightedEdge<int>>(edge12));
218+
edgeSet.insert(make_shared<CXXGraph::DirectedWeightedEdge<int>>(edge23));
219+
edgeSet.insert(make_shared<CXXGraph::DirectedWeightedEdge<int>>(edge31));
220+
edgeSet.insert(make_shared<CXXGraph::DirectedWeightedEdge<int>>(edge13));
221+
222+
CXXGraph::Graph<int> graph(edgeSet);
223+
224+
auto res = graph.dial(node1, 5);
225+
ASSERT_TRUE(res.success);
226+
ASSERT_EQ(res.errorMessage, "");
227+
ASSERT_EQ(res.minDistanceMap.at(node1.getId()), 0);
228+
ASSERT_EQ(res.minDistanceMap.at(node2.getId()), 3);
229+
ASSERT_EQ(res.minDistanceMap.at(node3.getId()), 2);
230+
}
231+
232+
/*
233+
* 2 Nodes, self loop
234+
* Node1 -> Node1 weight = 3
235+
* Node1 -> Node2 weight = 5
236+
*/
237+
TEST(DialTest, test_9) {
238+
CXXGraph::Node<int> node1("1", 1);
239+
CXXGraph::Node<int> node2("2", 2);
240+
241+
CXXGraph::DirectedWeightedEdge<int> edge11(1, node1, node1, 3);
242+
CXXGraph::DirectedWeightedEdge<int> edge12(1, node1, node2, 5);
243+
244+
CXXGraph::T_EdgeSet<int> edgeSet;
245+
edgeSet.insert(make_shared<CXXGraph::DirectedWeightedEdge<int>>(edge11));
246+
edgeSet.insert(make_shared<CXXGraph::DirectedWeightedEdge<int>>(edge12));
247+
248+
CXXGraph::Graph<int> graph(edgeSet);
249+
250+
auto res = graph.dial(node1, 5);
251+
ASSERT_TRUE(res.success);
252+
ASSERT_EQ(res.errorMessage, "");
253+
ASSERT_EQ(res.minDistanceMap.at(node1.getId()), 0);
254+
ASSERT_EQ(res.minDistanceMap.at(node2.getId()), 5);
255+
}
256+
257+
template <typename T>
258+
class BadDirectedWeightedEdge : public CXXGraph::DirectedWeightedEdge<T> {
259+
public:
260+
using Base = CXXGraph::DirectedWeightedEdge<T>;
261+
// forward to existing ctor
262+
BadDirectedWeightedEdge(const CXXGraph::id_t id,
263+
const CXXGraph::Node<T> &n1,
264+
const CXXGraph::Node<T> &n2,
265+
const double weight)
266+
: Base(id, n1, n2, weight) {}
267+
268+
const std::optional<bool> isDirected() const override {
269+
return std::nullopt;
270+
}
271+
};
272+
273+
/*
274+
* 2 Nodes, invalid directed weighted edge
275+
* The edge claims it's weighted but does not tell us direction
276+
* Node1 -> Node2 weight = 5
277+
*/
278+
TEST(DialTest, test_10) {
279+
CXXGraph::Node<int> node1("1", 1);
280+
CXXGraph::Node<int> node2("2", 2);
281+
282+
auto badEdge = std::make_shared<BadDirectedWeightedEdge<int>>(1, node1, node2, 5);
283+
284+
CXXGraph::T_EdgeSet<int> edgeSet;
285+
edgeSet.insert(badEdge);
286+
287+
CXXGraph::Graph<int> graph(edgeSet);
288+
289+
auto res = graph.dial(node1, 5);
290+
ASSERT_FALSE(res.success);
291+
ASSERT_EQ(res.errorMessage, CXXGraph::ERR_NO_DIR_OR_UNDIR_EDGE);
292+
ASSERT_TRUE(res.minDistanceMap.empty());
293+
}

0 commit comments

Comments
 (0)