diff --git a/config.xml b/config.xml index 3281e2070d699ab412ceaee3c92b7840efd5aa32..cb14b6a55f2998c5632dcfecb91555f86b29f169 100644 --- a/config.xml +++ b/config.xml @@ -1,3 +1,4 @@ + + dot + + + \ No newline at end of file diff --git a/docs/about.md b/docs/about.md index c2740defa9bfabdab77d7a6dd5196aba32d5d3c7..d23d095fd14a9f75e7a3f3fb4518326802e6fcef 100644 --- a/docs/about.md +++ b/docs/about.md @@ -39,6 +39,7 @@ version is a completely rewritten one. - [Dokuwiki](dokuwikiParser.md) - multi-language support - [prepared for optionally prerendering](prerendering.md) +- create [call graphs](callgraphs.md) of modules ### Third party addons - SemToNotes diff --git a/docs/callgraphs.md b/docs/callgraphs.md new file mode 100644 index 0000000000000000000000000000000000000000..424a241effea70e52b64a07b14452e3d4ba7b8cd --- /dev/null +++ b/docs/callgraphs.md @@ -0,0 +1,66 @@ +# Call graphs (call multigraphs) + +This modules examines XQuery modules and creates an SVG representation of their respective call graphs. +These call graphs are useful as an overview of how the SADE app and project specific extensions work and can be used as illustration of the app's architecture, for improving a module's structure while developing, ... + +To meet the different needs of users, three ways of using this module are possible: + +You can create the call graph of + +* a single module +* all modules that belong to a collection +* the whole SADE app + + + +## Requirements +Please make sure you have [GraphViz](http://graphviz.org/) installed wherever the database runs (on your computer, on a VM, ...). + + +## Configuration +For the module to work properly you have to consider on which kind of operating system (Windows, Unix, MacOS, ...) the database runs. +Simply change the following line in `config.xml` to the command line invocation of `dot` that is used by your OS: + +```xml +\dot +``` + +The option defaults to Unix' `dot` command. + + +## How to create call graphs +Before using the call graph module please make sure you have the module imported with + +``` +import module namespace callgraph="https://sade.textgrid.de/ns/callgraph" at "$(path/to/module)/callgraph.xqm"; +``` + +To generate a call graph all you have to do is calling the function + +``` +callgraph:main("/some/input/as/string", "filename/as/string") +``` +where the first input parameter can be the following: + +* the base URI of a single module, e.g. `/db/apps/sade/modules/some-module.xqm` +* the URI of a collection as path, e.g. `/db/apps/sade/modules/my-project-collection` +* `full` (generates a call graph for the whole SADE app) + +The second parameter is the desired filename __without__ file extension. + +The call graph SVG is stored to `/db/apps/sade/modules/callgraph/svg` while the GraphML representation can be found at `/db/apps/sade/modules/callgraph/graphml`. + + +## How it works (in detail) +Depending on which input option you select (cf. "How to create call graphs" above) one or more modules are examined by eXist-db's `inspect:inspect-module` function which returns some information about the module(s) and its functions. + +This information is then converted into a [GraphML](http://graphml.graphdrawing.org/) representation of the module as a directed graph in which all calling and called functions are represented as a `graphml:node` element. In case several modules are inspected duplicates are avoided. The calling/called connection between two functions is denoted by a `graphml:edge` element where the calling function becomes the edge's `@source` and the called one the edge's `@target`. + +This GraphML document is then saved to `/db/apps/sade/callgraph/graphml` and serves as input for generating a [DOT](https://graphviz.gitlab.io/_pages/doc/info/lang.html) representation of the graph which in turn is used by `dot` to create an SVG file that is saved to `/db/apps/sade/callgraph/svg`. + + +## Sample output + +The following image has been generated by the callgraph-module and illustrates how its modules and functions interact: + +![Call graph](http://localhost:8080/exist/apps/sade/modules/callgraph/svg/callgraph-modules.svg) \ No newline at end of file diff --git a/modules/callgraph/callgraph.xqm b/modules/callgraph/callgraph.xqm new file mode 100644 index 0000000000000000000000000000000000000000..b7b31ea579af64f6b315aae65a7097cdb3eb5b1f --- /dev/null +++ b/modules/callgraph/callgraph.xqm @@ -0,0 +1,221 @@ +xquery version "3.1"; + +(:~ + : This module creates an SVG image of call graph of + : + : * a given module + : * the modules of a given collection + : * the modules of the whole SADE app + : + : A module is defined as a file that ends with '.xqm'. + : While the SVG image is stored to /db/apps/sade/modules/callgraph/svg, + : the intermediate GraphML representation of the call graph is saved to + : /db/apps/sade/modules/callgraph/graphml and could be re-used in other + : applications. + : + : This module was roughly inspired by the graphviz app for eXist-db which can be + : found at https://github.com/KitWallace/graphviz. + : + : @author Michelle Weidling + : @since v3.1.0 + : @see https://github.com/KitWallace/graphviz + : + : :) + + +module namespace callgraph="https://sade.textgrid.de/ns/callgraph"; + +import module namespace config="https://sade.textgrid.de/ns/config" at "../config.xqm"; +import module namespace console="http://exist-db.org/xquery/console"; +import module namespace functx="http://www.functx.com"; +import module namespace inspect="http://exist-db.org/xquery/inspection"; +import module namespace inspect2graphml="https://sade.textgrid.de/ns/inspect2graphml" at "inspect2graphml.xqm"; + +declare namespace graphml="http://graphml.graphdrawing.org/xmlns"; +declare namespace xsi="http://www.w3.org/2001/XMLSchema-instance"; + +declare variable $callgraph:xslt := $config:app-root || "/modules/callgraph/graphml2dot.xsl"; +declare variable $callgraph:colors := + ("#90b0d4", "#e6f2ff", "#eee6ff", "#ffffe6", + "#f9ecec", "#bfe0ba", "#bfd2e3", "#dbaddb", + "#decbb2", "#e0b7b6", "#d9f09e", "#f5a1a4", + "#faf0a5", "#8acca0", "#cfb88c", "#d18ecb"); + +(:~ + : Creates an SVG file of one or more modules depending on the given $option. + : Possible options are: + : * an URI of a single module, e.g. "/db/apps/sade/modules/callgraph/tests/xqm/inspect2graphml-testmodule.xqm" + : * a collection URI, e.g. "/db/apps/sade/modules/callgraph/tests/xqm/" + : * "full" which will consider all *.xqm in the SADE app + : + : @author Michelle Weidling + : @since v3.1.0 + : @param $option Selects the modules which should be displayed in the output SVG file + : @param $filename The filename without extension, e.g. "output" + : @return Message that indicates a successfull transformation + : @error The given option is invalid + : @error The given filename is invalid + : :) +declare function callgraph:main($option as xs:string, $filename as xs:string) as xs:string { + if(ends-with($option, ".xqm") + or $option = "full" + or xmldb:collection-available($option)) then + let $filename := + if(contains($filename, ".")) then + error( QName("https://sade.textgrid.de/ns/app", "CALLGRAPH01"), + "Invalid filename '" || $filename || "'. Please enter a filename without file extension.") + else + $filename + let $dot := callgraph:get-dot($option, $filename) + let $svg-output := callgraph:get-svg($dot) + let $svg := callgraph:clear-svg($svg-output, $filename) + + return "Call graph creation successfull." + else + error( QName("https://sade.textgrid.de/ns/app", "CALLGRAPH02"), + "Invalid option '" || $option || "'. Please enter a base URI, a collection path or 'full' as argument.") +}; + + +(:~ + : Gets a DOT representation of the given module, the modules of a collection or + : all modules of the SADE app. + : + : @author Michelle Weidling + : @since v3.1.0 + : @see https://en.wikipedia.org/wiki/DOT_(graph_description_language) + : @param $option Selects the modules which should be displayed in the output SVG file (cf. callgraph:main) + : @return The DOT representation of the call graph + : @error GraphML couldn't be transformed to DOT + : @error The DOT file is empty + : :) +declare function callgraph:get-dot($option as xs:string, $filename as xs:string) +as xs:string { + let $graphml := inspect2graphml:main($option, $filename) + let $dot := + try { + (: $graphml[1] is graphml:graphml, + $graphml[2] is path to stored XML :) + callgraph:transform2dot($graphml[1]) + => string-join("") + } catch * { + error( QName("https://sade.textgrid.de/ns/app", "CALLGRAPH03"), + "Could not transform GraphML to DOT.") + } + + return + if(normalize-space($dot) != "") then + $dot + else + error( QName("https://sade.textgrid.de/ns/app", "CALLGRAPH04"), + "DOT file is empty.") +}; + + +(:~ + : Transforms the given GraphML elements to DOT. + : + : @author Michelle Weidling + : @since v3.1.0 + : @see https://en.wikipedia.org/wiki/DOT_(graph_description_language) + : @param $nodes The GraphML nodes generated by inspect2graphml:main + : @return The DOT representation of the call graph + : :) +declare function callgraph:transform2dot($nodes as element()*) as node()* { + for $node in $nodes return + typeswitch ($node) + + case element(graphml:graphml) return + (text{"digraph g {"}, + callgraph:transform2dot($node/node()), + text{"}"}) + + case element(graphml:graph) return + if($node/@id = "base-graph") then + callgraph:transform2dot($node/node()) + else + (text{"node [shape=box, style=filled, color="""}, + text{$callgraph:colors[count($node/preceding::graphml:graph) + 1]}, + text{"""];"}, + callgraph:transform2dot($node/node())) + + case element(graphml:node) return + if($node/parent::graphml:graph[@id = "base-graph"]) then + callgraph:transform2dot($node/node()) + else + (text{""""}, + text{$node/@id}, + text{""" [shape=box];"}) + + case element(graphml:edge) return + (text{""""}, + text{$node/@source}, + text{""""}, + text{" -> "}, + text{""""}, + text{$node/@target}, + text{""";"}) + + default return + callgraph:transform2dot($node/node()) +}; + + + +(:~ + : Creates an SVG file based of a given DOT file. + : + : @author Michelle Weidling + : @since v3.1.0 + : @see https://en.wikipedia.org/wiki/DOT_(graph_description_language) + : @param $dot A graph denoted in DOT + : @return The lines of the SVG file as element(line) + : @error DOT couldn't be transformed to SVG + : @error The SVG file is empty + : :) +declare function callgraph:get-svg($dot as xs:string) as element(line)+ { + let $conf := $config:app-root || "/config.xml" + let $cmd := doc($conf)//*[@key = "dot-cmd"]/string() + let $target-dir := doc($conf)//*[@key = "target-dir"]/string() + let $options := + + {$target-dir} + {$dot} + + let $output := + try { + process:execute(($cmd, "-Tsvg"), $options) + } catch * { + error( QName("https://sade.textgrid.de/ns/app", "CALLGRAPH05"), + "Could not transform the given DOT file to SVG.") + } + return + if($output//stdout/line) then + $output + else + error( QName("https://sade.textgrid.de/ns/app", "CALLGRAPH06"), + "SVG output empty.") +}; + + +(:~ + : Since the output of callgraph:get-svg consists of multiple line elements that + : contain the XML representation of the SVG, this function extracts the SVG data + : and creates a valid SVG file. + : + : @author Michelle Weidling + : @since v3.1.0 + : @param $svg Multiple line elements that hold the SVG data + : @param $filename The name of the generated SVG file + : @return The path to the stored SVG file + : :) +declare function callgraph:clear-svg($svg as element(execution), $filename as +xs:string) as xs:string { + let $lines := $svg//line + let $content := + for $line in subsequence($lines, 7) return + $line/string() + let $cleared-svg := string-join($content, "") + return + xmldb:store($config:app-root || "/modules/callgraph/svg/", $filename || ".svg", $cleared-svg) +}; \ No newline at end of file diff --git a/modules/callgraph/graphml/callgraph-modules-graphml.xml b/modules/callgraph/graphml/callgraph-modules-graphml.xml new file mode 100644 index 0000000000000000000000000000000000000000..34fee6ea6f4b8031687e01c3da9dec90d5f15ba5 --- /dev/null +++ b/modules/callgraph/graphml/callgraph-modules-graphml.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/callgraph/inspect2graphml.xqm b/modules/callgraph/inspect2graphml.xqm new file mode 100644 index 0000000000000000000000000000000000000000..4feceee2d183118bbab2231c944badccf334e22e --- /dev/null +++ b/modules/callgraph/inspect2graphml.xqm @@ -0,0 +1,194 @@ +xquery version "3.1"; +(:~ + : This module creates a GraphML representation of one or more given modules or + : even the whole SADE app. To achieve this we take the information retrieved by + : inspect:inspect-module and convert the relevant nodes to GraphML. + : + : The process was roughly inspired by the graphviz app for eXist-db which can + : be found at https://github.com/KitWallace/graphviz. + : + : @author Michelle Weidling + : @since v3.1.0 + : @see https://github.com/KitWallace/graphviz + : @see http://graphml.graphdrawing.org/specification.html + : + : :) + + +module namespace inspect2graphml="https://sade.textgrid.de/ns/inspect2graphml"; + +import module namespace config="https://sade.textgrid.de/ns/config" at "../config.xqm"; +import module namespace console="http://exist-db.org/xquery/console"; +import module namespace functx="http://www.functx.com"; +import module namespace inspect="http://exist-db.org/xquery/inspection"; + +declare namespace graphml="http://graphml.graphdrawing.org/xmlns"; +declare namespace xsi="http://www.w3.org/2001/XMLSchema-instance"; + + +(:~ + : The interface for other modules. + : + : @author Michelle Weidling + : @since v3.1.0 + : @param $option Selects the modules which should be displayed in the output SVG file (cf. callgraph:main for valid options) + : @return The graph representation as element(graphml:graphml) + : @return The path to the stored GraphML file + : :) +declare function inspect2graphml:main($option as xs:string, $filename +as xs:string) as item()+ { + let $graphml := inspect2graphml:get-graphml($option) + return + ($graphml, + xmldb:store($config:app-root || "/modules/callgraph/graphml/", $filename || "-graphml.xml", $graphml)) +}; + + +(:~ + : Creates a GraphML representation of one or more given modules or even the + : whole SADE app. + : + : @author Michelle Weidling + : @since v3.1.0 + : @param $option Selects the modules which should be displayed in the output SVG file (cf. callgraph:main for valid options) + : :) +declare function inspect2graphml:get-graphml($option as xs:string) as +element(graphml:graphml) { + let $xqms := inspect2graphml:get-xqms($option) + return + if(count($xqms) = 1) then + element graphml:graphml { + attribute xsi:schemaLocation {"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"}, + let $inspect-result := inspect:inspect-module(xs:anyURI($xqms)) + let $transformed-subgraph := inspect2graphml:transform($inspect-result, true()) + return local:sort-edges-and-nodes($transformed-subgraph) + } + + else + element graphml:graphml { + attribute xsi:schemaLocation {"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"}, + element graphml:graph { + attribute id {"base-graph"}, + attribute edgedefault {"directed"}, + for $xqm in $xqms return + let $inspect-result := inspect:inspect-module(xs:anyURI($xqm)) + let $transformed-subgraph := inspect2graphml:transform($inspect-result, false()) + + return + element graphml:node { + attribute id {util:hash($xqm, "md5")}, + local:sort-edges-and-nodes($transformed-subgraph) + } + } + } +}; + + +(:~ + : Transforms the relevant nodes that have been generated by inspect:inspect-module + : to GraphML elements. + : + : @author Michelle Weidling + : @since v3.1.0 + : @param $nodes The nodes that are the result of inspect:inspect-module + : @param $single-module A flag denoting if the user wants only a single module to be considered. In this case all function elements have to be converted to graphml:node which otherwise would lead to redundancies. + : @return The transformed node(s) + : :) +declare function inspect2graphml:transform($nodes as node()*, $single-module as xs:boolean) as node()* { + for $node in $nodes return + typeswitch ($node) + + case element(module) return + element graphml:graph { + attribute id {$node/@prefix}, + attribute edgedefault {"directed"}, + inspect2graphml:transform($node/node(), $single-module) + } + + case element(function) return + (local:make-node($node), + inspect2graphml:transform($node/node(), $single-module)) + + case element(calls) return + let $source-function := $node/ancestor::function[1] + let $prefix := substring-before($source-function/@name, ":") + for $called in $node/function + return + (element graphml:edge { + attribute source {$source-function/@name}, + attribute target {$called/@name} + }, + if($single-module + and not(substring-before($called/@name, ":") = $prefix)) then + local:make-node($called) + else + ()) + + default return + () +}; + + +(:~ + : Gets all relevant *.xqm files. + : + : @author Michelle Weidling + : @since v3.1.0 + : @param $option Selects the modules which should be displayed in the output SVG file (cf. callgraph:main for valid options) + : @return A sequence of module URIs + : :) +declare function inspect2graphml:get-xqms($option as xs:string) as xs:string* { + switch ($option) + case "full" return (collection($config:app-root)/base-uri())[ends-with(., ".xqm")] + + default return + if(ends-with($option, ".xqm")) then + $option + else + for $child in xmldb:get-child-resources($option) return + if(contains($child, ".xqm")) then + $option || "/" || $child + else + () +}; + + +(:~ + : Creates a graphml:node element. + : + : @author Michelle Weidling + : @since v3.1.0 + : @param $node The current result node of inspect:inspect-module + : @return A respective graphml:node element + : :) +declare function local:make-node($node as node()) as element(graphml:node) { + element graphml:node { + attribute id {$node/@name} + } +}; + + +(:~ + : As the output of inspect2graphml:transform mixes up graphml:node and + : graphml:edge, this function sorts them: We want all graphml:node to be listed + : first, followed by all graphml:edge elements. The order depend on the node ID + : and the source and target attribute respectively. + : + : + : @author Michelle Weidling + : @since v3.1.0 + : @param $graph A (sub-)graph with nodes and edges + : @return A graph with sorted nodes and edges + : :) +declare function local:sort-edges-and-nodes($graph as element(graphml:graph)) +as element(graphml:graph) { + element graphml:graph { + $graph/@*, + for $node in $graph/graphml:node + order by $node/@id/string() ascending + return $node, + for $edge in $graph/graphml:edge + order by $edge/@source, $edge/@target + return $edge + } +}; \ No newline at end of file diff --git a/modules/callgraph/svg/callgraph-modules.svg b/modules/callgraph/svg/callgraph-modules.svg new file mode 100644 index 0000000000000000000000000000000000000000..b6c898002d4261c258b4c5abb85edf6950e6ccba --- /dev/null +++ b/modules/callgraph/svg/callgraph-modules.svg @@ -0,0 +1,117 @@ + + + + g + + + callgraph:clear-svg + + callgraph:clear-svg + + + callgraph:get-dot + + callgraph:get-dot + + + inspect2graphml:main + + inspect2graphml:main + + + callgraph:get-dot->inspect2graphml:main + + + + + callgraph:get-svg + + callgraph:get-svg + + + callgraph:main + + callgraph:main + + + callgraph:main->callgraph:clear-svg + + + + + callgraph:main->callgraph:get-dot + + + + + callgraph:main->callgraph:get-svg + + + + + callgraph:transform2dot + + callgraph:transform2dot + + + callgraph:transform2dot->callgraph:transform2dot + + + + + inspect2graphml:get-graphml + + inspect2graphml:get-graphml + + + inspect2graphml:main->inspect2graphml:get-graphml + + + + + inspect2graphml:get-xqms + + inspect2graphml:get-xqms + + + inspect2graphml:get-graphml->inspect2graphml:get-xqms + + + + + inspect2graphml:transform + + inspect2graphml:transform + + + inspect2graphml:get-graphml->inspect2graphml:transform + + + + + local:sort-edges-and-nodes + + local:sort-edges-and-nodes + + + inspect2graphml:get-graphml->local:sort-edges-and-nodes + + + + + inspect2graphml:transform->inspect2graphml:transform + + + + + local:make-node + + local:make-node + + + inspect2graphml:transform->local:make-node + + + + + \ No newline at end of file diff --git a/modules/callgraph/tests/callgraph-test.xq b/modules/callgraph/tests/callgraph-test.xq new file mode 100644 index 0000000000000000000000000000000000000000..e5bcc0ad2585f0c26f7e070a2d9594612c3367f5 --- /dev/null +++ b/modules/callgraph/tests/callgraph-test.xq @@ -0,0 +1,112 @@ +xquery version "3.1"; + +(: This library module contains XQSuite tests for the callgraph module + : stored in callgraph.xqm :) + +module namespace callgraph-test = "https://sade.textgrid.de/ns/callgraph-test"; + +import module namespace callgraph="https://sade.textgrid.de/ns/callgraph" at "../callgraph.xqm"; + +declare namespace graphml="http://graphml.graphdrawing.org/xmlns"; +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +declare + %test:name("Testing filename error message by error code") + %test:args("invalid-filename.svg") + %test:assertError("CALLGRAPH01") + function callgraph-test:aa-test-error($option as xs:string) { + callgraph:main($option, "test-2") +}; + +declare + %test:name("Testing option error message by error code") + %test:args("an invalid option") + %test:assertError("CALLGRAPH02") + function callgraph-test:aa-test-error($option as xs:string) { + callgraph:main($option, "test-2") +}; + +declare + %test:name("Testing error message by error description") + %test:args("an invalid option") + %test:assertError("Invalid option 'an invalid option'. Please enter a base URI, a collection path or 'full' as argument.") + function callgraph-test:ab-test-error($option as xs:string) { + callgraph:main($option, "test-2") +}; + + +declare + %test:name("Test DOT output from graphml:graphml") + %test:args("") + %test:assertEquals("digraph g {", "}") + function callgraph-test:transform2dot-001($element as element()) { + callgraph:transform2dot($element) +}; + + +declare + %test:name("Test DOT output from graphml:graph") + %test:args("") + %test:assertEmpty + + %test:args("") + %test:assertEquals("node [shape=box, style=filled, color=""", "#90b0d4", """];") + function callgraph-test:transform2dot-002($element as element()) { + callgraph:transform2dot($element) +}; + + +declare + %test:name("Test DOT output from graphml:node") + %test:args("") + %test:assertEquals("node [shape=box, style=filled, color=""", "#90b0d4", """];", """", "some-function", """ [shape=box];") + + %test:args("") + %test:assertEmpty + function callgraph-test:transform2dot-003($element as element()) { + callgraph:transform2dot($element) +}; + + +declare + %test:name("Test DOT output from graphml:edge") + %test:args("") + %test:assertEquals("""", "some-function", """", " -> ", """", "another-function", """;") + function callgraph-test:transform2dot-004($element as element()) { + callgraph:transform2dot($element) +}; + + +declare + %test:name("Testing DOT ouput for a single module") + %test:args("/db/apps/sade/modules/callgraph/tests/xqm/inspect2graphml-testmodule.xqm") + %test:assertEquals("digraph g {node [shape=box, style=filled, color=""#90b0d4""];""inspect2graphml-testmodule:get-value"" [shape=box];""inspect2graphml-testmodule:main"" [shape=box];""inspect2graphml-testmodule:set-value"" [shape=box];""inspect2graphml-testmodule:main"" -> ""inspect2graphml-testmodule:get-value"";""inspect2graphml-testmodule:main"" -> ""inspect2graphml-testmodule:set-value"";""inspect2graphml-testmodule:set-value"" -> ""inspect2graphml-testmodule:get-value"";}") + function callgraph-test:ba-dot($option as xs:string) { + callgraph:get-dot($option, "inspect2graphml-testmodule-xqm") +}; + + +declare + %test:name("Testing DOT ouput for two modules") + %test:args("/db/apps/sade/modules/callgraph/tests/xqm/") + %test:assertEquals("digraph g {node [shape=box, style=filled, color=""#90b0d4""];""inspect2graphml-testmodule2:get-value"" [shape=box];""inspect2graphml-testmodule2:main"" [shape=box];""inspect2graphml-testmodule2:set-value"" [shape=box];""inspect2graphml-testmodule2:main"" -> ""inspect2graphml-testmodule2:get-value"";""inspect2graphml-testmodule2:main"" -> ""inspect2graphml-testmodule2:set-value"";""inspect2graphml-testmodule2:main"" -> ""inspect2graphml-testmodule:set-value"";""inspect2graphml-testmodule2:set-value"" -> ""inspect2graphml-testmodule:get-value"";node [shape=box, style=filled, color=""#e6f2ff""];""inspect2graphml-testmodule:get-value"" [shape=box];""inspect2graphml-testmodule:main"" [shape=box];""inspect2graphml-testmodule:set-value"" [shape=box];""inspect2graphml-testmodule:main"" -> ""inspect2graphml-testmodule:get-value"";""inspect2graphml-testmodule:main"" -> ""inspect2graphml-testmodule:set-value"";""inspect2graphml-testmodule:set-value"" -> ""inspect2graphml-testmodule:get-value"";}") + function callgraph-test:bb-dot($option as xs:string) { + callgraph:get-dot($option, "tests-collection") +}; + +declare + %test:name("Testing SVG error behavior") + %test:args("") + %test:assertError("CALLGRAPH06") + function callgraph-test:c-svg($dot as xs:string) { + callgraph:get-svg($dot) +}; + + +declare + %test:name("Testing SVG clearance for a simple module") + %test:args("/db/apps/sade/modules/callgraph/tests/xqm/inspect2graphml-testmodule.xqm") + %test:assertEquals("Call graph creation successfull.") + function callgraph-test:d-svg($option as xs:string) { + callgraph:main($option, "inspect2graphml-testmodule-xqm2") +}; diff --git a/modules/callgraph/tests/inspect2graphml-test.xq b/modules/callgraph/tests/inspect2graphml-test.xq new file mode 100644 index 0000000000000000000000000000000000000000..394bb532817c2db5740828fea2043bc89a9cf3d9 --- /dev/null +++ b/modules/callgraph/tests/inspect2graphml-test.xq @@ -0,0 +1,54 @@ +xquery version "3.1"; + +(: This library module contains XQSuite tests for the inspect2graphml module + : stored in inspect2graphml.xqm :) + +module namespace inspect2graphml-test = "https://sade.textgrid.de/ns/inspect2graphml-test"; + +import module namespace inspect2graphml="https://sade.textgrid.de/ns/inspect2graphml" at "../inspect2graphml.xqm"; + +declare namespace graphml="http://graphml.graphdrawing.org/xmlns"; +declare namespace test="http://exist-db.org/xquery/xqsuite"; + + +declare + %test:name("Testing the test") + %test:args("some input") + %test:assertEmpty + function inspect2graphml-test:a-test-the-test($node as text()) { + () +}; + + +declare + %test:name("Testing a simple module with module node as input") + %test:args("Some Documentation Michelle Weidling 1.0 the name of the current filexs:string The path where the HTML is storedDetermines the directory where an HTML file should be saved. 1.0 Michelle Weidling ") + %test:assertEquals("") + function inspect2graphml-test:ba-simple-graph($node as element(*)) { + inspect2graphml:transform($node, true()) +}; + +declare + %test:name("Testing a simple module with URI as input") + %test:args("/db/apps/sade/modules/callgraph/tests/xqm/inspect2graphml-testmodule.xqm") + %test:assertEquals("", "/db/apps/sade/modules/callgraph/graphml/inspect2graphml-test-graphml.xml") + function inspect2graphml-test:bb-simple-graph($option as xs:string) { + inspect2graphml:main($option, "inspect2graphml-test") +}; + + +declare + %test:name("Testing two simple modules with collection path as input") + %test:args("/db/apps/sade/modules/callgraph/tests/xqm/") + %test:assertEquals("", "/db/apps/sade/modules/callgraph/graphml/inspect2graphml-test2-graphml.xml") + function inspect2graphml-test:bc-simple-graph($option as xs:string) { + inspect2graphml:main($option, "inspect2graphml-test2") +}; + +declare + %test:name("Testing transformation from GraphML to DOT with one module") + %test:args("/db/apps/sade/modules/callgraph/tests/xqm/inspect2graphml-testmodule.xqm") + %test:assertEquals("", "/db/apps/sade/modules/callgraph/graphml/inspect2graphml-test3-graphml.xml") + function inspect2graphml-test:ca-simple-graphml-to-dot($xqm as xs:string) { + inspect2graphml:main($xqm, "inspect2graphml-test3") +}; diff --git a/modules/callgraph/tests/xqm/inspect2graphml-testmodule.xqm b/modules/callgraph/tests/xqm/inspect2graphml-testmodule.xqm new file mode 100644 index 0000000000000000000000000000000000000000..219c4fe1cdf56bd2012b1924cd0e938c7f9a2dcb --- /dev/null +++ b/modules/callgraph/tests/xqm/inspect2graphml-testmodule.xqm @@ -0,0 +1,21 @@ +xquery version "3.1"; + +module namespace inspect2graphml-testmodule="https://sade.textgrid.de/ns/inspect2graphml-test-module"; + +declare function inspect2graphml-testmodule:main() as xs:boolean { + let $url := "some-url" + let $url-return := inspect2graphml-testmodule:get-value($url) + let $set-value := inspect2graphml-testmodule:set-value($url) + return + true() +}; + +declare function inspect2graphml-testmodule:get-value($url as xs:string) as xs:string { + "return value" +}; + +declare function inspect2graphml-testmodule:set-value($url as xs:string) as empty-sequence() { + let $value := inspect2graphml-testmodule:get-value($url) + return + () +}; \ No newline at end of file diff --git a/modules/callgraph/tests/xqm/inspect2graphml-testmodule2.xqm b/modules/callgraph/tests/xqm/inspect2graphml-testmodule2.xqm new file mode 100644 index 0000000000000000000000000000000000000000..193fd8df46ddfec61915f3e8aef09e2511913add --- /dev/null +++ b/modules/callgraph/tests/xqm/inspect2graphml-testmodule2.xqm @@ -0,0 +1,25 @@ +xquery version "3.1"; + +module namespace inspect2graphml-testmodule2="https://sade.textgrid.de/ns/inspect2graphml-test-module2"; + +import module namespace inspect2graphml-testmodule="https://sade.textgrid.de/ns/inspect2graphml-test-module" at "inspect2graphml-testmodule.xqm"; + + +declare function inspect2graphml-testmodule2:main() as xs:boolean { + let $url := "some-url" + let $url-return := inspect2graphml-testmodule2:get-value($url) + let $set-value1 := inspect2graphml-testmodule2:set-value($url) + let $set-value2 := inspect2graphml-testmodule:set-value($url) + return + true() +}; + +declare function inspect2graphml-testmodule2:get-value($url as xs:string) as xs:string { + "return value" +}; + +declare function inspect2graphml-testmodule2:set-value($url as xs:string) as empty-sequence() { + let $value := inspect2graphml-testmodule:get-value($url) + return + () +}; \ No newline at end of file diff --git a/test.xq b/test.xq index d9d5568ba83fa424c56c9e6c29a137ea329b5597..93e218b07ef6bd442848f7088df32d6e8aa5dc22 100644 --- a/test.xq +++ b/test.xq @@ -2,4 +2,13 @@ xquery version "3.1"; import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql"; import module namespace tests="https://sade.textgrid.de/ns/tests" at "test.xqm"; -test:suite(util:list-functions("https://sade.textgrid.de/ns/tests")) +(: callgraph :) +import module namespace callgraph-test = "https://sade.textgrid.de/ns/callgraph-test" at "modules/callgraph/tests/callgraph-test.xq"; +import module namespace inspect2graphml-test = "https://sade.textgrid.de/ns/inspect2graphml-test" at "modules/callgraph/tests/inspect2graphml-test.xq"; + + +test:suite(util:list-functions("https://sade.textgrid.de/ns/tests")), + +(: * CALLGRAPH * :) +test:suite(util:list-functions("https://sade.textgrid.de/ns/callgraph-test")), +test:suite(util:list-functions("https://sade.textgrid.de/ns/inspect2graphml-test")) \ No newline at end of file diff --git a/test.xqm b/test.xqm index 402a2c9c575217654a4a50be8bb51fe0ba082ee4..fbf9a21bcb6cbd4ac476ca9bdf1f76d0e8db6882 100644 --- a/test.xqm +++ b/test.xqm @@ -8,7 +8,7 @@ import module namespace multiviewer="https://sade.textgrid.de/ns/multiviewer" at import module namespace nav="https://sade.textgrid.de/ns/navigation" at "modules/navigation.xqm"; import module namespace tgconnect="https://sade.textgrid.de/ns/connect" at "modules/textgrid/connect.xqm"; -declare namespace test="http://exist-db.org/xquery/xqsuite"; +import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql"; declare variable $tests:node := ; declare variable $tests:model := map{};