1import unittest
2import sys
3from altgraph.ObjectGraph import ObjectGraph
4from altgraph.Graph import Graph
5
6try:
7    from StringIO import StringIO
8except ImportError:
9    from io import StringIO
10
11
12class Node (object):
13    def __init__(self, graphident):
14        self.graphident = graphident
15
16class SubNode (Node):
17    pass
18
19class ArgNode (object):
20    def __init__(self, graphident, *args, **kwds):
21        self.graphident = graphident
22        self.args = args
23        self.kwds = kwds
24
25    def __repr__(self):
26        return '<ArgNode %s>'%(self.graphident,)
27
28class TestObjectGraph (unittest.TestCase):
29
30    def test_constructor(self):
31        graph = ObjectGraph()
32        self.assertTrue(isinstance(graph, ObjectGraph))
33
34        g = Graph()
35        graph = ObjectGraph(g)
36        self.assertTrue(graph.graph is g)
37        self.assertEqual(graph.debug, 0)
38        self.assertEqual(graph.indent, 0)
39
40        graph = ObjectGraph(debug=5)
41        self.assertEqual(graph.debug, 5)
42
43    def test_repr(self):
44        graph = ObjectGraph()
45        self.assertEqual(repr(graph), '<ObjectGraph>')
46
47
48    def testNodes(self):
49        graph = ObjectGraph()
50        n1 = Node("n1")
51        n2 = Node("n2")
52        n3 = Node("n3")
53        n4 = Node("n4")
54
55        n1b = Node("n1")
56
57        self.assertTrue(graph.getIdent(graph)  is graph)
58        self.assertTrue(graph.getRawIdent(graph)  is graph)
59
60        graph.addNode(n1)
61        graph.addNode(n2)
62        graph.addNode(n3)
63
64        self.assertTrue(n1 in graph)
65        self.assertFalse(n4 in graph)
66        self.assertTrue("n1" in graph)
67        self.assertFalse("n4" in graph)
68
69        self.assertTrue(graph.findNode(n1) is n1)
70        self.assertTrue(graph.findNode(n1b) is n1)
71        self.assertTrue(graph.findNode(n2) is n2)
72        self.assertTrue(graph.findNode(n4) is None)
73        self.assertTrue(graph.findNode("n1") is n1)
74        self.assertTrue(graph.findNode("n2") is n2)
75        self.assertTrue(graph.findNode("n4") is None)
76
77        self.assertEqual(graph.getRawIdent(n1), "n1")
78        self.assertEqual(graph.getRawIdent(n1b), "n1")
79        self.assertEqual(graph.getRawIdent(n4), "n4")
80        self.assertEqual(graph.getRawIdent("n1"), None)
81
82        self.assertEqual(graph.getIdent(n1), "n1")
83        self.assertEqual(graph.getIdent(n1b), "n1")
84        self.assertEqual(graph.getIdent(n4), "n4")
85        self.assertEqual(graph.getIdent("n1"), "n1")
86
87        self.assertTrue(n3 in graph)
88        graph.removeNode(n3)
89        self.assertTrue(n3 not in graph)
90        graph.addNode(n3)
91        self.assertTrue(n3 in graph)
92
93        n = graph.createNode(SubNode, "n1")
94        self.assertTrue(n is n1)
95
96        n = graph.createNode(SubNode, "n8")
97        self.assertTrue(isinstance(n, SubNode))
98        self.assertTrue(n in graph)
99        self.assertTrue(graph.findNode("n8") is n)
100
101        n = graph.createNode(ArgNode, "args", 1, 2, 3, a='a', b='b')
102        self.assertTrue(isinstance(n, ArgNode))
103        self.assertTrue(n in graph)
104        self.assertTrue(graph.findNode("args") is n)
105        self.assertEqual(n.args, (1, 2, 3))
106        self.assertEqual(n.kwds, {'a':'a', 'b':'b'})
107
108    def testEdges(self):
109        graph = ObjectGraph()
110        n1 = graph.createNode(ArgNode, "n1", 1)
111        n2 = graph.createNode(ArgNode, "n2", 1)
112        n3 = graph.createNode(ArgNode, "n3", 1)
113        n4 = graph.createNode(ArgNode, "n4", 1)
114
115        graph.createReference(n1, n2, "n1-n2")
116        graph.createReference("n1", "n3", "n1-n3")
117        graph.createReference("n2", n3)
118
119        g = graph.graph
120        e = g.edge_by_node("n1", "n2")
121        self.assertTrue(e is not None)
122        self.assertEqual(g.edge_data(e), "n1-n2")
123
124        e = g.edge_by_node("n1", "n3")
125        self.assertTrue(e is not None)
126        self.assertEqual(g.edge_data(e), "n1-n3")
127
128        e = g.edge_by_node("n2", "n3")
129        self.assertTrue(e is not None)
130        self.assertEqual(g.edge_data(e), None)
131
132        e = g.edge_by_node("n1", "n4")
133        self.assertTrue(e is None)
134
135        graph.removeReference(n1, n2)
136        e = g.edge_by_node("n1", "n2")
137        self.assertTrue(e is None)
138
139        graph.removeReference("n1", "n3")
140        e = g.edge_by_node("n1", "n3")
141        self.assertTrue(e is None)
142
143        graph.createReference(n1, n2, "foo")
144        e = g.edge_by_node("n1", "n2")
145        self.assertTrue(e is not None)
146        self.assertEqual(g.edge_data(e), "foo")
147
148
149    def test_flatten(self):
150        graph = ObjectGraph()
151        n1 = graph.createNode(ArgNode, "n1", 1)
152        n2 = graph.createNode(ArgNode, "n2", 2)
153        n3 = graph.createNode(ArgNode, "n3", 3)
154        n4 = graph.createNode(ArgNode, "n4", 4)
155        n5 = graph.createNode(ArgNode, "n5", 5)
156        n6 = graph.createNode(ArgNode, "n6", 6)
157        n7 = graph.createNode(ArgNode, "n7", 7)
158        n8 = graph.createNode(ArgNode, "n8", 8)
159
160        graph.createReference(graph, n1)
161        graph.createReference(graph, n7)
162        graph.createReference(n1, n2)
163        graph.createReference(n1, n4)
164        graph.createReference(n2, n3)
165        graph.createReference(n2, n5)
166        graph.createReference(n5, n6)
167        graph.createReference(n4, n6)
168        graph.createReference(n4, n2)
169
170        self.assertFalse(isinstance(graph.flatten(), list))
171
172        fl = list(graph.flatten())
173        self.assertTrue(n1 in fl)
174        self.assertTrue(n2 in fl)
175        self.assertTrue(n3 in fl)
176        self.assertTrue(n4 in fl)
177        self.assertTrue(n5 in fl)
178        self.assertTrue(n6 in fl)
179        self.assertTrue(n7 in fl)
180        self.assertFalse(n8 in fl)
181
182        fl = list(graph.flatten(start=n2))
183        self.assertFalse(n1 in fl)
184        self.assertTrue(n2 in fl)
185        self.assertTrue(n3 in fl)
186        self.assertFalse(n4 in fl)
187        self.assertTrue(n5 in fl)
188        self.assertTrue(n6 in fl)
189        self.assertFalse(n7 in fl)
190        self.assertFalse(n8 in fl)
191
192        graph.createReference(n1, n5)
193        fl = list(graph.flatten(lambda n: n.args[0] % 2 != 0))
194        self.assertTrue(n1 in fl)
195        self.assertFalse(n2 in fl)
196        self.assertFalse(n3 in fl)
197        self.assertFalse(n4 in fl)
198        self.assertTrue(n5 in fl)
199        self.assertFalse(n6 in fl)
200        self.assertTrue(n7 in fl)
201        self.assertFalse(n8 in fl)
202
203    def test_iter_nodes(self):
204        graph = ObjectGraph()
205        n1 = graph.createNode(ArgNode, "n1", 1)
206        n2 = graph.createNode(ArgNode, "n2", 2)
207        n3 = graph.createNode(ArgNode, "n3", 3)
208        n4 = graph.createNode(ArgNode, "n4", 4)
209        n5 = graph.createNode(ArgNode, "n5", 5)
210        n6 = graph.createNode(ArgNode, "n6", 5)
211
212        nodes = graph.nodes()
213        if sys.version[0] == '2':
214            self.assertTrue(hasattr(nodes, 'next'))
215        else:
216            self.assertTrue(hasattr(nodes, '__next__'))
217        self.assertTrue(hasattr(nodes, '__iter__'))
218
219        nodes = list(nodes)
220        self.assertEqual(len(nodes), 6)
221        self.assertTrue(n1 in nodes)
222        self.assertTrue(n2 in nodes)
223        self.assertTrue(n3 in nodes)
224        self.assertTrue(n4 in nodes)
225        self.assertTrue(n5 in nodes)
226        self.assertTrue(n6 in nodes)
227
228    def test_get_edges(self):
229        graph = ObjectGraph()
230        n1 = graph.createNode(ArgNode, "n1", 1)
231        n2 = graph.createNode(ArgNode, "n2", 2)
232        n3 = graph.createNode(ArgNode, "n3", 3)
233        n4 = graph.createNode(ArgNode, "n4", 4)
234        n5 = graph.createNode(ArgNode, "n5", 5)
235        n6 = graph.createNode(ArgNode, "n6", 5)
236
237        graph.createReference(n1, n2)
238        graph.createReference(n1, n3)
239        graph.createReference(n3, n1)
240        graph.createReference(n5, n1)
241        graph.createReference(n2, n4)
242        graph.createReference(n2, n5)
243        graph.createReference(n6, n2)
244
245        outs, ins = graph.get_edges(n1)
246
247        self.assertFalse(isinstance(outs, list))
248        self.assertFalse(isinstance(ins, list))
249
250        ins = list(ins)
251        outs = list(outs)
252
253
254        self.assertTrue(n1 not in outs)
255        self.assertTrue(n2 in outs)
256        self.assertTrue(n3 in outs)
257        self.assertTrue(n4 not in outs)
258        self.assertTrue(n5 not in outs)
259        self.assertTrue(n6 not in outs)
260
261        self.assertTrue(n1 not in ins)
262        self.assertTrue(n2 not in ins)
263        self.assertTrue(n3 in ins)
264        self.assertTrue(n4 not in ins)
265        self.assertTrue(n5 in ins)
266        self.assertTrue(n6 not in ins)
267
268    def test_filterStack(self):
269        graph = ObjectGraph()
270        n1 = graph.createNode(ArgNode, "n1", 0)
271        n11 = graph.createNode(ArgNode, "n1.1", 1)
272        n12 = graph.createNode(ArgNode, "n1.2", 0)
273        n111 = graph.createNode(ArgNode, "n1.1.1", 0)
274        n112 = graph.createNode(ArgNode, "n1.1.2",2)
275        n2 = graph.createNode(ArgNode, "n2", 0)
276        n3 = graph.createNode(ArgNode, "n2", 0)
277
278        graph.createReference(None, n1)
279        graph.createReference(None, n2)
280        graph.createReference(n1, n11)
281        graph.createReference(n1, n12)
282        graph.createReference(n11, n111)
283        graph.createReference(n11, n112)
284
285        self.assertTrue(n1 in graph)
286        self.assertTrue(n2 in graph)
287        self.assertTrue(n11 in graph)
288        self.assertTrue(n12 in graph)
289        self.assertTrue(n111 in graph)
290        self.assertTrue(n112 in graph)
291        self.assertTrue(n2 in graph)
292        self.assertTrue(n3 in graph)
293
294        visited, removes, orphans = graph.filterStack(
295                [lambda n: n.args[0] != 1, lambda n: n.args[0] != 2])
296
297        self.assertEqual(visited, 6)
298        self.assertEqual(removes, 2)
299        self.assertEqual(orphans, 1)
300
301        e = graph.graph.edge_by_node(n1.graphident, n111.graphident)
302        self.assertEqual(graph.graph.edge_data(e), "orphan")
303
304        self.assertTrue(n1 in graph)
305        self.assertTrue(n2 in graph)
306        self.assertTrue(n11 not in graph)
307        self.assertTrue(n12 in graph)
308        self.assertTrue(n111 in graph)
309        self.assertTrue(n112 not in graph)
310        self.assertTrue(n2 in graph)
311        self.assertTrue(n3 in graph)
312
313
314class TestObjectGraphIO (unittest.TestCase):
315    def setUp(self):
316        self._stdout = sys.stdout
317
318    def tearDown(self):
319        sys.stdout = self._stdout
320
321    def test_msg(self):
322        graph = ObjectGraph()
323
324        sys.stdout = fp = StringIO()
325        graph.msg(0, "foo")
326        self.assertEqual(fp.getvalue(), "foo \n")
327
328        sys.stdout = fp = StringIO()
329        graph.msg(5, "foo")
330        self.assertEqual(fp.getvalue(), "")
331
332        sys.stdout = fp = StringIO()
333        graph.debug = 10
334        graph.msg(5, "foo")
335        self.assertEqual(fp.getvalue(), "foo \n")
336
337        sys.stdout = fp = StringIO()
338        graph.msg(0, "foo", 1, "a")
339        self.assertEqual(fp.getvalue(), "foo 1 'a'\n")
340
341        sys.stdout = fp = StringIO()
342        graph.msgin(0, "hello", "world")
343        graph.msg(0, "test me")
344        graph.msgout(0, "bye bye")
345        self.assertEqual(fp.getvalue(), "hello 'world'\n  test me \nbye bye \n")
346
347
348if __name__ == "__main__": # pragma: no cover
349    unittest.main()
350