framework: add timeout parameter to cmdline sandbox/z.abramowska/timeout
authorZofia Abramowska <z.abramowska@samsung.com>
Thu, 22 May 2025 08:15:52 +0000 (10:15 +0200)
committerZofia Abramowska <z.abramowska@samsung.com>
Thu, 22 May 2025 09:21:16 +0000 (11:21 +0200)
Change-Id: I9a82736df504f94bc92489d4cbfe08dd38c7daea

src/framework/include/dpl/test/test_runner.h
src/framework/src/test_runner.cpp
src/framework/src/test_runner_child.cpp

index 6f9de4fabb2dc44a2a479ee3fa2f9eb01598c3c9..d38284ca583d867967bf2d91163706789573e710 100644 (file)
@@ -71,6 +71,7 @@ class TestRunner
         m_currentTestCase(nullptr)
       , m_terminate(false)
       , m_allowChildLogs(false)
+      , m_pipeTimeout(90)
       , m_deferDeepness(0U)
       , m_firstDeferredExceptionType(DeferredExceptionType::DEFERRED_FAILED)
     {}
@@ -99,6 +100,9 @@ class TestRunner
     bool m_terminate;
     bool m_allowChildLogs;
 
+    // Timeout for child test in seconds
+    int m_pipeTimeout;
+
     void Banner();
     void InvalidArgs(const std::string& message = "Invalid arguments!");
     void Usage();
@@ -126,8 +130,9 @@ class TestRunner
     int ExecTestRunner(ArgsList args);
     // The runner will terminate as soon as possible (after current test).
     void Terminate();
-    bool GetAllowChildLogs();
+    bool GetAllowChildLogs() const;
     bool GetRunIgnored() const;
+    int GetTimeout() const;
 
     void deferFailedException(const DPL::Test::TestFailed &ex);
     void deferIgnoredException(const DPL::Test::TestIgnored &ex);
index 0d676eb646d662f758c95401cb0548c6bf8b5c29..e70e158bbd258b435593a986b82d356e5f992a8c 100644 (file)
@@ -36,6 +36,7 @@
 #include <exception>
 #include <functional>
 #include <memory>
+#include <stdexcept>
 #include <string>
 #include <unistd.h>
 
@@ -510,6 +511,9 @@ void TestRunner::Usage()
     fprintf(stderr, "  --allowchildlogs\t Allow to print logs from child process on screen.\n");
     fprintf(stderr, "       When active child process will be able to print logs on stdout and stderr.\n");
     fprintf(stderr, "       Both descriptors will be closed after test.\n");
+    fprintf(
+        stderr,
+        "  --timeout=<timeout>\tTimeout for child test cases in seconds (default: 90)");
     fprintf(stderr, "  --help\t This help\n\n");
     std::for_each(m_collectors.begin(),
                   m_collectors.end(),
@@ -563,6 +567,7 @@ int TestRunner::ExecTestRunner(ArgsList args)
         const std::string listInGroup = "--listingroup=";
         const std::string allowChildLogs = "--allowchildlogs";
         const std::string onlyFromXML = "--only-from-xml=";
+        const std::string timeout = "--timeout=";
 
         if (currentCollector) {
             if (currentCollector->ParseCollectorSpecificArg(arg)) {
@@ -630,13 +635,32 @@ int TestRunner::ExecTestRunner(ArgsList args)
         } else if (arg.find(allowChildLogs) == 0) {
             arg.erase(0, allowChildLogs.length());
             m_allowChildLogs = true;
+        } else if (arg.find(timeout) == 0) {
+            arg.erase(0, timeout.length());
+            try {
+                m_pipeTimeout = std::stoi(arg);
+            } catch (std::invalid_argument const &ex) {
+                InvalidArgs("Timeout is not a valid number\n");
+                Usage();
+                return -1;
+            } catch (std::out_of_range const &ex) {
+                InvalidArgs("Timeout is out of range\n");
+                Usage();
+                return -1;
+            }
+
+            if (m_pipeTimeout < 0) {
+                InvalidArgs("Timeout cannot be negative\n");
+                Usage();
+                return -1;
+            }
+
         } else if (arg == "--help") {
             showHelp = true;
         } else if (arg.find(output) == 0) {
             arg.erase(0, output.length());
             if (m_collectors.find(arg) != m_collectors.end()) {
-                InvalidArgs(
-                    "Multiple outputs of the same type are not supported!");
+                InvalidArgs("Multiple outputs of the same type are not supported!");
                 Usage();
                 return -1;
             }
@@ -775,7 +799,7 @@ void TestRunner::Terminate()
     m_terminate = true;
 }
 
-bool TestRunner::GetAllowChildLogs()
+bool TestRunner::GetAllowChildLogs() const
 {
     return m_allowChildLogs;
 }
@@ -785,6 +809,11 @@ bool TestRunner::GetRunIgnored() const
     return m_runIgnored;
 }
 
+int TestRunner::GetTimeout() const
+{
+    return m_pipeTimeout;
+}
+
 void TestRunner::deferFailedException(const DPL::Test::TestFailed &ex)
 {
     if (m_deferDeepness <= 0)
index 1516334fc594fad0ed602cd7c14969ca60de6fff..4ef1b48cc12ae788fda32e8e6323d5df28d9f802 100644 (file)
@@ -302,6 +302,8 @@ void RunChildProc(const std::function<void(void)> &testFunc)
         throw TestFailed("Child creation failed");
     }
 
+    int timeout = TestRunnerSingleton::Instance().GetTimeout();
+
     if (pid != 0) {
         // parent code
         pipe.setUsage(PipeWrapper::READONLY);
@@ -310,7 +312,7 @@ void RunChildProc(const std::function<void(void)> &testFunc)
         std::string message;
         PerformanceResultPtr performance;
 
-        int pipeReturn = pipe.receive(code, message, performance, time(0) + 90);
+        int pipeReturn = pipe.receive(code, message, performance, time(0) + timeout);
 
         if (pipeReturn != PipeWrapper::SUCCESS) { // Timeout or reading error
             pipe.closeAll();