visualtest/src/action_configparser.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 10 Nov 2013 00:32:23 -0500
changeset 7924 fcb86d323770
permissions -rwxr-xr-x
Added Apoorv Upreti's GSoC2013 work: visual test suite.

See visualtest/README.txt for details.
icculus@7924
     1
/* See COPYING.txt for the full license governing this code. */
icculus@7924
     2
/**
icculus@7924
     3
 * \file action_configparser.c
icculus@7924
     4
 *
icculus@7924
     5
 * Source file for the parser for action config files.
icculus@7924
     6
 */
icculus@7924
     7
icculus@7924
     8
#include <SDL_stdinc.h>
icculus@7924
     9
#include <SDL_test.h>
icculus@7924
    10
#include <string.h>
icculus@7924
    11
#include "SDL_visualtest_action_configparser.h"
icculus@7924
    12
#include "SDL_visualtest_rwhelper.h"
icculus@7924
    13
#include "SDL_visualtest_parsehelper.h"
icculus@7924
    14
icculus@7924
    15
static void
icculus@7924
    16
FreeAction(SDLVisualTest_Action* action)
icculus@7924
    17
{
icculus@7924
    18
    if(!action)
icculus@7924
    19
        return;
icculus@7924
    20
    switch(action->type)
icculus@7924
    21
    {
icculus@7924
    22
        case SDL_ACTION_LAUNCH:
icculus@7924
    23
        {
icculus@7924
    24
            char* path;
icculus@7924
    25
            char* args;
icculus@7924
    26
icculus@7924
    27
            path = action->extra.process.path;
icculus@7924
    28
            args = action->extra.process.args;
icculus@7924
    29
icculus@7924
    30
            if(path)
icculus@7924
    31
                SDL_free(path);
icculus@7924
    32
            if(args)
icculus@7924
    33
                SDL_free(args);
icculus@7924
    34
icculus@7924
    35
            action->extra.process.path = NULL;
icculus@7924
    36
            action->extra.process.args = NULL;
icculus@7924
    37
        }
icculus@7924
    38
        break;
icculus@7924
    39
    }
icculus@7924
    40
}
icculus@7924
    41
icculus@7924
    42
int
icculus@7924
    43
SDLVisualTest_EnqueueAction(SDLVisualTest_ActionQueue* queue,
icculus@7924
    44
                            SDLVisualTest_Action action)
icculus@7924
    45
{
icculus@7924
    46
    SDLVisualTest_ActionNode* node;
icculus@7924
    47
    if(!queue)
icculus@7924
    48
    {
icculus@7924
    49
        SDLTest_LogError("queue argument cannot be NULL");
icculus@7924
    50
        return 0;
icculus@7924
    51
    }
icculus@7924
    52
icculus@7924
    53
    node = (SDLVisualTest_ActionNode*)SDL_malloc(
icculus@7924
    54
                                      sizeof(SDLVisualTest_ActionNode));
icculus@7924
    55
    if(!node)
icculus@7924
    56
    {
icculus@7924
    57
        SDLTest_LogError("malloc() failed");
icculus@7924
    58
        return 0;
icculus@7924
    59
    }
icculus@7924
    60
    node->action = action;
icculus@7924
    61
    node->next = NULL;
icculus@7924
    62
    queue->size++;
icculus@7924
    63
    if(!queue->rear)
icculus@7924
    64
        queue->rear = queue->front = node;
icculus@7924
    65
    else
icculus@7924
    66
    {
icculus@7924
    67
        queue->rear->next = node;
icculus@7924
    68
        queue->rear = node;
icculus@7924
    69
    }
icculus@7924
    70
    return 1;
icculus@7924
    71
}
icculus@7924
    72
icculus@7924
    73
int
icculus@7924
    74
