Merge branch 'cmake'

This commit is contained in:
Nils O. Selåsdal
2025-10-04 21:41:41 +02:00
48 changed files with 1917 additions and 321 deletions
+3
View File
@@ -8,3 +8,6 @@ log_subdir/
coverage/
install/
libucore-*
src/version.c
.cache/
compile_commands.json
+15
View File
@@ -0,0 +1,15 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${default}",
"${workspaceFolder}/include"
],
"defines": [],
"compilerPath": "/usr/bin/clang",
"intelliSenseMode": "macos-clang-arm64"
}
],
"version": 4
}
+11
View File
@@ -0,0 +1,11 @@
{
"files.associations": {
"*.h": "c",
},
"C_Cpp.default.includePath": [
"/opt/homebrew/include/",
"$(workspaceFolder)/include/",
],
"C_Cpp.default.cStandard": "gnu99"
}
+19
View File
@@ -0,0 +1,19 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "cmake",
"label": "CMake: build",
"command": "build",
"targets": [
"all"
],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [],
"detail": "CMake template build task"
}
]
}
+45
View File
@@ -0,0 +1,45 @@
cmake_minimum_required(VERSION 3.12)
project(libucore C)
execute_process(COMMAND git -C ${CMAKE_SOURCE_DIR} describe --abbrev=5 --dirty --always OUTPUT_VARIABLE version_revision WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_STRIP_TRAILING_WHITESPACE)
cmake_host_system_information(RESULT build_host QUERY HOSTNAME)
set(libucore_VERSION_MAJOR 1)
set(libucore_VERSION_MINOR 0)
set(libucore_VERSION_PATCH 0)
set(libucore_VERSION ${libucore_VERSION_MAJOR}.${libucore_VERSION_MINOR}.${libucore_VERSION_PATCH}.${version_revision})
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wundef -Wcast-qual -Wshadow -Wcast-align -pipe -Wno-unused-parameter -Werror=implicit-function-declaration -Winit-self")
add_definitions(-D_FILE_OFFSET_BITS=64)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -O2")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
option(CODE_COVERAGE "build with code coverage intrumentation" OFF)
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
# Set the property for multi-config generators as well, if applicable
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel)
endif()
set(build_type ${CMAKE_BUILD_TYPE})
if (CODE_COVERAGE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
add_definitions(-DCOVERAGE)
set(build_type "${build_type}-coverage")
endif()
option(BUILD_SANITIZE "build with address sanitizer" OFF)
if (BUILD_SANITIZE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
set(build_type "${build_type}-sanitize")
endif()
include_directories(include)
add_subdirectory(src)
add_subdirectory(test)
add_subdirectory(include)
+1 -1
View File
@@ -1192,7 +1192,7 @@ MATHJAX_EXTENSIONS =
# typically be disabled. For large projects the javascript based search engine
# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
SEARCHENGINE = NO
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a PHP enabled web server instead of at the web client
+11 -1
View File
@@ -66,6 +66,13 @@ AddOption('--stack-protection',
help = 'Build with stack protection support'
)
AddOption('--sanitizer',
dest = 'sanitizer',
action='store_true',
default=False,
help = 'Build with gcc sanitizer'
)
AddOption('--32',
dest='force32bit',
action='store_true',
@@ -126,6 +133,10 @@ if GetOption('coverage'):
env.Append(CFLAGS = ['--coverage'])
env.Append(LINKFLAGS = ['--coverage'])
if GetOption('sanitizer'):
env.Append(CFLAGS = ['-fsanitize=undefined', '-fsanitize=address'])
env.Append(LINKFLAGS = ['-fsanitize=undefined', '-fsanitize=address'])
# Generate substitute dictionary
subst_info = dict(('@' + key + '@', version_info[key]) for key in version_info)
subst_info['@prefix@'] = prefix
@@ -164,4 +175,3 @@ env.Package(target = 'libucore-' + version_info['version_str'] + '.tar.gz',
X_RPM_GROUP = 'Development/Libraries'
)
env.Default('src')
+1
View File
@@ -0,0 +1 @@
install(DIRECTORY ucore DESTINATION include)
+7 -2
View File
@@ -27,7 +27,7 @@ struct UCBitVec {
* Use as
* @code
* uc_bv_integer v[10];
* struct UCBitVec v = BITVEC_STATIC_INIT(v);
* struct UCBitVec v = UC_BV_STATIC_INIT(v);
* @endcode
*/
#define UC_BV_STATIC_INIT(vec_data)\
@@ -68,11 +68,16 @@ void uc_bv_set_all(struct UCBitVec *v);
/** Initialize bits from a array of ints, each array element maps to one bit.
* The bits are initialized from the int array so zero maps to zero and non-zero maps to one.
* e..g to set the 5 first bits, to 01110:
* int a[] = {0,1,1,1,0};
* int a[] = {0,1,1,1,0};
* set_bits_from_array(v,a,5);
* */
void uc_bv_set_bits_from_array(struct UCBitVec *v,const char *array,size_t array_len);
/** Find the index of the first zero bit in the bitvec.
* @param v The bitvec to search
* @return The index of the first zero bit, or -1 if all bits are set
*/
int uc_bv_find_first_zero(const struct UCBitVec *v);
#ifdef __cplusplus
}
+15
View File
@@ -2,6 +2,15 @@
#define UC_IOMUX_SIGNAL_H_
#include "ucore/iomux.h"
/** @addtogroup IOMux
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/** Callback signature for handling unix signals.
* @param mux associated mux
* @param signo unix signal number
@@ -45,4 +54,10 @@ int iomux_register_unixsignal(struct IOMux *mux,
*/
int iomux_unregister_unixsignal(struct IOMux *mux, int signo);
#ifdef __cplusplus
}
#endif
/** @} (addtogroup)*/
#endif
+30 -5
View File
@@ -10,10 +10,34 @@
*
* multiplication, subtraction and addition operations are provided.*/
//Use gcc builtins, supported since GCC 5
#if __GNUC__ >= 5
#define UC_SAT_ADD(a, b, type, max_val)\
({type res ;\
if (__builtin_add_overflow(a, b, &res)) {\
res = max_val;}\
res;})
#define UC_SAT_SUB(a, b, type)\
({type res ;\
if (__builtin_sub_overflow(a, b, &res)) {\
res = 0;}\
res;})
#define UC_SAT_MULT(a, b, type, max_val)\
({type res ;\
if (__builtin_mul_overflow(a, b, &res)) {\
res = max_val;}\
res;})
#else
#define UC_SAT_ADD(a, b, type, max_val)\
((type)((a) + (b)) >= (a) ? (a) + (b) : (max_val))
#define UC_SAT_SUB(a, b)\
#define UC_SAT_SUB(a, b, type)\
((a) >= (b) ? (a) - (b) : 0)
#define UC_SAT_MULT(a, b, type, max_val)\
@@ -21,6 +45,7 @@
(a) <= (max_val) / (b) ? (type) (a) * (type) (b) \
: (max_val))
#endif
static inline uint8_t uc_sat_addu8(uint8_t a, uint8_t b)
{
@@ -29,7 +54,7 @@ static inline uint8_t uc_sat_addu8(uint8_t a, uint8_t b)
static inline uint8_t uc_sat_subu8(uint8_t a, uint8_t b)
{
return UC_SAT_SUB(a, b);
return UC_SAT_SUB(a, b, uint8_t);
}
static inline uint8_t uc_sat_multu8(uint8_t a, uint8_t b)
@@ -44,7 +69,7 @@ static inline uint16_t uc_sat_addu16(uint16_t a, uint16_t b)
static inline uint16_t uc_sat_subu16(uint16_t a, uint16_t b)
{
return UC_SAT_SUB(a, b);
return UC_SAT_SUB(a, b, uint16_t);
}
static inline uint16_t uc_sat_multu16(uint16_t a, uint16_t b)
@@ -59,7 +84,7 @@ static inline uint32_t uc_sat_addu32(uint32_t a, uint32_t b)
static inline uint32_t uc_sat_subu32(uint32_t a, uint32_t b)
{
return UC_SAT_SUB(a, b);
return UC_SAT_SUB(a, b, uint32_t);
}
static inline uint32_t uc_sat_multu32(uint32_t a, uint32_t b)
@@ -74,7 +99,7 @@ static inline uint64_t uc_sat_addu64(uint64_t a, uint64_t b)
static inline uint64_t uc_sat_subu64(uint64_t a, uint64_t b)
{
return UC_SAT_SUB(a, b);
return UC_SAT_SUB(a, b, uint64_t);
}
static inline uint64_t uc_sat_multu64(uint64_t a, uint64_t b)
+112
View File
@@ -0,0 +1,112 @@
#ifndef UC_SLOT_ALLOCATOR_H_
#define UC_SLOT_ALLOCATOR_H_
#include <stddef.h>
#include <stdint.h>
#include "ucore/bitvec.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @file
* Fixed size slot memory allocator
*
* UCSlotAlloc is used to allocate fixed slots of memory from a pre-allocated
* piece of memory.
*
* The main use case is to keep allocated memory in a contiguous block for use
* maximum number of objects(slots) is known and relatively small. More than 131072 slots
* is not recommended.
*
* Note that this allocator is not thread safe.
*
* A bitmap is used to track which slots are allocated.
*/
typedef struct UCSlotAlloc UCSlotAlloc;
struct UCSlotAlloc {
const uint32_t slot_size;
const uint32_t num_slots;
struct UCBitVec bitmap;
uint8_t *slots;
};
/** Initialize a UCSlotAlloc with an array as the backing memory to allocate slots from.
* The macro can be used at local scope to allocate memory automatic (stack) storage,
* or at global scope where the backin array will have static storage duration
*
* Use as:
* @code
* UC_SLOT_ALLOC_DEF(my_allocator, sizeof foo, 1024)
* struct foo *foo = uc_slot_alloc(&my_allocator);
* if (foo == NULL) {
* // out of memory
* } else {
* .. use foo
* uc_slot_free(&my_allocator, foo);
* }
* @endcode
*
* @param var_name Variable name for the allocator
* @param v slot_size Memory size allocated for each slot
* @param v num_slots Number of slots to reserve memory for
*/
#define UC_SLOT_ALLOC_DEF(var_name, slot_size_, num_slots_) \
struct {\
uc_bv_integer bitmap[UC_BV_LEN((num_slots_))]; \
uint8_t memory[(num_slots_) * (slot_size_)] __attribute__((aligned)); \
} var_name ## _memory = { \
}; \
UCSlotAlloc var_name = { \
.slot_size = (slot_size_), \
.num_slots = (num_slots_), \
.bitmap = UC_BV_STATIC_INIT(var_name ## _memory.bitmap), \
.slots = var_name ## _memory.memory \
};
/** Similar to UC_SLOT_ALLOC_DEF but allows you to specify the backing memory that must
* be atleast as large as num_slots * slot_size. Note that an array of num_slots * slot_size
* bits is also allocated for the bitmap with this definition
*/
#define UC_SLOT_ALLOC_DEF_EX(var_name, slot_size_, num_slots_, memory) \
uc_bv_integer var_name ## _bitmap[UC_BV_LEN((num_slots_))] = {}; \
UCSlotAlloc var_name = { \
.slot_size = (slot_size_), \
.num_slots = (num_slots_), \
.bitmap = UC_BV_STATIC_INIT(var_name ## _bitmap), \
.slots = (memory) \
};
/** Allocate a memory slot
*
* @param sa The allocator to allocate from
* @return A pointer to the memory slot that's sa.slot_size big, or NULL if
* all slots are allocated
*/
void *uc_slot_alloc(UCSlotAlloc *sa);
/** Free a memory slot previously returned from uc_slot_alloc()
*
* @param sa The allocator to free from.
* @param slot The memory slot to free. Passing a NULL pointer is undefined behavior
*/
void uc_slot_free(UCSlotAlloc *restrict sa, void *restrict slot);
/** uc_slot_free() where the slot can be a NULL pointer */
#define uc_slot_free_safe(sa, slot) \
do { \
if ((slot) != NULL) { \
uc_slot_free((sa), (slot)); \
} \
} while (0)
#ifdef __cplusplus
}
#endif
#endif
+2 -1
View File
@@ -96,7 +96,8 @@ char* uc_sprintbs(char *result, unsigned short value);
/** Like http://swtch.com/plan9port/man/man3/getfields.html
*/
int getfields(char *str, char **args, int max, int mflag, const char *set);
int uc_getfields(char *str, char **args, int max, int mflag, const char *sep);
int uc_gettokens(char *str, char **args, int max, const char *sep);
//Converts bytes to a human representable test, (i.e. 12kB, 160 MB 1.78 GB etc.)
///result should be at least of size 12,
+9 -4
View File
@@ -38,7 +38,7 @@ void uc_strv_init(struct UCStrv *strv);
int uc_strv_grow(struct UCStrv *strv, size_t cnt);
/**
* Expand the UCStrv to hold attleast 1 more item if needed
* If needed, grow the UCStrv to hold atleast 1 more item.
*
* @param strv UCStrv to expand
* @return 0 on success, otherwise failure
@@ -46,7 +46,7 @@ int uc_strv_grow(struct UCStrv *strv, size_t cnt);
int uc_strv_check_expand(struct UCStrv *strv);
/**
* Append a string to the UCStrv, the string will be copied in
* Append a string to the UCStrv, the string will be copied in.
*
* @param strv UCStrv to append to
* @param str String to append, the string will be copied.
@@ -55,7 +55,7 @@ int uc_strv_check_expand(struct UCStrv *strv);
int uc_strv_append(struct UCStrv *strv, const char *restrict str);
/**
* Append a string to the strvec, nocopy variang.
* Append a string to the strvec without making a copy of the string.
* The string shold be dynamically allocated, as
* destroying the UCStrv will free() all items.
*
@@ -67,7 +67,7 @@ int uc_strv_append_nocopy(struct UCStrv *strv, char *restrict str);
/**
* Append a NULL pointer to the UCStrv, (cnt is not increased,
* so another _appended item will overwrite this NULL terminator)
* so another appended item will overwrite this NULL terminator)
*
* @param strv UCStrv to append to
* @return 0 on success, otherwise failure
@@ -101,6 +101,11 @@ void uc_strv_destroy(struct UCStrv *strv);
*/
int uc_strv_append_all(struct UCStrv *restrict a, struct UCStrv *restrict b, int copy);
/** Reverse the order of strings in a UCStrv
*
* @param strv strv to reverse.
*/
void uc_strv_reverse(struct UCStrv *strv);
#ifdef __cplusplus
}
#endif
+2
View File
@@ -96,6 +96,8 @@ void uc_timers_init_ex(struct UCTimers *t, struct UCoreClock *uclock);
* will be called when the timer expires, and the timer is removed from the engine
* User is responsible for the lifetime and memory of the UCTimer, which must exist until
* te timer is fired or removed.
* If the timer has previously been added, it will be removed first. So there
* is no need to call uc_timers_remove() to "re-schedule" a timer.
*
* @param timers timer engine to add timer to.
* @param timer timer to add
+51 -4
View File
@@ -4,6 +4,17 @@
#include "mbuf.h"
#include "iomux.h"
/** @addtogroup IOMux
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Return code from users write callback
*/
enum UC_WQ_RESULT {
/** INdicates the MBuf was fully processed and can be freed*/
UC_WQ_DONE = 1,
@@ -13,6 +24,8 @@ enum UC_WQ_RESULT {
UC_WQ_ABORT = -1
};
struct UCWQueue;
/**
* Callback that will be called when data can be written to the fd.
* The return value from this function must be strictly followed.
@@ -38,7 +51,9 @@ enum UC_WQ_RESULT {
* for this event.
*
*/
typedef enum UC_WQ_RESULT (*wqueue_write_cb)(struct IOMux *mux, struct IOMuxFD *fd, struct MBuf *mbuf);
typedef enum UC_WQ_RESULT (*wqueue_write_cb)(struct IOMux *mux,
struct UCWQueue *wqueue,
struct MBuf *mbuf);
/**
* Callback when read events are indicated.
@@ -49,17 +64,43 @@ typedef enum UC_WQ_RESULT (*wqueue_write_cb)(struct IOMux *mux, struct IOMuxFD *
* @param mux associated IOMux
* @param the fd of the current wqueue
*/
typedef enum UC_WQ_RESULT (*wqueue_read_cb)(struct IOMux *mux, struct IOMuxFD *fd);
typedef enum UC_WQ_RESULT (*wqueue_read_cb)(struct IOMux *mux,
struct UCWQueue *wqueue);
/** Represents a queue of data to write.
/**
* Callback to free a MBuf once it's fully written.
* @param the fd of the current wqueue
*/
typedef void (*wqueue_free_mbuf_cb)(struct MBuf *mbuf);
/**
* Represents a queue of data to write.
* UCWQueue replaces a raw IOMuxFD, and manages a queue
* of data to write, held as a list of struct MBuf.
* See also uc_wqueue_init
*
*/
struct UCWQueue {
/** Underlying IOMuxFD. This member needs to be registered
* with an IOMux, see the description of uc_wqueue_init
*/
struct IOMuxFD fd;
/** Linked list of struct MBuf
*/
struct TailQ queue;
/** Associated mux
*/
struct IOMux *mux;
/** Users callback for read events
*/
wqueue_read_cb read_cb;
/** Users callback for write events
*/
wqueue_write_cb write_cb;
/** Function used to free an MBuf - default is uc_mbuf_free()*/
wqueue_free_mbuf_cb free_cb;
/** Current number of queued struct MBuf
*/
unsigned int queue_len;
};
@@ -120,4 +161,10 @@ int uc_wqueue_enqueue(struct UCWQueue *wqueue, struct MBuf *mbuf);
*/
int uc_wqueue_flush(struct UCWQueue *wqueue);
#ifdef __cplusplus
}
#endif
/** @} (addtogroup)*/
#endif
+14
View File
@@ -0,0 +1,14 @@
configure_file (
"version.c.in"
"version.c"
)
file(GLOB SOURCE_FILES *.c)
add_library(
ucore SHARED
${SOURCE_FILES}
"${PROJECT_BINARY_DIR}/src/version.c"
)
set_target_properties(ucore PROPERTIES SOVERSION 1 VERSION 1.0.0)
target_link_libraries(ucore Threads::Threads)
install (TARGETS ucore DESTINATION lib)
+2
View File
@@ -21,3 +21,5 @@ ucore_env.Alias('install',
ucore_env.Install(os.path.join(prefix, 'lib'), [ucore_staticlib]))
ucore_env.Alias('install',
ucore_env.InstallVersionedLib(os.path.join(prefix, 'lib'), [ucore_sharedlib]))
ucore_env.Default([ucore_staticlib, ucore_sharedlib])
+19 -1
View File
@@ -2,6 +2,7 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "ucore/utils.h"
#include "ucore/bitvec.h"
#ifdef __GNUC__
@@ -12,6 +13,8 @@
#define unlikely(expr) (expr)
#endif
UC_STATIC_ASSERT(CHAR_BIT % 8 == 0);
static inline int bit_index(int b)
{
return b / (sizeof(uc_bv_integer) * CHAR_BIT);
@@ -41,7 +44,7 @@ struct UCBitVec *uc_bv_new(size_t nbits)
void uc_bv_free(struct UCBitVec *v)
{
if (v) {
if (likely(v != NULL)) {
free(v);
}
}
@@ -88,3 +91,18 @@ void uc_bv_set_all(struct UCBitVec *v)
memset(v->vec,0xff,v->vec_len * sizeof(uc_bv_integer));
}
int uc_bv_find_first_zero(const struct UCBitVec *v)
{
const size_t bits_per_word = sizeof(uc_bv_integer) * CHAR_BIT;
for (size_t i = 0; i < v->vec_len; i++) {
uc_bv_integer inverted = ~v->vec[i];
if (inverted != 0) {
int bit_pos = __builtin_ffsl(inverted) - 1; // ffsl returns 1-based index
return (int)(i * bits_per_word + bit_pos);
}
}
return -1;
}
+2 -2
View File
@@ -32,7 +32,7 @@ static void uc_cached_clock_now(const struct UCoreClock *uclock,
struct timeval *tv)
{
const struct UCoreCachedClock *cached_clock;
cached_clock = UC_CONST_CONTAINER_OF(uclock, const struct UCoreCachedClock, clock),
cached_clock = UC_CONST_CONTAINER_OF(uclock, struct UCoreCachedClock, clock),
*tv = cached_clock->cache;
}
@@ -55,7 +55,7 @@ void uc_cached_clock_update(struct UCoreCachedClock *uclock)
static void uc_settable_clock_now(const struct UCoreClock *uclock, struct timeval *tv)
{
const struct UCoreSettableClock *cached_clock;
cached_clock = UC_CONST_CONTAINER_OF(uclock, const struct UCoreSettableClock, clock),
cached_clock = UC_CONST_CONTAINER_OF(uclock, struct UCoreSettableClock, clock),
*tv = cached_clock->now;
}
+769 -35
View File
@@ -1,54 +1,788 @@
#include <stdint.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include "ucore/string.h"
#include "ucore/strvec.h"
#include "ucore/utils.h"
#include "ucore/backtrace.h"
//
enum UCCmdRc {
/**Executed ok */
UC_CMD_OK,
UC_CMDRC_OK,
/**Executed with warning */
UC_CMD_WARNING,
/*Not executed, incomplete command */
UC_CMD_INCOMPLETE,
UC_CMDRC_WARNING,
/*incomplete command */
UC_CMDRC_INCOMPLETE,
/*Command cann't uniquely be distinguished */
UC_CMDRC_AMBIGUOUS,
/* Command doesn't exist*/
UC_CMDRC_NOT_FOUND,
/*Not executed, generic error */
UC_CMD_ERROR,
UC_CMDRC_ERROR,
};
typedef enum UCCmdRc (*uc_cmd_handler)(int narg, char *args[]);
typedef void (*uc_cmd_write_cfg)(void);
#define UC_CMD_FL_HIDDEN (1 << 0)
struct UCCmdNode;
struct UCCmdDef;
struct UCCmdSettings {
const char *name;
const char *version;
const char *boot_cfg_file;
struct UCCmdNode *initial_node;
struct UCCmdNode *node_head;
enum UCCmdType {
UC_CMD_ROOT = 1,
UC_CMD_KEYWORD,
UC_CMD_LIST,
UC_CMD_STRING,
UC_CMD_END,
};
struct UCCmdNode {
int id;
uc_cmd_write_cfg write_func;
struct UCCmdDef *cmd_head; //linked list of UCCmdDef
struct UCCmdNode *next;
struct UCCmdWord {
char *word;
char *descr;
};
struct UCCmdList {
struct UCStrv words;
struct UCStrv descrs;
};
struct UCCmdArgs;
typedef enum UCCmdRc (*UCCmdHandler)(const struct UCCmdArgs *args);
struct UCCmdDef {
const char *cmd;
const char **help;
size_t cmd_len;
uc_cmd_handler cb;
const char *help;
UCCmdHandler callback;
uint32_t flags;
};
struct UCCmdDef *next;
struct UCCmdArgs {
struct UCStrv argv;
const struct UCCmdDef *cmd;
void *ctx;
};
struct UCCmdRunner;
typedef int (*UCCmdRootExit)(struct UCCmdRunner *r, int current_id, void *ctx);
struct UCCmdRoot {
int node_id;
UCCmdRootExit exit_callback;
};
/**
* Command are broken into words and inserted into a tree.
* the 3 commands:
* show all
* date
* show all bottles
* Results in the tree:
*
* +--------+ child +--------+ child +-------+ child +-----+
* | root |------->| show |------->| all |------>| END |
* +--------+ +--------+ +-------+ +-----+
* | next | next
* V V
* +--------+ child +-----+ +--------+ child +-----+
* | date |-----> | END | | bottles|------>| END |
* +--------+ +-----+ +--------+ +-----+
*
* END nodes are complete commands. Other child/next pointers will be nULL
*/
struct UCCmdNode {
enum UCCmdType type;
union {
struct UCCmdWord word;
struct UCCmdList list;
const struct UCCmdDef *cmd;
const struct UCCmdRootExit *root;
} data;
uint32_t flags;
struct UCCmdNode *next; //next at same level
struct UCCmdNode *child;
struct UCCmdNode *parent;
};
struct UCCmdRunner {
struct UCCmdNode *current_root;
struct UCCmdNode _root;
};
//max words in a single command
#define UC_CMD_MAX_WORDS 32
struct UCCmdTokenizer {
char *cmd_copy;
char *cmd_words[UC_CMD_MAX_WORDS];
int num_words;
};
void uc_cmd_init(const char *app_name, const char *version);
int uc_cmd_read_config(const char *filename);
void uc_cmd_set_configfile(const char *filename);
void uc_cmd_add_cmd(struct UCCmdDef *cmd, int parent_node_id);
void uc_cmd_set_default_node(int node_id);
void
print_args(const struct UCStrv *args);
static int uc_str_empty(const char *str)
{
while (*str) {
if (!isspace(*str++)) {
return 0;
}
}
return 0;
}
static int
uc_cmd_type_is_variable(enum UCCmdType type)
{
return type == UC_CMD_LIST ||
type == UC_CMD_STRING;
}
static void
uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd, const char *delim)
{
t->num_words = 0;
t->cmd_copy = strdup(cmd);
if (t->cmd_copy == NULL) {
assert(t->cmd_copy);
return;
}
if (delim == NULL) {
delim = "\r\n\t\v ";
}
t->num_words = uc_getfields(t->cmd_copy,
t->cmd_words,
ARRAY_SIZE(t->cmd_words),
1,
delim);
}
static void
uc_cmd_tokenize_destroy(struct UCCmdTokenizer *t)
{
free(t->cmd_copy);
t->num_words = 0;
t->cmd_copy = NULL;
}
void
uc_cmd_runner_init(struct UCCmdRunner *r)
{
memset(r, 0, sizeof *r);
r->current_root = &r->_root;
r->_root.type = UC_CMD_ROOT;
}
void
uc_cmd_node_dealloc(struct UCCmdNode *n)
{
struct UCCmdNode *next;
while (n) {
uc_cmd_node_dealloc(n->child);
next = n->next;
if (n->type == UC_CMD_KEYWORD) {
free(n->data.word.word);
free(n->data.word.descr);
} else if (n->type == UC_CMD_LIST) {
uc_strv_destroy(&n->data.list.words);
uc_strv_destroy(&n->data.list.descrs);
} else if (n->type == UC_CMD_STRING) {
free(n->data.word.word);
free(n->data.word.descr);
}
free(n);
n = next;
}
}
void
uc_cmd_runner_destroy(struct UCCmdRunner *r)
{
uc_cmd_node_dealloc(r->_root.child);
r->current_root->child = NULL;
}
static struct UCCmdNode *
uc_cmd_node_alloc(enum UCCmdType type, uint32_t flags)
{
struct UCCmdNode *n;
n = calloc(1, sizeof *n);
if (n == NULL) {
return NULL;
}
n->type = type;
n->flags = flags;
return n;
}
static struct
UCCmdNode *uc_cmd_node_create_list(const char *word)
{
struct UCCmdNode *node = NULL;
struct UCCmdTokenizer t;
uc_cmd_tokenize(&t, word, "() |\t\v");
if (t.num_words > 0) {
node = uc_cmd_node_alloc(UC_CMD_LIST, 0);
if (node != NULL) {
uc_strv_init(&node->data.list.words);
uc_strv_init(&node->data.list.descrs);
for (int i = 0; i < t.num_words; i++) {
uc_strv_append(&node->data.list.words, t.cmd_words[i]);
}
}
}
uc_cmd_tokenize_destroy(&t);
return node;
}
static struct UCCmdNode *
uc_cmd_node_create_word(enum UCCmdType type, const char *word)
{
struct UCCmdNode *node;
node = uc_cmd_node_alloc(type, 0);
if (node != NULL) {
node->data.word.word = strdup(word);
}
return node;
}
static struct UCCmdNode *
uc_cmd_node_create(const char *word)
{
struct UCCmdNode *node;
if (word[0] == '(') { //list (foo|bar|baz)
node = uc_cmd_node_create_list(word);
} else if (isupper(word[0])) {
node = uc_cmd_node_create_word(UC_CMD_STRING, word);
} else {
node = uc_cmd_node_create_word(UC_CMD_KEYWORD, word);
}
return node;
}
static int
uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *matches)
{
size_t word_len;
int found = 0;
if (word == NULL || word[0] == 0) {
return 0;
}
word_len = strlen(word);
if (n->type == UC_CMD_KEYWORD) {
if (strncmp(word, n->data.word.word, word_len) == 0) {
if (matches != NULL) {
uc_strv_append(matches, n->data.word.word);
}
found = 1;
}
} else if (n->type == UC_CMD_LIST) {
const struct UCStrv *v = &n->data.list.words;
assert(v);
for(size_t i = 0; i < v->cnt; i++) {
if (strncmp(word, v->strings[i], word_len) == 0) {
if (matches != NULL) {
uc_strv_append(matches, v->strings[i]);
}
found = 1;
}
}
} else if (n->type == UC_CMD_STRING) {
if (matches != NULL) {
uc_strv_append(matches, word);
}
found = 1;
}
return found;
}
static struct UCCmdNode *
uc_cmd_add(struct UCCmdNode *parent, const char *word)
{
struct UCCmdNode *new_node;
struct UCCmdNode **iter = &parent->child;
assert(parent);
new_node = uc_cmd_node_create(word);
if (new_node == NULL) {
return NULL;
}
new_node->parent = parent;
while (*iter) {
struct UCCmdNode *n = *iter;
if (uc_cmd_type_is_variable(new_node->type) && n->type != UC_CMD_END) {
//we don't support combinations of keywords and variables
//at the same level.
uc_cmd_node_dealloc(new_node);
return NULL;
}
//TODO check for ambiguous word (e.g. add "short" when "shorter" already exists)
if (new_node->type == UC_CMD_KEYWORD && uc_cmd_node_match(n, word, NULL)) {
uc_cmd_node_dealloc(new_node);
return *iter;
}
iter = &n->next;
}
*iter = new_node;
return new_node;
}
static int
uc_cmd_node_add_help(struct UCCmdNode *node)
{
struct UCCmdTokenizer t;
int i;
if (node->data.cmd->help == NULL) {
//allow helpless commands
return 0;
}
if (node->type != UC_CMD_END) {
return -10;
}
uc_cmd_tokenize(&t, node->data.cmd->help, "\n");
if (t.num_words <= 0) {
uc_cmd_tokenize_destroy(&t);
return -11;
}
i = t.num_words - 1;
//we have the last node in the tree
//Walk it up towards the root(backwards) and fill
//in help texts where it's missing.
while (node->parent) {
node = node->parent;
if (node->type == UC_CMD_ROOT) {
break;
}
if (i < 0) {
break;
}
if (node->type == UC_CMD_KEYWORD ||
node->type == UC_CMD_STRING) {
if (node->data.word.descr == NULL &&
!uc_str_empty(t.cmd_words[i])) {
node->data.word.descr = strdup(t.cmd_words[i]);
}
i--;
} else if (node->type == UC_CMD_LIST) {
if (node->data.list.descrs.cnt == 0) {
for (int k = (int)node->data.list.words.cnt -1; k >= 0; k++) {
if (i < 0) {
break;
}
uc_strv_append(&node->data.list.descrs, t.cmd_words[i]);
i--;
}
} else {
i -= (int)node->data.list.words.cnt;
}
}
}
uc_cmd_tokenize_destroy(&t);
if (node->type != UC_CMD_ROOT || i != -1) {
//we didn't consume all the help tokens, so the
//command definition is screwd up
return -20;
}
return 0;
}
int
uc_cmd_install_noassert(struct UCCmdRunner *r, struct UCCmdDef *cmd)
{
struct UCCmdNode *node = r->current_root;
struct UCCmdNode *new_node;
struct UCCmdTokenizer t;
int rc;
uc_cmd_tokenize(&t, cmd->cmd, NULL);
if (t.num_words <= 0) {
uc_cmd_tokenize_destroy(&t);
return -1;
}
for (int i = 0; i < t.num_words; i++) {
node = uc_cmd_add(node, t.cmd_words[i]);
if (node == NULL) {
uc_cmd_tokenize_destroy(&t);
return -2;
}
}
//TODO, check for duplicate command here.
new_node = uc_cmd_node_alloc(UC_CMD_END, 0);
if (new_node == NULL) {
uc_cmd_tokenize_destroy(&t);
return -1;
}
new_node->data.cmd = cmd;
new_node->next = node->child;
node->child = new_node;
new_node->parent = node;
rc = uc_cmd_node_add_help(new_node);
uc_cmd_tokenize_destroy(&t);
return rc;
}
void
uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd)
{
int rc;
rc = uc_cmd_install_noassert(r, cmd);
UC_ASSERT(rc == 0);
}
enum UCCmdRc
uc_cmd_find(struct UCCmdNode *first,
const struct UCCmdTokenizer *t,
struct UCStrv *matches,
struct UCCmdNode **result)
{
struct UCCmdNode *node = first;
struct UCCmdNode *found = NULL;
enum UCCmdRc rc = UC_CMDRC_NOT_FOUND;
for (int i = 0; i < t->num_words && node; i++) {
int n_found = 0;
while (node) {
if (uc_cmd_node_match(node, t->cmd_words[i], matches)) {
if (n_found == 0) {
//keep the 1. matched
found = node;
}
n_found++;
}
node = node->next;
}
if (n_found == 1) {
node = found->child;
rc = UC_CMDRC_OK;
} else if (n_found > 1) {
node = found;
rc = UC_CMDRC_AMBIGUOUS;
break;
}
}
*result = found;
if (found == NULL) {
rc = UC_CMDRC_NOT_FOUND;
}
return rc;
}
enum UCCmdRc
uc_cmd_parse_and_find(struct UCCmdRunner *r, const char *cmd_line,
struct UCStrv *matches,
struct UCCmdNode **result)
{
struct UCCmdNode *node = r->current_root->child;
struct UCCmdTokenizer t;
enum UCCmdRc rc = UC_CMDRC_ERROR;
//make a copy since getfields destroys the original string
uc_cmd_tokenize(&t, cmd_line, NULL);
if (t.num_words > 0) {
//match the commands towards the command tree
//
rc = uc_cmd_find(node, &t, matches, result);
}
uc_cmd_tokenize_destroy(&t);
return rc;
}
enum UCCmdRc
uc_cmd_help(struct UCCmdRunner *r, const char *cmd_line, struct UCStrv *completions)
{
struct UCCmdNode *found = NULL;
enum UCCmdRc rc;
rc = uc_cmd_parse_and_find(r, cmd_line, NULL, &found);
if (rc == UC_CMDRC_OK) {
struct UCCmdNode *node = found;
if (node->type == UC_CMD_LIST) {
uc_strv_append_all(completions, &node->data.list.descrs, 1);
} else if (node->type == UC_CMD_STRING ||
node->type == UC_CMD_KEYWORD) {
if (node->data.word.descr != NULL) {
uc_strv_append(completions, node->data.word.descr);
}
}
}
return rc;
}
enum UCCmdRc
uc_cmd_complete(struct UCCmdRunner *r, const char *cmd_line, struct UCStrv *completions)
{
struct UCCmdNode *found = NULL;
enum UCCmdRc rc;
rc = uc_cmd_parse_and_find(r, cmd_line, NULL, &found);
if (rc != UC_CMDRC_NOT_FOUND && found != NULL) {
struct UCCmdNode *node = found->child;
while (node) {
if (node->type == UC_CMD_END) {
uc_strv_append(completions, "<CR>");
} else if (node->type == UC_CMD_LIST) {
uc_strv_append_all(completions, &node->data.list.words, 1);
} else if (node->type == UC_CMD_STRING ||
node->type == UC_CMD_KEYWORD) {
uc_strv_append(completions, node->data.word.word);
}
node = node->next;
}
}
return rc;
}
enum UCCmdRc
uc_cmd_run_ctx(struct UCCmdRunner *r, const char *cmd_line, void *ctx)
{
struct UCCmdArgs args = {
.argv = UC_STRV_INITIALIZER,
.ctx = ctx,
};
struct UCCmdNode *found = NULL;
enum UCCmdRc rc;
rc = uc_cmd_parse_and_find(r, cmd_line, &args.argv, &found);
if (rc == UC_CMDRC_OK) {
found = found->child;
// Now check the current level for any UC_CMD_END
// which indicates a complete command
while (found) {
if (found->type == UC_CMD_END) {
break;
}
found = found->next;
}
if (found != NULL) {
const struct UCCmdDef *cmd = found->data.cmd;
args.cmd = cmd;
rc = cmd->callback(&args);
} else {
rc = UC_CMDRC_INCOMPLETE;
}
}
uc_strv_destroy(&args.argv);
return rc;
}
enum UCCmdRc
uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line)
{
return uc_cmd_run_ctx(r, cmd_line, NULL);
}
void print_args(const struct UCStrv *args)
{
for (size_t i = 0; i < args->cnt; i++) {
printf("arg %zu: '%s' ", i, args->strings[i]);
}
puts("");
}
enum UCCmdRc cmd1_cb(const struct UCCmdArgs *args)
{
puts(__func__);
print_args(&args->argv);
return UC_CMDRC_OK;
}
enum UCCmdRc cmd2_cb(const struct UCCmdArgs *args)
{
puts(__func__);
print_args(&args->argv);
return UC_CMDRC_OK;
}
enum UCCmdRc cmd3_cb(const struct UCCmdArgs *args)
{
puts(__func__);
print_args(&args->argv);
return UC_CMDRC_OK;
}
enum UCCmdRc cmd4_cb(const struct UCCmdArgs *args)
{
puts(__func__);
print_args(&args->argv);
return UC_CMDRC_OK;
}
void do_complete(struct UCCmdRunner *r, const char *command)
{
struct UCStrv completions = UC_STRV_INITIALIZER;
uc_cmd_complete(r, command, &completions);
if (completions.cnt > 0) {
printf("Possible completions for '%s' :\n", command);
for (size_t i = 0; i < completions.cnt; i++) {
printf("\t%s\n", completions.strings[i]);
}
} else {
printf("No completions for '%s' :\n", command);
}
uc_strv_destroy(&completions);
}
void do_help(struct UCCmdRunner *r, const char *command)
{
struct UCStrv completions = UC_STRV_INITIALIZER;
uc_cmd_help(r, command, &completions);
if (completions.cnt > 0) {
printf("help for '%s' :\n", command);
for (size_t i = 0; i < completions.cnt; i++) {
printf("\t%s\n", completions.strings[i]);
}
} else {
printf("No help for '%s' :\n", command);
}
uc_strv_destroy(&completions);
}
int main(int argc, char *argv[])
{
char line[128];
struct UCCmdRunner r;
struct UCCmdDef cmd1 = {
"show all",
"show stuff\nEverything\n",
cmd1_cb,
0,
NULL
};
struct UCCmdDef cmd2 = {
"show empty",
" \n everyhing that's empty\n",
cmd2_cb,
0,
NULL
};
struct UCCmdDef cmd3 = {
"show empty bottle",
NULL,
cmd3_cb,
0,
NULL
};
struct UCCmdDef cmd4 = {
"delete file NAME",
"delete\nfile\nName of the file\n",
cmd4_cb,
0,
NULL
};
uc_cmd_runner_init(&r);
uc_cmd_install(&r, &cmd1);
uc_cmd_install(&r, &cmd2);
uc_cmd_install(&r, &cmd3);
uc_cmd_install(&r, &cmd4);
uc_cmd_run(&r, "delete file /tmp/a");
uc_cmd_run(&r, "show all");
uc_cmd_run(&r, "show empty");
uc_cmd_run(&r, "sh emp b");
uc_cmd_run(&r, "");
do_help(&r, "delete file /tmp/a");
do_help(&r, "show empty");
do_help(&r, "show all");
do_help(&r, "sh");
do_help(&r, "");
/*
while (fgets(line,sizeof line, stdin)) {
enum UCCmdRc rc = uc_cmd_run(&r, line);
if (rc != UC_CMDRC_OK) {
printf("Command failed with code %d\n", rc);
}
}
*/
do_complete(&r, "sho em");
do_complete(&r, "show ");
do_complete(&r, "");
do_complete(&r, "delet ");
do_complete(&r, "delete ");
do_complete(&r, "delete file");
do_complete(&r, "delete fil");
uc_cmd_runner_destroy(&r);
return 1;
}
+1 -1
View File
@@ -2,7 +2,7 @@
#include "ucore/string.h"
int
getfields(char *str, char **args, int max, int mflag, const char *set)
uc_getfields(char *str, char **args, int max, int mflag, const char *set)
{
char r;
int intok, narg;
+58
View File
@@ -0,0 +1,58 @@
#include <string.h>
#include "ucore/string.h"
//tokenize string, and exclude the quotes
static char *qtoken(char *s, const char *sep)
{
int inquote = 0;
char *t = s;
while (*t != 0 && (inquote || strchr(sep, *t) == NULL)) {
if (*t != '"') {
*s++ = *t++;
continue;
}
if (!inquote) {
inquote = 1;
t++;
continue;
}
if (t[1] != '"') {
t++;
inquote = 0;
continue;
}
//double quotes, merged to 1 quote
t++;
*s++ = *t++;
}
if (*s != 0) {
*s = 0;
if (t == s) {
t++;
}
}
return t;
}
int uc_gettokens(char *str, char **args, int maxargs, const char *sep)
{
int nargs;
for (nargs = 0; nargs < maxargs; nargs++) {
while (*str != 0 && strchr(sep, *str) != NULL) {
*str++ = 0;
}
if (*str == 0) {
break;
}
args[nargs] = str;
str = qtoken(str, sep);
}
return nargs;
}
-1
View File
@@ -151,7 +151,6 @@ int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd, unsigned int what
if (fd->what != what) {
fd->what = what;
rc = mux->ops.update_events_impl(mux, fd);
fd->what = what;
}
return rc;
+2 -2
View File
@@ -44,7 +44,7 @@ static int iomux_select_update_events(struct IOMux *mux_, struct IOMuxFD *fd)
struct IOMuxSelect *mux = mux_->instance;
if (fd->fd < 0 || fd->fd >= FD_SETSIZE) {
return EINVAL;
return ENFILE;
}
if (fd->what & MUX_EV_READ)
@@ -70,7 +70,7 @@ static int iomux_select_register_fd(struct IOMux *mux_, struct IOMuxFD *fd)
rc = iomux_select_update_events(mux_, fd);
if (rc != 0) {
return ENFILE;
return rc;
}
mux->descriptors[fd->fd] = fd;
+2 -2
View File
@@ -1,4 +1,4 @@
/*Copyright (c) 2004 Nils O. Selåsdal <NOS {on} Utel {dot} no> */
/*Copyright (c) 2004 Nils O. Selsdal <NOS {on} Utel {dot} no> */
/*Straight forward attempt at a Mersenne Twister PRNG */
#include "ucore/mersenne_twister.h"
@@ -24,7 +24,7 @@ enum {
void mtsrand(int seed, MTRand *r)
{
int j;
unsigned j;
for (j = 0 ; j < N ; j++) {
r->x[j] = seed * ((j+1)<< 3)|0x1;
}
+67
View File
@@ -0,0 +1,67 @@
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "ucore/bitvec.h"
#include "ucore/slot_allocator.h"
void *uc_slot_alloc(UCSlotAlloc *sa)
{
int free_slot = uc_bv_find_first_zero(&sa->bitmap);
if (free_slot < 0) {
return NULL;
} else if ((size_t)free_slot >= sa->num_slots) { // bit vector may have more bits than slots
return NULL;
}
uc_bv_set_bit(&sa->bitmap, free_slot);
return sa->slots + free_slot * sa->slot_size;
}
void uc_slot_free(UCSlotAlloc *restrict sa, void *restrict slot)
{
assert((uint8_t *)slot >= sa->slots);
int slot_index = ((uint8_t *)slot - sa->slots) / sa->slot_size;
assert((size_t)slot_index < sa->num_slots);
uc_bv_clr_bit(&sa->bitmap, slot_index);
}
int main()
{
UC_SLOT_ALLOC_DEF(sa, 24, 1)
void *p1 = uc_slot_alloc(&sa);
printf("%p\n", &sa_memory.memory[0]);
printf("%p\n", p1);
void *p2 = uc_slot_alloc(&sa);
printf("%p\n", p2);
uc_slot_free(&sa, p1);
p2 = uc_slot_alloc(&sa);
printf("%p\n", p2);
printf("__malloc__\n");
void *v = malloc(24 * (1<<16));
UC_SLOT_ALLOC_DEF_EX(sa2, 24, (1<<16), v)
char *v2 = NULL;
for (int i = 0; i < 1<<16; i++) {
char *c = uc_slot_alloc(&sa2);
if (c == NULL) {
printf("uc_slot_alloc failed at %d\n", i);
break;
}
*c = i;
if (i == 0) {
v2 = c;
}
}
for (int i = (1<<16) -1 ; i >= 0; i--) {
uc_slot_free(&sa2, v2 + 24*i);
}
free(v);
return 0;
}
+11
View File
@@ -130,3 +130,14 @@ int uc_strv_append_all(struct UCStrv *restrict a, struct UCStrv *restrict b, int
return 0;
}
void uc_strv_reverse(struct UCStrv *strv)
{
for (size_t i = 0; i < strv->cnt / 2; i++) {
size_t k = strv->cnt - i - 1;
char *tmp = strv->strings[i];
strv->strings[i] = strv->strings[k];
strv->strings[k] = tmp;
}
}
+4 -4
View File
@@ -1,11 +1,11 @@
//Various info about the version and build.
//The SConscript file substitutes these at build time
const int ucore_version_major = @version_major@;
const int ucore_version_minor = @version_minor@;
const int ucore_version_patch = @version_patch@;
const int ucore_version_major = @libucore_VERSION_MAJOR@;
const int ucore_version_minor = @libucore_VERSION_MINOR@;
const int ucore_version_patch = @libucore_VERSION_PATCH@;
const char ucore_version_str[] = "@version_str@";
const char ucore_version_str[] = "@libucore_VERSION@";
const char ucore_build_host[] = "@build_host@";
const char ucore_build_type[] = "@build_type@";
+5 -5
View File
@@ -15,7 +15,7 @@ static int uc_wqueue_handle_write(struct UCWQueue *wqueue)
q = UC_TAILQ_FIRST(&wqueue->queue);
mbuf = UC_TAILQ_CONTAINER(q, struct MBuf, entry);
rc = wqueue->write_cb(mux, fd, mbuf);
rc = wqueue->write_cb(mux, wqueue, mbuf);
if (rc <= 0) {
//NOTE for rc < 0, nothing can touch the wqueue or fd
//any more, as it might been free'd
@@ -24,7 +24,7 @@ static int uc_wqueue_handle_write(struct UCWQueue *wqueue)
mbuf = uc_mbuf_dequeue(&wqueue->queue);
assert(mbuf != NULL);
uc_mbuf_free(mbuf);
wqueue->free_cb(mbuf);
wqueue->queue_len--;
}
@@ -58,7 +58,7 @@ static void uc_wqueue_cb(struct IOMux *mux, struct IOMuxFD *fd, unsigned int wha
if (rc >= 0 && what & MUX_EV_READ) {
rc = wqueue->read_cb(mux, fd);
rc = wqueue->read_cb(mux, wqueue);
//NOTE - can't touch the wqueue or fd after this point,
//as it might been free'd
}
@@ -71,7 +71,7 @@ void uc_wqueue_init(struct UCWQueue *wqueue, struct IOMux *mux)
memset(wqueue, 0, sizeof *wqueue);
wqueue->mux = mux;
wqueue->fd.callback = uc_wqueue_cb;
wqueue->free_cb = uc_mbuf_free;
uc_tailq_init(&wqueue->queue);
}
@@ -81,7 +81,7 @@ int uc_wqueue_clear(struct UCWQueue *wqueue)
int rc = 0;
while ((buf = uc_mbuf_dequeue(&wqueue->queue)) != NULL) {
uc_mbuf_free(buf);
wqueue->free_cb(buf);
wqueue->queue_len--;
}
+16
View File
@@ -0,0 +1,16 @@
file(GLOB TEST_SOURCE_FILES test_*.c)
link_libraries(check ucore Threads::Threads)
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
include_directories("/opt/homebrew/include")
link_directories("/opt/homebrew/lib")
list(REMOVE_ITEM TEST_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/test_ringbuf.c)
else()
link_libraries(rt)
endif()
add_executable(test_runner ${TEST_SOURCE_FILES})
add_custom_target(test COMMAND test_runner
DEPENDS test_runner
WORKING_DIRECTORY ${CMAKE_PROJECT_DIR})
+1 -1
View File
@@ -39,4 +39,4 @@ cmd = test_env.Command(target='test_phony' ,
action= test_env.Dir('.').abspath + '/' + test_executable)
test_env.Depends(cmd, prog)
test_env.AlwaysBuild(cmd)
test_env.Default(test_executable)
+5 -5
View File
@@ -9,7 +9,7 @@
#include <ucore/fd_utils.h>
int stdout_read(struct IOMux *mux, struct IOMuxFD *fd)
int stdout_read(struct IOMux *mux, struct UCWQueue *wqueue)
{
return 1;
}
@@ -24,9 +24,9 @@ void stdin_read_cb(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event)
printf("Read %d bytes\n", len);
if (len <= 0) {
uc_mbuf_free(mbuf);
iomux_unregister_fd(mux, fd);
uc_wqueue_clear(wqueue);
iomux_unregister_fd(mux, &wqueue->fd);
uc_wqueue_clear(wqueue);
iomux_unregister_fd(mux, fd);
return;
}
@@ -44,7 +44,7 @@ struct IOMuxFD stdin_fd = {
};
int stdout_write(struct IOMux *mux, struct IOMuxFD *fd, struct MBuf *mbuf)
int stdout_write(struct IOMux *mux, struct UCWQueue *wqueue, struct MBuf *mbuf)
{
uint32_t len;
ssize_t wlen;
@@ -52,7 +52,7 @@ int stdout_write(struct IOMux *mux, struct IOMuxFD *fd, struct MBuf *mbuf)
len = uc_mbuf_len(mbuf);
data = uc_mbuf_pull(mbuf, len);
wlen = write(fd->fd, data, len);
wlen = write(wqueue->fd.fd, data, len);
if (wlen < 0) {
if (errno != EWOULDBLOCK) {
+80
View File
@@ -0,0 +1,80 @@
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include "ucore/iomux.h"
void in_cb(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event)
{
char buf[16];
ssize_t rc;
rc = read(fd->fd, buf, sizeof buf);
printf("Read returned %ld\n", (long)rc);
if (rc <= 0) {
if (rc == -1 && errno == EAGAIN) {
return;
} else if (rc == -1) {
perror("read");
}
return;
}
iomux_unregister_fd(mux, fd);
close(fd->fd);
}
void out_cb(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event)
{
char str[] = "hello";
ssize_t rc;
rc = write(fd->fd, str, strlen(str));
printf("write returned %ld\n", (long)rc);
if (rc <= 0) {
if (rc == -1 && errno == EAGAIN) {
return;
} else {
perror("write");
}
iomux_unregister_fd(mux, fd);
}
}
int main(int argc, char *argv[])
{
int pipes[2];
pipe(pipes);
uc_set_nonblocking(pipes[0]);
uc_set_nonblocking(pipes[1]);
struct IOMuxFD rfd= {
.fd = pipes[0],
.what = MUX_EV_READ,
.callback = in_cb,
};
struct IOMuxFD wfd= {
.fd = pipes[1],
.what = MUX_EV_WRITE,
.callback = out_cb,
};
signal(SIGPIPE, SIG_IGN);
struct IOMux *mux = iomux_create(IOMUX_TYPE_SELECT);
iomux_register_fd(mux, &rfd);
iomux_register_fd(mux, &wfd);
iomux_run(mux);
return 0;
}
+42 -42
View File
@@ -8,12 +8,12 @@ START_TEST (test_2bcd_1234567890)
unsigned char bcd[5];
size_t len = uc_ascii2bcd(ascii, bcd, 0);
fail_if(len != 5, "len is %zu", len);
fail_if(bcd[0] != 0x21,"was 0x%x",bcd[0]);
fail_if(bcd[1] != 0x43,"was 0x%x",bcd[1]);
fail_if(bcd[2] != 0x65,"was 0x%x",bcd[2]);
fail_if(bcd[3] != 0x87,"was 0x%x",bcd[3]);
fail_if(bcd[4] != 0x09,"was 0x%x",bcd[4]);
ck_assert_int_eq(len, 5);
ck_assert_int_eq(bcd[0], 0x21);
ck_assert_int_eq(bcd[1], 0x43);
ck_assert_int_eq(bcd[2], 0x65);
ck_assert_int_eq(bcd[3], 0x87);
ck_assert_int_eq(bcd[4], 0x09);
}
END_TEST
@@ -23,7 +23,7 @@ START_TEST (test_2bcd_empty)
unsigned char bcd[1];
size_t len = uc_ascii2bcd(ascii, bcd, 3);
fail_if(len != 0, "len is %zu", len);
ck_assert_int_eq(len, 0);
}
END_TEST
@@ -33,8 +33,8 @@ START_TEST (test_2bcd_1_filler)
unsigned char bcd[1];
size_t len = uc_ascii2bcd(ascii, bcd, 0xa);
fail_if(len != 1, "len is %zu", len);
fail_if(bcd[0] != 0xa1,"was 0x%x",bcd[0]);
ck_assert_int_eq(len, 1);
ck_assert_int_ne(bcd[0], 0);
}
END_TEST
@@ -44,10 +44,10 @@ START_TEST (test_2bcd_2_filler)
unsigned char bcd[2];
size_t len = uc_ascii2bcd(ascii, bcd, 0xf);
fail_if(len != 2, "len is %zu", len);
fail_if(bcd[0] != 0x21,"was 0x%x",bcd[0]);
fail_if(bcd[1] != 0xf3,"was 0x%x",bcd[1]);
fail_if(UC_BCD_LEN(strlen(ascii)) != len);
ck_assert_int_eq(len , 2);
ck_assert_int_eq(bcd[0] , 0x21);
ck_assert_int_eq(bcd[1] , 0xf3);
ck_assert_int_eq(UC_BCD_LEN(strlen(ascii)) , len);
}
END_TEST
@@ -58,9 +58,9 @@ START_TEST (test_2bcd_3_filler)
unsigned char bcd[2];
size_t len = uc_ascii2bcd(ascii, bcd, 0x0);
fail_if(len != 2, "len is %zu", len);
fail_if(bcd[0] != 0x21,"was 0x%x",bcd[0]);
fail_if(bcd[1] != 0x03,"was 0x%x",bcd[1]);
ck_assert_int_eq(len , 2);
ck_assert_int_eq(bcd[0] , 0x21);
ck_assert_int_eq(bcd[1] , 0x03);
}
END_TEST
@@ -71,7 +71,7 @@ START_TEST (test_2bcd_non_digits)
unsigned char bcd[10];
size_t len = uc_ascii2bcd(ascii, bcd, 0x0);
fail_if(len != 0, "len is %zu", len);
ck_assert_int_eq(len , 0);
}
END_TEST
@@ -82,12 +82,12 @@ START_TEST (test_2bcd_phoneno)
unsigned char bcd[24];
size_t len = uc_ascii2bcd(ascii, bcd, 0xf);
fail_if(len != 5, "len is %zu", len);
fail_if(bcd[0] != 0x00,"was 0x%x",bcd[0]);
fail_if(bcd[1] != 0x74,"was 0x%x",bcd[1]);
fail_if(bcd[2] != 0x23,"was 0x%x",bcd[1]);
fail_if(bcd[3] != 0x33,"was 0x%x",bcd[1]);
fail_if(bcd[4] != 0xf4,"was 0x%x",bcd[1]);
ck_assert_int_eq(len , 5);
ck_assert_int_eq(bcd[0] , 0x00);
ck_assert_int_eq(bcd[1] , 0x74);
ck_assert_int_eq(bcd[2] , 0x23);
ck_assert_int_eq(bcd[3] , 0x33);
ck_assert_int_eq(bcd[4] , 0xf4);
}
END_TEST
@@ -98,8 +98,8 @@ START_TEST (test_2bcd_binary)
unsigned char bcd[24];
size_t len = uc_ascii2bcd(ascii, bcd, 0xf);
fail_if(len != 1, "len is %zu", len);
fail_if(bcd[0] != 0xf2,"0 was 0x%x",bcd[0]);
ck_assert_int_eq(len , 1);
ck_assert_int_eq(bcd[0], 0xf2);
}
END_TEST
@@ -110,13 +110,13 @@ START_TEST (test_2hex_1)
char ascii[sizeof bcd * 2 + 1];
size_t len = uc_bcd2ascii(bcd, sizeof bcd, ascii);
fail_if(len != 4, "len is %zu", len);
fail_if(ascii[0] != '1',"0 was %c",ascii[0]);
fail_if(ascii[1] != '2',"1 was %c",ascii[1]);
fail_if(ascii[2] != '3',"2 was %c",ascii[2]);
fail_if(ascii[3] != '4',"3 was %c",ascii[3]);
fail_if(ascii[4] != 0, "4 was %c",ascii[4]);
fail_if(UC_ASCII_LEN(sizeof bcd) != len);
ck_assert_int_eq(len, 4);
ck_assert_int_eq(ascii[0], '1');
ck_assert_int_eq(ascii[1], '2');
ck_assert_int_eq(ascii[2], '3');
ck_assert_int_eq(ascii[3], '4');
ck_assert_int_eq(ascii[4], 0);
ck_assert_int_eq(UC_ASCII_LEN(sizeof bcd) , len);
}
END_TEST
@@ -127,14 +127,14 @@ START_TEST (test_2hex_2)
char ascii[sizeof bcd * 2 + 1];
size_t len = uc_bcd2ascii(bcd, sizeof bcd, ascii);
fail_if(len != 6, "len is %zu", len);
fail_if(ascii[0] != '0',"0 was %c",ascii[0]);
fail_if(ascii[1] != 'F',"1 was %c",ascii[1]);
fail_if(ascii[2] != 'F',"2 was %c",ascii[2]);
fail_if(ascii[3] != 'F',"3 was %c",ascii[3]);
fail_if(ascii[4] != '0', "4 was %c",ascii[4]);
fail_if(ascii[5] != '0', "5 was %c",ascii[5]);
fail_if(ascii[6] != 0, "6 was %c",ascii[6]);
ck_assert_int_eq(len , 6);
ck_assert_int_eq(ascii[0] , '0');
ck_assert_int_eq(ascii[1] , 'F');
ck_assert_int_eq(ascii[2] , 'F');
ck_assert_int_eq(ascii[3] , 'F');
ck_assert_int_eq(ascii[4] , '0');
ck_assert_int_eq(ascii[5] , '0');
ck_assert_int_eq(ascii[6] , 0);
}
END_TEST
@@ -146,8 +146,8 @@ START_TEST (test_2hex_empty)
ascii[0] = 0xFF;
size_t len = uc_bcd2ascii(bcd, 0, ascii);
fail_if(len != 0, "len is %zu", len);
fail_if(ascii[0] != 0, "0 was %c",ascii[0]);
ck_assert_int_eq(len, 0);
ck_assert_int_eq(ascii[0], 0);
}
END_TEST
+39 -12
View File
@@ -9,7 +9,7 @@ START_TEST (test_bitvec_1)
size_t i;
for (i = 0; i < sizeof s * 8; i++)
fail_if(uc_bv_get_bit(&v, i), "bit %zu is not 0", i);
ck_assert_int_eq(uc_bv_get_bit(&v, i), 0);
}
END_TEST
@@ -23,7 +23,7 @@ START_TEST (test_bitvec_2)
uc_bv_set_bit(&v, i);
for (i = 0; i < sizeof s * 8; i++)
fail_if(uc_bv_get_bit(&v, i) != 1 , "bit %zu is not 1", i);
ck_assert_int_eq(uc_bv_get_bit(&v, i), 1);
}
END_TEST
@@ -34,13 +34,13 @@ START_TEST (test_bitvec_clearbit)
size_t i;
for (i = 0; i < sizeof(uc_bv_integer) * 8; i++)
fail_if(uc_bv_get_bit(&v, i) != 1 , "bit %zu is not 1", i);
ck_assert_int_eq(uc_bv_get_bit(&v, i), 1);
for (i = 0; i < sizeof(uc_bv_integer) * 8; i++)
uc_bv_clr_bit(&v, i);
for (i = 0; i < sizeof(uc_bv_integer) * 8; i++)
fail_if(uc_bv_get_bit(&v, i) != 0 , "bit %zu is not 0", i);
ck_assert_int_eq(uc_bv_get_bit(&v, i), 0);
}
END_TEST
@@ -48,14 +48,14 @@ END_TEST
START_TEST (test_bitvec_set_bits_from_array)
{
struct UCBitVec *v = uc_bv_new(5);
char a[] = {1, 0,1 ,0, 1};
char a[] = {1, 0, 1 ,0, 1};
uc_bv_set_bits_from_array(v,a , 5);
fail_if(uc_bv_get_bit(v, 0) != 1 , "bit 0 is wrong");
fail_if(uc_bv_get_bit(v, 1) != 0 , "bit 1 is wrong");
fail_if(uc_bv_get_bit(v, 2) != 1 , "bit 2 is wrong");
fail_if(uc_bv_get_bit(v, 3) != 0 , "bit 3 is wrong");
fail_if(uc_bv_get_bit(v, 4) != 1 , "bit 4 is wrong");
ck_assert_int_eq(uc_bv_get_bit(v, 0), 1);
ck_assert_int_eq(uc_bv_get_bit(v, 1), 0);
ck_assert_int_eq(uc_bv_get_bit(v, 2), 1);
ck_assert_int_eq(uc_bv_get_bit(v, 3), 0);
ck_assert_int_eq(uc_bv_get_bit(v, 4), 1);
uc_bv_free(v);
}
@@ -70,15 +70,40 @@ START_TEST (test_bitvec_setall_clearall)
uc_bv_set_all(v);
for (i = 0; i < 511; i++)
fail_if(uc_bv_get_bit(v, i) != 1 , "bit %zu is not 1", i);
ck_assert_int_eq(uc_bv_get_bit(v, i), 1);
uc_bv_clr_all(v);
for (i = 0; i < sizeof(uc_bv_integer) * 8; i++)
fail_if(uc_bv_get_bit(v, i) != 0 , "bit %zu is not 0", i);
ck_assert_int_eq(uc_bv_get_bit(v, i), 0);
uc_bv_free(v);
}
END_TEST
START_TEST (test_bitvec_find_first_zero)
{
uc_bv_integer buf[8];
struct UCBitVec v = UC_BV_STATIC_INIT(buf);
uc_bv_set_all(&v);
int bit = uc_bv_find_first_zero(&v);
ck_assert_int_eq(bit, -1);
uc_bv_clr_bit(&v, 0);
bit = uc_bv_find_first_zero(&v);
ck_assert_int_eq(bit, 0);
uc_bv_set_bit(&v, 0);
uc_bv_clr_bit(&v, 63);
bit = uc_bv_find_first_zero(&v);
ck_assert_int_eq(bit, 63);
uc_bv_set_bit(&v, 63);
uc_bv_clr_bit(&v, sizeof buf * CHAR_BIT - 1);
bit = uc_bv_find_first_zero(&v);
ck_assert_int_eq(bit, sizeof buf * CHAR_BIT - 1);
}
END_TEST
@@ -91,6 +116,8 @@ Suite *bitvec_suite(void)
tcase_add_test(tc, test_bitvec_set_bits_from_array);
tcase_add_test(tc, test_bitvec_clearbit);
tcase_add_test(tc, test_bitvec_setall_clearall);
tcase_add_test(tc, test_bitvec_find_first_zero);
suite_add_tcase(s, tc);
return s;
+9 -10
View File
@@ -60,8 +60,8 @@ START_TEST (test_gbuf_printf1)
fail_if(buf == NULL);
rc = uc_gbuf_printf(buf, "test %d", 1);
fail_if(rc != 6, "rc was %d", rc);
fail_if(buf->used != 6, "buf->used was %d", buf->used);
fail_if(rc != 6);
fail_if(buf->used != 6);
fail_if(strcmp("test 1", buf->buf) != 0);
uc_gbuf_unref(buf);
@@ -76,8 +76,8 @@ START_TEST (test_gbuf_printf2)
fail_if(buf == NULL);
rc = uc_gbuf_printf(buf, "test %d test %d test %d", 1, 2, 3);
fail_if(rc != 20, "rc was %d", rc);
fail_if(buf->used != 20, "buf->used was %d", buf->used);
fail_if(rc != 20);
fail_if(buf->used != 20);
fail_if(strcmp("test 1 test 2 test 3", buf->buf) != 0);
uc_gbuf_unref(buf);
@@ -92,14 +92,14 @@ START_TEST (test_gbuf_printf3)
fail_if(buf == NULL);
rc = uc_gbuf_printf(buf, "test %d test %d test %d", 1, 2, 3);
fail_if(rc != 20, "rc was %d", rc);
fail_if(buf->used != 20, "buf->used was %d", buf->used);
fail_if(rc != 20);
fail_if(buf->used != 20);
fail_if(strcmp("test 1 test 2 test 3", buf->buf) != 0);
rc = uc_gbuf_printf(buf, " test %d test %d", 4, 5);
fail_if(rc != 14, "rc was %d", rc);
fail_if(buf->used != 34, "buf->used was %d", buf->used);
fail_if(rc != 14);
fail_if(buf->used != 34);
fail_if(strcmp("test 1 test 2 test 3 test 4 test 5", buf->buf) != 0);
uc_gbuf_unref(buf);
@@ -110,11 +110,10 @@ START_TEST (test_gbuf_printf_empty_string)
{
int rc;
GBuf *buf = uc_new_gbuf(1);
const char *fmt = ""; //tricks gcc to not warn about empty format string
fail_if(buf == NULL);
rc = uc_gbuf_printf(buf, fmt);
rc = uc_gbuf_printf(buf, "");
fail_if(rc != 0);
fail_if(buf->used != 0);
uc_gbuf_unref(buf);
+1 -1
View File
@@ -154,7 +154,7 @@ START_TEST (test_dbuf_add_ensure_take)
fail_if(rc != 0);
//ok, dbuf adds the ensured capacity to the existing buflen
//so it becomes 100, not 90 even though the buffer is already empty
fail_if(uc_dbuf_remaining(buf) != 100, "remaining %zu", (uc_dbuf_remaining(buf)));
fail_if(uc_dbuf_remaining(buf) != 100);
fail_if(uc_dbuf_buflen(buf) != 100);
memset(buf->end, 0xDE, 90);
uc_dbuf_added(buf, 90);
+13 -13
View File
@@ -22,7 +22,7 @@ START_TEST (test_uc_hex_encode_2)
uc_hex_encode(binary, sizeof binary, hex);
fail_if(strcmp(hex,"7F8081") != 0, "was %s", hex);
fail_if(strcmp(hex,"7F8081") != 0);
}
END_TEST
@@ -34,7 +34,7 @@ START_TEST (test_uc_hex_encode_3)
uc_hex_encode(binary, sizeof binary, hex);
fail_if(strcmp(hex,"0001090B") != 0, "was %s", hex);
fail_if(strcmp(hex,"0001090B") != 0);
}
END_TEST
@@ -62,7 +62,7 @@ START_TEST (test_uc_hex_decode_1)
fail_if(binary[0] != 0x1f);
fail_if(binary[1] != 0x22);
fail_if(res != binary + 1, "binary %p, res %p", &binary[0], res);
fail_if(res != binary + 1);
}
END_TEST
@@ -78,7 +78,7 @@ START_TEST (test_uc_hex_decode_2)
fail_if(binary[0] != 0x00);
fail_if(binary[1] != 0xFF);
fail_if(binary[2] != 0x80);
fail_if(res != binary + 3, "binary %p, res %p", &binary[0], res);
fail_if(res != binary + 3);
}
END_TEST
@@ -110,7 +110,7 @@ START_TEST (test_uc_hex_decode_empty_string)
fail_if(binary[0] != 0x11);
fail_if(binary[1] != 0x11);
fail_if(binary[2] != 0x11);
fail_if(res != binary, "length %zu\n", res - binary);
fail_if(res != binary);
}
END_TEST
@@ -125,7 +125,7 @@ START_TEST (test_uc_hex_decode_spaces)
fail_if(binary[0] != 0x11);
fail_if(binary[1] != 0x12);
fail_if(binary[2] != 0x13);
fail_if(res != binary+3, "length %zu\n", res - binary);
fail_if(res != binary+3);
}
END_TEST
@@ -141,7 +141,7 @@ START_TEST (test_uc_hex_decode_spaces2)
fail_if(binary[0] != 0x11);
fail_if(binary[1] != 0x12);
fail_if(binary[2] != 0x13);
fail_if(res != binary+3, "length %zu\n", res - binary);
fail_if(res != binary+3);
}
END_TEST
@@ -156,7 +156,7 @@ START_TEST (test_uc_hex_decode_spaces_empty)
fail_if(binary[0] != 0x11);
fail_if(binary[1] != 0x12);
fail_if(res != binary, "length %zu\n", res - binary);
fail_if(res != binary);
}
END_TEST
@@ -201,7 +201,7 @@ START_TEST (test_uc_hex_encode_delim_1)
res = uc_hex_encode_delim(binary, sizeof binary, hex, sizeof hex, " ");
fail_if(strcmp(hex, "FF 00 7F 0A ") != 0, "hex was '%s'", hex);
fail_if(strcmp(hex, "FF 00 7F 0A ") != 0);
*res = 0;
fail_if(res != hex + 12);
@@ -216,8 +216,8 @@ START_TEST (test_uc_hex_encode_delim_2)
res = uc_hex_encode_delim(binary, sizeof binary, hex, sizeof hex, " \n");
fail_if(strcmp(hex, "FF \n00 ") != 0, "hex was '%s'", hex);
fail_if(res != hex + 7, "sz was %zu", res - hex);
fail_if(strcmp(hex, "FF \n00 ") != 0);
fail_if(res != hex + 7);
}
END_TEST
@@ -230,7 +230,7 @@ START_TEST (test_uc_hex_encode_delim_zero_len)
res = uc_hex_encode_delim(binary, 0, hex, sizeof hex, " \n");
fail_if(strcmp(hex, "") != 0, "hex was '%s'", hex);
fail_if(strcmp(hex, "") != 0);
fail_if(res != hex);
}
@@ -247,7 +247,7 @@ START_TEST (test_uc_hex_decode_lowercase)
fail_if(binary[0] != 0x1f);
fail_if(binary[1] != 0x22);
fail_if(res != binary + 1, "binary %p, res %p", &binary[0], res);
fail_if(res != binary + 1);
}
END_TEST
+39 -40
View File
@@ -61,8 +61,7 @@ START_TEST (test_logfile_location)
UC_LOGF(UC_LL_ERROR, 0, "Lorum ipson 5");
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(st.st_size != 380, "was %ld", (long)st.st_size);
fail_if(rc != 0);
}
END_TEST
@@ -85,7 +84,7 @@ START_TEST (test_logfile_delete_destination)
uc_log_init(&mods);
dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1);
dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 0);
fail_if(dest == NULL);
uc_log_add_destination(dest);
uc_log_add_destination(dest); //adding this twice should do nothing
@@ -97,8 +96,8 @@ START_TEST (test_logfile_delete_destination)
UC_LOGF(UC_LL_ERROR, 0, "Lorum ipson 5");
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(st.st_size != 380, "was %ld", (long)st.st_size);
fail_if(rc != 0);
fail_if(st.st_size != 260);
uc_log_delete_destination(dest);
@@ -110,8 +109,8 @@ START_TEST (test_logfile_delete_destination)
//since we deleted destinatiion, no more logging should appear in the file
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(st.st_size != 380, "was %ld", (long)st.st_size);
fail_if(rc != 0);
fail_if(st.st_size != 260);
}
END_TEST
@@ -143,8 +142,8 @@ START_TEST (test_logfile_no_location)
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(st.st_size != 52*2, "was %ld", (long)st.st_size);
fail_if(rc != 0);
fail_if(st.st_size != 52*2);
}
END_TEST
@@ -176,9 +175,9 @@ START_TEST (test_logfile_loglevel_surpressed_dest)
UC_LOGF(UC_LL_INFO, 1, "Lorum ipson %d", 1);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(rc != 0);
fail_if(st.st_size != 0, "was %ld", (long)st.st_size);
fail_if(st.st_size != 0);
}
END_TEST
@@ -210,9 +209,9 @@ START_TEST (test_logfile_loglevel_surpressed_module)
UC_LOGF(UC_LL_INFO, 0, "Lorum ipson %d", 100);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(rc != 0);
fail_if(st.st_size != 0, "was %ld", (long)st.st_size);
fail_if(st.st_size != 0);
}
END_TEST
@@ -235,7 +234,7 @@ START_TEST (test_logfile_reopen_files)
uc_log_init(&mods);
dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1);
dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 0);
fail_if(dest == NULL);
uc_log_add_destination(dest);
@@ -243,20 +242,20 @@ START_TEST (test_logfile_reopen_files)
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(st.st_size != 77*2, "was %ld", (long)st.st_size);
fail_if(rc != 0);
fail_if(st.st_size != 104);
rc = remove(FILE_NAME);
fail_if(rc != 0, "Remove failed %s", strerror(errno));
fail_if(rc != 0);
rc = uc_log_reopen_files();
fail_if(rc != 0, "uc_log_reopen_files failed: %d", rc);
fail_if(rc != 0);
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "2. stat failed: %s", strerror(errno));
fail_if(st.st_size != 77, "was %ld", (long)st.st_size);//should only one line there now
fail_if(rc != 0);
fail_if(st.st_size != 52);//should only one line there now
}
END_TEST
@@ -281,10 +280,10 @@ START_TEST (test_logfile_remove_dest)
uc_log_init(&mods);
dest1 = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1);
dest1 = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 0);
fail_if(dest1 == NULL);
dest2 = uc_log_new_stderr(UC_LL_WARNING, 1);
dest2 = uc_log_new_stderr(UC_LL_WARNING, 0);
fail_if(dest2 == NULL);
uc_log_add_destination(dest1);
@@ -294,16 +293,16 @@ START_TEST (test_logfile_remove_dest)
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(st.st_size != 77*2, "was %ld", (long)st.st_size);
fail_if(rc != 0);
fail_if(st.st_size != 104);
uc_log_remove_destination(dest1);
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1); //should not be logged now
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "2. stat failed: %s", strerror(errno));
fail_if(st.st_size != 77*2, "was %ld", (long)st.st_size);//should be same size
fail_if(rc != 0);
fail_if(st.st_size != 104);//should be same size
//removing the last destination should be fine too
uc_log_remove_destination(dest2);
@@ -311,8 +310,8 @@ START_TEST (test_logfile_remove_dest)
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "2. stat failed: %s", strerror(errno));
fail_if(st.st_size != 77*2, "was %ld", (long)st.st_size);//should be same size
fail_if(rc != 0);
fail_if(st.st_size != 104);//should be same size
}
END_TEST
@@ -337,7 +336,7 @@ START_TEST (test_logfile_full_filesystem)
uc_log_init(&mods);
dest = uc_log_new_file("/dev/full", UC_LL_DEBUG, 1);
fail_if(dest == NULL, "Cannot open /dev/full");
fail_if(dest == NULL);
uc_log_add_destination(dest);
for (i = 0; i < 1024; i++) {
@@ -397,7 +396,7 @@ START_TEST (test_logfile_invalid_file_after_reopen)
logging_rm_subdir();
rc = access(SUBDIR_FILE_NAME, W_OK);
fail_if(rc == 0, "Test setup is wrong. Can still access" SUBDIR_FILE_NAME "");
fail_if(rc == 0);
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1);
UC_LOGF(UC_LL_WARNING, 0, "Lorum ipson %d", 1);
@@ -440,8 +439,8 @@ START_TEST (test_logfile_raw)
UC_LOGFR(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(st.st_size != 14*2, "was %ld", (long)st.st_size);
fail_if(rc != 0);
fail_if(st.st_size != 14*2);
}
END_TEST
@@ -480,16 +479,16 @@ START_TEST (test_logfile_dest_mask)
UC_LOGFR(UC_LL_DEBUG, 0, "Lorum ipson %d", 1);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(st.st_size != 0, "was %ld", (long)st.st_size);
fail_if(rc != 0);
fail_if(st.st_size != 0);
uc_log_destination_set_mask(dest, "MOD1=DEBUG:mod2=Debug");
UC_LOGFR(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1);
UC_LOGFR(UC_LL_DEBUG, 1, "Lorum ipson %d\n", 1);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(st.st_size != 14*2, "was %ld", (long)st.st_size);
fail_if(rc != 0);
fail_if(st.st_size != 14*2);
}
END_TEST
@@ -519,8 +518,8 @@ START_TEST (test_loglevel_module_none)
UC_LOGFR(UC_LL_ERROR, 0, "Lorum ipson %d\n", 1);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(st.st_size != 0, "was %ld", (long)st.st_size);
fail_if(rc != 0);
fail_if(st.st_size != 0);
}
END_TEST
@@ -550,8 +549,8 @@ START_TEST (test_loglevel_dest_none)
UC_LOGFR(UC_LL_WARNING, 0, "Lorum ipson %d\n", 1);
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s", strerror(errno));
fail_if(st.st_size != 0, "was %ld", (long)st.st_size);
fail_if(rc != 0);
fail_if(st.st_size != 0);
}
END_TEST
+84 -84
View File
@@ -9,8 +9,8 @@ START_TEST (test_pack16_le_1)
uc_pack_16_le(v,r);
fail_if(r[0] != 0x34,"was 0x%x",r[0]);
fail_if(r[1] != 0x12,"was 0x%x",r[1]);
fail_if(r[0] != 0x34);
fail_if(r[1] != 0x12);
}
END_TEST
@@ -21,8 +21,8 @@ START_TEST (test_pack16_le_2)
uc_pack_16_le(v,r);
fail_if(r[0] != 0xEF,"was 0x%x",r[0]);
fail_if(r[1] != 0xFE,"was 0x%x",r[1]);
fail_if(r[0] != 0xEF);
fail_if(r[1] != 0xFE);
}
END_TEST
@@ -33,8 +33,8 @@ START_TEST (test_pack16_be_1)
uc_pack_16_be(v,r);
fail_if(r[0] != 0x12,"was 0x%x",r[0]);
fail_if(r[1] != 0x34,"was 0x%x",r[1]);
fail_if(r[0] != 0x12);
fail_if(r[1] != 0x34);
}
END_TEST
@@ -45,8 +45,8 @@ START_TEST (test_pack16_be_2)
uc_pack_16_be(v, r);
fail_if(r[0] != 0xFE,"was 0x%x",r[0]);
fail_if(r[1] != 0xEF,"was 0x%x",r[1]);
fail_if(r[0] != 0xFE);
fail_if(r[1] != 0xEF);
}
END_TEST
@@ -57,7 +57,7 @@ START_TEST (test_unpack16_le_1)
v = uc_unpack_16_le(r);
fail_if(v != 0x3412,"was 0x%x",v);
fail_if(v != 0x3412);
}
END_TEST
@@ -68,7 +68,7 @@ START_TEST (test_unpack16_le_2)
v = uc_unpack_16_le(r);
fail_if(v != 0xEFFE,"was 0x%x",v);
fail_if(v != 0xEFFE);
}
END_TEST
@@ -79,7 +79,7 @@ START_TEST (test_unpack16_be_1)
v = uc_unpack_16_be(r);
fail_if(v != 0x1234,"was 0x%x",v);
fail_if(v != 0x1234);
}
END_TEST
@@ -90,7 +90,7 @@ START_TEST (test_unpack16_be_2)
v = uc_unpack_16_be(r);
fail_if(v != 0xFEEF,"was 0x%x",v);
fail_if(v != 0xFEEF);
}
END_TEST
@@ -101,9 +101,9 @@ START_TEST (test_pack24_le_1)
uc_pack_24_le(v,r);
fail_if(r[0] != 0x56,"was 0x%x",r[0]);
fail_if(r[1] != 0x34,"was 0x%x",r[1]);
fail_if(r[2] != 0x12,"was 0x%x",r[2]);
fail_if(r[0] != 0x56);
fail_if(r[1] != 0x34);
fail_if(r[2] != 0x12);
}
END_TEST
@@ -114,9 +114,9 @@ START_TEST (test_pack24_le_2)
uc_pack_24_le(v,r);
fail_if(r[0] != 0xF6,"was 0x%x",r[0]);
fail_if(r[1] != 0xF7,"was 0x%x",r[1]);
fail_if(r[2] != 0xF8,"was 0x%x",r[2]);
fail_if(r[0] != 0xF6);
fail_if(r[1] != 0xF7);
fail_if(r[2] != 0xF8);
}
END_TEST
@@ -127,9 +127,9 @@ START_TEST (test_pack24_be_1)
uc_pack_24_be(v,r);
fail_if(r[0] != 0x12,"was 0x%x",r[0]);
fail_if(r[1] != 0x34,"was 0x%x",r[1]);
fail_if(r[2] != 0x56,"was 0x%x",r[2]);
fail_if(r[0] != 0x12);
fail_if(r[1] != 0x34);
fail_if(r[2] != 0x56);
}
END_TEST
@@ -140,9 +140,9 @@ START_TEST (test_pack24_be_2)
uc_pack_24_be(v,r);
fail_if(r[0] != 0xF8,"was 0x%x",r[0]);
fail_if(r[1] != 0xF7,"was 0x%x",r[1]);
fail_if(r[2] != 0xF6,"was 0x%x",r[2]);
fail_if(r[0] != 0xF8);
fail_if(r[1] != 0xF7);
fail_if(r[2] != 0xF6);
}
END_TEST
@@ -153,10 +153,10 @@ START_TEST (test_pack32_le_1)
uc_pack_32_le(v,r);
fail_if(r[0] != 0x78,"was 0x%x",r[0]);
fail_if(r[1] != 0x56,"was 0x%x",r[1]);
fail_if(r[2] != 0x34,"was 0x%x",r[2]);
fail_if(r[3] != 0x12,"was 0x%x",r[3]);
fail_if(r[0] != 0x78);
fail_if(r[1] != 0x56);
fail_if(r[2] != 0x34);
fail_if(r[3] != 0x12);
}
END_TEST
@@ -167,10 +167,10 @@ START_TEST (test_pack32_le_2)
uc_pack_32_le(v,r);
fail_if(r[0] != 0xF4,"was 0x%x",r[0]);
fail_if(r[1] != 0xF6,"was 0x%x",r[1]);
fail_if(r[2] != 0xF7,"was 0x%x",r[2]);
fail_if(r[3] != 0xF8,"was 0x%x",r[3]);
fail_if(r[0] != 0xF4);
fail_if(r[1] != 0xF6);
fail_if(r[2] != 0xF7);
fail_if(r[3] != 0xF8);
}
END_TEST
@@ -181,10 +181,10 @@ START_TEST (test_pack32_be_1)
uc_pack_32_be(v,r);
fail_if(r[3] != 0x78,"was 0x%x",r[3]);
fail_if(r[2] != 0x56,"was 0x%x",r[2]);
fail_if(r[1] != 0x34,"was 0x%x",r[1]);
fail_if(r[0] != 0x12,"was 0x%x",r[0]);
fail_if(r[3] != 0x78);
fail_if(r[2] != 0x56);
fail_if(r[1] != 0x34);
fail_if(r[0] != 0x12);
}
END_TEST
@@ -195,10 +195,10 @@ START_TEST (test_pack32_be_2)
uc_pack_32_be(v,r);
fail_if(r[3] != 0xF4,"was 0x%x",r[3]);
fail_if(r[2] != 0xF6,"was 0x%x",r[2]);
fail_if(r[1] != 0xF7,"was 0x%x",r[1]);
fail_if(r[0] != 0xF8,"was 0x%x",r[0]);
fail_if(r[3] != 0xF4);
fail_if(r[2] != 0xF6);
fail_if(r[1] != 0xF7);
fail_if(r[0] != 0xF8);
}
END_TEST
@@ -209,7 +209,7 @@ START_TEST (test_unpack24_le_1)
v = uc_unpack_24_le(r);
fail_if(v != 0x563412,"was 0x%x",v);
fail_if(v != 0x563412);
}
END_TEST
@@ -220,7 +220,7 @@ START_TEST (test_unpack24_le_2)
v = uc_unpack_24_le(r);
fail_if(v != 0xF6F7F8,"was 0x%x",v);
fail_if(v != 0xF6F7F8);
}
END_TEST
@@ -231,7 +231,7 @@ START_TEST (test_unpack24_be_1)
v = uc_unpack_24_be(r);
fail_if(v != 0x123456,"was 0x%x",v);
fail_if(v != 0x123456);
}
END_TEST
@@ -242,7 +242,7 @@ START_TEST (test_unpack24_be_2)
v = uc_unpack_24_be(r);
fail_if(v != 0xF8F7F6,"was 0x%x",v);
fail_if(v != 0xF8F7F6);
}
END_TEST
@@ -253,7 +253,7 @@ START_TEST (test_unpack32_le_1)
v = uc_unpack_32_le(r);
fail_if(v != 0x78563412,"was 0x%x",v);
fail_if(v != 0x78563412);
}
END_TEST
@@ -264,7 +264,7 @@ START_TEST (test_unpack32_le_2)
v = uc_unpack_32_le(r);
fail_if(v != 0xF4F6F7F8,"was 0x%x",v);
fail_if(v != 0xF4F6F7F8);
}
END_TEST
@@ -275,7 +275,7 @@ START_TEST (test_unpack32_be_1)
v = uc_unpack_32_be(r);
fail_if(v != 0x12345678,"was 0x%x",v);
fail_if(v != 0x12345678);
}
END_TEST
@@ -286,7 +286,7 @@ START_TEST (test_unpack32_be_2)
v = uc_unpack_32_be(r);
fail_if(v != 0xF8F7F6F4,"was 0x%x",v);
fail_if(v != 0xF8F7F6F4);
}
END_TEST
@@ -297,14 +297,14 @@ START_TEST (test_pack64_le_1)
uc_pack_64_le(v, r);
fail_if(r[0] != 0x88,"was 0x%x",r[0]);
fail_if(r[1] != 0x77,"was 0x%x",r[1]);
fail_if(r[2] != 0x66,"was 0x%x",r[2]);
fail_if(r[3] != 0x55,"was 0x%x",r[3]);
fail_if(r[4] != 0x44,"was 0x%x",r[4]);
fail_if(r[5] != 0x33,"was 0x%x",r[5]);
fail_if(r[6] != 0x22,"was 0x%x",r[6]);
fail_if(r[7] != 0x11,"was 0x%x",r[7]);
fail_if(r[0] != 0x88);
fail_if(r[1] != 0x77);
fail_if(r[2] != 0x66);
fail_if(r[3] != 0x55);
fail_if(r[4] != 0x44);
fail_if(r[5] != 0x33);
fail_if(r[6] != 0x22);
fail_if(r[7] != 0x11);
}
END_TEST
@@ -315,14 +315,14 @@ START_TEST (test_pack64_le_2)
uc_pack_64_le(v, r);
fail_if(r[0] != 0xF8,"was 0x%x",r[0]);
fail_if(r[1] != 0xF9,"was 0x%x",r[1]);
fail_if(r[2] != 0xFA,"was 0x%x",r[2]);
fail_if(r[3] != 0xFB,"was 0x%x",r[3]);
fail_if(r[4] != 0xFC,"was 0x%x",r[4]);
fail_if(r[5] != 0xFD,"was 0x%x",r[5]);
fail_if(r[6] != 0xFE,"was 0x%x",r[6]);
fail_if(r[7] != 0xFF,"was 0x%x",r[7]);
fail_if(r[0] != 0xF8);
fail_if(r[1] != 0xF9);
fail_if(r[2] != 0xFA);
fail_if(r[3] != 0xFB);
fail_if(r[4] != 0xFC);
fail_if(r[5] != 0xFD);
fail_if(r[6] != 0xFE);
fail_if(r[7] != 0xFF);
}
END_TEST
@@ -333,7 +333,7 @@ START_TEST (test_unpack64_le_1)
v = uc_unpack_64_le(r);
fail_if(v != 0x8877665544332211ULL,"was 0x%llx",v);
fail_if(v != 0x8877665544332211ULL);
}
END_TEST
@@ -345,7 +345,7 @@ START_TEST (test_unpack64_le_2)
v = uc_unpack_64_le(r);
fail_if(v != 0xF8F9FAFBFCFDFEFFULL,"was 0x%llx",v);
fail_if(v != 0xF8F9FAFBFCFDFEFFULL);
}
END_TEST
@@ -356,14 +356,14 @@ START_TEST (test_pack64_be_1)
uc_pack_64_be(v, r);
fail_if(r[0] != 0x11,"was 0x%x",r[0]);
fail_if(r[1] != 0x22,"was 0x%x",r[1]);
fail_if(r[2] != 0x33,"was 0x%x",r[2]);
fail_if(r[3] != 0x44,"was 0x%x",r[3]);
fail_if(r[4] != 0x55,"was 0x%x",r[4]);
fail_if(r[5] != 0x66,"was 0x%x",r[5]);
fail_if(r[6] != 0x77,"was 0x%x",r[6]);
fail_if(r[7] != 0x88,"was 0x%x",r[7]);
fail_if(r[0] != 0x11);
fail_if(r[1] != 0x22);
fail_if(r[2] != 0x33);
fail_if(r[3] != 0x44);
fail_if(r[4] != 0x55);
fail_if(r[5] != 0x66);
fail_if(r[6] != 0x77);
fail_if(r[7] != 0x88);
}
END_TEST
@@ -374,14 +374,14 @@ START_TEST (test_pack64_be_2)
uc_pack_64_be(v, r);
fail_if(r[0] != 0xFF,"was 0x%x",r[0]);
fail_if(r[1] != 0xFE,"was 0x%x",r[1]);
fail_if(r[2] != 0xFD,"was 0x%x",r[2]);
fail_if(r[3] != 0xFC,"was 0x%x",r[3]);
fail_if(r[4] != 0xFB,"was 0x%x",r[4]);
fail_if(r[5] != 0xFA,"was 0x%x",r[5]);
fail_if(r[6] != 0xF9,"was 0x%x",r[6]);
fail_if(r[7] != 0xF8,"was 0x%x",r[7]);
fail_if(r[0] != 0xFF);
fail_if(r[1] != 0xFE);
fail_if(r[2] != 0xFD);
fail_if(r[3] != 0xFC);
fail_if(r[4] != 0xFB);
fail_if(r[5] != 0xFA);
fail_if(r[6] != 0xF9);
fail_if(r[7] != 0xF8);
}
END_TEST
@@ -392,7 +392,7 @@ START_TEST (test_unpack64_be_1)
v = uc_unpack_64_be(r);
fail_if(v != 0x1122334455667788ULL,"was 0x%llx",v);
fail_if(v != 0x1122334455667788ULL);
}
END_TEST
@@ -403,7 +403,7 @@ START_TEST (test_unpack64_be_2)
v = uc_unpack_64_be(r);
fail_if(v != 0xFFFEFDFCFBFAF9F8ULL,"was 0x%llx",v);
fail_if(v != 0xFFFEFDFCFBFAF9F8ULL);
}
END_TEST
+1 -1
View File
@@ -10,7 +10,7 @@ START_TEST (test_ratelimit_1)
uc_ratelimit_init(&r, 30, 2);
for (i = 0; i < 30; i++) {
fail_if(!uc_ratelimit_allow(&r, now), "i = %d", i);
fail_if(!uc_ratelimit_allow(&r, now));
}
fail_if(uc_ratelimit_allow(&r, now));
}
+24 -24
View File
@@ -18,8 +18,8 @@ START_TEST (test_read_file_non_existing_file)
content = uc_read_file("non existing file 123765", &len, 1000000000);
saved_errno = errno;
fail_if(content != NULL);
fail_if(saved_errno == 0);
ck_assert_ptr_null(content);
ck_assert_int_ne(saved_errno, 0);
}
END_TEST
@@ -31,20 +31,20 @@ START_TEST (test_read_file_simple)
ssize_t rc;
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
fail_if(fd == -1);
ck_assert_int_ne(fd, -1);
rc = write(fd, "hello", 5);
fail_if(rc != 5, "rc was %ld", (long)rc);
ck_assert_int_eq(rc, 5);
close(fd);
content = uc_read_file(filename, &len, 1000000000);
unlink(filename);
fail_if(content == NULL);
fail_if(len != 5);
fail_if(strlen(content) != 5);
fail_if(strcmp("hello", content) != 0);
ck_assert_ptr_nonnull(content);
ck_assert_uint_eq(len, 5);
ck_assert_uint_eq(strlen(content), 5);
ck_assert_str_eq("hello", content);
free(content);
}
END_TEST
@@ -61,7 +61,7 @@ START_TEST (test_read_file_greater_than_max)
fail_if(fd == -1);
rc = write(fd, "hello", 5);
fail_if(rc != 5, "rc was %ld", (long)rc);
fail_if(rc != 5);
close(fd);
@@ -69,8 +69,8 @@ START_TEST (test_read_file_greater_than_max)
saved_errno = errno;
unlink(filename);
fail_if(content != NULL);
fail_if(saved_errno != EMSGSIZE, "was %d", saved_errno);
ck_assert_ptr_null(content);
ck_assert_int_eq(saved_errno, EMSGSIZE);
}
END_TEST
@@ -87,16 +87,16 @@ START_TEST (test_read_file_boundary)
fail_if(fd == -1);
rc = write(fd, buf, sizeof buf);
fail_if(rc != sizeof buf, "rc was %ld", (long)rc);
ck_assert_uint_eq(rc, sizeof buf);
close(fd);
content = uc_read_file(filename, &len, 1000000000);
unlink(filename);
fail_if(content == NULL);
fail_if(len != sizeof buf);
fail_if(strcmp("foobar", &content[1022]) != 0);
ck_assert_ptr_nonnull(content);
ck_assert_uint_eq(len, sizeof buf);
ck_assert_str_eq("foobar", &content[1022]);
free(content);
}
END_TEST
@@ -107,8 +107,8 @@ START_TEST (test_read_file_devnull)
size_t len = 123;
content = uc_read_file("/dev/null", &len, 1024);
fail_if(content == NULL);
fail_if(len != 0);
ck_assert_ptr_nonnull(content);
ck_assert_uint_eq(len, 0);
free(content);
}
@@ -125,14 +125,14 @@ START_TEST (test_read_file_too_big)
fail_if(fd == -1);
rc = write(fd, "hello", 5);
fail_if(rc != 5, "rc was %ld", (long)rc);
fail_if(rc != 5);
close(fd);
content = uc_read_file(filename, &len, 4);
fail_if(errno != EMSGSIZE);
fail_if(content != NULL);
ck_assert_int_eq(errno, EMSGSIZE);
ck_assert_ptr_null(content);
unlink(filename);
}
@@ -147,18 +147,18 @@ START_TEST (test_read_file_big)
ssize_t rc;
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
fail_if(fd == -1);
ck_assert_int_ne(fd, -1);
memset(buf, 'a', sizeof buf);
rc = write(fd, buf, sizeof buf);
fail_if(rc != sizeof buf, "rc was %ld", (long)rc);
ck_assert_uint_eq(rc, sizeof buf);
close(fd);
content = uc_read_file(filename, &len, 4096*16);
fail_if(content == NULL);
fail_if(len != sizeof buf);
fail_if(memcmp(content, buf, sizeof buf) != 0);
ck_assert_uint_eq(len, sizeof buf);
ck_assert_int_eq(memcmp(content, buf, sizeof buf), 0);
free(content);
+1 -1
View File
@@ -82,7 +82,7 @@ START_TEST (test_restart_counter_garble)
ck_assert_int_eq(0, uc_restart_counter_get(&cnt));
rc = uc_restart_counter_init(&cnt, FILE_NAME, 0);
fail_if(rc != UC_RC_OK, "%d", rc);
fail_if(rc != UC_RC_OK);
ck_assert_int_eq(1, uc_restart_counter_get(&cnt));
}
+4
View File
@@ -34,6 +34,7 @@ extern Suite *ticket_lock_suite(void);
extern Suite *restart_counter_suite(void);
extern Suite *iomux_suite(void);
extern Suite *iomux_signal_suite(void);
extern Suite *string_suite(void);
extern Suite *ringbuf_suite(void);
static suite_func suites[] = {
@@ -64,7 +65,10 @@ static suite_func suites[] = {
restart_counter_suite,
iomux_suite,
iomux_signal_suite,
string_suite,
#ifndef __APPLE__
ringbuf_suite
#endif
};
+213
View File
@@ -0,0 +1,213 @@
#include <check.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "ucore/string.h"
#include "ucore/utils.h"
START_TEST (test_getfields)
{
char str[] = "a;b;c";
char *letters[5] = {NULL};
int rc = uc_getfields(str, letters, 5, 0, ";");
ck_assert_int_eq(rc, 3);
ck_assert_str_eq("a", letters[0]);
ck_assert_str_eq("b", letters[1]);
ck_assert_str_eq("c", letters[2]);
}
END_TEST
START_TEST (test_getfields_consecutive)
{
char str[] = "a;;b;c;;;";
char *letters[7] = {NULL};
int rc = uc_getfields(str, letters, 5, 0, ";");
ck_assert_int_eq(rc, 5);
// This result is rather silly, but it's
// how getfields works with mflag=0
ck_assert_str_eq("a", letters[0]);
ck_assert_str_eq("", letters[1]);
ck_assert_str_eq("b", letters[2]);
ck_assert_str_eq("c", letters[3]);
ck_assert_str_eq(";;", letters[4]);
}
END_TEST
START_TEST (test_getfields_mflag)
{
char str[] = "a;b;c";
char *letters[5] = {NULL};
int rc = uc_getfields(str, letters, 5, 1, ";");
ck_assert_int_eq(rc, 3);
ck_assert_str_eq("a", letters[0]);
ck_assert_str_eq("b", letters[1]);
ck_assert_str_eq("c", letters[2]);
}
END_TEST
START_TEST (test_getfields_consecutive_mflag)
{
char str[] = "a;;b;c;;;";
char *letters[7] = {NULL};
int rc = uc_getfields(str, letters, 7, 1, ";");
ck_assert_int_eq(rc, 3);
// This result is rather silly, but it's
// how getfields works with mflag=0
ck_assert_str_eq("a", letters[0]);
ck_assert_str_eq("b", letters[1]);
ck_assert_str_eq("c", letters[2]);
}
END_TEST
START_TEST (test_getfields_too_many)
{
char str[] = "a\r\nb\r\nc\r\nd\r\ne";
char *letters[4] = {NULL};
int rc = uc_getfields(str, letters, 4, 0, "\r\n");
ck_assert_int_eq(rc, 4);
// This result is rather silly, but it's
// how getfields works with mflag=0
ck_assert_str_eq("a", letters[0]);
ck_assert_str_eq("", letters[1]);
ck_assert_str_eq("b", letters[2]);
ck_assert_str_eq("\nc\r\nd\r\ne", letters[3]);
}
END_TEST
START_TEST (test_getfields_too_many_mflag)
{
char str[] = "a\r\nb\r\nc\r\nd\r\ne";
char *letters[4] = {NULL};
int rc = uc_getfields(str, letters, 4, 1, "\r\n");
ck_assert_int_eq(rc, 4);
ck_assert_str_eq("a", letters[0]);
ck_assert_str_eq("b", letters[1]);
ck_assert_str_eq("c", letters[2]);
ck_assert_str_eq("d\r\ne", letters[3]);
}
END_TEST
START_TEST (test_getfields_empty)
{
char str[] = "";
char *letters[4] = {NULL};
int rc = uc_getfields(str, letters, 4, 0, ";\r\n");
ck_assert_int_eq(rc, 1);
ck_assert_str_eq("", letters[0]);
rc = uc_getfields(str, letters, 4, 1, ";\r\n");
ck_assert_int_eq(rc, 0);
}
END_TEST
START_TEST (test_gettokens)
{
char str[] = "a;b;c";
char *letters[5] = {NULL};
int rc = uc_gettokens(str, letters, 5,";");
ck_assert_int_eq(rc, 3);
ck_assert_str_eq("a", letters[0]);
ck_assert_str_eq("b", letters[1]);
ck_assert_str_eq("c", letters[2]);
}
END_TEST
START_TEST (test_gettokens_consecutive)
{
char str[] = "a;;;b;;c;";
char *letters[5] = {NULL};
int rc = uc_gettokens(str, letters, 5,";");
ck_assert_int_eq(rc, 3);
ck_assert_str_eq("a", letters[0]);
ck_assert_str_eq("b", letters[1]);
ck_assert_str_eq("c", letters[2]);
}
END_TEST
START_TEST (test_gettokens_empty)
{
char str[] = "";
char *letters[5] = {NULL};
int rc = uc_gettokens(str, letters, 5,";");
ck_assert_int_eq(rc, 0);
}
END_TEST
START_TEST (test_gettokens_quotes)
{
char str[] = "\"abc\";d;\"e \"";
char *letters[5] = {NULL};
int rc = uc_gettokens(str, letters, 5,";");
ck_assert_int_eq(rc, 3);
ck_assert_str_eq("abc", letters[0]);
ck_assert_str_eq("d", letters[1]);
ck_assert_str_eq("e ", letters[2]);
}
END_TEST
START_TEST (test_gettokens_double_quotes)
{
char str[] = "\"\"abc\"\";d;\"e\"\"f\"\"\"";
char *letters[5] = {NULL};
int rc = uc_gettokens(str, letters, 5,";");
ck_assert_int_eq(rc, 3);
ck_assert_str_eq("abc", letters[0]);
ck_assert_str_eq("d", letters[1]);
ck_assert_str_eq("e\"f\"", letters[2]);
}
END_TEST
Suite *string_suite(void)
{
Suite *s = suite_create("string");
TCase *tc = tcase_create("string");
tcase_add_test(tc, test_getfields);
tcase_add_test(tc, test_getfields_consecutive);
tcase_add_test(tc, test_getfields_mflag);
tcase_add_test(tc, test_getfields_consecutive_mflag);
tcase_add_test(tc, test_getfields_too_many);
tcase_add_test(tc, test_getfields_too_many_mflag);
tcase_add_test(tc, test_getfields_empty);
tcase_add_test(tc, test_gettokens);
tcase_add_test(tc, test_gettokens_consecutive);
tcase_add_test(tc, test_gettokens_empty);
tcase_add_test(tc, test_gettokens_quotes);
tcase_add_test(tc, test_gettokens_double_quotes);
suite_add_tcase(s, tc);
return s;
}
+39
View File
@@ -135,6 +135,44 @@ START_TEST (test_strv_append_all_nocopy)
}
END_TEST
START_TEST (test_strv_reverse)
{
struct UCStrv strv;
uc_strv_init(&strv);
uc_strv_append(&strv, "string1");
uc_strv_reverse(&strv);
ck_assert_str_eq("string1", strv.strings[0]);
uc_strv_destroy(&strv);
uc_strv_init(&strv);
uc_strv_append(&strv, "string1");
uc_strv_append(&strv, "string2");
uc_strv_reverse(&strv);
ck_assert_str_eq("string2", strv.strings[0]);
ck_assert_str_eq("string1", strv.strings[1]);
uc_strv_destroy(&strv);
uc_strv_init(&strv);
uc_strv_append(&strv, "string1");
uc_strv_append(&strv, "string2");
uc_strv_append(&strv, "string3");
uc_strv_reverse(&strv);
ck_assert_str_eq("string3", strv.strings[0]);
ck_assert_str_eq("string2", strv.strings[1]);
ck_assert_str_eq("string1", strv.strings[2]);
uc_strv_destroy(&strv);
}
END_TEST
Suite *strv_suite(void)
{
@@ -147,6 +185,7 @@ Suite *strv_suite(void)
tcase_add_test(tc, test_strv_null_terminate);
tcase_add_test(tc, test_strv_append_all_copy);
tcase_add_test(tc, test_strv_append_all_nocopy);
tcase_add_test(tc, test_strv_reverse);
suite_add_tcase(s, tc);