Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge remote-tracking branch 'github/master'
authorArnaud Giersch <arnaud.giersch@univ-fcomte.fr>
Fri, 14 Jun 2019 09:04:43 +0000 (11:04 +0200)
committerArnaud Giersch <arnaud.giersch@univ-fcomte.fr>
Fri, 14 Jun 2019 09:04:43 +0000 (11:04 +0200)
teshsuite/surf/lmm_usage/lmm_solve.cpp [new file with mode: 0644]
tools/cmake/Tests.cmake
tools/tesh/CMakeLists.txt
tools/tesh/catch-timeout-output.tesh [new file with mode: 0644]
tools/tesh/catch-timeout.tesh
tools/tesh/tesh.py

diff --git a/teshsuite/surf/lmm_usage/lmm_solve.cpp b/teshsuite/surf/lmm_usage/lmm_solve.cpp
new file mode 100644 (file)
index 0000000..a45df91
--- /dev/null
@@ -0,0 +1,249 @@
+/* Copyright (c) 2019. The SimGrid Team. All rights reserved.               */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "src/include/catch.hpp"
+#include "src/kernel/lmm/maxmin.hpp"
+#include "src/surf/surf_interface.hpp"
+#include "xbt/log.h"
+
+namespace lmm = simgrid::kernel::lmm;
+
+TEST_CASE("kernel::lmm Single constraint shared systems", "[kernel-lmm-shared-single-sys]")
+{
+  lmm::System* Sys = lmm::make_new_maxmin_system(false);
+
+  SECTION("Variable weight")
+  {
+    /*
+     * System under consideration:
+     * 1\times\rho_1^{1} + 1\times\rho_2^{2} + 1\times\rho_3^{3} \le 10
+     */
+
+    lmm::Constraint* sys_cnst = Sys->constraint_new(nullptr, 10);
+    lmm::Variable* sys_var_1  = Sys->variable_new(nullptr, 1, 0.0, 1);
+    lmm::Variable* sys_var_2  = Sys->variable_new(nullptr, 2, 0.0, 1);
+    lmm::Variable* sys_var_3  = Sys->variable_new(nullptr, 3, 0.0, 1);
+
+    Sys->expand(sys_cnst, sys_var_1, 1);
+    Sys->expand(sys_cnst, sys_var_2, 1);
+    Sys->expand(sys_cnst, sys_var_3, 1);
+    Sys->solve();
+
+    REQUIRE(double_equals(sys_var_1->get_value(), 5.45455, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_2->get_value(), 2.72727, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_3->get_value(), 1.81818, sg_maxmin_precision));
+  }
+
+  SECTION("Consumption weight")
+  {
+    /*
+     * System under consideration:
+     * 1\times\rho_1^{1} + 2\times\rho_2^{1} + 3\times\rho_3^{1} \le 10
+     */
+
+    lmm::Constraint* sys_cnst = Sys->constraint_new(nullptr, 10);
+    lmm::Variable* sys_var_1  = Sys->variable_new(nullptr, 1, 0.0, 1);
+    lmm::Variable* sys_var_2  = Sys->variable_new(nullptr, 1, 0.0, 1);
+    lmm::Variable* sys_var_3  = Sys->variable_new(nullptr, 1, 0.0, 1);
+
+    Sys->expand(sys_cnst, sys_var_1, 1);
+    Sys->expand(sys_cnst, sys_var_2, 2);
+    Sys->expand(sys_cnst, sys_var_3, 3);
+    Sys->solve();
+
+    REQUIRE(double_equals(sys_var_1->get_value(), 1.666667, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_2->get_value(), 1.666667, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_3->get_value(), 1.666667, sg_maxmin_precision));
+  }
+
+  SECTION("Consumption weight + variable weight")
+  {
+    /*
+     * Strange system under consideration:
+     * 56\times\rho_1^{74} + 21\times\rho_2^{6} + 2\times\rho_3^{2} \le 123
+     */
+
+    lmm::Constraint* sys_cnst = Sys->constraint_new(nullptr, 123);
+    lmm::Variable* sys_var_1  = Sys->variable_new(nullptr, 56, 0.0, 1);
+    lmm::Variable* sys_var_2  = Sys->variable_new(nullptr, 21, 0.0, 1);
+    lmm::Variable* sys_var_3  = Sys->variable_new(nullptr, 3, 0.0, 1);
+
+    Sys->expand(sys_cnst, sys_var_1, 74);
+    Sys->expand(sys_cnst, sys_var_2, 6);
+    Sys->expand(sys_cnst, sys_var_3, 2);
+    Sys->solve();
+
+    REQUIRE(double_equals(sys_var_1->get_value(), 0.9659686, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_2->get_value(), 2.575916, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_3->get_value(), 18.03141, sg_maxmin_precision));
+  }
+}
+
+TEST_CASE("kernel::lmm Multiple constraint shared systems", "[kernel-lmm-shared-multiple-sys]")
+{
+
+  lmm::System* Sys = lmm::make_new_maxmin_system(false);
+
+  SECTION("3 Constraints system")
+  {
+
+    /*
+     * System under consideration:
+     * 4\times\rho_1^{5.1} + 2.6\times\rho_2^{7} + 1.2\times\rho_3^{8.5} \le 14.6 \\
+     * 5\times\rho_4^{6.2} + 2\times\rho_2^{7}   + 4.1\times\rho_3^{8.5} \le 40.7 \\
+     * 6\times\rho_5^1                                                   \le 7
+     */
+
+    lmm::Constraint* sys_cnst_1 = Sys->constraint_new(nullptr, 14.6);
+    lmm::Constraint* sys_cnst_2 = Sys->constraint_new(nullptr, 10.7);
+    lmm::Constraint* sys_cnst_3 = Sys->constraint_new(nullptr, 7);
+
+    lmm::Variable* sys_var_1 = Sys->variable_new(nullptr, 5.1, 0.0, 1);
+    lmm::Variable* sys_var_2 = Sys->variable_new(nullptr, 7, 0.0, 2);
+    lmm::Variable* sys_var_3 = Sys->variable_new(nullptr, 8.5, 0.0, 2);
+    lmm::Variable* sys_var_4 = Sys->variable_new(nullptr, 6.2, 0.0, 1);
+    lmm::Variable* sys_var_5 = Sys->variable_new(nullptr, 1, 0.0, 1);
+
+    // Constraint 1
+    Sys->expand(sys_cnst_1, sys_var_1, 4);
+    Sys->expand(sys_cnst_1, sys_var_2, 2.6);
+    Sys->expand(sys_cnst_1, sys_var_3, 1.2);
+    // Constraint 2
+    Sys->expand(sys_cnst_2, sys_var_4, 5);
+    Sys->expand(sys_cnst_2, sys_var_2, 2);
+    Sys->expand(sys_cnst_2, sys_var_3, 4.1);
+    // Constraint 3
+    Sys->expand(sys_cnst_3, sys_var_5, 6);
+    Sys->solve();
+
+    REQUIRE(double_equals(sys_var_1->get_value(), 2.779119, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_2->get_value(), 0.9708181, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_3->get_value(), 0.7994973, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_4->get_value(), 1.096085, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_5->get_value(), 1.166667, sg_maxmin_precision));
+  }
+}
+
+TEST_CASE("kernel::lmm Single constraint unshared systems", "[kernel-lmm-unshared-single-sys]")
+{
+  lmm::System* Sys = lmm::make_new_maxmin_system(false);
+
+  SECTION("Variable weight")
+  {
+    /*
+     * System under consideration:
+     * 1\times\rho_1^{1} + 1\times\rho_2^{2} + 1\times\rho_3^{3} \le 10
+     */
+
+    lmm::Constraint* sys_cnst = Sys->constraint_new(nullptr, 10);
+    sys_cnst->unshare(); // FATPIPE
+    lmm::Variable* sys_var_1 = Sys->variable_new(nullptr, 1, 0.0, 1);
+    lmm::Variable* sys_var_2 = Sys->variable_new(nullptr, 2, 0.0, 1);
+    lmm::Variable* sys_var_3 = Sys->variable_new(nullptr, 3, 0.0, 1);
+
+    Sys->expand(sys_cnst, sys_var_1, 1);
+    Sys->expand(sys_cnst, sys_var_2, 1);
+    Sys->expand(sys_cnst, sys_var_3, 1);
+    Sys->solve();
+
+    REQUIRE(double_equals(sys_var_1->get_value(), 10, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_2->get_value(), 5, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_3->get_value(), 3.333333, sg_maxmin_precision));
+  }
+
+  SECTION("Consumption weight")
+  {
+    /*
+     * System under consideration:
+     * 1\times\rho_1^{1} + 2\times\rho_2^{1} + 3\times\rho_3^{1} \le 10
+     */
+
+    lmm::Constraint* sys_cnst = Sys->constraint_new(nullptr, 10);
+    sys_cnst->unshare();
+    lmm::Variable* sys_var_1 = Sys->variable_new(nullptr, 1, 0.0, 1);
+    lmm::Variable* sys_var_2 = Sys->variable_new(nullptr, 1, 0.0, 1);
+    lmm::Variable* sys_var_3 = Sys->variable_new(nullptr, 1, 0.0, 1);
+
+    Sys->expand(sys_cnst, sys_var_1, 1);
+    Sys->expand(sys_cnst, sys_var_2, 2);
+    Sys->expand(sys_cnst, sys_var_3, 3);
+    Sys->solve();
+
+    REQUIRE(double_equals(sys_var_1->get_value(), 3.333333, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_2->get_value(), 3.333333, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_3->get_value(), 3.333333, sg_maxmin_precision));
+  }
+
+  SECTION("Consumption weight + variable weight")
+  {
+    /*
+     * Strange system under consideration:
+     * 56\times\rho_1^{74} + 21\times\rho_2^{6} + 2\times\rho_3^{2} \le 123
+     */
+
+    lmm::Constraint* sys_cnst = Sys->constraint_new(nullptr, 123);
+    sys_cnst->unshare();
+    lmm::Variable* sys_var_1 = Sys->variable_new(nullptr, 56, 0.0, 1);
+    lmm::Variable* sys_var_2 = Sys->variable_new(nullptr, 21, 0.0, 1);
+    lmm::Variable* sys_var_3 = Sys->variable_new(nullptr, 3, 0.0, 1);
+
+    Sys->expand(sys_cnst, sys_var_1, 74);
+    Sys->expand(sys_cnst, sys_var_2, 6);
+    Sys->expand(sys_cnst, sys_var_3, 2);
+    Sys->solve();
+
+    REQUIRE(double_equals(sys_var_1->get_value(), 1.662162, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_2->get_value(), 4.432432, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_3->get_value(), 31.02703, sg_maxmin_precision));
+  }
+}
+
+TEST_CASE("kernel::lmm Multiple constraint unshared systems", "[kernel-lmm-unshared-multiple-sys]")
+{
+
+  lmm::System* Sys = lmm::make_new_maxmin_system(false);
+
+  SECTION("3 Constraints system")
+  {
+
+    /*
+     * System under consideration:
+     * 4\times\rho_1^{5.1} + 2.6\times\rho_2^{7} + 1.2\times\rho_3^{8.5} \le 14.6 \\
+     * 5\times\rho_4^{6.2} + 2\times\rho_2^{7}   + 4.1\times\rho_3^{8.5} \le 40.7 \\
+     * 6\times\rho_5^1                                                   \le 7
+     */
+
+    lmm::Constraint* sys_cnst_1 = Sys->constraint_new(nullptr, 14.6);
+    sys_cnst_1->unshare();
+    lmm::Constraint* sys_cnst_2 = Sys->constraint_new(nullptr, 10.7);
+    sys_cnst_2->unshare();
+    lmm::Constraint* sys_cnst_3 = Sys->constraint_new(nullptr, 7);
+    sys_cnst_3->unshare();
+
+    lmm::Variable* sys_var_1 = Sys->variable_new(nullptr, 5.1, 0.0, 1);
+    lmm::Variable* sys_var_2 = Sys->variable_new(nullptr, 7, 0.0, 2);
+    lmm::Variable* sys_var_3 = Sys->variable_new(nullptr, 8.5, 0.0, 2);
+    lmm::Variable* sys_var_4 = Sys->variable_new(nullptr, 6.2, 0.0, 1);
+    lmm::Variable* sys_var_5 = Sys->variable_new(nullptr, 1, 0.0, 1);
+
+    // Constraint 1
+    Sys->expand(sys_cnst_1, sys_var_1, 4);
+    Sys->expand(sys_cnst_1, sys_var_2, 2.6);
+    Sys->expand(sys_cnst_1, sys_var_3, 1.2);
+    // Constraint 2
+    Sys->expand(sys_cnst_2, sys_var_4, 5);
+    Sys->expand(sys_cnst_2, sys_var_2, 2);
+    Sys->expand(sys_cnst_2, sys_var_3, 4.1);
+    // Constraint 3
+    Sys->expand(sys_cnst_3, sys_var_5, 6);
+    Sys->solve();
+
+    REQUIRE(double_equals(sys_var_1->get_value(), 3.65, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_2->get_value(), 1.895429, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_3->get_value(), 1.560941, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_4->get_value(), 2.14, sg_maxmin_precision));
+    REQUIRE(double_equals(sys_var_5->get_value(), 1.166667, sg_maxmin_precision));
+  }
+}
index 2988ed0..30b8665 100644 (file)
@@ -100,7 +100,8 @@ set(UNIT_TESTS  src/xbt/unit-tests_main.cpp
                 src/xbt/config_test.cpp
                 src/xbt/dict_test.cpp
                 src/xbt/dynar_test.cpp
-                src/xbt/xbt_str_test.cpp)
+                src/xbt/xbt_str_test.cpp
+                teshsuite/surf/lmm_usage/lmm_solve.cpp)
 if (SIMGRID_HAVE_MC)
   set(UNIT_TESTS ${UNIT_TESTS} src/mc/sosp/Snapshot_test.cpp src/mc/sosp/PageStore_test.cpp)
 else()
