# -*- coding: utf-8 -*- # Test graph dot file generation # # Copyright (C) Andrew Bartlett 2018. # # Written by Douglas Bagnall # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """Tests for samba.graph""" import samba import samba.tests from samba import graph import re import itertools class DotFileTests(samba.tests.TestCaseInTempDir): def assertMatch(self, exp, s): m = re.match(exp, s) if m is None: self.fail("%r did not match /%s/" % (s, exp)) return m def assertHeader(self, lines, title, directed): self.assertEqual(lines[0], '/* generated by samba */') if directed: exp = r'^digraph \w+ {$' else: exp = r'^graph \w+ {$' self.assertMatch(exp, lines[1]) m = self.assertMatch(r'^label="([\w ]+)";$', lines[2]) self.assertEqual(m.group(1), title) self.assertMatch(r'^fontsize=10;$', lines[3]) self.assertMatch(r'$', lines[4]) self.assertEqual(lines[5], 'node[fontname=Helvetica; fontsize=10];') self.assertEqual(lines[6], '') def assertVertices(self, lines, names): for n, line in zip(names, lines): m = self.assertMatch(r'^"(\w+)";$', line) self.assertEqual(n, m.group(1)) def assertEdges(self, lines, edges, directed): connector = '->' if directed else '--' for edge, line in zip(edges, lines): a, b = edge m = self.assertMatch((r'^"(\w+)" ([>-]{2}) ' r'"(\w+)" ?(?:\[([^\]])\])?;$'), line) self.assertEqual(m.group(1), a) self.assertEqual(m.group(2), connector) self.assertEqual(m.group(3), b) if m.group(4): self.assertMatch(r'^[\w ]*$', m.group(4)) def test_basic_dot_files(self): vertices = tuple('abcdefgh') all_edges = tuple(itertools.combinations(vertices, 2)) line_edges = list(zip(vertices[1:], vertices[:-1])) ring_edges = line_edges + [(vertices[0], vertices[-1])] no_edges = [] # even join to even numbers, odd to odd disjoint_edges = [(a, b) for a, b in all_edges if ord(a) ^ ord(b) == 0] for name, edges in (('all', all_edges), ('line', line_edges), ('ring', ring_edges), ('no', no_edges), ('disjoint', disjoint_edges)): for directed, tag in ((True, "directed"), (False, "undirected")): title = "%s %s" % (name, tag) g = graph.dot_graph(vertices, edges, directed=directed, title=title) lines = g.split('\n') self.assertHeader(lines, title, directed) self.assertVertices(lines[7:], vertices) self.assertEdges(lines[len(vertices) + 7:], edges, directed) class DistanceTests(samba.tests.TestCase): def setUp(self): super().setUp() # a sorted list of colour set names. self.sorted_colour_sets = sorted( graph.COLOUR_SETS, # return '' for None, so it's sortable. key=lambda name: name or '') def test_simple_distance(self): edges = [('ant', 'bat'), ('cat', 'dog'), ('ant', 'elephant'), ('elephant', 'dog'), ('bat', 'dog'), ('frog', 'elephant'), ('frog', 'cat'), ('bat', 'elephant'), ('elephant', 'cat'), ('cat', 'ant'), ('cat', 'dog')] expected = { "utf8 True, colour None": ''' destination ╭────── ant │╭───── bat ││╭──── cat │││╭─── dog ││││╭── elephant source │││││╭─ frog ant ·1221- bat 3·211- cat 12·12- dog ---·-- elephant 2311·- frog 23121·''', 'utf8 True, colour ansi': ''' destination ╭────── ant │╭───── bat ││╭──── cat │││╭─── dog ││││╭── elephant source │││││╭─ frog  ant ·1221-  bat 3·211-  cat 12·12-  dog ---·-- elephant 2311·-  frog 23121· ''', 'utf8 True, colour ansi-heatmap': ''' destination ╭────── ant │╭───── bat ││╭──── cat │││╭─── dog ││││╭── elephant source │││││╭─ frog  ant ·1221-  bat 3·211-  cat 12·12-  dog ---·-- elephant 2311·-  frog 23121· ''', 'utf8 True, colour xterm-256color': ''' destination ╭────── ant │╭───── bat ││╭──── cat │││╭─── dog ││││╭── elephant source │││││╭─ frog  ant ·1221-  bat 3·211-  cat 12·12-  dog ---·-- elephant 2311·-  frog 23121· ''', 'utf8 True, colour xterm-256color-heatmap': ''' destination ╭────── ant │╭───── bat ││╭──── cat │││╭─── dog ││││╭── elephant source │││││╭─ frog  ant ·1221-  bat 3·211-  cat 12·12-  dog ---·-- elephant 2311·-  frog 23121· ''', 'utf8 False, colour None': ''' destination ,------ ant |,----- bat ||,---- cat |||,--- dog ||||,-- elephant source |||||,- frog ant 01221- bat 30211- cat 12012- dog ---0-- elephant 23110- frog 231210 ''', 'utf8 False, colour ansi': ''' destination ,------ ant |,----- bat ||,---- cat |||,--- dog ||||,-- elephant source |||||,- frog  ant 01221-  bat 30211-  cat 12012-  dog ---0-- elephant 23110-  frog 231210 ''', 'utf8 False, colour ansi-heatmap': ''' destination ,------ ant |,----- bat ||,---- cat |||,--- dog ||||,-- elephant source |||||,- frog  ant 01221-  bat 30211-  cat 12012-  dog ---0-- elephant 23110-  frog 231210 ''', 'utf8 False, colour xterm-256color': ''' destination ,------ ant |,----- bat ||,---- cat |||,--- dog ||||,-- elephant source |||||,- frog  ant 01221-  bat 30211-  cat 12012-  dog ---0-- elephant 23110-  frog 231210 ''', 'utf8 False, colour xterm-256color-heatmap': ''' destination ,------ ant |,----- bat ||,---- cat |||,--- dog ||||,-- elephant source |||||,- frog  ant 01221-  bat 30211-  cat 12012-  dog ---0-- elephant 23110-  frog 231210 ''' } for utf8 in (True, False): for colour in self.sorted_colour_sets: k = 'utf8 %s, colour %s' % (utf8, colour) s = graph.distance_matrix(None, edges, utf8=utf8, colour=colour) self.assertStringsEqual(s, expected[k], strip=True, msg='Wrong output: %s\n\n%s' % (k, s)) def test_simple_distance2(self): edges = [('ant', 'bat'), ('cat', 'bat'), ('bat', 'ant'), ('ant', 'cat')] expected = { 'utf8 True, colour None': ''' destination ╭─── ant │╭── bat source ││╭─ cat ant ·11 bat 1·2 cat 21· ''', 'utf8 True, colour ansi': ''' destination ╭─── ant │╭── bat source ││╭─ cat  ant ·11  bat 1·2  cat 21· ''', 'utf8 True, colour ansi-heatmap': ''' destination ╭─── ant │╭── bat source ││╭─ cat  ant ·11  bat 1·2  cat 21· ''', 'utf8 True, colour xterm-256color': ''' destination ╭─── ant │╭── bat source ││╭─ cat  ant ·11  bat 1·2  cat 21· ''', 'utf8 True, colour xterm-256color-heatmap': ''' destination ╭─── ant │╭── bat source ││╭─ cat  ant ·11  bat 1·2  cat 21· ''', 'utf8 False, colour None': ''' destination ,--- ant |,-- bat source ||,- cat ant 011 bat 102 cat 210 ''', 'utf8 False, colour ansi': ''' destination ,--- ant |,-- bat source ||,- cat  ant 011  bat 102  cat 210 ''', 'utf8 False, colour ansi-heatmap': ''' destination ,--- ant |,-- bat source ||,- cat  ant 011  bat 102  cat 210 ''', 'utf8 False, colour xterm-256color': ''' destination ,--- ant |,-- bat source ||,- cat  ant 011  bat 102  cat 210 ''', 'utf8 False, colour xterm-256color-heatmap': ''' destination ,--- ant |,-- bat source ||,- cat  ant 011  bat 102  cat 210 ''' } for utf8 in (True, False): for colour in self.sorted_colour_sets: k = 'utf8 %s, colour %s' % (utf8, colour) s = graph.distance_matrix(None, edges, utf8=utf8, colour=colour) self.assertStringsEqual(s, expected[k], strip=True, msg='Wrong output: %s\n\n%s' % (k, s)) def test_simple_distance3(self): edges = [('ant', 'bat'), ('bat', 'cat'), ('cat', 'dog'), ('dog', 'ant'), ('dog', 'eel')] expected = { 'utf8 True, colour None': ''' destination ╭───── ant │╭──── bat ││╭─── cat │││╭── dog source ││││╭─ eel ant ·1234 bat 3·123 cat 23·12 dog 123·1 eel ----· ''', 'utf8 True, colour ansi': ''' destination ╭───── ant │╭──── bat ││╭─── cat │││╭── dog source ││││╭─ eel  ant ·1234  bat 3·123  cat 23·12  dog 123·1  eel ----· ''', 'utf8 True, colour ansi-heatmap': ''' destination ╭───── ant │╭──── bat ││╭─── cat │││╭── dog source ││││╭─ eel  ant ·1234  bat 3·123  cat 23·12  dog 123·1  eel ----· ''', 'utf8 True, colour xterm-256color': ''' destination ╭───── ant │╭──── bat ││╭─── cat │││╭── dog source ││││╭─ eel  ant ·1234  bat 3·123  cat 23·12  dog 123·1  eel ----· ''', 'utf8 True, colour xterm-256color-heatmap': ''' destination ╭───── ant │╭──── bat ││╭─── cat │││╭── dog source ││││╭─ eel  ant ·1234  bat 3·123  cat 23·12  dog 123·1  eel ----· ''', 'utf8 False, colour None': ''' destination ,----- ant |,---- bat ||,--- cat |||,-- dog source ||||,- eel ant 01234 bat 30123 cat 23012 dog 12301 eel ----0 ''', 'utf8 False, colour ansi': ''' destination ,----- ant |,---- bat ||,--- cat |||,-- dog source ||||,- eel  ant 01234  bat 30123  cat 23012  dog 12301  eel ----0 ''', 'utf8 False, colour ansi-heatmap': ''' destination ,----- ant |,---- bat ||,--- cat |||,-- dog source ||||,- eel  ant 01234  bat 30123  cat 23012  dog 12301  eel ----0 ''', 'utf8 False, colour xterm-256color': ''' destination ,----- ant |,---- bat ||,--- cat |||,-- dog source ||||,- eel  ant 01234  bat 30123  cat 23012  dog 12301  eel ----0 ''', 'utf8 False, colour xterm-256color-heatmap': ''' destination ,----- ant |,---- bat ||,--- cat |||,-- dog source ||||,- eel  ant 01234  bat 30123  cat 23012  dog 12301  eel ----0 ''' } for utf8 in (True, False): for colour in self.sorted_colour_sets: k = 'utf8 %s, colour %s' % (utf8, colour) s = graph.distance_matrix(None, edges, utf8=utf8, colour=colour) self.assertStringsEqual(s, expected[k], strip=True, msg='Wrong output: %s\n\n%s' % (k, s))