Parallelized test case execution
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-unmanaged / tct-dali-toolkit-unmanaged-core.cpp
1 #include <stdio.h>
2 #include <string.h>
3 #include "tct-dali-toolkit-unmanaged-core.h"
4 #include <stdlib.h>
5 #include <getopt.h>
6 #include <sys/types.h>
7 #include <sys/wait.h>
8 #include <unistd.h>
9 #include <vector>
10 #include <map>
11
12 int RunTestCase( struct testcase_s& testCase )
13 {
14   int result = 1;
15   if( testCase.startup )
16   {
17     testCase.startup();
18   }
19   result = testCase.function();
20   if( testCase.cleanup )
21   {
22     testCase.cleanup();
23   }
24   return result;
25 }
26
27 #define MAX_NUM_CHILDREN 16
28
29 struct TestCase
30 {
31   int testCase;
32   const char* testCaseName;
33
34   TestCase()
35   : testCase(0),
36     testCaseName(NULL)
37   {
38   }
39
40   TestCase(int tc, const char* name)
41   : testCase(tc),
42     testCaseName(name)
43   {
44   }
45   TestCase(const TestCase& rhs)
46   : testCase(rhs.testCase),
47     testCaseName(rhs.testCaseName)
48   {
49   }
50   TestCase& operator=(const TestCase& rhs)
51   {
52     testCase = rhs.testCase;
53     testCaseName = rhs.testCaseName;
54     return *this;
55
56   }
57 };
58
59
60 typedef std::map<int, TestCase> RunningTestCases;
61
62 // Constantly runs up to MAX_NUM_CHILDREN processes
63 int RunAllInParallel(const char* processName, bool reRunFailed)
64 {
65   int numFailures = 0;
66   int numPasses = 0;
67   int numTestCases = sizeof(tc_array)/sizeof(struct testcase_s) - 1;
68
69   RunningTestCases children;
70   std::vector<int> failedTestCases;
71
72   // Fork up to MAX_NUM_CHILDREN processes, then
73   // wait. As soon as a proc completes, fork the next.
74
75   int nextTestCase = 0;
76   int numRunningChildren = 0;
77   while( nextTestCase < numTestCases || numRunningChildren > 0)
78   {
79     if( nextTestCase < numTestCases )
80     {
81       while( numRunningChildren < MAX_NUM_CHILDREN )
82       {
83         int pid = fork();
84         if( pid == 0 ) // Child process
85         {
86           close(STDOUT_FILENO);
87           close(STDERR_FILENO);
88           exit( RunTestCase( tc_array[nextTestCase] ) );
89         }
90         else if(pid == -1)
91         {
92           perror("fork");
93           exit(2);
94         }
95         else // Parent process
96         {
97           TestCase tc(nextTestCase, tc_array[nextTestCase].name);
98           children[pid] = tc;
99           nextTestCase++;
100           numRunningChildren++;
101         }
102       }
103     }
104
105     int status=0;
106     int childPid = waitpid(-1, &status, 0);
107     if( childPid == -1 )
108     {
109       perror("waitpid");
110       exit(2);
111     }
112
113     if( WIFEXITED(status) )
114     {
115       if( childPid > 0 )
116       {
117         int testResult = WEXITSTATUS(status);
118         if( testResult )
119         {
120           printf("Test case %s failed: %d\n", children[childPid].testCaseName, testResult);
121           failedTestCases.push_back(children[childPid].testCase);
122           numFailures++;
123         }
124         else
125         {
126           numPasses++;
127         }
128         numRunningChildren--;
129       }
130     }
131
132     else if( WIFSIGNALED(status) )
133     {
134       if( childPid > 0 )
135       {
136         RunningTestCases::iterator iter = children.find(childPid);
137         if( iter != children.end() )
138         {
139           printf("Test case %s exited with signal %d\n", iter->second.testCaseName, WTERMSIG(status));
140           failedTestCases.push_back(iter->second.testCase);
141         }
142         else
143         {
144           printf("Unknown child process: %d signaled %d\n", childPid, WTERMSIG(status));
145         }
146
147         numFailures++;
148         numRunningChildren--;
149       }
150     }
151   }
152
153   printf("\rNumber of test passes: %d                                        \n", numPasses);
154   printf("Number of test failures: %d\n", numFailures);
155
156   if( reRunFailed )
157   {
158     for( unsigned int i=0; i<failedTestCases.size(); i++)
159     {
160       printf("Running test case %s:\n", tc_array[failedTestCases[i]].name );
161       RunTestCase( tc_array[failedTestCases[i] ] );
162     }
163   }
164
165   return numFailures;
166 }
167
168 int FindAndRunTestCase(const char* testCaseName)
169 {
170   int result = 2;
171
172   for( int i = 0; tc_array[i].name; i++ )
173   {
174     if( !strcmp(testCaseName, tc_array[i].name) )
175     {
176       return RunTestCase( tc_array[i] );
177     }
178   }
179
180   printf("Unknown testcase name: \"%s\"\n", testCaseName);
181   return result;
182 }
183
184 int main(int argc, char * const argv[])
185 {
186   int result = -1;
187
188   const char* optString = "pr";
189   bool optParallel(false);
190   bool optRerunFailed(false);
191
192   int nextOpt = 0;
193   do
194   {
195     nextOpt = getopt( argc, argv, optString );
196     switch(nextOpt)
197     {
198       case 'p':
199         optParallel = true;
200         break;
201       case 'r':
202         optRerunFailed = true;
203         break;
204     }
205   } while( nextOpt != -1 );
206
207   if( optParallel )
208   {
209     result = RunAllInParallel(argv[0], optRerunFailed);
210   }
211   else
212   {
213     if (argc != 2) {
214       printf("Usage: %s <testcase name>\n", argv[0]);
215       return 2;
216     }
217     result = FindAndRunTestCase(argv[1]);
218   }
219   return result;
220 }