index ed44f89..5390d9c 100644 (file)
@@ -3,7 +3,7 @@ configure_file("${CMAKE_HOME_DIRECTORY}/tools/tesh/tesh.py"
 
 
 foreach(x setenv set-output-ignore set-output-sort set-return set-timeout background basic bg-basic bg-set-signal
-          catch-return catch-signal catch-timeout catch-wrong-output cd color ignore-regexp IO-bigsize IO-broken-pipe IO-orders)
+          catch-return catch-signal catch-timeout catch-timeout-output catch-wrong-output cd color ignore-regexp IO-bigsize IO-broken-pipe IO-orders)
   set(tesh_files  ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/${x}.tesh)
   if(NOT enable_memcheck AND NOT WIN32)
     ADD_TESH(tesh-self-${x} --setenv bindir=${CMAKE_BINARY_DIR}/bin ${CMAKE_HOME_DIRECTORY}/tools/tesh/${x}.tesh)
diff --git a/tools/tesh/catch-timeout-output.tesh b/tools/tesh/catch-timeout-output.tesh
new file mode 100644 (file)
index 0000000..227d93c
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/env tesh
+
+# Checks that the output of a timeout process can be printed.
+
+! expect return 2
+< ! timeout 1
+< $ sh -c 'echo "I crashed" && sleep 6'
+> Test suite from stdin
+> [(stdin):2] sh -c 'echo "I crashed" && sleep 6'
+> Test suite `(stdin)': NOK (<(stdin):2> timeout after 1 sec)
+> Output of <(stdin):2> mismatch:
+> --- expected
+> +++ obtained
+> @@ -0,0 +1 @@
+> +I crashed
+> Test suite `(stdin)': NOK (<(stdin):2> output mismatch)
+$ ${bindir:=.}/tesh
+
+
index 0bee596..a246c16 100644 (file)
@@ -1,6 +1,6 @@
 #!/usr/bin/env tesh
 
