aboutsummaryrefslogtreecommitdiff
path: root/tests/test_config_read.c
blob: 55c428f04fe9bd98a33ee278834f78129bcb1cfd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "spm.h"
#include "framework.h"

const char *mockConfig[] = {
        (const char *){"\n"  // empty line
         "; comment_semicolon\n"
         "# comment_hash\n"
         "string_unquoted = unquoted string\n"
         "string_quoted = \"quoted string\"\n"
         "inline_comment_semicolon = inline semicolon comment ; inline_comment_semicolon\n"
         "inline_comment_hash = inline hash comment # inline_comment_hash\n"
         "whitespace = \t    ignored\t          \n"
         "integer = 1\n"
         "decimal = 1.0\n"
         ""},
        (const char *){
            "oh\n"
            "no\n"
            "=\n"
            "extreme failure\n",
        },
        NULL, // end
};

#define SETARG_UINT(ARGINDEX, VALUE) .arg[ARGINDEX].unsigned_int = VALUE
#define GETARG_UINT(CASE, ARGINDEX) CASE.arg[ARGINDEX].unsigned_int

const char *testFmt = "case '%s': returned '%s', expected '%s'\n";
const char *testSizesFmt = "case '%s': returned '%zu', expected '%zu'\n";
struct TestCase testCase[] = {
    {.caseValue.sptr = "string_unquoted", .truthValue.sptr = "unquoted string", SETARG_UINT(0, 15), SETARG_UINT(1, 15)},
    {.caseValue.sptr = "string_quoted", .truthValue.sptr = "quoted string", SETARG_UINT(0, 13), SETARG_UINT(1, 13)},
    {.caseValue.sptr = "inline_comment_semicolon", .truthValue.sptr = "inline semicolon comment", SETARG_UINT(0, 24), SETARG_UINT(1, 24)},
    {.caseValue.sptr = "inline_comment_hash", .truthValue.sptr = "inline hash comment", SETARG_UINT(0, 19), SETARG_UINT(1, 19)},
    {.caseValue.sptr = "whitespace", .truthValue.sptr = "ignored", SETARG_UINT(0, 10), SETARG_UINT(1, 7)},
    {.caseValue.sptr = "integer", .truthValue.sptr = "1", SETARG_UINT(0, 7), SETARG_UINT(1, 1)},
    {.caseValue.sptr = "decimal", .truthValue.sptr = "1.0", SETARG_UINT(0, 7), SETARG_UINT(1, 3)},
    {.caseValue.sptr = "missing", .truthValue.sptr = NULL, SETARG_UINT(0, 0), SETARG_UINT(1, 0)},
};
size_t numCases = sizeof(testCase) / sizeof(struct TestCase);

int main(int argc, char *argv[]) {
    ConfigItem **config = NULL;
    char filename[NAME_MAX];

    memset(filename, '\0', sizeof(filename));
    sprintf(filename, "%s.%s.mock", basename(__FILE__), __FUNCTION__);

    mock(filename, (void *) mockConfig[0], sizeof(char), strlen(mockConfig[0]));
    config = config_read(filename);

    for (size_t i = 0; i < numCases; i++) {
        ConfigItem *item = NULL;
        const char *caseValue = testCase[i].caseValue.sptr;
        const char *truthValue = testCase[i].truthValue.sptr;

        item = config_get(config, caseValue);
        if (testCase[i].truthValue.sptr == NULL) {
            myassert(item == NULL, "item was not NULL\n");
            continue;
        }
        myassert(strcmp(caseValue, item->key) == 0, testFmt, caseValue, item->key, caseValue);
        myassert(strcmp(truthValue, item->value) == 0, testFmt, caseValue, item->value, truthValue);
        myassert(GETARG_UINT(testCase[i], 0) == item->key_length, testSizesFmt, caseValue, item->key_length, GETARG_UINT(testCase[i], 0));
        myassert(GETARG_UINT(testCase[i], 1) == item->value_length, testSizesFmt, caseValue, item->value_length, GETARG_UINT(testCase[i], 1));
    }

    config_free(config);
    unlink(filename);

    // Now throw some bad input data at it
    mock(filename, (void *) mockConfig[1], sizeof(char), strlen(mockConfig[1]));
    config = config_read(filename);
    myassert(config == NULL, "input data was invalid and config_read(\"%s\") did not return NULL.", filename);

    config_free(config);
    unlink(filename);

    return 0;
}