Merge: MModule has a c_name
authorJean Privat <jean@pryen.org>
Mon, 10 Nov 2014 23:35:07 +0000 (18:35 -0500)
committerJean Privat <jean@pryen.org>
Mon, 10 Nov 2014 23:35:07 +0000 (18:35 -0500)
In compiler/, all entities have a `c_name` method to get a fully qualified mangled C identifier also usable to name files. All, except for one small class of indomitable entities that still holds out against the namespaces.

`c_name` where developed before the proposition of projects. This PR add a `c_name` for mmodules and update the places where its simple name was used.

Pull-Request: #898
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>

14 files changed:
contrib/nitester/src/nitester.nit
lib/ai/examples/puzzle.nit
lib/neo4j/json_store.nit [new file with mode: 0644]
lib/neo4j/neo4j.nit
misc/jenkins/nitester-wrapper.sh [new file with mode: 0755]
misc/jenkins/unitrun.sh
src/doc/doc_pages.nit
src/metrics/generate_hierarchies.nit
src/nitunit.nit
tests/listfull.sh
tests/sav/nitmetrics_args1.res
tests/sav/nitunit_args1.res
tests/sav/puzzle_args1.res
tests/tests.sh

index 5edfe22..37b5594 100644 (file)
@@ -62,7 +62,7 @@ abstract class Processor
        var done_tag: Tag = 5.tag
 
        # Number of tasks within each task assignation with `task_tag`
-       var tasks_per_packet = 4
+       var tasks_per_packet = 1
 
        # Run the main logic of this node
        fun run is abstract
@@ -163,10 +163,8 @@ abstract class Processor
        # Gather and registar all tasks
        fun create_tasks
        do
-               var c = 0
-               for engine in engines do for prog in test_programs do
+               for prog in test_programs do for engine in engines do
                        tasks.add new Task(engine, prog)
-                       c += 1
                end
        end
 end
@@ -250,6 +248,8 @@ class Controller
                                        if res == 5 then result.fail = true
                                        if res == 6 then result.soso = true
                                        if res == 7 then result.skip = true
+                                       if res == 8 then result.todo = true
+                                       if res == 9 then result.skip_exec = true
                                        if res == 0 then result.unknown = true
 
                                        results.add result
@@ -305,6 +305,8 @@ class Controller
                print "* {results.fixmes.length} fixmes"
                print "* {results.sosos.length} sosos"
                print "* {results.skips.length} skips"
+               print "* {results.todos.length} todos"
+               print "* {results.skip_execs.length} skip execs"
                print "* {results.unknowns.length} unknowns (bug in tests.sh or nitester)"
        end
 
@@ -332,12 +334,12 @@ class Worker
        # Output file directory
        var out_dir = "/dev/shm/nit_out{rank}" is lazy
 
+       # Directory to store the xml files produced for Jenkins
+       var xml_dir = "~/jenkins_xml/"
+
        # Output file of the `tests.sh` script
        var tests_sh_out = "/dev/shm/nit_local_out{rank}" is lazy
 
-       # Path to the local copy of the Nit repository
-       var nit_copy_dir = "/dev/shm/nit{rank}/" is lazy
-
        # Source Nit repository, must be already updated and `make` before execution
        var nit_source_dir = "~/nit"
 
@@ -362,7 +364,6 @@ class Worker
        fun setup
        do
                if verbose > 0 then sys.system "hostname"
-               sys.system "git clone {nit_source_dir} {nit_copy_dir}"
        end
 
        # Clean up the testing environment
@@ -372,7 +373,6 @@ class Worker
        do
                if comp_dir.file_exists then comp_dir.rmdir
                if out_dir.file_exists then out_dir.rmdir
-               if nit_copy_dir.file_exists then nit_copy_dir.rmdir
                if tests_sh_out.file_exists then tests_sh_out.file_delete
        end
 
@@ -395,17 +395,17 @@ class Worker
                                # Receive tasks to execute
                                mpi.recv_into(task_buffer, 0, 1, status.source, status.tag, comm_world)
                                var first_id = task_buffer[0]