-# This suite must be functional because we changed the timeout value to 10
+# This suite must be functional because we changed the timeout value to 1
 # before sleeping 6 secs.
 
 ! expect return 3
index aa1f65e..48ddd51 100755 (executable)
@@ -114,8 +114,7 @@ except NameError:
 #
 
 # Global variable. Stores which process group should be killed (or None otherwise)
-pgtokill = None
-
+running_pgids = list()
 
 def kill_process_group(pgid):
     if pgid is None:  # Nobody to kill. We don't know who to kill on windows, or we don't have anyone to kill on signal handler
@@ -131,8 +130,11 @@ def kill_process_group(pgid):
 
 def signal_handler(signal, frame):
     print("Caught signal {}".format(SIGNALS_TO_NAMES_DICT[signal]))
-    if pgtokill is not None:
-        kill_process_group(pgtokill)
+    global running_pgids
+    running_pgids_copy = running_pgids # Just in case of interthread conflicts.
+    for pgid in running_pgids_copy:
+        kill_process_group(pgid)
+    running_pgids.clear()
     tesh_exit(5)
 
 
@@ -324,9 +326,13 @@ class Cmd(object):
         args = shlex.split(self.args)
         #print (args)
 
-        global pgtokill
+        global running_pgids
+        local_pgid = None
 
         try:
