sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

harness_argparser.c (10306B)


      1 /* See COPYING.txt for the full license governing this code. */
      2 /**
      3  * \file harness_argparser.c
      4  *
      5  * Source file for functions to parse arguments to the test harness.
      6  */
      7 
      8 #include <SDL_test.h>
      9 #include <stdio.h>
     10 #include <string.h>
     11 
     12 #include "SDL_visualtest_harness_argparser.h"
     13 #include "SDL_visualtest_rwhelper.h"
     14 
     15 /** Maximum length of one line in the config file */
     16 #define MAX_CONFIG_LINE_LEN 400
     17 /** Default value for the timeout after which the SUT is forcefully killed */
     18 #define DEFAULT_SUT_TIMEOUT (60 * 1000)
     19 
     20 /* String compare s1 and s2 ignoring leading hyphens */
     21 static int
     22 StrCaseCmpIgnoreHyphen(char* s1, char* s2)
     23 {
     24     /* treat NULL pointer as empty strings */
     25     if(!s1)
     26         s1 = "";
     27     if(!s2)
     28         s2 = "";
     29 
     30     while(*s1 == '-')
     31         s1++;
     32     while(*s2 == '-')
     33         s2++;
     34 
     35     return SDL_strcasecmp(s1, s2);
     36 }
     37 
     38 /* parser an argument, updates the state object and returns the number of
     39    arguments processed; returns -1 on failure */
     40 static int
     41 ParseArg(char** argv, int index, SDLVisualTest_HarnessState* state)
     42 {
     43     if(!argv || !argv[index] || !state)
     44         return 0;
     45 
     46     if(StrCaseCmpIgnoreHyphen("sutapp", argv[index]) == 0)
     47     {
     48         index++;
     49         if(!argv[index])
     50         {
     51             SDLTest_LogError("Arguments parsing error: Invalid argument for sutapp.");
     52             return -1;
     53         }
     54         SDL_strlcpy(state->sutapp, argv[index], MAX_PATH_LEN);
     55         SDLTest_Log("SUT Application: %s", state->sutapp);
     56         return 2;
     57     }
     58     else if(StrCaseCmpIgnoreHyphen("output-dir", argv[index]) == 0)
     59     {
     60         index++;
     61         if(!argv[index])
     62         {
     63             SDLTest_LogError("Arguments parsing error: Invalid argument for output-dir.");
     64             return -1;
     65         }
     66         SDL_strlcpy(state->output_dir, argv[index], MAX_PATH_LEN);
     67         SDLTest_Log("Screenshot Output Directory: %s", state->output_dir);
     68         return 2;
     69     }
     70     else if(StrCaseCmpIgnoreHyphen("verify-dir", argv[index]) == 0)
     71     {
     72         index++;
     73         if(!argv[index])
     74         {
     75             SDLTest_LogError("Arguments parsing error: Invalid argument for verify-dir.");
     76             return -1;
     77         }
     78         SDL_strlcpy(state->verify_dir, argv[index], MAX_PATH_LEN);
     79         SDLTest_Log("Screenshot Verification Directory: %s", state->verify_dir);
     80         return 2;
     81     }
     82     else if(StrCaseCmpIgnoreHyphen("sutargs", argv[index]) == 0)
     83     {
     84         index++;
     85         if(!argv[index])
     86         {
     87             SDLTest_LogError("Arguments parsing error: Invalid argument for sutargs.");
     88             return -1;
     89         }
     90         SDL_strlcpy(state->sutargs, argv[index], MAX_SUT_ARGS_LEN);
     91         SDLTest_Log("SUT Arguments: %s", state->sutargs);
     92         return 2;
     93     }
     94     else if(StrCaseCmpIgnoreHyphen("timeout", argv[index]) == 0)
     95     {
     96         int hr, min, sec;
     97         index++;
     98         if(!argv[index] || SDL_sscanf(argv[index], "%d:%d:%d", &hr, &min, &sec) != 3)
     99         {
    100             SDLTest_LogError("Arguments parsing error: Invalid argument for timeout.");
    101             return -1;
    102         }
    103         state->timeout = (((hr * 60) + min) * 60 + sec) * 1000;
    104         SDLTest_Log("Maximum Timeout for each SUT run: %d milliseconds",
    105                     state->timeout);
    106         return 2;
    107     }
    108     else if(StrCaseCmpIgnoreHyphen("parameter-config", argv[index]) == 0)
    109     {
    110         index++;
    111         if(!argv[index])
    112         {
    113             SDLTest_LogError("Arguments parsing error: Invalid argument for parameter-config.");
    114             return -1;
    115         }
    116         SDLTest_Log("SUT Parameters file: %s", argv[index]);
    117         SDLVisualTest_FreeSUTConfig(&state->sut_config);
    118         if(!SDLVisualTest_ParseSUTConfig(argv[index], &state->sut_config))
    119         {
    120             SDLTest_LogError("Failed to parse SUT parameters file");
    121             return -1;
    122         }
    123         return 2;
    124     }
    125     else if(StrCaseCmpIgnoreHyphen("variator", argv[index]) == 0)
    126     {
    127         index++;
    128         if(!argv[index])
    129         {
    130             SDLTest_LogError("Arguments parsing error: Invalid argument for variator.");
    131             return -1;
    132         }
    133         SDLTest_Log("Variator: %s", argv[index]);
    134         if(SDL_strcasecmp("exhaustive", argv[index]) == 0)
    135             state->variator_type = SDL_VARIATOR_EXHAUSTIVE;
    136         else if(SDL_strcasecmp("random", argv[index]) == 0)
    137             state->variator_type = SDL_VARIATOR_RANDOM;
    138         else
    139         {
    140             SDLTest_LogError("Arguments parsing error: Invalid variator name.");
    141             return -1;
    142         }
    143         return 2;
    144     }
    145     else if(StrCaseCmpIgnoreHyphen("num-variations", argv[index]) == 0)
    146     {
    147         index++;
    148         if(!argv[index])
    149         {
    150             SDLTest_LogError("Arguments parsing error: Invalid argument for num-variations.");
    151             return -1;
    152         }
    153         state->num_variations = SDL_atoi(argv[index]);
    154         SDLTest_Log("Number of variations to run: %d", state->num_variations);
    155         if(state->num_variations <= 0)
    156         {
    157             SDLTest_LogError("Arguments parsing error: num-variations must be positive.");
    158             return -1;
    159         }
    160         return 2;
    161     }
    162     else if(StrCaseCmpIgnoreHyphen("no-launch", argv[index]) == 0)
    163     {
    164         state->no_launch = SDL_TRUE;
    165         SDLTest_Log("SUT will not be launched.");
    166         return 1;
    167     }
    168     else if(StrCaseCmpIgnoreHyphen("action-config", argv[index]) == 0)
    169     {
    170         index++;
    171         if(!argv[index])
    172         {
    173             SDLTest_LogError("Arguments parsing error: invalid argument for action-config");
    174             return -1;
    175         }
    176         SDLTest_Log("Action Config file: %s", argv[index]);
    177         SDLVisualTest_EmptyActionQueue(&state->action_queue);
    178         if(!SDLVisualTest_ParseActionConfig(argv[index], &state->action_queue))
    179         {
    180             SDLTest_LogError("SDLVisualTest_ParseActionConfig() failed");
    181             return -1;
    182         }
    183         return 2;
    184     }
    185     else if(StrCaseCmpIgnoreHyphen("config", argv[index]) == 0)
    186     {
    187         index++;
    188         if(!argv[index])
    189         {
    190             SDLTest_LogError("Arguments parsing error: invalid argument for config");
    191             return -1;
    192         }
    193 
    194         /* do nothing, this option has already been handled */
    195         return 2;
    196     }
    197     return 0;
    198 }
    199 
    200 /* TODO: Trailing/leading spaces and spaces between equals sign not supported. */
    201 static int
    202 ParseConfig(char* file, SDLVisualTest_HarnessState* state)
    203 {
    204     SDL_RWops* rw;
    205     SDLVisualTest_RWHelperBuffer buffer;
    206     char line[MAX_CONFIG_LINE_LEN];
    207 
    208     rw = SDL_RWFromFile(file, "r");
    209     if(!rw)
    210     {
    211         SDLTest_LogError("SDL_RWFromFile() failed");
    212         return 0;
    213     }
    214 
    215     SDLVisualTest_RWHelperResetBuffer(&buffer);
    216     while(SDLVisualTest_RWHelperReadLine(rw, line, MAX_CONFIG_LINE_LEN,
    217                                          &buffer, '#'))
    218     {
    219         char** argv;
    220         int i, num_params;
    221 
    222         /* count number of parameters and replace the trailing newline with 0 */
    223         num_params = 1;
    224         for(i = 0; line[i]; i++)
    225         {
    226             if(line[i] == '=')
    227             {
    228                 num_params = 2;
    229                 break;
    230             }
    231         }
    232 
    233         /* populate argv */
    234         argv = (char**)SDL_malloc((num_params + 1) * sizeof(char*));
    235         if(!argv)
    236         {
    237             SDLTest_LogError("malloc() failed.");
    238             SDL_RWclose(rw);
    239             return 0;
    240         }
    241 
    242         argv[num_params] = NULL;
    243         for(i = 0; i < num_params; i++)
    244         {
    245             argv[i] = strtok(i == 0 ? line : NULL, "=");
    246         }
    247 
    248         if(ParseArg(argv, 0, state) == -1)
    249         {
    250             SDLTest_LogError("ParseArg() failed");
    251             SDL_free(argv);
    252             SDL_RWclose(rw);
    253             return 0;
    254         }
    255         SDL_free(argv);
    256     }
    257     SDL_RWclose(rw);
    258 
    259     if(!state->sutapp[0])
    260         return 0;
    261     return 1;
    262 }
    263 
    264 int
    265 SDLVisualTest_ParseHarnessArgs(char** argv, SDLVisualTest_HarnessState* state)
    266 {
    267     int i;
    268 
    269     SDLTest_Log("Parsing commandline arguments..");
    270 
    271     if(!argv)
    272     {
    273         SDLTest_LogError("argv is NULL");
    274         return 0;
    275     }
    276     if(!state)
    277     {
    278         SDLTest_LogError("state is NULL");
    279         return 0;
    280     }
    281 
    282     /* initialize the state object */
    283     state->sutargs[0] = '\0';
    284     state->sutapp[0] = '\0';
    285     state->output_dir[0] = '\0';
    286     state->verify_dir[0] = '\0';
    287     state->timeout = DEFAULT_SUT_TIMEOUT;
    288     SDL_memset(&state->sut_config, 0, sizeof(SDLVisualTest_SUTConfig));
    289     SDL_memset(&state->action_queue, 0, sizeof(SDLVisualTest_ActionQueue));
    290     state->variator_type = SDL_VARIATOR_RANDOM;
    291     state->num_variations = -1;
    292     state->no_launch = SDL_FALSE;
    293 
    294     /* parse config file if passed */
    295     for(i = 0; argv[i]; i++)
    296     {
    297         if(StrCaseCmpIgnoreHyphen("config", argv[i]) == 0)
    298         {
    299             if(!argv[i + 1])
    300             {
    301                 SDLTest_Log("Arguments parsing error: invalid argument for config.");
    302                 return 0;
    303             }
    304             if(!ParseConfig(argv[i + 1], state))
    305             {
    306                 SDLTest_LogError("ParseConfig() failed");
    307                 return 0;
    308             }
    309         }
    310     }
    311 
    312     /* parse the arguments */
    313     for(i = 0; argv[i];)
    314     {
    315         int consumed = ParseArg(argv, i, state);
    316         if(consumed == -1 || consumed == 0)
    317         {
    318             SDLTest_LogError("ParseArg() failed");
    319             return 0;
    320         }
    321         i += consumed;
    322     }
    323 
    324     if(state->variator_type == SDL_VARIATOR_RANDOM && state->num_variations == -1)
    325         state->num_variations = 1;
    326 
    327     /* check to see if required options have been passed */
    328     if(!state->sutapp[0])
    329     {
    330         SDLTest_LogError("sutapp must be passed.");
    331         return 0;
    332     }
    333     if(!state->sutargs[0] && !state->sut_config.options)
    334     {
    335         SDLTest_LogError("Either sutargs or parameter-config must be passed.");
    336         return 0;
    337     }
    338     if(!state->output_dir[0])
    339     {
    340         SDL_strlcpy(state->output_dir, "./output", MAX_PATH_LEN);
    341     }
    342     if(!state->verify_dir[0])
    343     {
    344         SDL_strlcpy(state->verify_dir, "./verify", MAX_PATH_LEN);
    345     }
    346 
    347     return 1;
    348 }
    349 
    350 void
    351 SDLVisualTest_FreeHarnessState(SDLVisualTest_HarnessState* state)
    352 {
    353     if(state)
    354     {
    355         SDLVisualTest_EmptyActionQueue(&state->action_queue);
    356         SDLVisualTest_FreeSUTConfig(&state->sut_config);
    357     }
    358 }