Merge: nitunit: fix before and after methods
authorJean Privat <jean@pryen.org>
Mon, 6 Feb 2017 13:39:51 +0000 (08:39 -0500)
committerJean Privat <jean@pryen.org>
Mon, 6 Feb 2017 13:39:51 +0000 (08:39 -0500)
Before and after method were not actually called in the test suite process.

This PR enables the compilation and run of these methods.

The new behavior is: if the `before_module` test case fails, all the test cases and the `after_module` are skipped and marked as failed.

Pull-Request: #2359
Reviewed-by: Jean-Christophe Beaupré <jcbrinfo.public@gmail.com>
Reviewed-by: Jean Privat <jean@pryen.org>

lib/realtime.nit
src/loader.nit
src/mixin.nit
src/model/mmodule.nit
src/modelbuilder.nit
src/phase.nit
tests/sav/nitmetrics_args1.res
tests/sav/test_test_phase_args1.res

index 243b5d8..eac21df 100644 (file)
@@ -23,7 +23,7 @@ in "C header" `{
 
 in "C" `{
 
-#ifdef __MACH__
+#if defined(__MACH__) && !defined(CLOCK_REALTIME)
 /* OS X does not have clock_gettime, mascarade it and use clock_get_time
  * cf http://stackoverflow.com/questions/11680461/monotonic-clock-on-osx
 */
@@ -148,7 +148,7 @@ class Clock
        # Smallest time frame reported by clock
        fun resolution: Timespec `{
                struct timespec* tv = malloc( sizeof(struct timespec) );
-#ifdef __MACH__
+#if defined(__MACH__) && !defined(CLOCK_REALTIME)
                clock_serv_t cclock;
                int nsecs;
                mach_msg_type_number_t count;
index ac07e71..32749aa 100644 (file)
@@ -1045,7 +1045,7 @@ redef class ModelBuilder
        # (and `build_module_importation` that calls it).
        #
        # TODO (when the loader will be rewritten): use a better representation and move up rules in the model.
-       private var conditional_importations = new Array[SequenceRead[MModule]]
+       var conditional_importations = new Array[SequenceRead[MModule]]
 
        # Extends the current importations according to imported rules about conditional importation
        fun apply_conditional_importations(mmodule: MModule)
@@ -1061,7 +1061,7 @@ redef class ModelBuilder
                                for i in [1..ci.length[ do
                                        var m = ci[i]
                                        # Is imported?
-                                       if not mmodule.in_importation.greaters.has(m) then continue label
+                                       if mmodule == m or not mmodule.in_importation.greaters.has(m) then continue label
                                end
                                # Still here? It means that all conditions modules are loaded and imported
 
index 508fc67..1e39970 100644 (file)
@@ -46,10 +46,12 @@ redef class ToolContext
                        var location = mainmodule.location
                        var model = mainmodule.model
 
+                       # Create a fictive module if needed
                        if mainmodule == mmodules.first then
                                mainmodule = new MModule(model, null, mainmodule.name + "-d", location)
                                mainmodule.set_imported_mmodules(mmodules)
                                mainmodule.is_fictive = true
+                               mainmodule.first_real_mmodule = mmodules.first
                        end
 
                        var recv = mainmodule.sys_type
index 4cdd340..44eaffb 100644 (file)
@@ -251,15 +251,13 @@ class MModule
        # Is `self` a unit test module used by `nitunit`?
        var is_test_suite: Bool = false is writable
 
-       # Get the first non `is_fictive` module greater than self
-       fun first_real_mmodule: MModule
-       do
-               var mmodule = self
-               while mmodule.is_fictive do
-                       mmodule = mmodule.in_importation.direct_greaters.first
-               end
-               return mmodule
-       end
+       # Get the non-`is_fictive` module on which `self` is based on.
+       #
+       # On non-fictive module, this returns `self`.
+       # On fictive modules, this is used to refer the module which `self` is based on.
+       #
+       # This attribute should be set when a fictive module is created. See `is_fictive`.
+       var first_real_mmodule: MModule = self is writable
 
        redef fun parent_concern do return mgroup
 end
index 671fcd0..b442704 100644 (file)
@@ -38,14 +38,17 @@ redef class ToolContext
        do
                assert not mmodules.is_empty
                var mainmodule
-               if mmodules.length == 1 then
+               # We need a main module, so we build it by importing all modules
+               mainmodule = new MModule(modelbuilder.model, null, mmodules.first.name + "-m", new Location(mmodules.first.location.file, 0, 0, 0, 0))
+               mainmodule.is_fictive = true
+               mainmodule.first_real_mmodule = mmodules.first.first_real_mmodule
+               mainmodule.set_imported_mmodules(mmodules)
+               modelbuilder.apply_conditional_importations(mainmodule)
+               if mainmodule.in_importation.direct_greaters.length == 1 and mainmodule.in_importation.direct_greaters.first == mmodules.first then
+                       # Drop the fictive module if not needed
                        mainmodule = mmodules.first
                else
-                       # We need a main module, so we build it by importing all modules
-                       mainmodule = new MModule(modelbuilder.model, null, mmodules.first.name + "-m", new Location(mmodules.first.location.file, 0, 0, 0, 0))
-                       mainmodule.is_fictive = true
-                       mainmodule.set_imported_mmodules(mmodules)
-                       modelbuilder.apply_conditional_importations(mainmodule)
+                       # Or else run phases on it
                        modelbuilder.run_phases
                end
                return mainmodule
@@ -104,4 +107,22 @@ redef class ModelBuilder
                end
        end
 
+       # Load module `filename` and add it as a conditional importation of `mmodule`.
+       #
+       # This means that current (and future) submodules of `module` will also import `filename`.
+       fun inject_module_subimportation(mmodule: MModule, filename: String)
+       do
+               var am = load_module(filename)
+               if am == null then return # forward error
+               var mm = am.mmodule
+               if mm == null then return # forward error
+               # Add the new module before the existing submodules in the hierarchy
+               for subm in mmodule.in_importation.direct_smallers do
+                       subm.set_imported_mmodules([mm])
+               end
+               # Register the new module as a conditional_importations for future submodules
+               conditional_importations.add([mm, mmodule])
+               # Register the new amodule to be processed by `run_phases`
+               toolcontext.todo_nmodules.unshift am
+       end
 end
index c94dcdc..2d400c9 100644 (file)
@@ -86,6 +86,11 @@ redef class ToolContext
        # Set of already analyzed modules.
        private var phased_modules = new HashSet[AModule]
 
+       # List of module to process according to `run_phases`
+       #
+       # This allow some new modules to be found and added while analysing the code.
+       var todo_nmodules: Sequence[AModule]
+
        # Run all registered phases on a set of modules
        fun run_phases(nmodules: Collection[AModule])
        do
@@ -99,7 +104,11 @@ redef class ToolContext
                        self.info(" registered phases: {phase}", 2)
                end
 
-               for nmodule in nmodules do
+               var todo_nmodules = nmodules.to_a
+               self.todo_nmodules = todo_nmodules
+
+               while not todo_nmodules.is_empty do
+                       var nmodule = todo_nmodules.shift
                        if phased_modules.has(nmodule) then continue
                        phased_modules.add nmodule
 
index 2eb19e5..b7fdbd8 100644 (file)
   total: 0
 --- Poset metrics ---
 ## Module importation hierarchy
-Number of nodes: 1
-Number of edges: 1 (1.00 per node)
-Number of direct edges: 0 (0.00 per node)
+Number of nodes: 2
+Number of edges: 3 (1.50 per node)
+Number of direct edges: 1 (0.50 per node)
 Distribution of greaters
- population: 1
+ population: 2
  minimum value: 1
- maximum value: 1
- total value: 1
- average value: 1.00
+ maximum value: 2
+ total value: 3
+ average value: 1.50
  distribution:
-  <=1: sub-population=1 (100.00%); cumulated value=1 (100.00%)
+  <=1: sub-population=1 (50.00%); cumulated value=1 (33.33%)
+  <=2: sub-population=1 (50.00%); cumulated value=2 (66.66%)
 Distribution of direct greaters
- population: 1
+ population: 2
  minimum value: 0
- maximum value: 0
- total value: 0
- average value: 0.00
+ maximum value: 1
+ total value: 1
+ average value: 0.50
  distribution:
-  <=0: sub-population=1 (100.00%); cumulated value=0 (na%)
+  <=0: sub-population=1 (50.00%); cumulated value=0 (0.00%)
+  <=1: sub-population=1 (50.00%); cumulated value=1 (100.00%)
 Distribution of smallers
- population: 1
+ population: 2
  minimum value: 1
- maximum value: 1
- total value: 1
- average value: 1.00
+ maximum value: 2
+ total value: 3
+ average value: 1.50
  distribution:
-  <=1: sub-population=1 (100.00%); cumulated value=1 (100.00%)
+  <=1: sub-population=1 (50.00%); cumulated value=1 (33.33%)
+  <=2: sub-population=1 (50.00%); cumulated value=2 (66.66%)
 Distribution of direct smallers
- population: 1
+ population: 2
  minimum value: 0
- maximum value: 0
- total value: 0
- average value: 0.00
+ maximum value: 1
+ total value: 1
+ average value: 0.50
  distribution:
-  <=0: sub-population=1 (100.00%); cumulated value=0 (na%)
+  <=0: sub-population=1 (50.00%); cumulated value=0 (0.00%)
+  <=1: sub-population=1 (50.00%); cumulated value=1 (100.00%)
 ## Classdef hierarchy
 Number of nodes: 7
 Number of edges: 13 (1.85 per node)
@@ -205,7 +209,7 @@ Distribution of direct smallers
   <=0: sub-population=6 (85.71%); cumulated value=0 (0.00%)
   <=8: sub-population=1 (14.28%); cumulated value=6 (100.00%)
 --- Metrics of refinement usage ---
-Number of modules: 1
+Number of modules: 2
 
 Number of classes: 7
   Number of interface kind: 1 (14.28%)
@@ -417,17 +421,17 @@ generating module_hierarchy.dot
          std: 0.0
          sum: 0
        mnoc: number of child modules
-         avg: 0.0
-         max: base_simple3 (0)
-         min: base_simple3 (0)
+         avg: 1.0
+         max: base_simple3 (1)
+         min: base_simple3 (1)
          std: 0.0
-         sum: 0
+         sum: 1
        mnod: number of descendant modules
-         avg: 0.0
-         max: base_simple3 (0)
-         min: base_simple3 (0)
+         avg: 1.0
+         max: base_simple3 (1)
+         min: base_simple3 (1)
          std: 0.0
-         sum: 0
+         sum: 1
        mdit: depth in module tree
          avg: 0.0
          max: base_simple3 (0)
@@ -479,17 +483,17 @@ generating module_hierarchy.dot
          std: 0.0
          sum: 0
        mnoc: number of child modules
-         avg: 0.0
-         max: base_simple3 (0)
-         min: base_simple3 (0)
+         avg: 1.0
+         max: base_simple3 (1)
+         min: base_simple3 (1)
          std: 0.0
-         sum: 0
+         sum: 1
        mnod: number of descendant modules
-         avg: 0.0
-         max: base_simple3 (0)
-         min: base_simple3 (0)
+         avg: 1.0
+         max: base_simple3 (1)
+         min: base_simple3 (1)
          std: 0.0
-         sum: 0
+         sum: 1
        mdit: depth in module tree
          avg: 0.0
          max: base_simple3 (0)
index 03cf44d..aa04d7f 100644 (file)
@@ -1,6 +1,6 @@
 It works
 I have 1 packages
-I have 1 modules
+I have 2 modules
 I have 7 classes
 For 7 definitions of classes
 I have 15 methods