]> gitweb.factorcode.org Git - factor.git/blob - extra/graphviz/graphviz-tests.factor
Fixes #2966
[factor.git] / extra / graphviz / graphviz-tests.factor
1 USING: accessors arrays assocs continuations formatting graphviz
2 graphviz.notation graphviz.render graphviz.render.private
3 images.loader.private io.directories io.encodings.ascii
4 io.encodings.latin1 io.encodings.utf8 io.files io.launcher kernel
5 locals make math math.combinatorics math.parser namespaces
6 sequences sequences.extras sets splitting system tools.test ;
7 IN: graphviz.tests
8
9 ! XXX hack
10 : force-error-message ( flag -- elts )
11     [
12         [ default-graphviz-program , , "?" , ] { } make
13         try-output-process
14         ! To balance the stack height, have to return a default
15         ! 'elts' value, though it shouldn't ever get pushed:
16         f
17     ] [
18         nip output>>
19         "Use one of: " split1 nip "\n" ?tail drop
20         split-words
21     ] recover ;
22
23 ! http://www.graphviz.org/Download_macos.php#comment-474
24 : remove-sfdp-in-case-homebrew-is-dumb ( seq -- seq' )
25     os macosx? [ "sfdp" swap remove ] when ;
26
27 SYMBOLS: supported-layouts supported-formats ;
28
29 : init-supported-layouts/formats ( -- )
30     "-K" force-error-message standard-layouts intersect
31     remove-sfdp-in-case-homebrew-is-dumb
32     supported-layouts set-global
33
34     "-T" force-error-message standard-formats intersect
35     supported-formats set-global ;
36
37 ! Can't predict file extension since we use Graphviz's actual
38 ! -O flag, so just look to see that there seems to be some sort
39 ! of output.
40 : graphviz-output-appears-to-exist? ( base -- ? )
41     "." directory-files [ swap head? ] with count 1 = ;
42
43 : next! ( seq -- elt ) [ first ] [ 1 rotate! ] bi ;
44
45 :: smoke-test ( graph -- pass? )
46     supported-formats get-global next! :> -T
47     supported-layouts get-global next! :> -K
48     [
49         graph "smoke-test" -T -K graphviz
50         "smoke-test" graphviz-output-appears-to-exist?
51     ] with-test-directory ;
52
53 : preview-smoke-test ( graph -- pass? )
54     [ file-exists? ] with-preview ;
55
56 : K_n ( n -- graph )
57     <graph>
58     [node "point" =shape ];
59     [graph "t" =labelloc "circo" =layout ];
60     over number>string "K " prepend =label
61     swap <iota> 2 [ first2 add-edge ] each-combination ;
62
63 :: partite-set ( n color -- cluster )
64     color <cluster>
65         color =color
66         [node color =color ];
67         n <iota> [
68             number>string color prepend add-node
69         ] each ;
70
71 :: K_n,m ( n m -- graph )
72     <graph>
73     [node "point" =shape ];
74     [graph "t" =labelloc "dot" =layout "LR" =rankdir ];
75     n "#FF0000" partite-set
76     m "#0000FF" partite-set
77     add-edge
78     n m "K %d,%d" sprintf =label ;
79
80 : add-cycle ( graph n -- graph' )
81     [ <iota> add-path ] [ 1 - 0 add-edge ] bi ;
82
83 : C_n ( n -- graph )
84     <graph>
85     [graph "t" =labelloc "circo" =layout ];
86     [node "point" =shape ];
87     over number>string "C " prepend =label
88     swap add-cycle ;
89
90 : W_n ( n -- graph )
91     <graph>
92     [graph "t" =labelloc "twopi" =layout ];
93     [node "point" =shape ];
94     over number>string "W " prepend =label
95     over add-node
96     over 1 - add-cycle
97     swap [ ] [ 1 - <iota> >array ] bi add-edge ;
98
99 : cluster-example ( -- graph )
100     <digraph>
101         "dot" =layout
102         0 <cluster>
103             "filled" =style
104             "lightgrey" =color
105             [node "filled" =style "white" =color ];
106             { "a0" "a1" "a2" "a3" } ~->
107             "process #1" =label
108         add
109         1 <cluster>
110             [node "filled" =style ];
111             { "b0" "b1" "b2" "b3" } ~->
112             "process #2" =label
113             "blue" =color
114         add
115         "start" "a0" ->
116         "start" "b0" ->
117         "a1" "b3" ->
118         "b2" "a3" ->
119         "a3" "a0" ->
120         "a3" "end" ->
121         "b3" "end" ->
122         "start" [add-node "Mdiamond" =shape ];
123         "end" [add-node "Msquare" =shape ];
124     ;
125
126 : colored-circle ( i -- node )
127     [ <node> ] keep
128     [ 16.0 / 0.5 + =width ]
129     [ 16.0 / 0.5 + =height ]
130     [ 16 * "#%2x0000" sprintf =fillcolor ] tri ;
131
132 : colored-circles-example ( -- graph )
133     <graph>
134     [graph "3,3" =size "circo" =layout ];
135     [node "filled" =style
136           "circle" =shape
137           "true"   =fixedsize
138           ""       =label ];
139     [edge "invis" =style ];
140     0 [add-node "invis" =style "none" =shape ];
141     16 <iota> [
142         [ 0 -- ] [ colored-circle add ] bi
143     ] each ;
144
145 : dfa-example ( -- graph )
146     <digraph>
147         "LR" =rankdir
148         "8,5" =size
149         [node "doublecircle" =shape ];
150         { "LR_0" "LR_3" "LR_4" "LR_8" } add-nodes
151         [node "circle" =shape ];
152         "LR_0" "LR_2" [-> "SS(B)" =label ];
153         "LR_0" "LR_1" [-> "SS(S)" =label ];
154         "LR_1" "LR_3" [-> "S($end)" =label ];
155         "LR_2" "LR_6" [-> "SS(b)" =label ];
156         "LR_2" "LR_5" [-> "SS(a)" =label ];
157         "LR_2" "LR_4" [-> "S(A)" =label ];
158         "LR_5" "LR_7" [-> "S(b)" =label ];
159         "LR_5" "LR_5" [-> "S(a)" =label ];
160         "LR_6" "LR_6" [-> "S(b)" =label ];
161         "LR_6" "LR_5" [-> "S(a)" =label ];
162         "LR_7" "LR_8" [-> "S(b)" =label ];
163         "LR_7" "LR_5" [-> "S(a)" =label ];
164         "LR_8" "LR_6" [-> "S(b)" =label ];
165         "LR_8" "LR_5" [-> "S(a)" =label ];
166     ;
167
168 : record-example ( -- graph )
169     <digraph>
170         [graph "LR" =rankdir "8,8" =size ];
171         [node 8 =fontsize "record" =shape ];
172
173         "node0" [add-node
174             "<f0> 0x10ba8| <f1>" =label
175         ];
176         "node1" [add-node
177             "<f0> 0xf7fc4380| <f1> | <f2> |-1" =label
178         ];
179         "node2" [add-node
180             "<f0> 0xf7fc44b8| | |2" =label
181         ];
182         "node3" [add-node
183             "<f0> 3.43322790286038071e-06|44.79998779296875|0" =label
184         ];
185         "node4" [add-node
186             "<f0> 0xf7fc4380| <f1> | <f2> |2" =label
187         ];
188         "node5" [add-node
189             "<f0> (nil)| | |-1" =label
190         ];
191         "node6" [add-node
192             "<f0> 0xf7fc4380| <f1> | <f2> |1" =label
193         ];
194         "node7" [add-node
195             "<f0> 0xf7fc4380| <f1> | <f2> |2" =label
196         ];
197         "node8" [add-node
198             "<f0> (nil)| | |-1" =label
199         ];
200         "node9" [add-node
201             "<f0> (nil)| | |-1" =label
202         ];
203         "node10" [add-node
204             "<f0> (nil)| <f1> | <f2> |-1" =label
205         ];
206         "node11" [add-node
207             "<f0> (nil)| <f1> | <f2> |-1" =label
208         ];
209         "node12" [add-node
210             "<f0> 0xf7fc43e0| | |1" =label
211         ];
212
213         "node0" "node1"   [-> "f0" =tailport "f0" =headport ];
214         "node0" "node2"   [-> "f1" =tailport "f0" =headport ];
215         "node1" "node3"   [-> "f0" =tailport "f0" =headport ];
216         "node1" "node4"   [-> "f1" =tailport "f0" =headport ];
217         "node1" "node5"   [-> "f2" =tailport "f0" =headport ];
218         "node4" "node3"   [-> "f0" =tailport "f0" =headport ];
219         "node4" "node6"   [-> "f1" =tailport "f0" =headport ];
220         "node4" "node10"  [-> "f2" =tailport "f0" =headport ];
221         "node6" "node3"   [-> "f0" =tailport "f0" =headport ];
222         "node6" "node7"   [-> "f1" =tailport "f0" =headport ];
223         "node6" "node9"   [-> "f2" =tailport "f0" =headport ];
224         "node7" "node3"   [-> "f0" =tailport "f0" =headport ];
225         "node7" "node1"   [-> "f1" =tailport "f0" =headport ];
226         "node7" "node8"   [-> "f2" =tailport "f0" =headport ];
227         "node10" "node11" [-> "f1" =tailport "f0" =headport ];
228         "node10" "node12" [-> "f2" =tailport "f0" =headport ];
229         "node11" "node1"  [-> "f2" =tailport "f0" =headport ];
230     ;
231
232 :: with-global-value ( value variable quot -- )
233     variable get-global "orig" [
234         [ value variable set-global quot call ]
235         [ "orig" get variable set-global ] finally
236     ] with-variable ; inline
237
238 : preview-format-test ( format -- pass? )
239     preview-format [
240         <graph> preview-smoke-test
241     ] with-global-value ;
242
243 : valid-preview-formats ( -- formats )
244     types get keys "jpe" suffix
245     supported-formats get-global intersect ;
246
247 : encoding-test ( encoding -- pass? )
248     graph-encoding [ <graph> smoke-test ] with-global-value ;
249
250 default-graphviz-program [
251
252     init-supported-layouts/formats
253
254     { t } [ 5 K_n smoke-test ] unit-test
255     { t } [ 6 K_n smoke-test ] unit-test
256     { t } [ 7 K_n smoke-test ] unit-test
257     { t } [ 8 K_n preview-smoke-test ] unit-test
258
259     { t } [ 8 6 K_n,m smoke-test ] unit-test
260     { t } [ 7 5 K_n,m smoke-test ] unit-test
261     { t } [ 3 9 K_n,m smoke-test ] unit-test
262     { t } [ 3 4 K_n,m preview-smoke-test ] unit-test
263
264     { t } [ 5 C_n smoke-test ] unit-test
265     { t } [ 6 C_n smoke-test ] unit-test
266     { t } [ 7 C_n smoke-test ] unit-test
267     { t } [ 8 C_n preview-smoke-test ] unit-test
268
269     { t } [ 5 W_n smoke-test ] unit-test
270     { t } [ 6 W_n smoke-test ] unit-test
271     { t } [ 7 W_n smoke-test ] unit-test
272     { t } [ 8 W_n preview-smoke-test ] unit-test
273
274     { t } [ cluster-example smoke-test ] unit-test
275     { t } [ cluster-example preview-smoke-test ] unit-test
276
277     { t } [ colored-circles-example smoke-test ] unit-test
278     { t } [ colored-circles-example preview-smoke-test ] unit-test
279
280     { t } [ dfa-example smoke-test ] unit-test
281     { t } [ dfa-example preview-smoke-test ] unit-test
282
283     { t } [ record-example smoke-test ] unit-test
284     { t } [ record-example preview-smoke-test ] unit-test
285
286     { t } [
287         valid-preview-formats [ preview-format-test ] all?
288     ] unit-test
289
290     [
291         supported-formats get-global valid-preview-formats diff
292         [ preview-format-test ] attempt-all
293     ] [ unsupported-preview-format? ] must-fail-with
294
295     { t } [ latin1 encoding-test ] unit-test
296
297     { t } [ utf8 encoding-test ] unit-test
298
299     [ ascii encoding-test ] [ unsupported-encoding? ] must-fail-with
300
301 ] when