SDLVisualTest_DequeueAction(SDLVisualTest_ActionQueue* queue)
icculus@7924
    75
{
icculus@7924
    76
    SDLVisualTest_ActionNode* node;
icculus@7924
    77
    if(!queue)
icculus@7924
    78
    {
icculus@7924
    79
        SDLTest_LogError("queue argument cannot be NULL");
icculus@7924
    80
        return 0;
icculus@7924
    81
    }
icculus@7924
    82
    if(SDLVisualTest_IsActionQueueEmpty(queue))
icculus@7924
    83
    {
icculus@7924
    84
        SDLTest_LogError("cannot dequeue from empty queue");
icculus@7924
    85
        return 0;
icculus@7924
    86
    }
icculus@7924
    87
    if(queue->front == queue->rear)
icculus@7924
    88
    {
icculus@7924
    89
        FreeAction(&queue->front->action);
icculus@7924
    90
        SDL_free(queue->front);
icculus@7924
    91
        queue->front = queue->rear = NULL;
icculus@7924
    92
    }
icculus@7924
    93
    else
icculus@7924
    94
    {
icculus@7924
    95
        node = queue->front;
icculus@7924
    96
        queue->front = queue->front->next;
icculus@7924
    97
        FreeAction(&node->action);
icculus@7924
    98
        SDL_free(node);
icculus@7924
    99
    }
icculus@7924
   100
    queue->size--;
icculus@7924
   101
    return 1;
icculus@7924
   102
}
icculus@7924
   103
icculus@7924
   104
void
icculus@7924
   105
SDLVisualTest_InitActionQueue(SDLVisualTest_ActionQueue* queue)
icculus@7924
   106
{
icculus@7924
   107
    if(!queue)
icculus@7924
   108
    {
icculus@7924
   109
        SDLTest_LogError("queue argument cannot be NULL");
icculus@7924
   110
        return;
icculus@7924
   111
    }
icculus@7924
   112
    queue->front = NULL;
icculus@7924
   113
    queue->rear = NULL;
icculus@7924
   114
    queue->size = 0;
icculus@7924
   115
}
icculus@7924
   116
icculus@7924
   117
SDLVisualTest_Action*
icculus@7924
   118
SDLVisualTest_GetQueueFront(SDLVisualTest_ActionQueue* queue)
icculus@7924
   119
{
icculus@7924
   120
    if(!queue)
icculus@7924
   121
    {
icculus@7924
   122
        SDLTest_LogError("queue argument cannot be NULL");
icculus@7924
   123
        return NULL;
icculus@7924
   124
    }
icculus@7924
   125
    if(!queue->front)
icculus@7924
   126
    {
icculus@7924
   127
        SDLTest_LogError("cannot get front of empty queue");
icculus@7924
   128
        return NULL;
icculus@7924
   129
    }
icculus@7924
   130
icculus@7924
   131
    return &queue->front->action;
icculus@7924
   132
}
icculus@7924
   133
icculus@7924
   134
int
icculus@7924
   135
SDLVisualTest_IsActionQueueEmpty(SDLVisualTest_ActionQueue* queue)
icculus@7924
   136
{
icculus@7924
   137
    if(!queue)
icculus@7924
   138
    {
icculus@7924
   139
        SDLTest_LogError("queue argument cannot be NULL");
icculus@7924
   140
        return 1;
icculus@7924
   141
    }
icculus@7924
   142
icculus@7924
   143
    if(queue->size > 0)
icculus@7924
   144
        return 0;
icculus@7924
   145
    return 1;
icculus@7924
   146
}
icculus@7924
   147
icculus@7924
   148
void
icculus@7924
   149
SDLVisualTest_EmptyActionQueue(SDLVisualTest_ActionQueue* queue)
icculus@7924
   150
{
icculus@7924
   151
    if(queue)
icculus@7924
   152
    {
icculus@7924
   153
        while(!SDLVisualTest_IsActionQueueEmpty(queue))
icculus@7924
   154
            SDLVisualTest_DequeueAction(queue);
icculus@7924
   155
    }
icculus@7924
   156
}
icculus@7924
   157
icculus@7924
   158
/* Since the size of the queue is not likely to be larger than 100 elements
icculus@7924
   159
   we can get away with using insertion sort. */
icculus@7924
   160
static void
icculus@7924
   161
