visualtest/src/harness_argparser.c
author Sam Lantinga
Tue, 10 Jan 2017 08:54:33 -0800
changeset 10806 36f40b8cc979
parent 7924 fcb86d323770
permissions -rw-r--r--
Fixed bugs 2570, 3145, improved OpenGL ES context support on Windows and X11

Mark Callow

The attached patch does the following for the X11 and Windows platforms, the only ones where SDL attempts to use context_create_es_profile:

- Adds SDL_HINT_OPENGL_ES_DRIVER by which the application can
say to use the OpenGL ES driver & EGL rather than the Open GL
driver. (For bug #2570)
- Adds code to {WIN,X11}_GL_InitExtensions to determine the maximum
OpenGL ES version supported by the OpenGL driver (for bug #3145)
- Modifies the test that determines whether to use the OpenGL
driver or the real OpenGL ES driver to take into account the
hint, the requested and supported ES version and whether ES 1.X
is being requested. (For bug #2570 & bug #3145)
- Enables the testgles2 test for __WINDOWS__ and __LINUX__ and adds
the test to the VisualC projects.

With the fix in place I have run testdraw2, testgl and testgles2 without any issues and have run my own apps that use OpenGL, OpenGL ES 3 and OpenGL ES 1.1.
     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 }