test/prop_tests.c

Sun, 29 Dec 2019 11:30:39 +0100

author
Mike Becker <universe@uap-core.de>
date
Sun, 29 Dec 2019 11:30:39 +0100
changeset 379
477404eb380e
parent 259
2f5dea574a75
permissions
-rw-r--r--

fix: index buffer in string replace was not freed

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS 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 COPYRIGHT HOLDER OR 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.
 */

#include "prop_tests.h"
#include <ucx/mempool.h>

UCX_TEST(test_ucx_properties_new) {
    UcxProperties *parser = ucx_properties_new();
    
    UCX_TEST_BEGIN
            
    UCX_TEST_ASSERT(parser != NULL, "failed");
    UCX_TEST_ASSERT(parser->buffer == NULL, "parser has buffer");
    UCX_TEST_ASSERT(parser->tmp == NULL, "parser has tmp buffer");
    
    UCX_TEST_END
            
    ucx_properties_free(parser);
}

UCX_TEST(test_ucx_properties_next) {  
    const char *tests[] = {
        "name = value\n",
        "name=value\n",
        "n=value\n",
        "name=v\n",
        "n=v\n",
        "name = value # comment\n",
        "#comment\nn=v\n",
        "# comment1\n# comment2\n\n    \n\nname = value\n",
        "    name     =      value\n",
        "name = value\n\n"
    };
    
    const char *names[] = {
        "name",
        "name",
        "n",
        "name",
        "n",
        "name",
        "n",
        "name",
        "name",
        "name"
    };
    
    const char *values[] = {
        "value",
        "value",
        "value",
        "v",
        "v",
        "value",
        "v",
        "value",
        "value",
        "value"
    };
    
    UCX_TEST_BEGIN
    
    sstr_t name;
    sstr_t value;
    
    for(int i=0;i<10;i++) {
        UcxProperties *parser = ucx_properties_new();
        
        ucx_properties_fill(parser, (char*)tests[i], strlen(tests[i]));
        UCX_TEST_ASSERT(parser->buffer == tests[i], "fill failed");
        UCX_TEST_ASSERT(parser->buflen == strlen(tests[i]), "wrong buflen");
        
        int r = ucx_properties_next(parser, &name, &value);
        sstr_t n = sstr((char*)names[i]);
        sstr_t v = sstr((char*)values[i]);
        UCX_TEST_ASSERT(r == 1, "next returned 0");
        UCX_TEST_ASSERT((!sstrcmp(name, n)), "wrong property name");
        UCX_TEST_ASSERT((!sstrcmp(value, v)), "wrong property value");
        
        r = ucx_properties_next(parser, &name, &value);
        UCX_TEST_ASSERT(r == 0, "next returned 1");
        UCX_TEST_ASSERT(parser->tmp == NULL, "tmp not NULL");
        UCX_TEST_ASSERT(parser->tmpcap == 0, "tmpcap not NULL");
        UCX_TEST_ASSERT(parser->tmplen == 0, "tmplen not NULL");
        
        ucx_properties_free(parser);
    }
    
    UCX_TEST_END       
}

UCX_TEST(test_ucx_properties_next_multi) {
    const char *names[] = {
        "a",
        "b",
        "c",
        "uap",
        "name",
        "key1",
        "key2",
        "key3"
    };
    
    const char *values[] = {
        "a value",
        "b value",
        "core",
        "core",
        "ucx",
        "value1",
        "value2",
        "value3"
    };
    
    const char *str = "#\n"
        "# properties\n"
        "# contains key/value pairs\n"
        "#\n"
        "a = a value\n"
        "b = b value\n"
        "c = core\n"
        "\n# test\n"
        "uap = core\n"
        "name = ucx\n"
        "# no = property\n"
        "key1 = value1\n"
        "#key1 = wrong value\n"
        "#key2 = not value 2\n"
        "key2 = value2\n"
        "\n\n\n        \n           key3=value3\n";
    
    UcxProperties *parser = ucx_properties_new();
    
    UCX_TEST_BEGIN
    
    ucx_properties_fill(parser, (char*)str, strlen(str));
    
    sstr_t name;
    sstr_t value;
    for(int i=0;i<8;i++) {
        int r = ucx_properties_next(parser, &name, &value);
        UCX_TEST_ASSERT(r == 1, "next returned 0");
        UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)names[i]))), "wrong name");
        UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)values[i]))),
                "wrong value");
    }
    int r = ucx_properties_next(parser, &name, &value);
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    UCX_TEST_END
    
    ucx_properties_free(parser);
}