SortQueue(SDLVisualTest_ActionQueue* queue)
icculus@7924
   162
{
icculus@7924
   163
    SDLVisualTest_ActionNode* head;
icculus@7924
   164
    SDLVisualTest_ActionNode* tail;
icculus@7924
   165
icculus@7924
   166
    if(!queue || SDLVisualTest_IsActionQueueEmpty(queue))
icculus@7924
   167
        return;
icculus@7924
   168
icculus@7924
   169
    head = queue->front;
icculus@7924
   170
    for(tail = head; tail && tail->next;)
icculus@7924
   171
    {
icculus@7924
   172
        SDLVisualTest_ActionNode* pos;
icculus@7924
   173
        SDLVisualTest_ActionNode* element = tail->next;
icculus@7924
   174
icculus@7924
   175
        if(element->action.time < head->action.time)
icculus@7924
   176
        {
icculus@7924
   177
            tail->next = tail->next->next;
icculus@7924
   178
            element->next = head;
icculus@7924
   179
            head = element;
icculus@7924
   180
        }
icculus@7924
   181
        else if(element->action.time >= tail->action.time)
icculus@7924
   182
        {
icculus@7924
   183
            tail = tail->next;
icculus@7924
   184
        }
icculus@7924
   185
        else
icculus@7924
   186
        {
icculus@7924
   187
            for(pos = head;
icculus@7924
   188
                (pos->next->action.time < element->action.time);
icculus@7924
   189
                pos = pos->next);
icculus@7924
   190
            tail->next = tail->next->next;
icculus@7924
   191
            element->next = pos->next;
icculus@7924
   192
            pos->next = element;
icculus@7924
   193
        }
icculus@7924
   194
    }
icculus@7924
   195
icculus@7924
   196
    queue->front = head;
icculus@7924
   197
    queue->rear = tail;
icculus@7924
   198
}
icculus@7924
   199
icculus@7924
   200
int
icculus@7924
   201
SDLVisualTest_InsertIntoActionQueue(SDLVisualTest_ActionQueue* queue,
icculus@7924
   202
                                    SDLVisualTest_Action action)
icculus@7924
   203
{
icculus@7924
   204
    SDLVisualTest_ActionNode* n;
icculus@7924
   205
    SDLVisualTest_ActionNode* prev;
icculus@7924
   206
    SDLVisualTest_ActionNode* newnode;
icculus@7924
   207
    if(!queue)
icculus@7924
   208
    {
icculus@7924
   209
        SDLTest_LogError("queue argument cannot be NULL");
icculus@7924
   210
        return 0;
icculus@7924
   211
    }
icculus@7924
   212
icculus@7924
   213
    if(SDLVisualTest_IsActionQueueEmpty(queue))
icculus@7924
   214
    {
icculus@7924
   215
        if(!SDLVisualTest_EnqueueAction(queue, action))
icculus@7924
   216
        {
icculus@7924
   217
            SDLTest_LogError("SDLVisualTest_EnqueueAction() failed");
icculus@7924
   218
            return 0;
icculus@7924
   219
        }
icculus@7924
   220
        return 1;
icculus@7924
   221
    }
icculus@7924
   222
icculus@7924
   223
    newnode = (SDLVisualTest_ActionNode*)malloc(sizeof(SDLVisualTest_ActionNode));
icculus@7924
   224
    if(!newnode)
icculus@7924
   225
    {
icculus@7924
   226
        SDLTest_LogError("malloc() failed");
icculus@7924
   227
        return 0;
icculus@7924
   228
    }
icculus@7924
   229
    newnode->action = action;
icculus@7924
   230
icculus@7924
   231
    queue->size++;
icculus@7924
   232
    for(n = queue->front, prev = NULL; n; n = n->next)
icculus@7924
   233
    {
icculus@7924
   234
        if(action.time < n->action.time)
icculus@7924
   235
        {
icculus@7924
   236
            if(prev)
icculus@7924
   237
            {
icculus@7924
   238
                prev->next = newnode;
icculus@7924
   239
                newnode->next = n;
icculus@7924
   240
            }
icculus@7924
   241
            else
icculus@7924
   242
            {
icculus@7924
   243
                newnode->next = queue->front;
icculus@7924
   244
                queue->front = newnode;
icculus@7924
   245
            }
icculus@7924
   246
            return 1;
icculus@7924
   247
        }
icculus@7924
   248
        prev = n;
icculus@7924
   249
    }
icculus@7924
   250
icculus@7924
   251
    queue->rear->next = newnode;
icculus@7924
   252
    newnode->next = NULL;
icculus@7924
   253
    queue->rear = newnode;
icculus@7924
   254
icculus@7924
   255
    return 1;
icculus@7924
   256
}
icculus@7924
   257