-                               for task_id in [first_id .. first_id + tasks_per_packet] do
+                               for task_id in [first_id .. first_id + tasks_per_packet[ do
 
                                        # If id is over all known tasks, stop right here
                                        if task_id >= tasks.length then break
                                        var task = tasks[task_id]
 
                                        # Command line to execute test
-                                       var cmd = "XMLDIR={out_dir} ERRLIST={out_dir}/errlist TMPDIR={out_dir} " +
+                                       var cmd = "XMLDIR={xml_dir} ERRLIST={out_dir}/errlist TMPDIR={out_dir} " +
                                                "CCACHE_DIR={ccache_dir} CCACHE_TEMPDIR={ccache_dir} CCACHE_BASEDIR={comp_dir} " +
-                                               "./tests.sh --compdir {comp_dir} --outdir {out_dir} -o \"--make-flags '-j1'\"" +
-                                               " --node --engine {task.engine} {nit_copy_dir / "tests" / task.test_program} > {tests_sh_out}"
+                                               "./tests.sh --compdir {comp_dir} --outdir {out_dir} " +
+                                               " --node --engine {task.engine} {task.test_program} > {tests_sh_out}"
 
                                        # Execute test
                                        sys.system cmd
@@ -446,6 +446,8 @@ class Worker
                                                if line.has("[======= fail") then res = 5
                                                if line.has("[======= soso") then res = 6
                                                if line.has("[skip]") then res = 7
+                                               if line.has("[todo]") then res = 8
+                                               if line.has("[skip exec]") then res = 9
 
                                                if res == null then
                                                        res = 0
@@ -552,9 +554,15 @@ class Result
        # Is `self` result a _soso_?
        var soso = false
 
-       # Is `self` skipped test?
+       # Has `self` been skipped?
        var skip = false
 
+       # Is `self` TODO?
+       var todo = false
+
+       # Has the execution of `self` been skipped?
+       var skip_exec = false
+
        # Is `self` an unknown result, probably an error
        var unknown = false
 
@@ -566,6 +574,10 @@ class Result
                if ok_empty then err = "0k"
                if fixme then err = "fixme"
                if fail then err = "fail"
+               if soso then err = "soso"
+               if skip then err = "skip"
+               if todo then err = "todo"
+               if skip_exec then err = "skip_exec"
 
                return "{task} arg{arg} alt{alt} => {err}"
        end
@@ -582,6 +594,8 @@ class ResultSet
        var fails = new HashSet[Result]
        var sosos = new HashSet[Result]
        var skips = new HashSet[Result]
+       var todos = new HashSet[Result]
+       var skip_execs = new HashSet[Result]
        var unknowns = new HashSet[Result]
 
        # TODO remove
@@ -596,6 +610,8 @@ class ResultSet
                if result.fail then fails.add result
                if result.soso then sosos.add result
                if result.skip then skips.add result
+               if result.todo then todos.add result
+               if result.skip_exec then skip_execs.add result
                if result.unknown then unknowns.add result
 
                super
index 782fee6..d07c1be 100644 (file)
@@ -285,6 +285,6 @@ for arg in args do
                break
        end
 
-       print "Solved, after looking at {r.steps} positions during {c.lapse}"
+       print "Solved, after looking at {r.steps} positions"
        pb.print_plan(r.plan)
 end
diff --git a/lib/neo4j/json_store.nit b/lib/neo4j/json_store.nit
new file mode 100644 (file)
index 0000000..49e055c
--- /dev/null
@@ -0,0 +1,199 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT. This software 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. You can modify it is you want, provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You are allowed to redistribute it and sell it, alone or is a part of
+# another product.
+
+# Uses JSON as a storage medium for a Neo4j subgraph.
+module neo4j::json_store
+
+import neo4j
+private import template
+
+# A Neo4j graph that uses as a storage medium.
+#
+# The graph is stored as a JSON object with the following properties:
+#
+# * `"nodes"`: An array with all nodes. Each node is an object with the
+# following properties:
+#      * `"id"`: The ID (`Int`) that uniquely identifies the node in the current
+#      graph.
+#      * `"labels"`: An array of all applied labels.
+#      * `"properties"`: An object mapping each defined property to its value.
+# * `"links"`: An array with all relationships. Each relationship is an object
+# with the following properties:
+#      * `"type"`: The type (`String`) of the relationship.
+#      * `"properties"`: An object mapping each defined property to its value.
+#      * `"from"`: The ID (`Int`) of the source node.
+#      * `"to"`: The ID (`Int`) of the destination node.
+#
+# TODO Refine the graph API instead when it will be available.
+class JsonGraph
+       super Jsonable
+
+       # All nodes in the graph.
+       var nodes: SimpleCollection[NeoNode] = new Array[NeoNode]
+
+       # All relationships in the graph.
+       var links: SimpleCollection[NeoEdge] = new Array[NeoEdge]
+
+       # Create an empty graph.
+       init do end
+
+       # Retrieve the graph from the specified JSON value.
+       #
+       #     var graph = new JsonGraph
+       #     var a = new NeoNode
+       #     a.labels.add "Foo"
+       #     a["answer"] = 42
+       #     a["Ultimate question of"] = new JsonArray.from(["life",
+       #               "the Universe", "and Everything."])
+       #     graph.nodes.add a
+       #     var b = new NeoNode
+       #     b.labels.add "Foo"
+       #     b.labels.add "Bar"
+       #     graph.nodes.add b
+       #     graph.links.add new NeoEdge(a, "BAZ", b)
+       #     #
+       #     graph = new JsonGraph.from_json(graph.to_json)
+       #     assert 1 == graph.links.length
+       #     for link in graph.links do
+       #       assert "BAZ" == link.rel_type
+       #       assert a.labels == link.from.labels
+       #       for k, v in a.properties do assert v == link.from.properties[k]
+       #       assert b.labels == link.to.labels
+       #       for k, v in b.properties do assert v == link.to.properties[k]
+       #     end
+       #     assert 2 == graph.nodes.length
+       init from_json(t: Text) do
+               from_json_object(t.to_jsonable.as(JsonObject))
+       end
+
+       # Retrieve the graph from the specified JSON object.
+       init from_json_object(o: JsonObject) do
+               var node_by_id = new HashMap[Int, NeoNode]
+               var nodes = o["nodes"].as(JsonArray)
+               for json_node in nodes do
+                       assert json_node isa JsonObject
+                       var node = new NeoNode.from_json_object(json_node)
+                       node_by_id[json_node["id"].as(Int)] = node
+                       self.nodes.add node
+               end
+               var links = o["links"].as(JsonArray)
+               for json_link in links do
+                       assert json_link isa JsonObject
+                       var from = node_by_id[json_link["from"].as(Int)]
+                       var to = node_by_id[json_link["to"].as(Int)]
+                       var rel_type = json_link["type"].as(String)
+                       var json_properties = json_link["properties"].as(JsonObject)
+                       var link = new NeoEdge(from, rel_type, to)
+                       link.properties.recover_with(json_properties)
+                       self.links.add link
+               end
+       end
+
+       redef fun to_json do
+               var t = new Template
+               t.add "\{\"nodes\":["
+               var i = 0
+               for n in nodes do
+                       if i > 0 then t.add ","
+                       t.add n.to_json
+                       i += 1
+               end
+               t.add "],\"links\":["
+               i = 0
+               for link in links do
+                       if i > 0 then t.add ","
+                       t.add link.to_json
+                       i += 1
+               end
+               t.add "]\}"
+               return t.write_to_string
+       end
+end
+
+# Make `NeoNode` `Jsonable`.
+redef class NeoNode
+       super Jsonable
+
+       # Retrieve the node from the specified JSON value.
+       #
+       # Note: Here, the `"id"` is optional and ignored.
+       #
+       # SEE: `JsonGraph`
+       #
+       #     var node = new NeoNode.from_json("""
+       #     {
+       #       "labels": ["foo", "Bar"],
+       #       "properties": {
+       #               "baz": 42
+       #       }
+       #     }
+       #     """)
+       #     assert ["foo", "Bar"] == node.labels
+       #     assert 42 == node["baz"]
+       init from_json(t: Text) do
+               from_json_object(t.to_jsonable.as(JsonObject))
+       end
+
+       # Retrieve the node from the specified JSON value.
+       #
+       # Note: Here, the `"id"` is optional and ignored.
+       #
+       # SEE: `JsonGraph`
+       init from_json_object(o: JsonObject) do
+               init
+               var labels = o["labels"].as(JsonArray)
+               for lab in labels do self.labels.add(lab.as(String))
+               var json_properties = o["properties"].as(JsonObject)
+               properties.recover_with(json_properties)
+       end
+
+       # Get the JSON representation of `self`.
+       #
+       # SEE: `JsonGraph`
+       redef fun to_json do
+               var t = new Template
+               t.add "\{\"id\":"
+               t.add object_id.to_json
+               t.add ",\"labels\":["
+               var i = 0
+               for lab in labels do
+                       if i > 0 then t.add ","
+                       t.add lab.to_json
+                       i += 1
+               end
+               t.add "],\"properties\":"
+               t.add properties.to_json
+               t.add "}"
+               return t.write_to_string
+       end
+
+       redef fun to_s do return to_json
+end
+
+# Make `NeoEdge` `Jsonable`.
+redef class NeoEdge
+       super Jsonable
+
+       redef fun to_json do
+               var t = new Template
+               t.add "\{\"type\":"
+               t.add rel_type.to_json
+               t.add ",\"properties\":"
+               t.add properties.to_json
+               t.add ",\"from\":"
+               t.add from.object_id.to_json
+               t.add ",\"to\":"
+               t.add to.object_id.to_json
+               t.add "}"
+               return t.write_to_string
+       end
+
+       redef fun to_s do return to_json
+end
index 6629b80..b84a60b 100644 (file)
@@ -300,7 +300,7 @@ class Neo4jClient
        # Perform a `CypherQuery`
        # see: CypherQuery
        fun cypher(query: CypherQuery): Jsonable do
-               return post("{cypher_url}", query.to_json)
+               return post("{cypher_url}", query.to_rest)
        end
 
        # GET JSON data from `url`
@@ -436,8 +436,8 @@ class CypherQuery
                return self
        end
 
-       # Translate the query to JSON
-       fun to_json: JsonObject do
+       # Translate the query to the body of a corresponding Neo4j REST request.
+       fun to_rest: JsonObject do
                var obj = new JsonObject
                obj["query"] = query
                if not params.is_empty then
@@ -446,7 +446,7 @@ class CypherQuery
                return obj
        end
 
-       redef fun to_s do return to_json.to_s
+       redef fun to_s do return to_rest.to_s
 end
 
 # The fundamental units that form a graph are nodes and relationships.
@@ -546,9 +546,6 @@ abstract class NeoEntity
 
        # Is the property `key` set?
        fun has_key(key: String): Bool do return properties.has_key(key)
-
-       # Translate `self` to JSON
-       fun to_json: JsonObject do return properties
 end
 
 # Nodes are used to represent entities stored in base.
@@ -595,7 +592,7 @@ class NeoNode
                var tpl = new FlatBuffer
                tpl.append "\{"
                tpl.append "labels: [{labels.join(", ")}],"
-               tpl.append "data: {to_json}"
+               tpl.append "data: {properties.to_json}"
                tpl.append "\}"
                return tpl.write_to_string
        end
@@ -743,7 +740,8 @@ class NeoEdge
        # Get edge type
        fun rel_type: nullable String do return internal_type
 
-       redef fun to_json do
+       # Get the JSON body of a REST request that create the relationship.
+       private fun to_rest: JsonObject do
                var obj = new JsonObject
                if to.is_linked then
                        obj["to"] = to.url
@@ -891,7 +889,7 @@ class NeoBatch
                else
                        job.to = "\{{edge.from.batch_id.to_s}\}/relationships"
                end
-               job.body = edge.to_json
+               job.body = edge.to_rest
        end
 
        # Create multiple edges
@@ -902,7 +900,7 @@ class NeoBatch
                var request = new JsonPOST(client.batch_url, client.curl)
                # request.headers["X-Stream"] = "true"
                var json_jobs = new JsonArray
-               for job in jobs.values do json_jobs.add job.to_json
+               for job in jobs.values do json_jobs.add job.to_rest
                request.data = json_jobs
                var response = request.execute
                var res = client.parse_response(response)
@@ -1003,7 +1001,7 @@ class NeoJob
        var body: nullable Jsonable = null
 
        # JSON formated job
-       fun to_json: JsonObject do
+       fun to_rest: JsonObject do
                var job = new JsonObject
                job["id"] = id
                job["method"] = method
diff --git a/misc/jenkins/nitester-wrapper.sh b/misc/jenkins/nitester-wrapper.sh
new file mode 100755 (executable)
index 0000000..2f9e20f
--- /dev/null
@@ -0,0 +1,47 @@
+#!/bin/bash
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This script is a wrapper for `nitester` which also manages a local repo
+#
+# The first argument _must_ be the hash of the commit at the head of the
+# branch to test. The other arguments are passed on to `nitester`.
+
+hash=$1
+shift
+
+set +x
+
+local_repo=nit/
+remote_repo=privat
+
+tools_dir=misc/jenkins/
+
+cd $local_repo
+git clean -fdxq .
+
+git fetch $remote_repo
+git checkout $hash
+
+# Make nitg and tools
+$tools_dir/unitrun.sh "run-make-0initial_make" make
+
+# Make nitester
+$tools_dir/unitrun.sh "run-make-nitester" make -C contrib/nitester/
+
+# Run tests
+cd tests
+mkdir -p out
+rm ~/jenkins_xml/*.xml
+mpirun -np 30 ../contrib/nitester/bin/nitester $@
index 54d875c..10dfd38 100755 (executable)
@@ -24,9 +24,18 @@ fi
 name=$1
 shift
 
+# Detect a working time command
+if env time --quiet -f%U true 2>/dev/null; then
+       TIME="env time --quiet -f%U -o '${name}.t.out'"
+elif env time -f%U true 2>/dev/null; then
+       TIME="env time -f%U -o '${name}.t.out'"
+else
+       TIME=
+fi
+
 # Magic here! This tee and save both stdout and stderr in distinct files without messing with them
 # Time  just get the user time
-/usr/bin/time -f%U --quiet -o "${name}.t.out" "$@" > >(tee "${name}.out") 2> >(tee "${name}.2.out" >&2)
+$TIME "$@" > >(tee "${name}.out") 2> >(tee "${name}.2.out" >&2)
 res=$?
 
 c=`echo "${name%-*}" | tr "-" "."`
index db5ba9b..5d71b02 100644 (file)
@@ -997,15 +997,15 @@ class NitdocModule
                # build graph
                var op = new RopeBuffer
                var name = "dep_module_{mmodule.nitdoc_id}"
-               op.append("digraph {name} \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
+               op.append("digraph \"{name.escape_to_dot}\" \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
                for mmodule in poset do
                        if mmodule == self.mmodule then
-                               op.append("\"{mmodule.name}\"[shape=box,margin=0.03];\n")
+                               op.append("\"{mmodule.name.escape_to_dot}\"[shape=box,margin=0.03];\n")
                        else
-                               op.append("\"{mmodule.name}\"[URL=\"{mmodule.nitdoc_url}\"];\n")
+                               op.append("\"{mmodule.name.escape_to_dot}\"[URL=\"{mmodule.nitdoc_url.escape_to_dot}\"];\n")
                        end
                        for omodule in poset[mmodule].direct_greaters do
-                               op.append("\"{mmodule.name}\"->\"{omodule.name}\";\n")
+                               op.append("\"{mmodule.name.escape_to_dot}\"->\"{omodule.name.escape_to_dot}\";\n")
                        end
                end
                op.append("\}\n")
@@ -1378,7 +1378,7 @@ class NitdocClass
 
                var op = new RopeBuffer
                var name = "dep_class_{mclass.nitdoc_id}"
-               op.append("digraph {name} \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
+               op.append("digraph \"{name.escape_to_dot}\" \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
                var classes = poset.to_a
                var todo = new Array[MClass]
                var done = new HashSet[MClass]
@@ -1389,18 +1389,18 @@ class NitdocClass
                        if done.has(c) then continue
                        done.add c
                        if c == mclass then
-                               op.append("\"{c.name}\"[shape=box,margin=0.03];\n")
+                               op.append("\"{c.name.escape_to_dot}\"[shape=box,margin=0.03];\n")
                        else
-                               op.append("\"{c.name}\"[URL=\"{c.nitdoc_url}\"];\n")
+                               op.append("\"{c.name.escape_to_dot}\"[URL=\"{c.nitdoc_url.escape_to_dot}\"];\n")
                        end
                        var smallers = poset[c].direct_smallers
                        if smallers.length < 10 then
                                for c2 in smallers do
-                                       op.append("\"{c2.name}\"->\"{c.name}\";\n")
+                                       op.append("\"{c2.name.escape_to_dot}\"->\"{c.name.escape_to_dot}\";\n")
                                end
                                todo.add_all smallers
                        else
-                               op.append("\"...\"->\"{c.name}\";\n")
+                               op.append("\"...\"->\"{c.name.escape_to_dot}\";\n")
                        end
                end
                op.append("\}\n")
index e902b05..3522245 100644 (file)
@@ -53,12 +53,12 @@ do
                dot.mprojects.add(g.mproject)
        end
        var projectpath = toolcontext.output_dir.join_path("project_hierarchy.dot")
-       print "generating {projectpath}"
+       print "generating project_hierarchy.dot"
        dot.write_to_file(projectpath)
 
        var modulepath = toolcontext.output_dir.join_path("module_hierarchy.dot")
        dot.mprojects.add_all(model.mprojects)
-       print "generating {modulepath}"
+       print "generating module_hierarchy.dot"
        dot.write_to_file(modulepath)
 end
 
index 0a8973d..c057beb 100644 (file)
@@ -73,9 +73,8 @@ end
 var file = toolcontext.opt_output.value
 if file == null then file = "nitunit.xml"
 page.write_to_file(file)
-print "Results saved in {file}"
 # print docunits results
-print "\nDocUnits:"
+print "DocUnits:"
 if modelbuilder.unit_entities == 0 then
        print "No doc units found"
 else if modelbuilder.failed_entities == 0 and not toolcontext.opt_noact.value then
index 087e573..778d0d3 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/sh
-printf "%s\n" "$@" *.nit \
+printf "%s\n" "$@" \
+       ../src/nit*.nit \
+       ../src/test_*.nit \
        ../examples/*.nit \
        ../examples/*/*.nit \
        ../examples/shoot/src/shoot_logic.nit \
@@ -12,5 +14,4 @@ printf "%s\n" "$@" *.nit \
        ../lib/*/examples/*.nit \
        ../contrib/friendz/src/solver_cmd.nit \
        ../contrib/pep8analysis/src/pep8analysis.nit \
-       ../src/nit*.nit \
-       ../src/test_*.nit
+       *.nit
index 481e468..e5ac8bd 100644 (file)
@@ -470,8 +470,8 @@ Average number of composing class definition by runtime class: 2.00
 Total size of tables (classes and instances): 38 (not including stuff like info for subtyping or call-next-method)
 Average size of table by runtime class: 6.33
 Values never redefined: 32 (84.21%)
-generating out/nitmetrics_args1.write/project_hierarchy.dot
-generating out/nitmetrics_args1.write/module_hierarchy.dot
+generating project_hierarchy.dot
+generating module_hierarchy.dot
 
 # Inheritance metrics
 
index 3b5b590..3a07d20 100644 (file)
@@ -4,8 +4,6 @@ test_nitunit.nit:23,2--25,0: FAILURE: nitunit.test_nitunit.test_nitunit::X.test_
 
 test_test_nitunit.nit:36,2--40,4: ERROR: test_foo1 (in file .nitunit/test_test_nitunit_TestX_test_foo1.nit): Runtime error: Assert failed (test_test_nitunit.nit:39)
 
-Results saved in out/nitunit_args1.write
-
 DocUnits:
 Entities: 27; Documented ones: 3; With nitunits: 3; Failures: 2
 
index 17ccd5a..6c361fe 100644 (file)
@@ -2,5 +2,5 @@ Initial: eabf.cdgh
 eab
 f.c
 dgh
-Solved, after looking at 14 positions during 0.0s
+Solved, after looking at 14 positions
 Solution in 10 moves: right(>) down(v) left(<) left(<) up(^) right(>) right(>) up(^) left(<) left(<)
index 8179c9c..76ecf2c 100755 (executable)
@@ -457,7 +457,9 @@ todos=""
 if [ "x$XMLDIR" = "x" ]; then
        xml="tests-$engine.xml"
 else
-       xml="$XMLDIR/tests-$engine.xml"
+       sum=`echo $@ | md5sum | cut -f1 -d " "`
+       xml="$XMLDIR/tests-$engine-$sum.xml"
+       mkdir -p "$XMLDIR"
 fi
 
 echo >$xml "<testsuites><testsuite>"