UCX_TEST(test_ucx_properties_next_part) {
    UcxProperties *parser = ucx_properties_new();
    const char *str;
    int r;
    sstr_t name;
    sstr_t value;
    
    UCX_TEST_BEGIN
    
    str = "";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value);
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = "  \n";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = "name";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = "    ";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = "= ";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = "value";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = "\n";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 1, "next returned 0");
    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"name"))), "wrong name");
    UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"value"))), "wrong value");
    
    // second round
    str = "#comment\n";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = "#comment\nname = ";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = "value\na = b\n";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 1, "next returned 0");
    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"name"))), "wrong name");
    UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"value"))), "wrong value");
    
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 1, "next returned 0");
    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"a"))), "wrong name");
    UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"b"))), "wrong value");
    
    str = "# comment\n#\n#\ntests = ";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = "test1 ";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = "test2 test3 test4\n";
    sstr_t testv = sstr((char*)"test1 test2 test3 test4");
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 1, "next returned 0");
    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"tests"))), "wrong name");
    UCX_TEST_ASSERT((!sstrcmp(value, testv)), "wrong value");
    
    // test if ucx_properties_next finds a name/value after a tmp comment
    str = "# just a comment";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = " in 3";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = " parts\na = 1\n";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 1, "next returned 0");
    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"a"))), "wrong name");
    UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"1"))), "wrong value");
    
    UCX_TEST_END
    
    ucx_properties_free(parser);
}

UCX_TEST(test_ucx_properties_next_long) {
    UcxProperties *parser = ucx_properties_new();
    int r;
    size_t name_len = 512;
    char *long_name = (char*)malloc(name_len);
    memset(long_name, 'a', 70);
    memset(long_name+70, 'b', 242);
    memset(long_name+312, 'c', 200);
    
    size_t value_len = 2048;
    char *long_value = (char*)malloc(value_len);
    memset(long_value, 'x', 1024);
    memset(long_value+1024, 'y', 1024);
    
    UCX_TEST_BEGIN
    
    sstr_t name;
    sstr_t value;
    
    ucx_properties_fill(parser, long_name, 10);
    r = ucx_properties_next(parser, &name, &value);
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    ucx_properties_fill(parser, long_name+10, 202);
    r = ucx_properties_next(parser, &name, &value);
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    ucx_properties_fill(parser, long_name+212, 200);
    r = ucx_properties_next(parser, &name, &value);
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    ucx_properties_fill(parser, long_name+412, 100);
    r = ucx_properties_next(parser, &name, &value);
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    const char *str = " = ";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    r = ucx_properties_next(parser, &name, &value);
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    ucx_properties_fill(parser, long_value, 512);
    r = ucx_properties_next(parser, &name, &value); 
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    ucx_properties_fill(parser, long_value+512, 1024);
    r = ucx_properties_next(parser, &name, &value);
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    ucx_properties_fill(parser, long_value+1536, 512);
    r = ucx_properties_next(parser, &name, &value);
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    str = "\n#comment\nkey = value\n";
    ucx_properties_fill(parser, (char*)str, strlen(str));    
    r = ucx_properties_next(parser, &name, &value);
    sstr_t n = sstrn(long_name, name_len);
    sstr_t v = sstrn(long_value, value_len);
    UCX_TEST_ASSERT(r == 1, "next returned 0");
    UCX_TEST_ASSERT((!sstrcmp(name, n)), "wrong name");
    UCX_TEST_ASSERT((!sstrcmp(value, v)), "wrong value");
    
    r = ucx_properties_next(parser, &name, &value);
    UCX_TEST_ASSERT(r == 1, "next returned 0");
    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"key"))), "wrong name");
    UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"value"))), "wrong value");
    
    r = ucx_properties_next(parser, &name, &value);
    UCX_TEST_ASSERT(r == 0, "next returned 1");
    
    UCX_TEST_END
    
    free(long_name);
    free(long_value);
    ucx_properties_free(parser);
}