icculus@7924
   258
int
icculus@7924
   259
SDLVisualTest_ParseActionConfig(char* file, SDLVisualTest_ActionQueue* queue)
icculus@7924
   260
{
icculus@7924
   261
    char line[MAX_ACTION_LINE_LENGTH];
icculus@7924
   262
    SDLVisualTest_RWHelperBuffer buffer;
icculus@7924
   263
    char* token_ptr;
icculus@7924
   264
    int linenum;
icculus@7924
   265
    SDL_RWops* rw;
icculus@7924
   266
icculus@7924
   267
    if(!file)
icculus@7924
   268
    {
icculus@7924
   269
        SDLTest_LogError("file argument cannot be NULL");
icculus@7924
   270
        return 0;
icculus@7924
   271
    }
icculus@7924
   272
    if(!queue)
icculus@7924
   273
    {
icculus@7924
   274
        SDLTest_LogError("queue argument cannot be NULL");
icculus@7924
   275
        return 0;
icculus@7924
   276
    }
icculus@7924
   277
icculus@7924
   278
    rw = SDL_RWFromFile(file, "r");
icculus@7924
   279
    if(!rw)
icculus@7924
   280
    {
icculus@7924
   281
        SDLTest_LogError("SDL_RWFromFile() failed");
icculus@7924
   282
        return 0;
icculus@7924
   283
    }
icculus@7924
   284
icculus@7924
   285
    SDLVisualTest_RWHelperResetBuffer(&buffer);
icculus@7924
   286
    SDLVisualTest_InitActionQueue(queue);
icculus@7924
   287
    linenum = 0;
icculus@7924
   288
    while(SDLVisualTest_RWHelperReadLine(rw, line, MAX_ACTION_LINE_LENGTH,
icculus@7924
   289
                                         &buffer, '#'))
icculus@7924
   290
    {
icculus@7924
   291
        SDLVisualTest_Action action;
icculus@7924
   292
        int hr, min, sec;
icculus@7924
   293
icculus@7924
   294
        /* parse time */
icculus@7924
   295
        token_ptr = strtok(line, " ");
icculus@7924
   296
        if(!token_ptr ||
icculus@7924
   297
           (SDL_sscanf(token_ptr, "%d:%d:%d", &hr, &min, &sec) != 3))
icculus@7924
   298
        {
icculus@7924
   299
            SDLTest_LogError("Could not parse time token at line: %d",
icculus@7924
   300
                             linenum);
icculus@7924
   301
            SDLVisualTest_EmptyActionQueue(queue);
icculus@7924
   302
            SDL_RWclose(rw);
icculus@7924
   303
            return 0;
icculus@7924
   304
        }
icculus@7924
   305
        action.time = (((hr * 60 + min) * 60) + sec) * 1000;
icculus@7924
   306
icculus@7924
   307
        /* parse type */
icculus@7924
   308
        token_ptr = strtok(NULL, " ");
icculus@7924
   309
        if(SDL_strcasecmp(token_ptr, "launch") == 0)
icculus@7924
   310
            action.type = SDL_ACTION_LAUNCH;
icculus@7924
   311
        else if(SDL_strcasecmp(token_ptr, "kill") == 0)
icculus@7924
   312
            action.type = SDL_ACTION_KILL;
icculus@7924
   313
        else if(SDL_strcasecmp(token_ptr, "quit") == 0)
icculus@7924
   314
            action.type = SDL_ACTION_QUIT;
icculus@7924
   315
        else if(SDL_strcasecmp(token_ptr, "screenshot") == 0)
icculus@7924
   316
            action.type = SDL_ACTION_SCREENSHOT;
icculus@7924
   317
        else if(SDL_strcasecmp(token_ptr, "verify") == 0)
icculus@7924
   318
            action.type = SDL_ACTION_VERIFY;
icculus@7924
   319
        else
icculus@7924
   320
        {
icculus@7924
   321
            SDLTest_LogError("Could not parse type token at line: %d",
icculus@7924
   322
                             linenum);
icculus@7924
   323
            SDLVisualTest_EmptyActionQueue(queue);
icculus@7924
   324
            SDL_RWclose(rw);
icculus@7924
   325
            return 0;
icculus@7924
   326
        }
icculus@7924
   327
icculus@7924
   328
        /* parse the extra field */
icculus@7924
   329
        if(action.type == SDL_ACTION_LAUNCH)
icculus@7924
   330
        {
icculus@7924
   331
            int len;
icculus@7924
   332
            char* args;
icculus@7924
   333
            char* path;
icculus@7924
   334
            token_ptr = strtok(NULL, " ");
icculus@7924
   335
            len = token_ptr ? SDL_strlen(token_ptr) : 0;
icculus@7924
   336
            if(len <= 0)
icculus@7924
   337
            {
icculus@7924
   338
                SDLTest_LogError("Please specify the process to launch at line: %d",
icculus@7924
   339
                                 linenum);
icculus@7924
   340
                SDLVisualTest_EmptyActionQueue(queue);
icculus@7924
   341
                SDL_RWclose(rw);
icculus@7924
   342
                return 0;
icculus@7924
   343
            }
icculus@7924
   344
            path = (char*)SDL_malloc(sizeof(char) * (len + 1));
icculus@7924
   345
            if(!path)
icculus@7924
   346
            {
icculus@7924
   347
                SDLTest_LogError("malloc() failed");
icculus@7924
   348
                SDLVisualTest_EmptyActionQueue(queue);
icculus@7924
   349
                SDL_RWclose(rw);
icculus@7924
   350
                return 0;
icculus@7924
   351
            }
icculus@7924
   352
            SDL_strlcpy(path, token_ptr, len + 1);
icculus@7924
   353
icculus@7924
   354
            token_ptr = strtok(NULL, "");
icculus@7924
   355
            len = token_ptr ? SDL_strlen(token_ptr) : 0;
icculus@7924
   356
            if(len > 0)
icculus@7924
   357
            {
icculus@7924
   358
                args = (char*)SDL_malloc(sizeof(char) * (len + 1));
icculus@7924
   359
                if(!args)
icculus@7924
   360
                {
icculus@7924
   361
                    SDLTest_LogError("malloc() failed");
icculus@7924
   362
                    SDL_free(path);
icculus@7924
   363
                    SDLVisualTest_EmptyActionQueue(queue);
icculus@7924
   364
                    SDL_RWclose(rw);
icculus@7924
   365
                    return 0;
icculus@7924
   366
                }
icculus@7924
   367
                SDL_strlcpy(args, token_ptr, len + 1);
icculus@7924
   368
            }
icculus@7924
   369
            else
icculus@7924
   370
                args = NULL;
icculus@7924
   371
icculus@7924
   372
            action.extra.process.path = path;
icculus@7924
   373
            action.extra.process.args = args;
icculus@7924
   374
        }
icculus@7924
   375
icculus@7924
   376
        /* add the action to the queue */
icculus@7924
   377
        if(!SDLVisualTest_EnqueueAction(queue, action))
icculus@7924
   378
        {
icculus@7924
   379
            SDLTest_LogError("SDLVisualTest_EnqueueAction() failed");
icculus@7924
   380
            if(action.type == SDL_ACTION_LAUNCH)
icculus@7924
   381
            {
icculus@7924
   382
                SDL_free(action.extra.process.path);
icculus@7924
   383
                if(action.extra.process.args)
icculus@7924
   384
                    SDL_free(action.extra.process.args);
icculus@7924
   385
            }
icculus@7924
   386
            SDLVisualTest_EmptyActionQueue(queue);
icculus@7924
   387
            SDL_RWclose(rw);
icculus@7924
   388
            return 0;
icculus@7924
   389
        }
icculus@7924
   390
    }
icculus@7924
   391
    /* sort the queue of actions */
icculus@7924
   392
    SortQueue(queue);
icculus@7924
   393
icculus@7924
   394
    SDL_RWclose(rw);
icculus@7924
   395
    return 1;
icculus@7924
   396
}