提交 85023c97 编写于 作者: E Emmanuel Leblond

Merge version 4

上级 682ec92a
......@@ -4,8 +4,13 @@
# Compiler settings
CC ?= gcc
CFLAGS ?= -O2
CFLAGS += -fPIC -Wall -ansi -std=c99 -pedantic
CFLAGS += -fPIC -Wall -Wextra -ansi -pedantic
ifndef DEBUG
CFLAGS += -O2
else
CFLAGS += -g
endif
# Ar settings to build the library
AR ?= ar
......@@ -57,16 +62,20 @@ libiniparser.so: $(OBJS)
clean:
$(RM) $(OBJS)
@(cd test ; $(MAKE) clean)
veryclean:
$(RM) $(OBJS) libiniparser.a libiniparser.so*
rm -rf ./html ; mkdir html
cd example ; $(MAKE) veryclean
cd test ; $(MAKE) veryclean
docs:
@(cd doc ; $(MAKE))
check: default
check: libiniparser.so
@(cd test ; $(MAKE))
.PHONY: default clean veryclean docs check
.PHONY: example
example: libiniparser.a
@(cd example ; $(MAKE))
Welcome to iniParser -- version 3.2
released 16 May 2015
This modules offers parsing of ini files from the C level.
See a complete documentation in HTML format, from this directory
open the file html/index.html with any HTML-capable browser.
Enjoy!
N.Devillard
[![Build Status](https://travis-ci.org/touilleMan/iniparser4.svg?branch=master)](https://travis-ci.org/touilleMan/iniparser4)
# Iniparser 4 #
## I - Overview
This modules offers parsing of ini files from the C level.
See a complete documentation in HTML format, from this directory
open the file html/index.html with any HTML-capable browser.
Key features :
- Small : around 1500 sloc inside 4 files (2 .c and 2 .h)
- Portable : no dependancies, written in `-ansi -pedantic` C89
- Fully reintrant : easy to make it thread-safe (just surround
library calls by mutex)
## II - Building project
A simple `make` at the root of the project should be enough to get the static
(i.e. `libiniparser.a`) and shared (i.e. `libiniparser.so.0`) libraries compiled.
You should consider trying the following rules too :
- `make check` : run the unitary tests
- `make example` : compile the example, run it with `./example/iniexample`
## III - License
This software is released under MIT License.
See LICENSE for full informations
## IV - Versions
Current version is 4.0 which introduces breaking changes in the api.
Older versions 3.1 and 3.2 with the legacy api are available as tags.
PROJECT_NAME = iniparser
PROJECT_NUMBER = 3.2
PROJECT_NUMBER = 4.0
OUTPUT_DIRECTORY = ..
OUTPUT_LANGUAGE = English
EXTRACT_ALL = YES
......
#
# iniparser tests Makefile
#
CC = gcc
CFLAGS = -g -I../src
LFLAGS = -L.. -liniparser
AR = ar
ARFLAGS = rcv
RM = rm -f
default: all
all: iniexample parse
iniexample: iniexample.c
$(CC) $(CFLAGS) -o iniexample iniexample.c -I../src -L.. -liniparser
parse: parse.c
$(CC) $(CFLAGS) -o parse parse.c -I../src -L.. -liniparser
clean veryclean:
$(RM) iniexample example.ini parse
......@@ -25,7 +25,11 @@ void create_example_ini_file(void)
{
FILE * ini ;
ini = fopen("example.ini", "w");
if ((ini=fopen("example.ini", "w"))==NULL) {
fprintf(stderr, "iniparser: cannot create example.ini\n");
return ;
}
fprintf(ini,
"#\n"
"# This is an example of ini file\n"
......@@ -58,7 +62,7 @@ int parse_ini_file(char * ini_name)
int b ;
int i ;
double d ;
char * s ;
const char * s ;
ini = iniparser_load(ini_name);
if (ini==NULL) {
......
......@@ -18,10 +18,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#else
#include <unistd.h>
#endif
/** Maximum value size for integers and doubles. */
#define MAXVALSZ 1024
......@@ -36,21 +33,6 @@
Private functions
---------------------------------------------------------------------------*/
/* Doubles the allocated size associated to a pointer */
/* 'size' is the current allocated size. */
static void * mem_double(void * ptr, size_t size)
{
void * newptr ;
newptr = calloc(2*size, 1);
if (newptr==NULL) {
return NULL ;
}
memcpy(newptr, ptr, size);
free(ptr);
return newptr ;
}
/*-------------------------------------------------------------------------*/
/**
@brief Duplicate a string
......@@ -61,7 +43,7 @@ static void * mem_double(void * ptr, size_t size)
for systems that do not have it.
*/
/*--------------------------------------------------------------------------*/
char * xstrdup(const char * s)
static char * xstrdup(const char * s)
{
char * t ;
size_t len ;
......@@ -69,13 +51,55 @@ char * xstrdup(const char * s)
return NULL ;
len = strlen(s) + 1 ;
t = malloc(len) ;
t = (char*) malloc(len) ;
if (t) {
memcpy(t, s, len) ;
}
return t ;
}
/*-------------------------------------------------------------------------*/
/**
@brief Double the size of the dictionary
@param d Dictionary to grow
@return This function returns non-zero in case of failure
*/
/*--------------------------------------------------------------------------*/
static int dictionary_grow(dictionary * d)
{
char ** new_val ;
char ** new_key ;
unsigned * new_hash ;
new_val = (char**) calloc(d->size * 2, sizeof *d->val);
new_key = (char**) calloc(d->size * 2, sizeof *d->key);
new_hash = (unsigned*) calloc(d->size * 2, sizeof *d->hash);
if (!new_val || !new_key || !new_hash) {
/* An allocation failed, leave the dictionary unchanged */
if (new_val)
free(new_val);
if (new_key)
free(new_key);
if (new_hash)
free(new_hash);
return -1 ;
}
/* Initialize the newly allocated space */
memcpy(new_val, d->val, d->size * sizeof(char *));
memcpy(new_key, d->key, d->size * sizeof(char *));
memcpy(new_hash, d->hash, d->size * sizeof(unsigned));
/* Delete previous data */
free(d->val);
free(d->key);
free(d->hash);
/* Actually update the dictionary */
d->size *= 2 ;
d->val = new_val;
d->key = new_key;
d->hash = new_hash;
return 0 ;
}
/*---------------------------------------------------------------------------
Function codes
---------------------------------------------------------------------------*/
......@@ -97,6 +121,9 @@ unsigned dictionary_hash(const char * key)
unsigned hash ;
size_t i ;
if (!key)
return 0 ;
len = strlen(key);
for (hash=0, i=0 ; i<len ; i++) {
hash += (unsigned)key[i] ;
......@@ -119,7 +146,7 @@ unsigned dictionary_hash(const char * key)
it. If you do not know in advance (roughly) the number of entries in the
dictionary, give size=0.
*/
/*--------------------------------------------------------------------------*/
/*----------CCC----------------------------------------------------------------*/
dictionary * dictionary_new(size_t size)
{
dictionary * d ;
......@@ -127,13 +154,13 @@ dictionary * dictionary_new(size_t size)
/* If no size was specified, allocate space for DICTMINSZ */
if (size<DICTMINSZ) size=DICTMINSZ ;
d = calloc(1, sizeof *d) ;
d = (dictionary*) calloc(1, sizeof *d) ;
if (d) {
d->size = size ;
d->val = calloc(size, sizeof *d->val);
d->key = calloc(size, sizeof *d->key);
d->hash = calloc(size, sizeof *d->hash);
d->val = (char**) calloc(size, sizeof *d->val);
d->key = (char**) calloc(size, sizeof *d->key);
d->hash = (unsigned*) calloc(size, sizeof *d->hash);
}
return d ;
}
......@@ -149,10 +176,10 @@ dictionary * dictionary_new(size_t size)
/*--------------------------------------------------------------------------*/
void dictionary_del(dictionary * d)
{
size_t i ;
ssize_t i ;
if (d==NULL) return ;
for (i=0 ; i< (size_t)d->size ; i++) {
for (i=0 ; i<d->size ; i++) {
if (d->key[i]!=NULL)
free(d->key[i]);
if (d->val[i]!=NULL)
......@@ -179,13 +206,13 @@ void dictionary_del(dictionary * d)
dictionary object, you should not try to free it or modify it.
*/
/*--------------------------------------------------------------------------*/
char * dictionary_get(dictionary * d, const char * key, char * def)
const char * dictionary_get(const dictionary * d, const char * key, const char * def)
{
unsigned hash ;
size_t i ;
ssize_t i ;
hash = dictionary_hash(key);
for (i=0 ; i<(size_t)d->size ; i++) {
for (i=0 ; i<d->size ; i++) {
if (d->key[i]==NULL)
continue ;
/* Compare hash */
......@@ -227,8 +254,8 @@ char * dictionary_get(dictionary * d, const char * key, char * def)
/*--------------------------------------------------------------------------*/
int dictionary_set(dictionary * d, const char * key, const char * val)
{
size_t i ;
unsigned hash ;
ssize_t i ;
unsigned hash ;
if (d==NULL || key==NULL) return -1 ;
......@@ -236,7 +263,7 @@ int dictionary_set(dictionary * d, const char * key, const char * val)
hash = dictionary_hash(key) ;
/* Find if value is already in dictionary */
if (d->n>0) {
for (i=0 ; i<(size_t)d->size ; i++) {
for (i=0 ; i<d->size ; i++) {
if (d->key[i]==NULL)
continue ;
if (hash==d->hash[i]) { /* Same hash value */
......@@ -244,7 +271,7 @@ int dictionary_set(dictionary * d, const char * key, const char * val)
/* Found a value: modify and return */
if (d->val[i]!=NULL)
free(d->val[i]);
d->val[i] = val ? xstrdup(val) : NULL ;
d->val[i] = (val ? xstrdup(val) : NULL);
/* Value has been modified: return */
return 0 ;
}
......@@ -254,17 +281,9 @@ int dictionary_set(dictionary * d, const char * key, const char * val)
/* Add a new value */
/* See if dictionary needs to grow */
if (d->n==d->size) {
/* Reached maximum size: reallocate dictionary */
d->val = mem_double(d->val, d->size * sizeof *d->val) ;
d->key = mem_double(d->key, d->size * sizeof *d->key) ;
d->hash = mem_double(d->hash, d->size * sizeof *d->hash) ;
if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) {
/* Cannot grow dictionary */
return -1 ;
}
/* Double size */
d->size *= 2 ;
if (dictionary_grow(d) != 0)
return -1;
}
/* Insert key in the first empty slot. Start at d->n and wrap at
......@@ -275,7 +294,7 @@ int dictionary_set(dictionary * d, const char * key, const char * val)
}
/* Copy key */
d->key[i] = xstrdup(key);
d->val[i] = val ? xstrdup(val) : NULL ;
d->val[i] = (val ? xstrdup(val) : NULL) ;
d->hash[i] = hash;
d->n ++ ;
return 0 ;
......@@ -295,14 +314,14 @@ int dictionary_set(dictionary * d, const char * key, const char * val)
void dictionary_unset(dictionary * d, const char * key)
{
unsigned hash ;
size_t i ;
ssize_t i ;
if (key == NULL) {
if (key == NULL || d == NULL) {
return;
}
hash = dictionary_hash(key);
for (i=0 ; i<(size_t)d->size ; i++) {
for (i=0 ; i<d->size ; i++) {
if (d->key[i]==NULL)
continue ;
/* Compare hash */
......@@ -314,7 +333,7 @@ void dictionary_unset(dictionary * d, const char * key)
}
}
}
if (i>=(size_t)d->size)
if (i>=d->size)
/* Key not found */
return ;
......@@ -341,16 +360,16 @@ void dictionary_unset(dictionary * d, const char * key)
output file pointers.
*/
/*--------------------------------------------------------------------------*/
void dictionary_dump(dictionary * d, FILE * out)
void dictionary_dump(const dictionary * d, FILE * out)
{
size_t i ;
ssize_t i ;
if (d==NULL || out==NULL) return ;
if (d->n<1) {
fprintf(out, "empty dictionary\n");
return ;
}
for (i=0 ; i<(size_t)d->size ; i++) {
for (i=0 ; i<d->size ; i++) {
if (d->key[i]) {
fprintf(out, "%20s\t[%s]\n",
d->key[i],
......@@ -359,47 +378,3 @@ void dictionary_dump(dictionary * d, FILE * out)
}
return ;
}
/* Test code */
#ifdef TESTDIC
#define NVALS 20000
int main(int argc, char *argv[])
{
dictionary * d ;
char * val ;
int i ;
char cval[90] ;
/* Allocate dictionary */
printf("allocating...\n");
d = dictionary_new(0);
/* Set values in dictionary */
printf("setting %d values...\n", NVALS);
for (i=0 ; i<NVALS ; i++) {
sprintf(cval, "%04d", i);
dictionary_set(d, cval, "salut");
}
printf("getting %d values...\n", NVALS);
for (i=0 ; i<NVALS ; i++) {
sprintf(cval, "%04d", i);
val = dictionary_get(d, cval, DICT_INVALID_KEY);
if (val==DICT_INVALID_KEY) {
printf("cannot get value for key [%s]\n", cval);
}
}
printf("unsetting %d values...\n", NVALS);
for (i=0 ; i<NVALS ; i++) {
sprintf(cval, "%04d", i);
dictionary_unset(d, cval);
}
if (d->n != 0) {
printf("error deleting values\n");
}
printf("deallocating...\n");
dictionary_del(d);
return 0 ;
}
#endif
/* vim: set ts=4 et sw=4 tw=75 */
......@@ -21,11 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#else
#include <unistd.h>
#endif
#ifdef __cplusplus
extern "C" {
......@@ -48,7 +44,7 @@ extern "C" {
/*-------------------------------------------------------------------------*/
typedef struct _dictionary_ {
int n ; /** Number of entries in dictionary */
int size ; /** Storage size */
ssize_t size ; /** Storage size */
char ** val ; /** List of string values */
char ** key ; /** List of string keys */
unsigned * hash ; /** List of hash values for keys */
......@@ -111,7 +107,7 @@ void dictionary_del(dictionary * vd);
dictionary object, you should not try to free it or modify it.
*/
/*--------------------------------------------------------------------------*/
char * dictionary_get(dictionary * d, const char * key, char * def);
const char * dictionary_get(const dictionary * d, const char * key, const char * def);
/*-------------------------------------------------------------------------*/
......@@ -168,19 +164,7 @@ void dictionary_unset(dictionary * d, const char * key);
output file pointers.
*/
/*--------------------------------------------------------------------------*/
void dictionary_dump(dictionary * d, FILE * out);
/*-------------------------------------------------------------------------*/
/**
@brief Duplicate a string
@param s String to duplicate
@return Pointer to a newly allocated string, to be freed with free()
This is a replacement for strdup(). This implementation is provided
for systems that do not have it.
*/
/*--------------------------------------------------------------------------*/
char * xstrdup(const char * s);
void dictionary_dump(const dictionary * d, FILE * out);
#ifdef __cplusplus
}
......
此差异已折叠。
......@@ -50,7 +50,7 @@ extern "C" {
*/
/*--------------------------------------------------------------------------*/
int iniparser_getnsec(dictionary * d);
int iniparser_getnsec(const dictionary * d);
/*-------------------------------------------------------------------------*/
......@@ -68,7 +68,7 @@ int iniparser_getnsec(dictionary * d);
*/
/*--------------------------------------------------------------------------*/
char * iniparser_getsecname(dictionary * d, int n);
const char * iniparser_getsecname(const dictionary * d, int n);
/*-------------------------------------------------------------------------*/
......@@ -83,7 +83,7 @@ char * iniparser_getsecname(dictionary * d, int n);
*/
/*--------------------------------------------------------------------------*/
void iniparser_dump_ini(dictionary * d, FILE * f);
void iniparser_dump_ini(const dictionary * d, FILE * f);
/*-------------------------------------------------------------------------*/
/**
......@@ -98,7 +98,7 @@ void iniparser_dump_ini(dictionary * d, FILE * f);
*/
/*--------------------------------------------------------------------------*/
void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f);
void iniparser_dumpsection_ini(const dictionary * d, const char * s, FILE * f);
/*-------------------------------------------------------------------------*/
/**
......@@ -113,7 +113,7 @@ void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f);
purposes mostly.
*/
/*--------------------------------------------------------------------------*/
void iniparser_dump(dictionary * d, FILE * f);
void iniparser_dump(const dictionary * d, FILE * f);
/*-------------------------------------------------------------------------*/
/**
......@@ -123,7 +123,7 @@ void iniparser_dump(dictionary * d, FILE * f);
@return Number of keys in section
*/
/*--------------------------------------------------------------------------*/
int iniparser_getsecnkeys(dictionary * d, char * s);
int iniparser_getsecnkeys(const dictionary * d, const char * s);
/*-------------------------------------------------------------------------*/
/**
......@@ -133,13 +133,15 @@ int iniparser_getsecnkeys(dictionary * d, char * s);
@return pointer to statically allocated character strings
This function queries a dictionary and finds all keys in a given section.
The returned pointer is obtained with malloc(3), and can be freed
with free(3).
Each pointer in the returned char pointer-to-pointer is pointing to
a string allocated in the dictionary; do not free or modify them.
This function returns NULL in case of error.
*/
/*--------------------------------------------------------------------------*/
char ** iniparser_getseckeys(dictionary * d, char * s);
const char ** iniparser_getseckeys(const dictionary * d, const char * s);
/*-------------------------------------------------------------------------*/
/**
......@@ -156,7 +158,7 @@ char ** iniparser_getseckeys(dictionary * d, char * s);
the dictionary, do not free or modify it.
*/
/*--------------------------------------------------------------------------*/
char * iniparser_getstring(dictionary * d, const char * key, char * def);
const char * iniparser_getstring(const dictionary * d, const char * key, const char * def);
/*-------------------------------------------------------------------------*/
/**
......@@ -185,7 +187,7 @@ char * iniparser_getstring(dictionary * d, const char * key, char * def);
Credits: Thanks to A. Becker for suggesting strtol()
*/
/*--------------------------------------------------------------------------*/
int iniparser_getint(dictionary * d, const char * key, int notfound);
int iniparser_getint(const dictionary * d, const char * key, int notfound);
/*-------------------------------------------------------------------------*/
/**
......@@ -200,7 +202,7 @@ int iniparser_getint(dictionary * d, const char * key, int notfound);
the notfound value is returned.
*/
/*--------------------------------------------------------------------------*/
double iniparser_getdouble(dictionary * d, const char * key, double notfound);
double iniparser_getdouble(const dictionary * d, const char * key, double notfound);
/*-------------------------------------------------------------------------*/
/**
......@@ -234,7 +236,7 @@ double iniparser_getdouble(dictionary * d, const char * key, double notfound);
necessarily have to be 0 or 1.
*/
/*--------------------------------------------------------------------------*/
int iniparser_getboolean(dictionary * d, const char * key, int notfound);
int iniparser_getboolean(const dictionary * d, const char * key, int notfound);
/*-------------------------------------------------------------------------*/
......@@ -243,10 +245,10 @@ int iniparser_getboolean(dictionary * d, const char * key, int notfound);
@param ini Dictionary to modify.
@param entry Entry to modify (entry name)
@param val New value to associate to the entry.
@return int 0 if Ok, -1 otherwise.
@return int 0 if Ok, -1 otherwise.
If the given entry can be found in the dictionary, it is modified to
contain the provided value. If it cannot be found, -1 is returned.
contain the provided value. If it cannot be found, the entry is created.
It is Ok to set val to NULL.
*/
/*--------------------------------------------------------------------------*/
......@@ -277,7 +279,7 @@ void iniparser_unset(dictionary * ini, const char * entry);
of querying for the presence of sections in a dictionary.
*/
/*--------------------------------------------------------------------------*/
int iniparser_find_entry(dictionary * ini, const char * entry) ;
int iniparser_find_entry(const dictionary * ini, const char * entry) ;
/*-------------------------------------------------------------------------*/
/**
......
#include <assert.h>
#include <setjmp.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "CuTest.h"
/*-------------------------------------------------------------------------*
* CuStr
*-------------------------------------------------------------------------*/
char* CuStrAlloc(int size)
{
char* newStr = (char*) malloc( sizeof(char) * (size) );
return newStr;
}
char* CuStrCopy(const char* old)
{
int len = strlen(old);
char* newStr = CuStrAlloc(len + 1);
strcpy(newStr, old);
return newStr;
}
/*-------------------------------------------------------------------------*
* CuString
*-------------------------------------------------------------------------*/
void CuStringInit(CuString* str)
{
str->length = 0;
str->size = STRING_MAX;
str->buffer = (char*) malloc(sizeof(char) * str->size);
str->buffer[0] = '\0';
}
CuString* CuStringNew(void)
{
CuString* str = (CuString*) malloc(sizeof(CuString));
str->length = 0;
str->size = STRING_MAX;
str->buffer = (char*) malloc(sizeof(char) * str->size);
str->buffer[0] = '\0';
return str;
}
void CuStringDelete(CuString *str)
{
if (!str) return;
free(str->buffer);
free(str);
}
void CuStringResize(CuString* str, int newSize)
{
str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize);
str->size = newSize;
}
void CuStringAppend(CuString* str, const char* text)
{
int length;
if (text == NULL) {
text = "NULL";
}
length = strlen(text);
if (str->length + length + 1 >= str->size)
CuStringResize(str, str->length + length + 1 + STRING_INC);
str->length += length;
strcat(str->buffer, text);
}
void CuStringAppendChar(CuString* str, char ch)
{
char text[2];
text[0] = ch;
text[1] = '\0';
CuStringAppend(str, text);
}
void CuStringAppendFormat(CuString* str, const char* format, ...)
{
va_list argp;
char buf[HUGE_STRING_LEN];
va_start(argp, format);
vsprintf(buf, format, argp);
va_end(argp);
CuStringAppend(str, buf);
}
void CuStringInsert(CuString* str, const char* text, int pos)
{
int length = strlen(text);
if (pos > str->length)
pos = str->length;
if (str->length + length + 1 >= str->size)
CuStringResize(str, str->length + length + 1 + STRING_INC);
memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1);
str->length += length;
memcpy(str->buffer + pos, text, length);
}
/*-------------------------------------------------------------------------*
* CuTest
*-------------------------------------------------------------------------*/
void CuTestInit(CuTest* t, const char* name, TestFunction function)
{
t->name = CuStrCopy(name);
t->failed = 0;
t->ran = 0;
t->message = NULL;
t->function = function;
t->jumpBuf = NULL;
}
CuTest* CuTestNew(const char* name, TestFunction function)
{
CuTest* tc = CU_ALLOC(CuTest);
CuTestInit(tc, name, function);
return tc;
}
void CuTestDelete(CuTest *t)
{
if (!t) return;
free(t->name);
free(t);
}
void CuTestRun(CuTest* tc)
{
jmp_buf buf;
tc->jumpBuf = &buf;
if (setjmp(buf) == 0)
{
tc->ran = 1;
(tc->function)(tc);
}
tc->jumpBuf = 0;
}
static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string)
{
char buf[HUGE_STRING_LEN];
sprintf(buf, "%s:%d: ", file, line);
CuStringInsert(string, buf, 0);
tc->failed = 1;
tc->message = string->buffer;
if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0);
}
void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message)
{
CuString string;
CuStringInit(&string);
if (message2 != NULL)
{
CuStringAppend(&string, message2);
CuStringAppend(&string, ": ");
}
CuStringAppend(&string, message);
CuFailInternal(tc, file, line, &string);
}
void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition)
{
if (condition) return;
CuFail_Line(tc, file, line, NULL, message);
}
void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
const char* expected, const char* actual)
{
CuString string;
if ((expected == NULL && actual == NULL) ||
(expected != NULL && actual != NULL &&
strcmp(expected, actual) == 0))
{
return;
}
CuStringInit(&string);
if (message != NULL)
{
CuStringAppend(&string, message);
CuStringAppend(&string, ": ");
}
CuStringAppend(&string, "expected <");
CuStringAppend(&string, expected);
CuStringAppend(&string, "> but was <");
CuStringAppend(&string, actual);
CuStringAppend(&string, ">");
CuFailInternal(tc, file, line, &string);
}
void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
int expected, int actual)
{
char buf[STRING_MAX];
if (expected == actual) return;
sprintf(buf, "expected <%d> but was <%d>", expected, actual);
CuFail_Line(tc, file, line, message, buf);
}
void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
double expected, double actual, double delta)
{
char buf[STRING_MAX];
if (fabs(expected - actual) <= delta) return;
sprintf(buf, "expected <%f> but was <%f>", expected, actual);
CuFail_Line(tc, file, line, message, buf);
}
void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
const void* expected, const void* actual)
{
char buf[STRING_MAX];
if (expected == actual) return;
sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual);
CuFail_Line(tc, file, line, message, buf);
}
/*-------------------------------------------------------------------------*
* CuSuite
*-------------------------------------------------------------------------*/
void CuSuiteInit(CuSuite* testSuite)
{
testSuite->count = 0;
testSuite->failCount = 0;
memset(testSuite->list, 0, sizeof(testSuite->list));
}
CuSuite* CuSuiteNew(void)
{
CuSuite* testSuite = CU_ALLOC(CuSuite);
CuSuiteInit(testSuite);
return testSuite;
}
void CuSuiteDelete(CuSuite *testSuite)
{
unsigned int n;
for (n=0; n < MAX_TEST_CASES; n++)
{
if (testSuite->list[n])
{
CuTestDelete(testSuite->list[n]);
}
}
free(testSuite);
}
void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase)
{
assert(testSuite->count < MAX_TEST_CASES);
testSuite->list[testSuite->count] = testCase;
testSuite->count++;
}
void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2)
{
int i;
for (i = 0 ; i < testSuite2->count ; ++i)
{
CuTest* testCase = testSuite2->list[i];
CuSuiteAdd(testSuite, testCase);
}
}
void CuSuiteRun(CuSuite* testSuite)
{
int i;
for (i = 0 ; i < testSuite->count ; ++i)
{
CuTest* testCase = testSuite->list[i];
CuTestRun(testCase);
if (testCase->failed) { testSuite->failCount += 1; }
}
}
void CuSuiteSummary(CuSuite* testSuite, CuString* summary)
{
int i;
for (i = 0 ; i < testSuite->count ; ++i)
{
CuTest* testCase = testSuite->list[i];
CuStringAppend(summary, testCase->failed ? "F" : ".");
}
CuStringAppend(summary, "\n\n");
}
void CuSuiteDetails(CuSuite* testSuite, CuString* details)
{
int i;
int failCount = 0;
if (testSuite->failCount == 0)
{
int passCount = testSuite->count - testSuite->failCount;
const char* testWord = passCount == 1 ? "test" : "tests";
CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord);
}
else
{
if (testSuite->failCount == 1)
CuStringAppend(details, "There was 1 failure:\n");
else
CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount);
for (i = 0 ; i < testSuite->count ; ++i)
{
CuTest* testCase = testSuite->list[i];
if (testCase->failed)
{
failCount++;
CuStringAppendFormat(details, "%d) %s: %s\n",
failCount, testCase->name, testCase->message);
}
}
CuStringAppend(details, "\n!!!FAILURES!!!\n");
CuStringAppendFormat(details, "Runs: %d ", testSuite->count);
CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount);
CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount);
}
}
#ifndef CU_TEST_H
#define CU_TEST_H
#include <setjmp.h>
#include <stdarg.h>
#define CUTEST_VERSION "CuTest 1.5"
/* CuString */
char* CuStrAlloc(int size);
char* CuStrCopy(const char* old);
#define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE)))
#define HUGE_STRING_LEN 8192
#define STRING_MAX 256
#define STRING_INC 256
typedef struct
{
int length;
int size;
char* buffer;
} CuString;
void CuStringInit(CuString* str);
CuString* CuStringNew(void);
void CuStringRead(CuString* str, const char* path);
void CuStringAppend(CuString* str, const char* text);
void CuStringAppendChar(CuString* str, char ch);
void CuStringAppendFormat(CuString* str, const char* format, ...);
void CuStringInsert(CuString* str, const char* text, int pos);
void CuStringResize(CuString* str, int newSize);
void CuStringDelete(CuString* str);
/* CuTest */
typedef struct CuTest CuTest;
typedef void (*TestFunction)(CuTest *);
struct CuTest
{
char* name;
TestFunction function;
int failed;
int ran;
const char* message;
jmp_buf *jumpBuf;
};
void CuTestInit(CuTest* t, const char* name, TestFunction function);
CuTest* CuTestNew(const char* name, TestFunction function);
void CuTestRun(CuTest* tc);
void CuTestDelete(CuTest *t);
/* Internal versions of assert functions -- use the public versions */
void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message);
void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition);
void CuAssertStrEquals_LineMsg(CuTest* tc,
const char* file, int line, const char* message,
const char* expected, const char* actual);
void CuAssertIntEquals_LineMsg(CuTest* tc,
const char* file, int line, const char* message,
int expected, int actual);
void CuAssertDblEquals_LineMsg(CuTest* tc,
const char* file, int line, const char* message,
double expected, double actual, double delta);
void CuAssertPtrEquals_LineMsg(CuTest* tc,
const char* file, int line, const char* message,
const void* expected, const void* actual);
/* public assert functions */
#define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms))
#define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond))
#define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond))
#define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
#define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac))
#define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
#define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac))
#define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl))
#define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl))
#define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
#define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac))
#define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",(p != NULL))
#define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),(p != NULL))
/* CuSuite */
#define MAX_TEST_CASES 1024
#define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST))
typedef struct
{
int count;
CuTest* list[MAX_TEST_CASES];
int failCount;
} CuSuite;
void CuSuiteInit(CuSuite* testSuite);
CuSuite* CuSuiteNew(void);
void CuSuiteDelete(CuSuite *testSuite);
void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase);
void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2);
void CuSuiteRun(CuSuite* testSuite);
void CuSuiteSummary(CuSuite* testSuite, CuString* summary);
void CuSuiteDetails(CuSuite* testSuite, CuString* details);
#endif /* CU_TEST_H */
NOTE
The license is based on the zlib/libpng license. For more details see
http://www.opensource.org/licenses/zlib-license.html. The intent of the
license is to:
- keep the license as simple as possible
- encourage the use of CuTest in both free and commercial applications
and libraries
- keep the source code together
- give credit to the CuTest contributors for their work
If you ship CuTest in source form with your source distribution, the
following license document must be included with it in unaltered form.
If you find CuTest useful we would like to hear about it.
LICENSE
Copyright (c) 2003 Asim Jalis
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in
a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
#
# iniparser tests Makefile
#
CC ?= gcc
CC = gcc
CFLAGS = -g -I../src
LFLAGS = -L.. -liniparser
AR = ar
ARFLAGS = rcv
RM = rm -f
ifndef V
QUIET_CC = @echo "CC $@";
QUIET_MAKE_TESTS = @echo "GN Alltests.c";
endif
DEPS = $(shell ls ../src/*.[ch])
default: all
SRC = $(shell ls *.c | sed 's/AllTests.c//')
OBJ = $(SRC:.c=.o)
all: iniexample parse
INCLUDE = -I../src
CFLAGS = -pipe -ansi -pedantic -Wall -Wextra -g
LDFLAGS =
all: check
iniexample: iniexample.c
$(CC) $(CFLAGS) -o iniexample iniexample.c -I../src -L.. -liniparser
check: testrun
@./testrun
parse: parse.c
$(CC) $(CFLAGS) -o parse parse.c -I../src -L.. -liniparser
clean veryclean:
$(RM) iniexample example.ini parse
testrun: AllTests.o $(OBJ)
$(QUIET_CC)$(CC) -o $@ AllTests.o $(OBJ) $(LDFLAGS)
AllTests.o: $(OBJ)
$(QUIET_MAKE_TESTS)./make-tests.sh > AllTests.c
$(QUIET_CC)$(CC) -c -o AllTests.o AllTests.c $(CFLAGS) $(INCLUDE)
%.o: %.c $(DEPS)
$(QUIET_CC)$(CC) -c -o $@ $< $(CFLAGS) $(INCLUDE)
clean veryclean:
rm -rf AllTests.c
rm -rf $(OBJ) AllTests.o
rm -rf testrun
#!/usr/bin/env bash
# Auto generate single AllTests file for CuTest.
# Searches through all *.c files in the current directory.
# Prints to stdout.
# Author: Asim Jalis
# Date: 01/08/2003
if test $# -eq 0 ; then FILES=*.c ; else FILES=$* ; fi
echo '
/* This is auto-generated code. Edit at your own peril. */
#include <stdio.h>
#include <stdlib.h>
#include "CuTest.h"
'
cat $FILES | grep '^void Test' |
sed -e 's/(.*$//' \
-e 's/$/(CuTest*);/' \
-e 's/^/extern /'
echo \
'
void RunAllTests(void)
{
CuString *output = CuStringNew();
CuSuite* suite = CuSuiteNew();
'
cat $FILES | grep '^void Test' |
sed -e 's/^void //' \
-e 's/(.*$//' \
-e 's/^/ SUITE_ADD_TEST(suite, /' \
-e 's/$/);/'
echo \
'
CuSuiteRun(suite);
CuSuiteSummary(suite, output);
CuSuiteDetails(suite, output);
printf("%s\n", output->buffer);
CuStringDelete(output);
CuSuiteDelete(suite);
}
int main(void)
{
RunAllTests();
return 0;
}
'
#
# All of these should trigger syntax errors
#
[section]
hello
world
hello \
world
a + b ;
# Stress testing buffers for overflows
[long]
# Shitload key size
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1
# Shitload data size
[long]
a=\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890;
# spaced2.ini
[blanks]
a=1
b=1;
c=1; comment
d=1# comment
\ No newline at end of file
#
# Twisted.ini
# This file is meant for regression tests
# Different blank settings around the equal sign
[blanks]
a=1
b=1;
c=1; comment
d=1# comment
e =1
f =1;
g =1; comment
h =1# comment
i= 1
j= 1;
k= 1; comment
l= 1# comment
m = 1
n = 1;
o = 1; comment
p = 1# comment
q=1 ;
r=1 ; comment
s=1 ;comment
t=1 #comment
# Empty values
[empty]
a = ''
b = ""
c = '' ;
d = "" ;
e = '' ; comment
f = "" ; comment
g =
h = ;
i = ; comment
j = # comment
k=
l=;
m=;comment
n=#
# Peculiar values
[peculiar]
a=';';
b='#'#
c=';';comment
d='#'#comment
e=\;
f=\#
g=\;comment
h=\#comment
i=;;
j=##
k=;;;;;;;;;;
l=##########
# Quotes
[quotes]
s1='
s2=''
s3='''
s4=''''
d1="
d2=""
d3="""
d4=""""
m1='"'
m2="'"
h1=hello'world
h2='hello'world
h3='hello'world'
h4=hello"world
h5="hello"world
h6="hello"world"
# Section names
[a]
[ b]
[c ]
[ d ]
[ begin end ]
[ open[ ]
# Multi-line inputs
[multi]
a = begin\
end
b = begin \
end
c = begin \
end
d = 1\
2\
3\
4
e = 1 \
2 \
3 \
4
f = 1 ; \
hidden = because of the preceding backslash multi-lining the comment ;
visible = 1
g = 1 #\
and now this comment is hidden too \
and this one too
h = 1
multi \
line \
key = 1
multi \
line \
key = \
multi \
line \
value ;
# end of file
#include <stdio.h>
#include <stdlib.h>
#include "CuTest.h"
/* We need to directly insert the .c file in order to test the */
/* static functions as well */
#include "dictionary.c"
void Test_xstrdup(CuTest *tc)
{
size_t i;
char *dup_str;
const char *strings[] = {
"",
"test",
" "
};
char *string_very_long;
/* NULL test */
CuAssertPtrEquals(tc, NULL, xstrdup(NULL));
for (i = 0 ; i < sizeof(strings) / sizeof(char *) ; ++i) {
dup_str = xstrdup(strings[i]);
CuAssertStrEquals(tc, strings[i], dup_str);
free(dup_str);
}
/* test a overflowing string */
string_very_long = (char*) malloc(10 * 1024);
memset(string_very_long, '#', 10 * 1024);
string_very_long[10 * 1024 - 1] = '\0';
dup_str = xstrdup(string_very_long);
CuAssertStrEquals(tc, string_very_long, dup_str);
free(string_very_long);
free(dup_str);
}
void Test_dictionary_grow(CuTest *tc)
{
unsigned i;
dictionary *dic;
dic = dictionary_new(DICTMINSZ);
CuAssertPtrNotNull(tc, dic);
CuAssertIntEquals(tc, 0, dic->n);
CuAssertIntEquals(tc, DICTMINSZ, dic->size);
for (i = 1 ; i < 10 ; ++i) {
CuAssertIntEquals(tc, 0, dictionary_grow(dic));
CuAssertIntEquals(tc, 0, dic->n);
CuAssertIntEquals(tc, (1 << i) * DICTMINSZ, dic->size);
}
}
void Test_dictionary_hash(CuTest *tc)
{
/* NULL test */
CuAssertIntEquals(tc, 0, dictionary_hash(NULL));
}
void Test_dictionary_growing(CuTest *tc)
{
int i, j;
char sec_name[32];
char key_name[64];
dictionary *dic;
dic = dictionary_new(DICTMINSZ);
CuAssertPtrNotNull(tc, dic);
CuAssertIntEquals(tc, 0, dic->n);
/* Makes the dictionary grow */
for (i = 1 ; i < 101; ++i) {
sprintf(sec_name, "sec%d", i);
CuAssertIntEquals(tc, 0, dictionary_set(dic, sec_name, ""));
for (j = 1 ; j < 11; ++j) {
sprintf(key_name, "%s:key%d", sec_name, j);
CuAssertIntEquals(tc, 0, dictionary_set(dic, key_name, "dummy_value"));
CuAssertIntEquals(tc, i + (i - 1) * 10 + j, dic->n);
}
}
/* Shrink the dictionary */
for (i = 100 ; i > 0; --i) {
sprintf(sec_name, "sec%d", i);
for (j = 10 ; j > 0; --j) {
sprintf(key_name, "%s:key%d", sec_name, j);
dictionary_unset(dic, key_name);
}
dictionary_unset(dic, sec_name);
CuAssertIntEquals(tc, (i - 1) * (11), dic->n);
}
dictionary_del(dic);
}
static char *get_dump(dictionary *d)
{
FILE *fd;
char *dump_buff;
int dump_size;
/* Dump the dictionary in temporary file */
fd = tmpfile();
if (fd == NULL)
return NULL;
dictionary_dump(d, fd);
/* Retrieve the dump file */
dump_size = ftell(fd);
if (dump_size == -1) {
fclose(fd);
return NULL;
}
rewind(fd);
dump_buff = (char*) calloc(1, dump_size + 1);
if (dump_buff == NULL) {
fclose(fd);
return NULL;
}
fread(dump_buff, 1, dump_size, fd);
fclose(fd);
return dump_buff;
}
void Test_dictionary_unset(CuTest *tc)
{
int i, j;
char sec_name[32];
char key_name[64];
dictionary *dic1;
dictionary *dic2;
char *dic1_dump;
char *dic2_dump;
/* try dummy unsets */
dictionary_unset(NULL, NULL);
dictionary_unset(NULL, key_name);
/* Generate two similar dictionaries */
dic1 = dictionary_new(DICTMINSZ);
CuAssertPtrNotNull(tc, dic1);
for (i = 1 ; i < 10; ++i) {
sprintf(sec_name, "sec%d", i);
dictionary_set(dic1, sec_name, "");
for (j = 1 ; j < 10; ++j) {
sprintf(key_name, "%s:key%d", sec_name, j);
dictionary_set(dic1, key_name, "dummy_value");
}
}
dic2 = dictionary_new(DICTMINSZ);
CuAssertPtrNotNull(tc, dic2);
for (i = 1 ; i < 10; ++i) {
sprintf(sec_name, "sec%d", i);
dictionary_set(dic2, sec_name, "");
for (j = 1 ; j < 10; ++j) {
sprintf(key_name, "%s:key%d", sec_name, j);
dictionary_set(dic2, key_name, "dummy_value");
}
}
/* Make sure the dictionaries are the same */
dic1_dump = get_dump(dic1);
dic2_dump = get_dump(dic2);
CuAssertStrEquals(tc, dic1_dump, dic2_dump);
free(dic1_dump);
free(dic2_dump);
/* Those tests should not change the dictionary */
dictionary_unset(dic2, NULL);
dictionary_unset(dic2, "bad_key");
/* dic1 and dic2 must still be the same */
dic1_dump = get_dump(dic1);
dic2_dump = get_dump(dic2);
CuAssertStrEquals(tc, dic1_dump, dic2_dump);
free(dic1_dump);
free(dic2_dump);
}
void Test_dictionary_dump(CuTest *tc)
{
int i, j;
char sec_name[32];
char key_name[64];
dictionary *dic;
char *dump_buff;
const char dump_real[] = "\
sec1\t[]\n\
sec1:key1\t[dummy_value]\n\
sec1:key2\t[dummy_value]\n\
sec1:key3\t[dummy_value]\n\
sec1:key4\t[dummy_value]\n\
sec2\t[]\n\
sec2:key1\t[dummy_value]\n\
sec2:key2\t[dummy_value]\n\
sec2:key3\t[dummy_value]\n\
sec2:key4\t[dummy_value]\n\
";
dic = dictionary_new(DICTMINSZ);
CuAssertPtrNotNull(tc, dic);
/* Try dummy values */
dictionary_dump(NULL, NULL);
dictionary_dump(dic, NULL);
/* Try with empty dictionary first */
dump_buff = get_dump(dic);
CuAssertStrEquals(tc, "empty dictionary\n", dump_buff);
free(dump_buff);
/* Populate the dictionary */
for (i = 1 ; i < 3; ++i) {
sprintf(sec_name, "sec%d", i);
dictionary_set(dic, sec_name, "");
for (j = 1 ; j < 5; ++j) {
sprintf(key_name, "%s:key%d", sec_name, j);
dictionary_set(dic, key_name, "dummy_value");
}
}
/* Check the dump file */
dump_buff = get_dump(dic);
CuAssertStrEquals(tc, dump_real, dump_buff);
free(dump_buff);
dictionary_del(dic);
}
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "CuTest.h"
#include "dictionary.h"
/* We need to directly insert the .c file in order to test the */
/* static functions as well */
#include "iniparser.c"
#define GOOD_INI_PATH "ressources/good_ini"
#define BAD_INI_PATH "ressources/bad_ini"
/* Tool function to create and populate a generic non-empty dictionary */
static dictionary * generate_dictionary(unsigned sections, unsigned entries_per_section)
{
unsigned i, j ;
dictionary * dic;
char sec_name[32];
char key_name[64];
char key_value[32];
dic = dictionary_new(sections + sections * entries_per_section);
if (dic == NULL)
return NULL;
/* Insert the sections */
for (i = 0; i < sections; ++i) {
sprintf(sec_name, "sec%d", i);
dictionary_set(dic, sec_name, "");
for (j = 0; j < entries_per_section; ++j) {
/* Populate the section with the entries */
sprintf(key_name, "%s:key%d", sec_name, j);
sprintf(key_value, "value-%d/%d", i, j);
dictionary_set(dic, key_name, key_value);
}
}
return dic;
}
void Test_iniparser_strlwc(CuTest *tc)
{
char out_buffer[128];
/* NULL ptr as input */
CuAssertPtrEquals(tc, NULL, strlwc(NULL, NULL, 0));
CuAssertPtrEquals(tc, NULL, strlwc(NULL, out_buffer, sizeof (out_buffer)));
CuAssertPtrEquals(tc, NULL, strlwc("", NULL, sizeof (out_buffer)));
CuAssertPtrEquals(tc, NULL, strlwc("", out_buffer, 0));
CuAssertPtrEquals(tc, NULL, strlwc(NULL, NULL, 0));
/* empty string */
CuAssertStrEquals(tc, "", strlwc("", out_buffer, sizeof (out_buffer)));
CuAssertStrEquals(tc, " ", strlwc(" ", out_buffer, sizeof (out_buffer)));
CuAssertStrEquals(tc, "test", strlwc("test", out_buffer, sizeof (out_buffer)));
CuAssertStrEquals(tc, "test", strlwc("TEST", out_buffer, sizeof (out_buffer)));
CuAssertStrEquals(tc, "test", strlwc("TeSt", out_buffer, sizeof (out_buffer)));
CuAssertStrEquals(tc, "test test",
strlwc("TEST TEST", out_buffer, sizeof (out_buffer)));
CuAssertStrEquals(tc, "very long string !!!!!!!",
strlwc("very long string !!!!!!!", out_buffer, sizeof (out_buffer)));
CuAssertStrEquals(tc, "cutted string", strlwc("cutted string<---here", out_buffer, 14));
/* test using same buffer as input and output */
strcpy(out_buffer, "OVERWRITE ME !");
CuAssertPtrNotNull(tc, strlwc(out_buffer, out_buffer, sizeof(out_buffer)));
CuAssertStrEquals(tc, "overwrite me !", out_buffer);
}
void Test_iniparser_strstrip(CuTest *tc)
{
/* First element in the array is the expected stripping result */
const char *strings_empty[] = {
"",
" ",
"\n\n\n\n",
"\t\t\t\t",
"\n \t\n\t\n "
};
const char *strings_test[] = {
"test",
"test ",
"test ",
" test",
" test ",
"\ttest\t",
"\ttest\n"
};
const char *test_with_spaces = "I am a test with\tspaces.";
char stripped[ASCIILINESZ+1];
char error_msg[128];
unsigned i;
/* NULL ptr as input */
strstrip(NULL);
/* empty string */
for (i = 0 ; i < sizeof (strings_empty) / sizeof (char *) ; ++i) {
strcpy(stripped, strings_empty[i]);
strstrip(stripped);
sprintf(error_msg, "Bad stripping : strstrip(\"%s\") ==> \"%s\"",
strings_empty[i], stripped);
CuAssertStrEquals_Msg(tc, error_msg, stripped, strings_empty[0]);
}
/* test string */
for (i = 0 ; i < sizeof (strings_test) / sizeof (char *) ; ++i) {
strcpy(stripped, strings_test[i]);
strstrip(stripped);
sprintf(error_msg, "Bad stripping : strstrip(\"%s\") ==> \"%s\"",
strings_test[i], stripped);
CuAssertStrEquals_Msg(tc, error_msg, strings_test[0], stripped);
}
strcpy(stripped, ".");
strstrip(stripped);
CuAssertStrEquals(tc, ".", stripped);
/* string containing spaces */
strcpy(stripped, test_with_spaces);
strstrip(stripped);
CuAssertStrEquals(tc, test_with_spaces, stripped);
}
void Test_iniparser_getnsec(CuTest *tc)
{
int i;
char sec_name[32];
dictionary *dic;
/* NULL test */
CuAssertIntEquals(tc, -1, iniparser_getnsec(NULL));
/* Empty dictionary */
dic = dictionary_new(10);
CuAssertIntEquals(tc, 0, iniparser_getnsec(dic));
dictionary_del(dic);
/* Regular dictionary */
dic = generate_dictionary(512, 0);
CuAssertIntEquals(tc, 512, iniparser_getnsec(dic));
/* Check after removing sections */
for (i = 1; i < 512; ++i) {
sprintf(sec_name, "sec%d", i);
dictionary_unset(dic, sec_name);
CuAssertIntEquals(tc, 512 - i, iniparser_getnsec(dic));
}
dictionary_del(dic);
/* Mix sections and regular keys */
dic = generate_dictionary(10, 512);
CuAssertIntEquals(tc, 10, iniparser_getnsec(dic));
dictionary_del(dic);
}
void Test_iniparser_getsecname(CuTest *tc)
{
unsigned i;
char sec_name[32];
dictionary *dic;
/* NULL test */
CuAssertTrue(tc, iniparser_getsecname(NULL, 0) == NULL);
/* Empty dictionary */
dic = dictionary_new(10);
CuAssertPtrEquals(tc, NULL, iniparser_getsecname(dic, 0));
dictionary_del(dic);
/* Sections without entries dictionary */
dic = generate_dictionary(100, 0);
for (i = 0; i < 100; ++i) {
sprintf(sec_name, "sec%d", i);
CuAssertStrEquals(tc, sec_name, iniparser_getsecname(dic, i));
}
dictionary_del(dic);
/* Generic dictionary */
dic = generate_dictionary(10, 100);
for (i = 0; i < 10; ++i) {
sprintf(sec_name, "sec%d", i);
CuAssertStrEquals(tc, sec_name, iniparser_getsecname(dic, i));
}
dictionary_del(dic);
}
void Test_iniparser_getseckeys(CuTest *tc)
{
unsigned i;
char key_name[64];
dictionary *dic;
const char ** sections;
/* NULL test */
CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(NULL, NULL));
CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(NULL, "dummy"));
/* Empty dictionary */
dic = dictionary_new(10);
CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, NULL));
CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, "dummy"));
dictionary_del(dic);
/* Generic dictionary */
dic = generate_dictionary(100, 10);
CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, NULL));
CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, "dummy"));
sections = iniparser_getseckeys(dic, "sec42");
CuAssertPtrNotNull(tc, sections);
for (i = 0; i < 10; ++i) {
sprintf(key_name, "sec42:key%d", i);
CuAssertStrEquals(tc, key_name, sections[i]);
}
free(sections);
/* Remove some keys to make the dictionary more real */
dictionary_unset(dic, "sec42");
dictionary_unset(dic, "sec99:key9");
dictionary_unset(dic, "sec0:key0");
dictionary_unset(dic, "sec0:key1");
dictionary_unset(dic, "sec0:key2");
CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, "sec42"));
sections = iniparser_getseckeys(dic, "sec99");
CuAssertPtrNotNull(tc, sections);
for (i = 0; i < 9; ++i) {
sprintf(key_name, "sec99:key%d", i);
CuAssertStrEquals(tc, key_name, sections[i]);
}
free(sections);
sections = iniparser_getseckeys(dic, "sec0");
CuAssertPtrNotNull(tc, sections);
for (i = 0; i < 7; ++i) {
sprintf(key_name, "sec0:key%d", i + 3);
CuAssertStrEquals(tc, key_name, sections[i]);
}
free(sections);
dictionary_del(dic);
}
void Test_iniparser_getstring(CuTest *tc)
{
dictionary *dic;
/* NULL test */
CuAssertPtrEquals(tc, NULL, iniparser_getstring(NULL, NULL, NULL));
CuAssertPtrEquals(tc, NULL, iniparser_getstring(NULL, "dummy", NULL));
/* Check the def return element */
dic = dictionary_new(10);
CuAssertPtrEquals(tc, NULL, iniparser_getstring(dic, "dummy", NULL));
CuAssertStrEquals(tc, "def", iniparser_getstring(dic, NULL, "def"));
CuAssertStrEquals(tc, "def", iniparser_getstring(dic, "dummy", "def"));
dictionary_del(dic);
/* Generic dictionary */
dic = generate_dictionary(100, 10);
CuAssertStrEquals(tc, "value-0/0",
iniparser_getstring(dic, "sec0:key0", NULL));
CuAssertStrEquals(tc, "value-42/5",
iniparser_getstring(dic, "sec42:key5", NULL));
CuAssertStrEquals(tc, "value-99/9",
iniparser_getstring(dic, "sec99:key9", NULL));
dictionary_del(dic);
}
void Test_iniparser_getint(CuTest *tc)
{
unsigned i;
char key_name[64];
dictionary *dic;
const struct { int num; const char *value; } good_val[] = {
{ 0, "0" },
{ 1, "1" },
{ -1, "-1" },
{ 1000, "1000" },
{ 077, "077" },
{ -01000, "-01000" },
{ 0xFFFF, "0xFFFF" },
{ -0xFFFF, "-0xFFFF" },
{ 0x4242, "0x4242" },
{ 0, NULL} /* must be last */
};
const char *bad_val[] = {
"",
"notanumber",
"0x",
"k2000",
" ",
"0xG1"
};
/* NULL test */
CuAssertIntEquals(tc, -42, iniparser_getint(NULL, NULL, -42));
CuAssertIntEquals(tc, -42, iniparser_getint(NULL, "dummy", -42));
/* Check the def return element */
dic = dictionary_new(10);
CuAssertIntEquals(tc, 42, iniparser_getint(dic, "dummy", 42));
CuAssertIntEquals(tc, 0xFFFF, iniparser_getint(dic, NULL, 0xFFFF));
CuAssertIntEquals(tc, -0xFFFF, iniparser_getint(dic, "dummy", -0xFFFF));
dictionary_del(dic);
/* Generic dictionary */
dic = dictionary_new(10);
for (i = 0; good_val[i].value != NULL; ++i) {
sprintf(key_name, "int:value%d", i);
dictionary_set(dic, key_name, good_val[i].value);
}
for (i = 0; good_val[i].value != NULL; ++i) {
sprintf(key_name, "int:value%d", i);
CuAssertIntEquals(tc, good_val[i].num,
iniparser_getint(dic, key_name, 0));
}
dictionary_del(dic);
/* Test bad names */
dic = dictionary_new(10);
for (i = 0; i < sizeof (bad_val) / sizeof (char *); ++i) {
sprintf(key_name, "int:bad%d", i);
dictionary_set(dic, key_name, bad_val[i]);
}
for (i = 0; i < sizeof (bad_val) / sizeof (char *); ++i) {
sprintf(key_name, "int:bad%d", i);
CuAssertIntEquals(tc, 0,
iniparser_getint(dic, key_name, 0));
}
dictionary_del(dic);
}
void Test_iniparser_getdouble(CuTest *tc)
{
dictionary *dic;
/* NULL test */
CuAssertDblEquals(tc, -42, iniparser_getdouble(NULL, NULL, -42), 0);
CuAssertDblEquals(tc, 4.2, iniparser_getdouble(NULL, "dummy", 4.2), 0);
/* Check the def return element */
dic = dictionary_new(10);
CuAssertDblEquals(tc, 3.1415, iniparser_getdouble(dic, "dummy", 3.1415), 0);
CuAssertDblEquals(tc, 0xFFFFFFFF, iniparser_getdouble(dic, NULL, 0xFFFFFFFF), 0);
CuAssertDblEquals(tc, -0xFFFFFFFF, iniparser_getdouble(dic, "dummy", -0xFFFFFFFF), 0);
/* Insert some values */
dictionary_set(dic, "double", "");
dictionary_set(dic, "double:good0", "0");
dictionary_set(dic, "double:good1", "-0");
dictionary_set(dic, "double:good2", "1.0");
dictionary_set(dic, "double:good3", "3.1415");
dictionary_set(dic, "double:good4", "6.6655957");
dictionary_set(dic, "double:good5", "-123456789.123456789");
/* Add dummy stuff too */
dictionary_set(dic, "double:bad0", "foo");
/* Get back the values */
CuAssertDblEquals(tc, 0, iniparser_getdouble(dic, "double:good0", 0xFF), 0);
CuAssertDblEquals(tc, 0, iniparser_getdouble(dic, "double:good1", 0xFF), 0);
CuAssertDblEquals(tc, 1.0, iniparser_getdouble(dic, "double:good2", 0xFF), 0);
CuAssertDblEquals(tc, 3.1415, iniparser_getdouble(dic, "double:good3", 0xFF), 0);
CuAssertDblEquals(tc, 6.6655957, iniparser_getdouble(dic, "double:good4", 0xFF), 0);
CuAssertDblEquals(tc, -123456789.123456789,
iniparser_getdouble(dic, "double:good5", 0xFF), 0);
CuAssertDblEquals(tc, 0, iniparser_getdouble(dic, "double:bad0", 42.42), 0);
dictionary_del(dic);
}
void Test_iniparser_getboolean(CuTest *tc)
{
unsigned i;
char key_name[64];
dictionary *dic;
const char *token_true[] = {
"1",
"true",
"t",
"TRUE",
"T",
"yes",
"y",
"YES"
"Y",
NULL
};
const char *token_false[] = {
"0",
"false",
"f",
"FALSE",
"F",
"no",
"n",
"NO",
"N",
NULL
};
/* NULL test */
CuAssertIntEquals(tc, 1, iniparser_getboolean(NULL, NULL, 1));
CuAssertIntEquals(tc, 1, iniparser_getboolean(NULL, "dummy", 1));
/* Check the def return element */
dic = dictionary_new(10);
CuAssertIntEquals(tc, 1, iniparser_getboolean(dic, "dummy", 1));
CuAssertIntEquals(tc, 0, iniparser_getboolean(dic, NULL, 0));
CuAssertIntEquals(tc, 1, iniparser_getboolean(dic, "dummy", 1));
for (i = 0; token_true[i] != NULL; ++i) {
sprintf(key_name, "bool:true%d", i);
iniparser_set(dic, key_name, token_true[i]);
}
for (i = 0; token_false[i] != NULL; ++i) {
sprintf(key_name, "bool:false%d", i);
iniparser_set(dic, key_name, token_false[i]);
}
for (i = 0; token_true[i] != NULL; ++i) {
sprintf(key_name, "bool:true%d", i);
CuAssertIntEquals(tc, 1, iniparser_getboolean(dic, key_name, 0));
}
for (i = 0; token_false[i] != NULL; ++i) {
sprintf(key_name, "bool:false%d", i);
CuAssertIntEquals(tc, 0, iniparser_getboolean(dic, key_name, 1));
}
/* Test bad boolean */
iniparser_set(dic, "bool:bad0", "");
iniparser_set(dic, "bool:bad1", "m'kay");
iniparser_set(dic, "bool:bad2", "42");
iniparser_set(dic, "bool:bad3", "_true");
CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad0", 0xFF));
CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad1", 0xFF));
CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad2", 0xFF));
CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad3", 0xFF));
dictionary_del(dic);
}
void Test_iniparser_line(CuTest *tc)
{
char section [ASCIILINESZ+1] ;
char key [ASCIILINESZ+1] ;
char val [ASCIILINESZ+1] ;
/* Test empty line */
CuAssertIntEquals(tc, LINE_EMPTY, iniparser_line("", section, key, val));
CuAssertIntEquals(tc, LINE_EMPTY, iniparser_line(" ", section, key, val));
CuAssertIntEquals(tc, LINE_EMPTY, iniparser_line("\t", section, key, val));
/* Test valid syntax */
CuAssertIntEquals(tc, LINE_SECTION, iniparser_line("[s]", section, key, val));
CuAssertStrEquals(tc, "s", section);
CuAssertIntEquals(tc, LINE_SECTION, iniparser_line("[ section ]", section, key, val));
CuAssertStrEquals(tc, "section", section);
CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("k=1", section, key, val));
CuAssertStrEquals(tc, "k", key);
CuAssertStrEquals(tc, "1", val);
CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key = 0x42", section, key, val));
CuAssertStrEquals(tc, "key", key);
CuAssertStrEquals(tc, "0x42", val);
CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key= value with spaces", section, key, val));
CuAssertStrEquals(tc, "key", key);
CuAssertStrEquals(tc, "value with spaces", val);
CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("k =_!<>''", section, key, val));
CuAssertStrEquals(tc, "k", key);
CuAssertStrEquals(tc, "_!<>''", val);
CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("empty_value =", section, key, val));
CuAssertStrEquals(tc, "empty_value", key);
CuAssertStrEquals(tc, "", val);
CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key =\tval # comment", section, key, val));
CuAssertStrEquals(tc, "key", key);
CuAssertStrEquals(tc, "val", val);
CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key \n\n = \n val", section, key, val));
CuAssertStrEquals(tc, "key", key);
CuAssertStrEquals(tc, "val", val);
CuAssertIntEquals(tc, LINE_COMMENT, iniparser_line(";comment", section, key, val));
CuAssertIntEquals(tc, LINE_COMMENT, iniparser_line(" # comment", section, key, val));
/* Test syntax error */
CuAssertIntEquals(tc, LINE_ERROR, iniparser_line("empty_value", section, key, val));
CuAssertIntEquals(tc, LINE_ERROR, iniparser_line("not finished\\", section, key, val));
CuAssertIntEquals(tc, LINE_ERROR, iniparser_line("0x42 / 0b101010", section, key, val));
}
void Test_iniparser_load(CuTest *tc)
{
DIR *dir;
struct dirent *curr;
struct stat curr_stat;
dictionary *dic;
char ini_path[256];
/* Dummy tests */
dic = iniparser_load("/you/shall/not/path");
CuAssertPtrEquals(tc, NULL, dic);
/* Test all the good .ini files */
dir = opendir(GOOD_INI_PATH);
CuAssertPtrNotNullMsg(tc, "Cannot open good .ini conf directory", dir);
for (curr = readdir(dir); curr != NULL; curr = readdir(dir)) {
sprintf(ini_path, "%s/%s", GOOD_INI_PATH, curr->d_name);
stat(ini_path, &curr_stat);
if (S_ISREG(curr_stat.st_mode)) {
dic = iniparser_load(ini_path);
CuAssertPtrNotNullMsg(tc, ini_path, dic);
dictionary_del(dic);
}
}
closedir(dir);
/* Test all the bad .ini files */
dir = opendir(BAD_INI_PATH);
CuAssertPtrNotNullMsg(tc, "Cannot open bad .ini conf directory", dir);
for (curr = readdir(dir); curr != NULL; curr = readdir(dir)) {
sprintf(ini_path, "%s/%s", BAD_INI_PATH, curr->d_name);
stat(ini_path, &curr_stat);
if (S_ISREG(curr_stat.st_mode)) {
dic = iniparser_load(ini_path);
CuAssertPtrEquals_Msg(tc, ini_path, NULL, dic);
dictionary_del(dic);
}
}
closedir(dir);
}
void Test_dictionary_wrapper(CuTest *tc)
{
dictionary *dic;
dic = dictionary_new(10);
CuAssertIntEquals(tc, -1, iniparser_set(dic, NULL, NULL));
CuAssertIntEquals(tc, -1, iniparser_set(NULL, "section", "value"));
CuAssertIntEquals(tc, 0, iniparser_set(dic, "section", NULL));
CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", "value"));
CuAssertStrEquals(tc, "value", iniparser_getstring(dic, "section:key", NULL));
/* reset the key's value*/
CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", NULL));
CuAssertStrEquals(tc, NULL, iniparser_getstring(dic, "section:key", "dummy"));
CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", "value"));
CuAssertStrEquals(tc, "value", iniparser_getstring(dic, "section:key", NULL));
iniparser_unset(dic, "section:key");
CuAssertStrEquals(tc, "dummy", iniparser_getstring(dic, "section:key", "dummy"));
CuAssertStrEquals(tc, NULL, iniparser_getstring(dic, "section", "dummy"));
CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", NULL));
CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key1", NULL));
CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key2", NULL));
iniparser_unset(dic, "section");
CuAssertStrEquals(tc, NULL, iniparser_getstring(dic, "section", NULL));
iniparser_freedict(dic);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册