UCX_TEST(test_ucx_properties2map) {
    UcxMempool *mp = ucx_mempool_new(64);
    UcxMap *map = ucx_map_new_a(mp->allocator, 16);
    UcxProperties *parser = ucx_properties_new();
    
    UCX_TEST_BEGIN
    
    const char *str = "key1 = value1\nkey2 = value2\n\n#comment\n\nkey3 = value3\n";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    
    int r = ucx_properties2map(parser, map);
    
    UCX_TEST_ASSERT(r == 0, "properties2map failed");
    UCX_TEST_ASSERT(map->count == 3, "wrong number of properties");
    
    char *v1 = (char*)ucx_map_cstr_get(map, "key1");
    char *v2 = (char*)ucx_map_cstr_get(map, "key2");
    char *v3 = (char*)ucx_map_cstr_get(map, "key3");
    
    UCX_TEST_ASSERT(v1, "value for key1 not found");
    UCX_TEST_ASSERT(v2, "value for key2 not found");
    UCX_TEST_ASSERT(v3, "value for key3 not found");
    
    UCX_TEST_ASSERT((!strcmp(v1, "value1")), "wrong value for key1");
    UCX_TEST_ASSERT((!strcmp(v2, "value2")), "wrong value for key2");
    UCX_TEST_ASSERT((!strcmp(v3, "value3")), "wrong value for key3");
    
    // second test
    ucx_map_free(map);
    map = ucx_map_new_a(mp->allocator, 16);
    
    str = "\n#comment\n";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    
    r = ucx_properties2map(parser, map);
    UCX_TEST_ASSERT(r == 0, "properties2map failed");
    UCX_TEST_ASSERT(map->count == 0, "wrong number of properties");
    
    str = "key1 = value1\nsyntax error line\n";
    ucx_properties_fill(parser, (char*)str, strlen(str));
    
    r = ucx_properties2map(parser, map);
    UCX_TEST_ASSERT(r == 1, "properties2map should return 1");
    UCX_TEST_ASSERT(map->count == 1, "wrong number of properties");
    
    char *v = (char*)ucx_map_cstr_get(map, "key1");
    UCX_TEST_ASSERT((!strcmp(v, "value1")), "wrong value");
    
    UCX_TEST_END
    
    ucx_mempool_destroy(mp);
    ucx_properties_free(parser);
}

UCX_TEST(test_ucx_properties_load) { 
    UCX_TEST_BEGIN
    FILE *f = tmpfile();
    UCX_TEST_ASSERT(f, "test file cannot be opened, test aborted");
    
    fprintf(f, "# properties file\n\nkey1 = value1\nkey2 = value2\n");
    fprintf(f, "\n\nkey3    = value3\n\n");
    
    size_t name_len = 512;
    char *long_name = (char*)malloc(name_len);
    memset(long_name, 'k', 512);
    
    size_t value_len = 2048;
    char *long_value = (char*)malloc(value_len);
    memset(long_value, 'v', 2048);
    
    fwrite(long_name, 1, name_len, f);
    fprintf(f, "    =    ");
    fwrite(long_value, 1, value_len, f);
    fprintf(f, "                         \n");
    
    fprintf(f, "\n\n\n\nlast_key = property value\n");
    
    fflush(f);
    fseek(f, 0, SEEK_SET);
    
    UcxMap *map = ucx_map_new(8);
    int r = ucx_properties_load(map, f);
    
    UCX_TEST_ASSERT(r == 0, "ucx_properties_load failed");
    UCX_TEST_ASSERT(map->count == 5, "wrong number of properties");
    
    char *v1 = (char*)ucx_map_cstr_get(map, "key1");
    char *v2 = (char*)ucx_map_cstr_get(map, "key2");
    char *v3 = (char*)ucx_map_cstr_get(map, "key3");
    char *lv = (char*)ucx_map_sstr_get(map, sstrn(long_name, name_len));
    char *lk = (char*)ucx_map_cstr_get(map, "last_key");
    
    UCX_TEST_ASSERT(v1, "value for key1 not found");
    UCX_TEST_ASSERT(v2, "value for key2 not found");
    UCX_TEST_ASSERT(v3, "value for key3 not found");
    UCX_TEST_ASSERT(lv, "value for long key not found");
    UCX_TEST_ASSERT(lk, "value for last_key not found");
    
    UCX_TEST_ASSERT((!strcmp(v1, "value1")), "wrong value for key1");
    UCX_TEST_ASSERT((!strcmp(v2, "value2")), "wrong value for key2");
    UCX_TEST_ASSERT((!strcmp(v3, "value3")), "wrong value for key3");
    sstr_t long1 = sstrn(long_value, value_len);
    sstr_t long2 = sstr(lv);
    UCX_TEST_ASSERT((!sstrcmp(long1, long2)), "wrong value for long key");
    UCX_TEST_ASSERT(!strcmp(lk, "property value"), "wrong value for last_key");
    
    free(v1);
    free(v2);
    free(v3);
    free(lv);
    free(lk);
    ucx_map_free(map);
    fclose(f);
    
    free(long_name);
    free(long_value);
    
    UCX_TEST_END
}

UCX_TEST(test_ucx_properties_store) {
    UcxMap *map1 = ucx_map_new(16);
    ucx_map_cstr_put(map1, "key1", "value1");
    ucx_map_cstr_put(map1, "key2", "value2");
    ucx_map_cstr_put(map1, "key3", "value3");
    ucx_map_cstr_put(map1, "key4", "value4");
    ucx_map_cstr_put(map1, "property.key1", "some value 1");
    ucx_map_cstr_put(map1, "property.key2", "some value 2");
    ucx_map_cstr_put(map1, "property.key3", "some value 3");
    ucx_map_cstr_put(map1, "property.key4", "some value 4");
    
    UCX_TEST_BEGIN
    
    FILE *f = tmpfile();
    fprintf(f, "#\n# test property file\n#\n#\n");
    ucx_properties_store(map1, f);
    
    fflush(f);
    fseek(f, 0, SEEK_SET);
    UcxMap *map2 = ucx_map_new(16);
    ucx_properties_load(map2, f);
    
    UCX_TEST_ASSERT(map2->count == 8, "wrong number of properties in map2");
    
    char *v1 = (char*)ucx_map_cstr_get(map2, "key1");
    char *v2 = (char*)ucx_map_cstr_get(map2, "key2");
    char *v3 = (char*)ucx_map_cstr_get(map2, "key3");
    char *v4 = (char*)ucx_map_cstr_get(map2, "key4");
    char *v5 = (char*)ucx_map_cstr_get(map2, "property.key1");
    char *v6 = (char*)ucx_map_cstr_get(map2, "property.key2");
    char *v7 = (char*)ucx_map_cstr_get(map2, "property.key3");
    char *v8 = (char*)ucx_map_cstr_get(map2, "property.key4");
    
    UCX_TEST_ASSERT(v1 && v2 && v3 && v4 && v5 && v6 && v7 && v8,
            "missing values");
    
    UCX_TEST_ASSERT((!strcmp(v1, "value1")), "wrong value 1");
    UCX_TEST_ASSERT((!strcmp(v2, "value2")), "wrong value 2");
    UCX_TEST_ASSERT((!strcmp(v3, "value3")), "wrong value 3");
    UCX_TEST_ASSERT((!strcmp(v4, "value4")), "wrong value 4");
    UCX_TEST_ASSERT((!strcmp(v5, "some value 1")), "wrong value 5");
    UCX_TEST_ASSERT((!strcmp(v6, "some value 2")), "wrong value 6");
    UCX_TEST_ASSERT((!strcmp(v7, "some value 3")), "wrong value 7");
    UCX_TEST_ASSERT((!strcmp(v8, "some value 4")), "wrong value 8");
    
    free(v1);
    free(v2);
    free(v3);
    free(v4);
    free(v5);
    free(v6);
    free(v7);
    free(v8);
    ucx_map_free(map2);
    fclose(f);
    
    UCX_TEST_END
    
    ucx_map_free(map1);
}

mercurial