OSSP CVS Repository

ossp - ossp-pkg/var/var_test.c 1.40
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/var/var_test.c 1.40
/*
**  OSSP var -- Variable Expansion
**  Copyright (c) 2001-2002 The OSSP Project (http://www.ossp.org/)
**  Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/)
**
**  This file is part of OSSP var, a variable expansion
**  library which can be found at http://www.ossp.org/pkg/lib/var/.
**
**  Permission to use, copy, modify, and distribute this software for
**  any purpose with or without fee is hereby granted, provided that
**  the above copyright notice and this permission notice appear in all
**  copies.
**
**  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
**  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
**  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
**  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
**  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
**  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
**  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
**  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
**  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
**  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
**  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
**  SUCH DAMAGE.
**
**  var_test.c: library regression test.
*/

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>

#include "var.h"

static var_rc_t 
var_operation(
    var_t *var, void *ctx,
    const char  *op_ptr, size_t op_len,
    const char  *arg_ptr, size_t arg_len,
    const char  *val_ptr, size_t val_len,
    char **out_ptr, size_t *out_len, size_t *out_size)
{
    int i;

    fprintf(stderr, "op=<%s>(%d) arg=<%s>(%d) val=<%s>(%d)\n", 
            op_ptr, op_len, arg_ptr, arg_len, val_ptr, val_len);
    if (val_ptr == NULL) {
        *out_ptr = "";
        *out_len = 0;
        *out_size = 0;
        return VAR_OK;
    }
    if (op_len == 6 && strncmp(op_ptr, "return", 6) == 0) {
        *out_ptr = malloc(arg_len);
        *out_len = arg_len;
        *out_size = arg_len;
        memcpy(*out_ptr, arg_ptr, arg_len);
        return VAR_OK;
    }
    else if (op_len == 5 && strncmp(op_ptr, "upper", 5) == 0) {
        *out_ptr = malloc(val_len);
        *out_len = val_len;
        *out_size = val_len;
        for (i = 0; i < val_len; i++)
            (*out_ptr)[i] = (char)toupper((int)(val_ptr[i]));
        return VAR_OK;
    }
    else if (op_len == 5 && strncmp(op_ptr, "lower", 5) == 0) {
        *out_ptr = malloc(val_len);
        *out_len = val_len;
        *out_size = val_len;
        for (i = 0; i < val_len; i++)
            (*out_ptr)[i] = (char)tolower((int)(val_ptr[i]));
        return VAR_OK;
    }
    else 
        return VAR_ERR_UNDEFINED_OPERATION;
}

struct variable {
    const char *name;
    const unsigned int idx;
    const char *data;
};

static var_rc_t var_lookup(
    var_t *var, void *context,
    const char *varname, size_t name_len, int idx,
    const char **data, size_t *data_len,
    size_t *buffer_size)
{
    const struct variable *vars = context;
    size_t i, counter, length;
    static char buf[((sizeof(int)*8)/3)+10]; /* sufficient size: <#bits> x log_10(2) + safety */

    if (idx >= 0) {
        for (i = 0; vars[i].name; ++i) {
            if (strncmp(varname, vars[i].name, name_len) == 0 && vars[i].idx == idx) {
                *data = vars[i].data;
                *data_len = strlen(*data);
                *buffer_size = 0;
                return VAR_OK;
            }
        }
    }
    else {
        for (i = 0; vars[i].name; ++i) {
            if (strncmp(varname, vars[i].name, name_len) == 0) {
                counter = 1;
                length = strlen(vars[i].data);
                while (   vars[i + counter].data
                       && strncmp(varname, vars[i + counter].name, name_len) == 0)
                    counter++;
                if (counter == 1)
                    sprintf(buf, "%d", length);
                else
                    sprintf(buf, "%d", counter);
                *data = buf;
                *data_len = strlen(buf);
                *buffer_size = 0;
                return VAR_OK;
            }
        }
    }
    return VAR_ERR_UNDEFINED_VARIABLE;
}

struct test_case {
    const char *input;
    const char *expected;
};

int main(int argc, char **argv)
{
    const struct variable vars[] = {
        { "ARRAY",     0, "entry0" },
        { "ARRAY",     1, "entry1" },
        { "ARRAY",     2, "entry2" },
        { "ARRAY",     3, "entry3" },
        { "BAR",       0, "type" },
        { "EMPTY",     0, "" },
        { "FOO",       0, "os" },
        { "HEINZ",     0, "heinz0" },
        { "HEINZ",     1, "heinz1" },
        { "HOME",      0, "/home/regression-tests" },
        { "MULTILINE", 0, "line1\nline2\n" },
        { "NUMBER",    0, "+2" },
        { "NUMEXP",    0, "((16)%5)" },
        { "OSTYPE",    0, "regression-os" },
        { "TERM",      0, "regression-term" },
        { NULL,        0, NULL }
        };

    const struct test_case tests[] = {
        { "${HOME}${!!}",                 "/home/regression-tests${!!}"                    },
        { "$HOME",                        "/home/regression-tests"                         },
        { "${FOO}",                       "os"                                             },
        { "${BAR}",                       "type"                                           },
        { "${${FOO:u}${BAR:u}:l:u}",      "REGRESSION-OS"                                  },
        { "${UNDEFINED}",                 "${UNDEFINED}"                                   },
        { "${OSTYPE:#}",                  "13"                                             },
        { "${EMPTY:-test${FOO}test}",     "testostest"                                     },
        { "${EMPTY:-test${FOO:u}test}",   "testOStest"                                     },
        { "${TERM:-test${FOO}test}",      "regression-term"                                },
        { "${EMPTY:+FOO}",                ""                                               },
        { "${HOME:+test${FOO}test}",      "testostest"                                     },
        { "${HOME:+${OS${BAR:u}}}",       "regression-os"                                  },
        { "${HOME:+OS${UNDEFINED:u}}",    "OS${UNDEFINED:u}"                               },
        { "${UNDEFINED:+OS${BAR:u}}",     "${UNDEFINED:+OS${BAR:u}}"                       },
        { "${HOME:*heinz}",               ""                                               },
        { "${EMPTY:*claus}",              "claus"                                          },
        { "${TERM}",                      "regression-term"                                },
        { "${HOME:s/reg/bla/}",           "/home/blaression-tests"                         },
        { "${HOME:s/e/bla/}",             "/hombla/regression-tests"                       },
        { "${HOME:s/e/bla/g}",            "/hombla/rblagrblassion-tblasts"                 },
        { "${HOME:s/\\//_/g}",            "_home_regression-tests"                         },
        { "${HOME:s/[eso]/_/g}",          "/h_m_/r_gr___i_n-t__t_"                         },
        { "${HOME:s/[esO]/_/g}",          "/hom_/r_gr___ion-t__t_"                         },
        { "${HOME:s/[esO]/_/gi}",         "/h_m_/r_gr___i_n-t__t_"                         },
        { "${OSTYPE:s/^[re]/_/g}",        "_egression-os"                                  },
        { "${EMPTY:s/^[re]/_/g}",         ""                                               },
        { "${HOME:s/.*\\x{}/heinz/}",     "heinz"                                          },
        { "${HOME:s/e/bla/t}",            "/hombla/regression-tests"                       },
        { "${HOME:s/E/bla/t}",            "/home/regression-tests"                         },
        { "${HOME:s/E/bla/ti}",           "/hombla/regression-tests"                       },
        { "${HOME:s/E/bla/tig}",          "/hombla/rblagrblassion-tblasts"                 },
        { "${HOME:s/^(.*)$/<\\1>/}",      "</home/regression-tests>"                       },
        { "${HOME:o1-5}",                 "home/"                                          },
        { "${HOME:o1,5}",                 "home/"                                          },
        { "${HOME:o5,}",                  "/regression-tests"                              },
        { "${HOME:o5-}",                  "/regression-tests"                              },
        { "${HOME:o7,13}",                "egressi"                                        },
        { "${HOME:y/a-z/A-YZ/}",          "/HOME/REGRESSION-TESTS"                         },
        { "${HOME:y/e-g/a-c/}",           "/homa/racrassion-tasts"                         },
        { "${FOO:p/15/../l}",             "os............."                                },
        { "${FOO:p/15/12345/l}",          "os1234512345123"                                },
        { "${FOO:p/15/../r}",             ".............os"                                },
        { "${FOO:p/15/12345/r}",          "1234512345123os"                                },
        { "${FOO:p/15/../c}",             "......os......."                                },
        { "${FOO:p/15/12345/c}",          "123451os1234512"                                },
        { "${FOO:s/os/\\x{4F}\\123/g}",   "OS"                                             },
        { "${FOO:s/os/\\1\\x4F\\123/t}",  "\\1OS"                                          },
        { "${HOME:s/g(res)s/x\\1x/g}",    "/home/rexresxion-tests"                         },
        { "${HOME:s/(s+)/_\\1_/g}",       "/home/regre_ss_ion-te_s_t_s_"                   },
        { "${HOME:s/\\x65/\\x45/g}",      "/homE/rEgrEssion-tEsts"                         },
        { "${HOME:s/(s*)/x\\1X/g}",       "xX/xXhxXoxXmxXexX/xXrxXexXgxXrxXexssXxXixXoxXnxX-xXtxXexsXxXtxsX" },
        { "${HOME:s/./\\\\/g}",           "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"   },
        { "${ARRAY[1]}",                  "entry1",                                        },
        { "${ARRAY[5+4*2-1]}",            "${ARRAY[5+4*2-1]}",                             },
        { "${ARRAY[(5+(3+4)*2)%16]}",     "entry3",                                        },
        { "${ARRAY[(5+(3+4)*2)/9]}",      "entry2",                                        },
        { "${ARRAY[+1--2]}",              "entry3"                                         },
        { "${ARRAY[-1]}",                 "4"                                              },
        { "${HOME[-1]}",                  "22"                                             },
        { "${ARRAY[$NUMBER]}",            "entry2"                                         },
        { "${ARRAY[$NUMEXP]}",            "entry1"                                         },
        { "${ARRAY[$NUMEXP-1]}",          "entry0"                                         },
        { "${ARRAY[${UNDEFINED}-1]}",     "${ARRAY[${UNDEFINED}-1]}"                       },
        { "${ARRAY[5/(${UNDEFINED})]}",   "${ARRAY[5/(${UNDEFINED})]}"                     },
        { "[${ARRAY[#]}-]",               "entry0-entry1-entry2-entry3-"                   },
        { "[${ARRAY[#+1]}-]",             "entry1-entry2-entry3-"                          },
        { "-[${ARRAY[#]}:]{1,$NUMBER}-",  "-entry1:entry2:-"                               },
        { "-[${ARRAY[#]}:]{1,3,5}-",      "-entry1::-"                                     },
        { "${MULTILINE:s/^/ | /g}",       " | line1\n | line2\n"                           },
        { "${HOME:%upper}",               "/HOME/REGRESSION-TESTS"                         },
        { "${HOME:%upper:%lower}",        "/home/regression-tests"                         },
        { "${EMPTY:%return($HOME)}",      "/home/regression-tests"                         },
        {
        "[${ARRAY}:${ARRAY[#]}-]",
        "entry0:entry0-entry0:entry1-entry0:entry2-entry0:entry3-"
        },
        {
        "[${HEINZ[#]}:${ARRAY[#]}-]",
        "heinz0:entry0-heinz1:entry1-:entry2-:entry3-"
        },
        {
        "[${HEINZ[#]}:[${ARRAY[#]}] ]",
        "heinz0:entry0entry1entry2entry3 heinz1:entry0entry1entry2entry3 "
        },
        {
        "[${HEINZ[#]}: [${ARRAY[#]}${ARRAY[#+1]:+, }]${HEINZ[#+1]:+; }]",
        "heinz0: entry0, entry1, entry2, entry3; heinz1: entry0, entry1, entry2, entry3"
        },
        {
        "[${ARRAY[#]}:[${ARRAY[#]},]{1,2,} ]{0,2,}",
        "entry0:entry1,entry3, entry2:entry1,entry3, "
        },
    };
    char *tmp;
    size_t tmp_len;
    var_rc_t rc;
    size_t i;
    char buffer[1024];
    var_t *var;
    char *err;

    if ((rc = var_create(&var)) != VAR_OK) {
        var_strerror(NULL, rc, &err);
        printf("unable to create variable expansion context: %s (%d)\n", err, rc);
        return 1;
    }
    if ((rc = var_config(var, VAR_CONFIG_CB_VALUE, var_lookup, vars)) != VAR_OK) {
        var_strerror(NULL, rc, &err);
        printf("unable to configure variable expansion context: %s (%d)\n", err, rc);
        return 1;
    }
    if ((rc = var_config(var, VAR_CONFIG_CB_OPERATION, var_operation, NULL)) != VAR_OK) {
        var_strerror(NULL, rc, &err);
        printf("unable to configure variable expansion context: %s (%d)\n", err, rc);
        return 1;
    }

    for (i = 0; i < sizeof(tests)/sizeof(struct test_case); ++i) {
        printf("Test case #%02d: Original input is '%s'.\n", i,
               tests[i].input);
        rc = var_unescape(var, tests[i].input, strlen(tests[i].input), buffer, sizeof(buffer), 0);
        if (rc != VAR_OK) {
            var_strerror(var, rc, &err);
            printf("Test case #%d: var_unescape() failed: %s (%d)\n", i, err, rc);
            return 1;
        }
        printf("Test case #%02d: Unescaped input is '%s'.\n", i, buffer);
        rc = var_expand(var, buffer, strlen(buffer), &tmp, &tmp_len, 0);
        if (rc != VAR_OK) {
            var_strerror(var, rc, &err);
            printf("Test case #%d: var_expand() failed: %s (%d).\n", i, err, rc);
            return 1;
        }
        printf("Test case #%02d: Expanded output is '%s'.\n", i, tmp);
        if (   tmp_len != strlen(tests[i].expected)
            || tmp == NULL
            || memcmp(tests[i].expected, tmp, tmp_len) != 0) {
            printf("Test case #%d: Expected result '%s' but got '%s'.\n",
                   i, tests[i].expected, tmp);
            return 1;
        }
        free(tmp);
    }
    var_destroy(var);
    return 0;
}


CVSTrac 2.0.1