+            preexec_function = None
+            if not isWindows():
+                preexec_function = lambda: os.setpgid(0, 0)
             proc = subprocess.Popen(
                 args,
                 bufsize=1,
@@ -334,10 +340,11 @@ class Cmd(object):
                 stdout=subprocess.PIPE,
                 stderr=subprocess.STDOUT,
                 universal_newlines=True,
-                start_new_session=True)
+                preexec_fn=preexec_function)
             try:
                 if not isWindows():
-                    pgtokill = os.getpgid(proc.pid)
+                    local_pgid = os.getpgid(proc.pid)
+                    running_pgids.append(local_pgid)
             except OSError:
                 # os.getpgid failed. OK. No cleanup.
                 pass
@@ -363,12 +370,21 @@ class Cmd(object):
         cmdName = FileReader().filename + ":" + str(self.linenumber)
         try:
             (stdout_data, stderr_data) = proc.communicate("\n".join(self.input_pipe), self.timeout)
-            pgtokill = None
+            local_pgid = None
+            timeout_reached = False
         except subprocess.TimeoutExpired:
+            timeout_reached = True
             print("Test suite `" + FileReader().filename + "': NOK (<" +
                   cmdName + "> timeout after " + str(self.timeout) + " sec)")
-            kill_process_group(pgtokill)
-            tesh_exit(3)
+            running_pgids.remove(local_pgid)
+            kill_process_group(local_pgid)
+            # Try to get the output of the timeout process, to help in debugging.
+            try:
+                (stdout_data, stderr_data) = proc.communicate(timeout=1)
+            except subprocess.TimeoutExpired:
+                print("[{file}:{number}] Could not retrieve output. Killing the process group failed?".format(
+                    file=FileReader().filename, number=self.linenumber))
+                tesh_exit(3)
 
         if self.output_display:
             print(stdout_data)
@@ -435,6 +451,9 @@ class Cmd(object):
                     print("Obtained output kept as requested: " + os.path.abspath("obtained"))
                 tesh_exit(2)
 
+        if timeout_reached:
+            tesh_exit(3)
+
         #print ((proc.returncode, self.expect_return))
 
         if proc.returncode != self.expect_return: