Merge branch 'master' of /var/lib/git/libucore

This commit is contained in:
Nils O. Selåsdal
2013-09-13 20:42:23 +02:00
39 changed files with 1843 additions and 150 deletions
+1
View File
@@ -4,3 +4,4 @@ build/
tags tags
doc/ doc/
log_subdir/ log_subdir/
coverage/
+1 -1
View File
@@ -655,7 +655,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories # directories like "/usr/src/myproject". Separate the files or directories
# with spaces. # with spaces.
INPUT = src INPUT = include
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+14
View File
@@ -36,6 +36,12 @@ AddOption('--test_xml',
help='Create a result.xml when running the testsuite' help='Create a result.xml when running the testsuite'
) )
AddOption('--coverage',
dest='coverage',
action='store_true',
help='Build with coverage (gcov) support'
)
AddOption('--stack-protection', AddOption('--stack-protection',
dest = 'stack_protection', dest = 'stack_protection',
action='store_true', action='store_true',
@@ -59,6 +65,11 @@ def InstallPerm(env, dest, files, perm):
env = Environment(tools = ['default', 'textfile']) env = Environment(tools = ['default', 'textfile'])
#allow shell environment to override compiler
if os.environ.has_key('CC'):
env['CC'] = os.environ['CC']
env.AddMethod(InstallPerm) env.AddMethod(InstallPerm)
Export('env', 'build_type', 'prefix', 'version_info', 'test_xml') Export('env', 'build_type', 'prefix', 'version_info', 'test_xml')
@@ -80,6 +91,9 @@ if GetOption('stack_protection'):
env.Append(CFLAGS = ['-fstack-protector', '--param=ssp-buffer-size=4']) env.Append(CFLAGS = ['-fstack-protector', '--param=ssp-buffer-size=4'])
env.Append(CPPDEFINES = ['_FORTIFY_SOURCE=2']) env.Append(CPPDEFINES = ['_FORTIFY_SOURCE=2'])
if GetOption('coverage'):
env.Append(CFLAGS = ['--coverage'])
env.Append(LINKFLAGS = ['--coverage'])
#put all .sconsign files in one place #put all .sconsign files in one place
env.SConsignFile() env.SConsignFile()
Executable
+8
View File
@@ -0,0 +1,8 @@
#!/bin/sh
scons --coverage test
mkdir -p coverage && cd coverage
lcov -c -d ../build/src/ -o libucore.info
genhtml libucore.info
echo "Test report available at file:///$(pwd)/index.html"
+1 -1
View File
@@ -30,7 +30,7 @@
* Atomically increment *ptr * Atomically increment *ptr
* @return *ptr before the increment * @return *ptr before the increment
*/ */
#define UC_ATOMIC_INC(ptr) UC_ATOMIC_SUB((ptr), 1) #define UC_ATOMIC_INC(ptr) UC_ATOMIC_ADD((ptr), 1)
/** /**
+5 -1
View File
@@ -3,7 +3,10 @@
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
/** @addtogroup Timers
* @{
* Clock abstractions
*/
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -117,5 +120,6 @@ void uc_settable_clock_set(struct UCoreSettableClock *uclock,
} }
#endif #endif
/** @} (addtogroup) */
#endif #endif
+127
View File
@@ -0,0 +1,127 @@
#ifndef dbuf_H_
#define dbuf_H_
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* dbuf is a generic buffer that will grow automatically.
* call buf_ensure() to reserve space, and don't write more data
* than you told buf_ensure() to reserve.
*
* You write data to buf->end
* When finished writing data
* you call dbuf_added/( with the no. of bytes you've added.
*
* You read data from buf->start, the buffer has dbuf_len() bytes of data
* When you've read and processed the data, call dbuf_take()
* to indicate you're done with the data.
*
* typically(but add error checking)
* @code
* DBuf buf;
* dbuf_init(&buf,4096);
* for(;;) {
* dbuf_ensure(buf,4096);
* size_t len = fread(buf,4096,1,f);
* dbuf_added(&buf,len);
* char *end;
* while((end = memchr(buf.start,'\n',dbuf_len(&dbuf))) != NULL) { //look for a newline
* ++end;
* int linelen = end - buf.start;
* process_line(buf.start,linelen);
* dbuf_take(&dbuf,linelen);
* }
* }
* @endcode
*/
typedef struct DBuf DBuf;
struct DBuf {
/** Start of user data */
unsigned char *start;
/** End of user data */
unsigned char *end;
/** Start of underlying buffer. Internal use.*/
unsigned char *bufstart;
/** End of underlying buffer. Internal use.*/
unsigned char *bufend;
};
/** Free the internals of a DBuf, does not free buf itself.
* Does nothing if buf == NULL
*
* @param buf buffer to free
*/
void uc_dbuf_free(DBuf *buf);
/** Initialize a dbuf.
*
* @param buf buffer to initialize
* @param initlen inital capacity of the buffer
* @return 0 on success
*/
int uc_dbuf_init(DBuf *buf,size_t initlen);
/** Get length of user data in the buffer
*
* @param buf buffer to get length of
* @return length of the user data
*/
size_t uc_dbuf_len(DBuf *buf);
/** Allocated size of the buffer
*
* @param buf buffer to get allocated length of
* @return allocated length of the underlying buffer
*/
size_t uc_dbuf_buflen(DBuf *buf);
/** Get remaining space in the buffer
*
* @param buf buffer
* @return remaining space (after buf->end) in the buffer
*/
size_t uc_dbuf_remaining(DBuf *buf);
/** ensure the buffer can hold 'capacity' no of bytes,
*
* @param buf buffer
* @param capacity ensure there is room for capacity bytes after buf->end
* @return 0 on success
*/
int uc_dbuf_ensure(DBuf *buf,size_t capacity);
/** Trim the buffer to hold no more space than needed.
*
* @param buf buffer to trum
*/
void uc_dbuf_trim(DBuf *buf);
/** Indicate you've taken 'len' bytes out of the buffer.
* Advances buf->start by len bytes
* This may re-set buf->start and buf->end if e.g. all data
* is taken out of the buffer.
*
* @param buf buffer
* @param len length that was taken out of the buffer
* @return 0 on success. Non-zero if len is larger than the bufer capacity
*/
int uc_dbuf_take(DBuf *buf,size_t len);
/** Indicate you've added 'len' bytes to the buffer
* Advances buf->end by len bytes
* User must always make sure (e.g. by using uc_dbuf_ensure)
* that the buffer has the capacity to add @len bytes
*
* @param buf buffer
* @param len length that was added to the buffer.
*/
void uc_dbuf_added(DBuf *buf,size_t len);
#ifdef __cplusplus
}
#endif
#endif
+31 -7
View File
@@ -10,42 +10,66 @@ extern "C" {
* @param fd file descriptor * @param fd file descriptor
* @return 0 on success -1 on failure * @return 0 on success -1 on failure
*/ */
int set_nonblocking(int fd); int uc_set_nonblocking(int fd);
/** /**
* set the file descriptor to blocking * set the file descriptor to blocking
* @param fd file descriptor * @param fd file descriptor
* @return 0 on success -1 on failure * @return 0 on success -1 on failure
*/ */
int set_blocking(int fd); int uc_set_blocking(int fd);
/** /**
* set the socket file descriptor to SO_REUSEADDR * set the socket file descriptor to SO_REUSEADDR
* @param fd file descriptor * @param fd file descriptor
* @return 0 on success -1 on failure * @return 0 on success -1 on failure
*/ */
int set_reuseaddr(int sockfd); int uc_set_reuseaddr(int sockfd);
/** /**
* enable TCP keepalive on the socket * enable TCP keepalive on the socket
* @param fd file descriptor * @param fd file descriptor
* @return 0 on success -1 on failure * @return 0 on success -1 on failure
*/ */
int set_tcp_keepalive(int sockfd); int uc_set_tcp_keepalive(int sockfd);
struct UCKeepConfig {
/** The maximum number of keepalive probes TCP should
* send before dropping the connection. (TCP_KEEPCNT socket option)
*/
int keepcnt;
/** The time (in seconds) the connection needs to remain
* idle before TCP starts sending keepalive probes (TCP_KEEPIDLE socket option)
*/
int keepidle;
/** The time (in seconds) between individual keepalive probes.
* (TCP_KEEPINTVL socket option)
*/
int keepintvl;
};
/** Set the keepalive options on the socket
* This also enables TCP keepalive on the socket
*
* @param fd file descriptor
* @param fd file descriptor
* @return 0 on success -1 on failure
*/
int uc_set_tcp_keepalive_cfg(int sockfd, const struct UCKeepConfig *cfg);
/** /**
* Set the socket send timeout, in miliseconds * Set the socket send timeout, in miliseconds
* @param fd file descriptor * @param fd file descriptor
* @return 0 on success -1 on failure * @return 0 on success -1 on failure
*/ */
int set_send_timeout(int sockfd,long timeoutms); int uc_set_send_timeout(int sockfd,long timeoutms);
/** /**
* Set the socket receive timeout, in miliseconds * Set the socket receive timeout, in miliseconds
* @param fd file descriptor * @param fd file descriptor
* @return 0 on success -1 on failure * @return 0 on success -1 on failure
*/ */
int set_receive_timeout(int sockfd,long timeoutms); int uc_set_receive_timeout(int sockfd,long timeoutms);
/* /*
* Set the IP DSCP (differnetiated services code point) header value * Set the IP DSCP (differnetiated services code point) header value
@@ -53,7 +77,7 @@ int set_receive_timeout(int sockfd,long timeoutms);
* @param fd file descriptor * @param fd file descriptor
* @return 0 on success -1 on failure * @return 0 on success -1 on failure
*/ */
int set_ip_dscp(int fd, unsigned int dscp); int uc_set_ip_dscp(int fd, unsigned int dscp);
#ifdef __cplusplus #ifdef __cplusplus
+45 -8
View File
@@ -2,7 +2,18 @@
#define IO_MUX_H_ #define IO_MUX_H_
#include "timers.h" #include "timers.h"
/** @addtogroup IOMux
* @{
* The IOMux is an I/O multiplexer, implementing a main eventloop.
* The event loop can be used to register callbacks for activity on
* file descriptors such as sockets and pips, and for timers.
*
* The IOMux is backed either by the select() system call, or the epoll
* facility on Linux. Several IOMuxes can run in different threads concurrently,
* but note that the IOMux itself is not thread safe so operations in one thread
* cannot work on an IOMux running in another thread.
*
* */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -22,9 +33,20 @@ enum IOMUX_TYPE {
IOMUX_TYPE_EPOLL IOMUX_TYPE_EPOLL
}; };
/** Opaque struct */ /** The IOMux used to issue mux operations. This is to be treated as an opaque
* handle. Use iomux_create() or iomux_create_ex() to create an IOMux, register
* callbakcs, and call iomux_run() to process the events
*/
struct IOMux; struct IOMux;
struct IOMuxFD; struct IOMuxFD;
/** Callback function used in struct IOMuxFD
* @param mux the mux that issued the callback.
* @param fd the file desciptor structure.
* @param event A bitmask of the MUX_EV_XX values. Both a read and a write event
* might be signalled in the same callback
*/
typedef void (*iomux_cb)(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event); typedef void (*iomux_cb)(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event);
/** Represents a watched file descriptor */ /** Represents a watched file descriptor */
@@ -43,6 +65,9 @@ struct IOMuxFD {
}; };
/** Creates a new IOMux. /** Creates a new IOMux.
*
* @param type the underlying implementation to use @see IOMUX_TYPE
* @return Newly allocated IOMux. NULL if memory allocation fails.
*/ */
struct IOMux *iomux_create(enum IOMUX_TYPE type); struct IOMux *iomux_create(enum IOMUX_TYPE type);
@@ -58,19 +83,30 @@ struct IOMux *iomux_create_ex(enum IOMUX_TYPE type, struct UCoreClock *uclock);
void iomux_delete(struct IOMux *mux); void iomux_delete(struct IOMux *mux);
/** Runs the event loop of the mux /** Runs the event loop of the mux
* returns if the number of file descriptors and timers are 0 or *
* @return if the number of file descriptors and timers are 0 or
* an error occurs */ * an error occurs */
int iomux_run(struct IOMux *mux); int iomux_run(struct IOMux *mux);
/* Adds a file descriptor to the watch set, /* Adds a file descriptor to the watch set.
* returns 0 on success, an errno value on error */ * The file descriptor integer value must reside in only
* one struct IOMuxFD. Adding e.g. the same file descriptor
* in 2 different struct IOMuxFD, one for read events and one for
* write events is not supported.
*
* @return 0 on success, an errno value on error
*/
int iomux_register_fd(struct IOMux *mux, struct IOMuxFD *fd); int iomux_register_fd(struct IOMux *mux, struct IOMuxFD *fd);
/** Removes the file descriptor*/ /** Removes the file descriptor
*
* @return 0 on success, an errno value on error
*/
int iomux_unregister_fd(struct IOMux *mux, struct IOMuxFD *fd); int iomux_unregister_fd(struct IOMux *mux, struct IOMuxFD *fd);
/** Updates the events to watch for in fd->what /** Updates the events to watch for in fd->what
* returns 0 on success, an errno value on error */ * @return 0 on success, an errno value on error
*/
int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd); int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd);
@@ -100,7 +136,7 @@ int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd);
iomux_update_events((mux), (fd));\ iomux_update_events((mux), (fd));\
}) })
/** Returns a UCTimer instance tied to this mux. /** @return a UCTimer instance tied to this mux.
* Used to schedule timers within this mux. * Used to schedule timers within this mux.
*/ */
struct UCTimers *iomux_get_timers(struct IOMux *mux); struct UCTimers *iomux_get_timers(struct IOMux *mux);
@@ -109,5 +145,6 @@ struct UCTimers *iomux_get_timers(struct IOMux *mux);
} }
#endif #endif
/** @} (addtogroup)*/
#endif #endif
+75
View File
@@ -0,0 +1,75 @@
#ifndef UC_MBUF_H_
#define UC_MBUF_H_
#include <stdint.h>
#include <stddef.h>
#ifdef __GNUC__
# define UC_INLINE inline __attribute__((always_inline))
#else
# define UC_INLINE inline
#endif
enum UC_MBUF_FLAGS {
UC_MBUF_FL_MALLOC = 0x0001, //MBuf and MBuf->bufstart are seperatly malloc'd
UC_MBUF_FL_MALLOC_BUF = 0x0001, //MBuf is not malloc'd. MBuf->bufstart is malloc'd
UC_MBUF_FL_MALLOC_INLINE = 0x0002, //MBuf is one big malloc. Can't be resized
UC_MBUF_FL_STATIC = 0x0004, //MBuf and MBuf->bustart is user controlled. Can't be resized
};
struct MBuf {
struct MBuf *next;
uint8_t *p1;
uint8_t *p2;
uint8_t *p3;
uint8_t *p4;
void *cookie;
uint32_t flags;
uint32_t allocated;
uint8_t *bufstart;
uint8_t *head;
uint8_t *tail;
uint8_t inline_data[0];
};
/* Conventions:
* push - prepend data to the buffer (in the head room part)
* pull - remove data from the beginning of the message.
* put - Add data to the buffer.
*/
struct MBuf *uc_mbuf_new_hr(uint32_t len, uint32_t headroom);
#define uc_mbuf_new(len) uc_mbuf_new_hr((len), 0)
struct MBuf *uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom);
#define uc_mbuf_new_inline(len) uc_mbuf_new_inline_hr((len), 0)
void uc_mbuf_free(struct MBuf *mbuf);
struct MBuf *uc_mbuf_copy_data(struct MBuf *mbuf);
void uc_mbuf_init(struct MBuf *mbuf, uint8_t *buf, uint32_t len, uint32_t headroom, uint32_t flags);
void uc_mbuf_zero(struct MBuf *mbuf);
void uc_mbuf_reset(struct MBuf *mbuf);
static UC_INLINE uint32_t uc_mbuf_len(struct MBuf *mbuf)
{
return (uint32_t)(mbuf->tail - mbuf->head);
}
static UC_INLINE uint32_t uc_mbuf_tailroom(struct MBuf *mbuf)
{
return mbuf->allocated - (uint32_t)(mbuf->tail - mbuf->bufstart);
}
static inline uint32_t uc_mbuf_headroom(struct MBuf *mbuf)
{
return (uint32_t)(mbuf->head - mbuf->bufstart);
}
uint8_t *uc_mbuf_put(struct MBuf *mbuf, uint32_t size);
uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size);
uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size);
#undef UC_INLINE
#endif
+6 -3
View File
@@ -1,8 +1,11 @@
#include <stdint.h> #include <stdint.h>
/** Implementation of saturated operation on uintaa_t. /** Implementation of saturated operation on uintxx_t.
* Opaerations are clamped betweehn 0 and UINTaa_MAa instead of *
* wrapping around*/ * Operations are clamped between 0 and UINTxx_MAX instead of
* wrapping around.
*
* multiplication, subtraction and addition operations are provided.*/
#define UC_SAT_ADD(a, b, type, max_val)\ #define UC_SAT_ADD(a, b, type, max_val)\
((type)((a) + (b)) >= (a) ? (a) + (b) : (max_val)) ((type)((a) + (b)) >= (a) ? (a) + (b) : (max_val))
-4
View File
@@ -9,10 +9,6 @@ extern "C" {
#endif #endif
size_t
uc_base64_enc(const unsigned char *data,size_t len,unsigned char *result);
size_t
uc_base64_dec(const unsigned char *data, size_t len, unsigned char *result);
char* char*
uc_hex_encode(const uint8_t *in, size_t len, char *out); uc_hex_encode(const uint8_t *in, size_t len, char *out);
+90
View File
@@ -0,0 +1,90 @@
#include <stddef.h>
#ifndef UC_STRVEC_H_
#define UC_STRVEC_H_
#ifdef __cplusplus
extern "C" {
#endif
/** A Vector of strings.*/
struct UCStrv
{
/** number of strings */
size_t cnt;
/** allocated room in strings (internal use) */
size_t allocated;
/** Array of strings */
char **strings;
};
/** Initialize a UCStrv
*
* @param strv
*/
void uc_strv_init(struct UCStrv *strv);
/**
* Grow the UCStrv so it can hold n more items
*
* @param strv UCStrv to grow
* @param cnt expand strvec to hold this cnt more items
* @return 0 on success, otherwise failure
**/
int uc_strv_grow(struct UCStrv *strv, size_t cnt);
/**
* Expand the UCStrv to hold 1 more item
*
* @param strv UCStrv to expand
* @return 0 on success, otherwise failure
**/
int uc_strv_expand(struct UCStrv *strv);
/**
* 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.
* @return 0 on success, otherwise failure
**/
int uc_strv_append(struct UCStrv *strv, const char *str);
/**
* Append a string to the strvec, nocopy variang.
* The string shold be dynamically allocated, as
* destroying the UCStrv will free() all items.
*
* @param strv UCStrv to add to
* @param str the string to append
* @return 0 on success, otherwise failure
**/
int uc_strv_append_nocopy(struct UCStrv *strv, char *str);
/**
* Append a NULL pointer to the UCStrv, (cnt is not increased,
* so another _appended item will overwrite this NULL terminator)
*
* @param strv UCStrv to append to
* @return 0 on success, otherwise failure
**/
int uc_strv_null_terminate(struct UCStrv *strv);
/**
* free all strings in this UCStrv, cnt will be 0 after this
* @param strv UCStrv to clear
*/
void uc_strv_clear(struct UCStrv *strv);
/**
* free all elements as well as the underlying array, the UCStrv is
* unusable after this call
*
* @param strv UCStrv to destroy
*/
void uc_strv_destroy(struct UCStrv *strv);
#ifdef __cplusplus
}
#endif
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef UCORE_SUPERVISOR_H_
#define UCORE_SUPERVISOR_H_
/** Supervises this process - restart if it dies.
*
* The program should call supervise() at a pristine state (all relevant file descriptors closed, etc).
* supervise() will return 0 if all is ok, and the program can continue.(returning != 0 means
* the supervisor couldn't start, and the calling process must exit)
*
* This will run the actual process as a child process. If that child process dies by any means,
* supervise will create another child process, where supervise() returns 0 again.
*
* To kill the supervisor process and the supervised process, send SIGERM/SIGHUP/SIGINT to the
* parent supervisor process.
* Sending SIGUSR1 to the parent supervisor process will terminate the current child process and
* restart it.
*
* The supervised child process must exit if it recieves a SIGTERM
* @return 0 on success, non-zero on failure (e.g. fork() fails)*/
int uc_supervise(void);
#endif
+6
View File
@@ -6,6 +6,11 @@
#include <sys/time.h> #include <sys/time.h>
#include "rbtree.h" #include "rbtree.h"
/** @addtogroup Timers
* @{
* Timer management for managing timeouts
*/
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -147,4 +152,5 @@ int uc_timers_run(struct UCTimers *timers);
} }
#endif #endif
/** @{ (addtogroup) */
#endif #endif
+4 -2
View File
@@ -48,12 +48,14 @@
//struct foo *f = CONTAINER_OF(p, struct foo, zap); //struct foo *f = CONTAINER_OF(p, struct foo, zap);
#define CONTAINER_OF(ptr, type, member) ({ \ #define CONTAINER_OF(ptr, type, member) ({ \
typeof( ((type *)0)->member ) *__mptr = (ptr); \ typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (unsigned char *)__mptr - offsetof(type, member) ); }) (type *)((void *)(unsigned char *)__mptr - offsetof(type, member) ); })
//the void* cast is to suppress alignment warnings
//Same as CONTAINER_OF, but for a const pointer to avoid gcc warnings.. //Same as CONTAINER_OF, but for a const pointer to avoid gcc warnings..
#define CONST_CONTAINER_OF(ptr, type, member) ({ \ #define CONST_CONTAINER_OF(ptr, type, member) ({ \
const typeof( ((const type *)0)->member ) *__mptr = (ptr); \ const typeof( ((const type *)0)->member ) *__mptr = (ptr); \
(const type *)( (const unsigned char *)__mptr - offsetof(const type, member) ); }) (const type *)((const void *)(const unsigned char *)__mptr - offsetof(const type, member) ); })
/** Align a value. /** Align a value.
* @param val value to align * @param val value to align
+10 -8
View File
@@ -35,16 +35,18 @@ void uc_backtrace_buf(char *buf, size_t len)
buf[0] = 0; buf[0] = 0;
lines = backtrace_symbols(buffer, ptrs); lines = backtrace_symbols(buffer, ptrs);
for (i = 1; i < ptrs; i++) { if (lines != NULL) {
for (i = 1; i < ptrs; i++) {
int rc = snprintf(buf, remaining, "%s\n", lines[i]); int rc = snprintf(buf, remaining, "%s\n", lines[i]);
if (rc <= 0 || (size_t)rc >= remaining) { if (rc <= 0 || (size_t)rc >= remaining) {
break; break;
}
remaining -= rc;
buf += rc;
} }
remaining -= rc;
buf += rc;
} }
free(lines); free(lines);
-52
View File
@@ -1,52 +0,0 @@
#include <stdint.h>
#include "ucore/string.h"
static const uint8_t basecode[128] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff
};
#define deccode(c) ((c > 127) ? 0xff : basecode[(c)])
size_t
uc_base64_dec(const unsigned char *data, size_t len, unsigned char *result)
{
size_t i = 0, j = 0, pad;
uint8_t c[4];
while ((i + 3) < len) {
pad = 0;
c[0] = deccode(data[i ]); pad += (c[0] == 0xff);
c[1] = deccode(data[i+1]); pad += (c[1] == 0xff);
c[2] = deccode(data[i+2]); pad += (c[2] == 0xff);
c[3] = deccode(data[i+3]); pad += (c[3] == 0xff);
switch (pad) {
case 1:
result[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
result[j++] = ((c[1] & 0x0f) << 4) | ((c[2] & 0x3c) >> 2);
result[j] = (c[2] & 0x03) << 6;
break;
case 2:
result[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
result[j] = (c[1] & 0x0f) << 4;
break;
default:
result[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
result[j++] = ((c[1] & 0x0f) << 4) | ((c[2] & 0x3c) >> 2);
result[j++] = ((c[2] & 0x03) << 6) | (c[3] & 0x3f);
}
i += 4;
}
return j;
}
-43
View File
@@ -1,43 +0,0 @@
#include <stdint.h>
#include <stdlib.h>
#include "ucore/string.h"
static const char basecode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define PAD '='
size_t
uc_base64_enc(const unsigned char *data,size_t len,unsigned char *result)
{
size_t i = 0, j = 0;
size_t pad;
while (i < len) {
pad = 3 - (len - i);
switch(pad) {
case 2:
result[j] = basecode[data[i]>>2];
result[j+1] = basecode[(data[i] & 0x03) << 4];
result[j+2] = PAD;
result[j+3] = PAD;
break;
case 3:
result[j ] = basecode[data[i]>>2];
result[j+1] = basecode[((data[i] & 0x03) << 4) | ((data[i+1] & 0xf0) >> 4)];
result[j+2] = basecode[(data[i+1] & 0x0f) << 2];
result[j+3] = PAD;
break;
default:
result[j ] = basecode[data[i]>>2];
result[j+1] = basecode[((data[i] & 0x03) << 4) | ((data[i+1] & 0xf0) >> 4)];
result[j+2] = basecode[((data[i+1] & 0x0f) << 2) | ((data[i+2] & 0xc0) >> 6)];
result[j+3] = basecode[data[i+2] & 0x3f];
break;
}
j += 4;
i += 3;
}
return j;
}
+114
View File
@@ -0,0 +1,114 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "ucore/dbuf.h"
void
uc_dbuf_free(DBuf *buf)
{
if (buf != NULL)
free(buf->bufstart);
}
int
uc_dbuf_init(DBuf *buf, size_t initlen)
{
unsigned char *tmp = malloc(initlen);
if (tmp == NULL)
return -1;
buf->start = buf->bufstart = buf->end = tmp;
buf->bufend = tmp + initlen;
return 0;
}
size_t
uc_dbuf_len(DBuf *buf)
{
return buf->end - buf->start;
}
size_t
uc_dbuf_buflen(DBuf *buf)
{
return buf->bufend - buf->bufstart;
}
size_t
uc_dbuf_remaining(DBuf *buf)
{
return buf->bufend - buf->end;
}
int
uc_dbuf_ensure(DBuf *buf, size_t capacity)
{
size_t sz, remaining, len;
remaining = uc_dbuf_remaining(buf);
if (remaining >= capacity)
return 0;
len = uc_dbuf_len(buf);
sz = buf->start - buf->bufstart;
if (buf->bufstart != buf->start)
memmove(buf->bufstart, buf->start, len);
if (sz + remaining < capacity) {
size_t newlen = uc_dbuf_buflen(buf) + capacity;
void *tmp = realloc(buf->bufstart, newlen);
if (tmp == NULL)
return 1;
buf->bufstart = tmp;
buf->bufend = buf->bufstart + newlen;
}
buf->start = buf->bufstart;
buf->end = buf->start + len;
return 0;
}
void
uc_dbuf_trim(DBuf *buf)
{
size_t len = uc_dbuf_len(buf);
void *tmp;
if (len == 0)
return;
if (buf->bufstart != buf->start)
memmove(buf->bufstart, buf->start, len);
tmp = realloc(buf->bufstart, len);
if (tmp != NULL)
buf->bufstart = tmp;
buf->start = buf->bufstart;
buf->bufend = buf->end = buf->bufstart + len;
}
int
uc_dbuf_take(DBuf *buf, size_t len)
{
size_t buflen = uc_dbuf_len(buf);
if (len == buflen) {
buf->start = buf->end = buf->bufstart;
} else if (len < buflen) {
buf->start = buf->start + len;
} else {
//should maybe assert. This is a serious offence
return 1;
}
return 0;
}
void
uc_dbuf_added(DBuf *buf, size_t len)
{
assert(len <= uc_dbuf_remaining(buf));
buf->end += len;
}
+43 -9
View File
@@ -2,20 +2,23 @@
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#include "ucore/fd_utils.h" #include "ucore/fd_utils.h"
int set_nonblocking(int fd) int uc_set_nonblocking(int fd)
{ {
int flags = fcntl(fd,F_GETFL,NULL); int flags = fcntl(fd,F_GETFL,NULL);
if(flags < 0 ) { if(flags < 0 ) {
return flags; return flags;
} }
return fcntl(fd,F_SETFL,flags | O_NONBLOCK); return fcntl(fd,F_SETFL,flags | O_NONBLOCK);
} }
int set_blocking(int fd) int uc_set_blocking(int fd)
{ {
int flags = fcntl(fd,F_GETFL,NULL); int flags = fcntl(fd,F_GETFL,NULL);
if(flags < 0 ) { if(flags < 0 ) {
@@ -25,43 +28,74 @@ int set_blocking(int fd)
return fcntl(fd,F_SETFL,flags&~O_NONBLOCK); return fcntl(fd,F_SETFL,flags&~O_NONBLOCK);
} }
int set_reuseaddr(int sockfd) int uc_set_reuseaddr(int sockfd)
{ {
int opt = 1; int opt = 1;
return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)); return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt));
} }
int set_tcp_keepalive(int sockfd) int uc_set_tcp_keepalive(int sockfd)
{ {
int optval = 1; int optval = 1;
return setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)); return setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
} }
int uc_set_tcp_keepalive_cfg(int sockfd, const struct UCKeepConfig *cfg)
{
int rc;
int set_send_timeout(int sockfd,long timeoutms) //first turn on keepalive
rc = uc_set_tcp_keepalive(sockfd);
if (rc != 0) {
return rc;
}
//set the keepalive options
rc = setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &cfg->keepcnt, sizeof cfg->keepcnt);
if (rc != 0) {
return rc;
}
rc = setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &cfg->keepidle, sizeof cfg->keepintvl);
if (rc != 0) {
return rc;
}
rc = setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &cfg->keepintvl, sizeof cfg->keepintvl);
if (rc != 0) {
return rc;
}
return 0;
}
int uc_set_send_timeout(int sockfd,long timeoutms)
{ {
struct timeval so_sndtimeo = {timeoutms/1000,(timeoutms%1000)*1000}; struct timeval so_sndtimeo = {timeoutms/1000,(timeoutms%1000)*1000};
return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &so_sndtimeo, sizeof(so_sndtimeo)); return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &so_sndtimeo, sizeof(so_sndtimeo));
} }
int set_receive_timeout(int sockfd,long timeoutms) int uc_set_receive_timeout(int sockfd,long timeoutms)
{ {
struct timeval so_sndtimeo = {timeoutms/1000,(timeoutms%1000)*1000}; struct timeval so_sndtimeo = {timeoutms/1000,(timeoutms%1000)*1000};
return setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &so_sndtimeo, sizeof(so_sndtimeo)); return setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &so_sndtimeo, sizeof(so_sndtimeo));
} }
int
set_ip_dscp(int fd, unsigned int dscp) { int uc_set_ip_dscp(int fd, unsigned int dscp)
{
int val; int val;
//only 6 bits for dscp
if (dscp > 63) { if (dscp > 63) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
val = dscp << 2; val = dscp << 2;
return setsockopt(fd, IPPROTO_IP, IP_TOS, &val, sizeof val); return setsockopt(fd, IPPROTO_IP, IP_TOS, &val, sizeof val);
} }
+1 -1
View File
@@ -183,7 +183,7 @@ again:
fd->callback(mux_, fd, events); fd->callback(mux_, fd, events);
//be sure not to use fd after the callback, it might been removed. //be sure not to use fd after the callback, it might been removed.
mux->pending_events[i].data.ptr = NULL; mux->pending_events[i].data.ptr = NULL; //clear from pending list
event_cnt++; event_cnt++;
} }
+2 -1
View File
@@ -168,17 +168,18 @@ again:
} }
if (FD_ISSET(mux->descriptors[i]->fd, &read_set)) { if (FD_ISSET(mux->descriptors[i]->fd, &read_set)) {
rc--;
events |= MUX_EV_READ; events |= MUX_EV_READ;
} }
if (FD_ISSET(mux->descriptors[i]->fd, &write_set)) { if (FD_ISSET(mux->descriptors[i]->fd, &write_set)) {
rc--;
events |= MUX_EV_WRITE; events |= MUX_EV_WRITE;
} }
if (events) { if (events) {
assert(mux->descriptors[i]->callback != NULL); assert(mux->descriptors[i]->callback != NULL);
mux->descriptors[i]->callback(mux_, mux->descriptors[i], events); mux->descriptors[i]->callback(mux_, mux->descriptors[i], events);
rc--;
event_cnt++; event_cnt++;
} }
} }
+119
View File
@@ -0,0 +1,119 @@
#include <string.h>
#include <stdlib.h>
#include "ucore/mbuf.h"
uint8_t *uc_mbuf_put(struct MBuf *mbuf, uint32_t size)
{
uint8_t *data = mbuf->tail;
if (uc_mbuf_tailroom(mbuf) < size) {
return NULL;
}
mbuf->tail += size;
return data;
}
uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size)
{
if (uc_mbuf_headroom(mbuf) < size) {
return NULL;
}
mbuf->head -= size;
return mbuf->head;
}
uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size)
{
uint8_t *data = mbuf->head;
if (uc_mbuf_len(mbuf) < size) {
return NULL;
}
mbuf->head += size;
return data;
}
void uc_mbuf_init(struct MBuf *mbuf, uint8_t *buf, uint32_t len, uint32_t headroom, uint32_t flags)
{
mbuf->bufstart = buf;
mbuf->next = NULL;
mbuf->p1 = mbuf->p2 = mbuf->p3 = mbuf->p4 = NULL;
mbuf->cookie = NULL;
mbuf->flags = flags;
mbuf->allocated = len + headroom;
mbuf->head = mbuf->bufstart + headroom;
mbuf->tail = mbuf->head;
}
struct MBuf *uc_mbuf_new_hr(uint32_t len, uint32_t headroom)
{
struct MBuf *mbuf;
uint8_t *buf;
mbuf = malloc(sizeof *mbuf);
if (mbuf == NULL)
return mbuf;
buf = malloc(len + headroom);
if (buf == NULL) {
free(mbuf);
return NULL;
}
uc_mbuf_init(mbuf, buf, len, headroom, UC_MBUF_FL_MALLOC);
return mbuf;
}
struct MBuf *uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom)
{
struct MBuf *mbuf;
mbuf = malloc(sizeof *mbuf + len + headroom);
if (mbuf == NULL)
return mbuf;
uc_mbuf_init(mbuf, mbuf->inline_data, len, headroom, UC_MBUF_FL_MALLOC_INLINE);
return mbuf;
}
void uc_mbuf_free(struct MBuf *mbuf)
{
if (mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_BUF))
free(mbuf->bufstart);
if (mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_INLINE))
free(mbuf);
}
void uc_mbuf_zero(struct MBuf *mbuf)
{
memset(mbuf->bufstart, 0, mbuf->allocated);
}
struct MBuf *uc_mbuf_copy_data(struct MBuf *mbuf)
{
uint32_t len;
struct MBuf *copy;
uint8_t *data;
len = uc_mbuf_len(mbuf);
copy = uc_mbuf_new_hr(len, uc_mbuf_headroom(mbuf));
if (copy == NULL) {
return NULL;
}
data = uc_mbuf_put(copy, len);
memcpy(data, mbuf->head, len);
return copy;
}
+107
View File
@@ -0,0 +1,107 @@
#include <string.h>
#include <stdlib.h>
#include "ucore/strvec.h"
void uc_strv_init(struct UCStrv *strv)
{
strv->cnt = 0;
strv->allocated = 0;
strv->strings = NULL;
}
int uc_strv_grow(struct UCStrv *strv, size_t cnt)
{
size_t allocate = strv->allocated + cnt;
void *tmp = realloc(strv->strings, sizeof *strv->strings * allocate);
if (tmp == NULL) {
return -1;
}
strv->strings = tmp;
strv->allocated = allocate;
return 0;
}
int uc_strv_expand(struct UCStrv *strv)
{
int rc = 0;
if (strv->cnt >= strv->allocated) {
rc = uc_strv_grow(strv, 1);
}
return rc;
}
int uc_strv_append(struct UCStrv *strv, const char *str)
{
int rc;
char *dup;
rc = uc_strv_expand(strv);
if (rc != 0) {
return rc;
}
dup = strdup(str);
if (dup == NULL) {
return -2;
}
strv->strings[strv->cnt] = dup;
strv->cnt++;
return 0;
}
int uc_strv_append_nocopy(struct UCStrv *strv, char *str)
{
int rc;
rc = uc_strv_expand(strv);
if (rc != 0) {
return rc;
}
strv->strings[strv->cnt] = str;
strv->cnt++;
return 0;
}
int uc_strv_null_terminate(struct UCStrv *strv)
{
int rc;
rc = uc_strv_expand(strv);
if (rc != 0) {
return rc;
}
strv->strings[strv->cnt] = NULL;
strv->cnt++;
return 0;
}
void uc_strv_clear(struct UCStrv *strv)
{
size_t i;
for (i = 0; i < strv->cnt; i++) {
free(strv->strings[i]);
strv->strings[i] = NULL;
}
strv->cnt = 0;
}
void uc_strv_destroy(struct UCStrv *strv)
{
uc_strv_clear(strv);
free(strv->strings);
strv->strings = NULL;
}
+180
View File
@@ -0,0 +1,180 @@
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <syslog.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#define CLEAN_EXIT 11
#define BAD_EXIT 22
#define RESTART 33
//seconds to wait before restarting the process
#define RESTART_GRACE 1
static volatile sig_atomic_t restart_flag = 0;
static volatile sig_atomic_t exit_flag = 0;
static void restart_handler(int sig)
{
(void)sig;
restart_flag = 1;
}
static void exit_handler(int sig)
{
(void)sig;
exit_flag = 1;
}
static void kill_supervised_process(pid_t pid)
{
kill(pid, SIGTERM);
/* Todo.. verify we killed it, otherwise take more
* desperate measures*/
}
static int watch(pid_t pid)
{
int status;
pid_t rc;
again:
rc = waitpid(pid, &status, 0);
if (rc == -1 && errno == EINTR) {
if (restart_flag) {
restart_flag = 0;
kill_supervised_process(pid);
/* next waitpid should notify us of the death and
* we'll restart the process */
goto again;
} else if (exit_flag) {
exit_flag = 0;
return CLEAN_EXIT;
}
goto again;
} else if (rc == -1) {
return BAD_EXIT;
}
if (WIFSIGNALED(status)) {
syslog(LOG_ERR, "supervised process(pid %ld) exited cause of signal %d, status = 0x%X", (long)pid, WTERMSIG(status), status);
return RESTART;
} else if (WIFEXITED(status)) {
syslog(LOG_ERR, "supervised process(pid %ld) exited with code %d, status = 0x%X", (long)pid, WTERMSIG(status), status);
return RESTART;
}
/* Ok, can we ever get here ? */
syslog(LOG_ERR, "waitpid of supervised process(pid %ld) status = 0x%X", (long)pid, status);
if (kill(pid, 0) == 0) {
syslog(LOG_ERR, "supervised process(pid %ld) seems to still be alive, not restarting", (long)pid);
goto again;
}
return RESTART;
}
static struct sigaction orig_usr1_sa;
static struct sigaction orig_term_sa;
static struct sigaction orig_hup_sa;
static struct sigaction orig_int_sa;
static void restore_signal_handlers(void)
{
sigaction(SIGUSR1, &orig_usr1_sa, NULL);
sigaction(SIGTERM, &orig_term_sa, NULL);
sigaction(SIGHUP, &orig_hup_sa, NULL);
sigaction(SIGINT, &orig_int_sa, NULL);
}
static void install_signal_handlers(void)
{
struct sigaction act;
memset(&act, 0, sizeof act);
act.sa_handler = restart_handler;
sigaction(SIGUSR1, &act, &orig_usr1_sa);
act.sa_handler = exit_handler;
sigaction(SIGTERM, &act, &orig_term_sa);
sigaction(SIGHUP, &act, &orig_hup_sa);
sigaction(SIGINT, &act, &orig_int_sa);
}
//See notes in supervisor.h
int uc_supervise(void)
{
pid_t pid;
pid = fork();
if (pid == -1) {
syslog(LOG_ERR, "Cannot create supervisor : %s", strerror(errno));
return -1;
} else if (pid == 0) {
return 0;
}
//close_files();
install_signal_handlers();
syslog(LOG_INFO, "Supervising pid %ld", (long)pid);
for (;;) {
int cmd = watch(pid);
switch (cmd) {
case CLEAN_EXIT:
syslog(LOG_INFO, "Terminating supervised pid %lu", (unsigned long)pid);
kill_supervised_process(pid);
wait(NULL);
syslog(LOG_INFO, "Exiting");
exit(0);
break;
case BAD_EXIT:
syslog(LOG_ERR, "watch() error, exiting");
exit(55);
break;
case RESTART: {
pid_t new_pid = -1;
while (new_pid == -1) {
sleep(RESTART_GRACE);
syslog(LOG_INFO, "Restarting supervised pid %lu", (unsigned long)pid);
closelog();
new_pid = fork();
if (new_pid == -1) {
syslog(LOG_INFO, "Cannot restart. %s", strerror(errno));
} else if (new_pid == 0) { //return so the original process continues
restore_signal_handlers();
return 0;
}
}
pid = new_pid;
syslog(LOG_INFO, "Supervising new pid %lu", (unsigned long)new_pid);
}
break;
default:
exit(38);
break;
}
}
return 0x76;
}
+4 -3
View File
@@ -19,11 +19,11 @@ static int timers_cmp(const RBNode *a_, const RBNode *b_)
} else if (a->seq > b->seq) { } else if (a->seq > b->seq) {
return 1; return 1;
} else { //should never happen } else { //should never happen
//assert(0); assert(0);
return 0; return 0;
} }
} }
//assert(0); assert(0);
return 0; //silence compiler return 0; //silence compiler
} }
@@ -56,8 +56,9 @@ void uc_timers_add(struct UCTimers *timers, struct UCTimer *timer, int sec, int
struct timeval tmp; struct timeval tmp;
assert(timer->callback != NULL); assert(timer->callback != NULL);
if (timer->callback == NULL) //must be set. if (timer->callback == NULL) { //must be set.
return; return;
}
tmp.tv_sec = sec; tmp.tv_sec = sec;
tmp.tv_usec = usec; tmp.tv_usec = usec;
+9 -5
View File
@@ -6,8 +6,10 @@ uc_tvadd(struct timeval *dst, const struct timeval *a, const struct timeval *b)
dst->tv_sec = a->tv_sec + b->tv_sec; dst->tv_sec = a->tv_sec + b->tv_sec;
dst->tv_usec = a->tv_usec + b->tv_usec; dst->tv_usec = a->tv_usec + b->tv_usec;
if (dst->tv_usec >= 1000000) if (dst->tv_usec >= 1000000) {
dst->tv_sec++, dst->tv_usec -= 1000000; dst->tv_sec++;
dst->tv_usec -= 1000000;
}
return dst; return dst;
} }
@@ -18,8 +20,10 @@ uc_tvsub(struct timeval *dst, const struct timeval *a, const struct timeval *b)
dst->tv_sec = a->tv_sec - b->tv_sec; dst->tv_sec = a->tv_sec - b->tv_sec;
dst->tv_usec = a->tv_usec - b->tv_usec; dst->tv_usec = a->tv_usec - b->tv_usec;
if (dst->tv_usec < 0) if (dst->tv_usec < 0) {
dst->tv_sec--, dst->tv_usec += 1000000; dst->tv_sec--;
dst->tv_usec += 1000000;
}
return dst; return dst;
} }
@@ -41,7 +45,7 @@ uc_tvcmp(const struct timeval *a, const struct timeval *b)
} }
struct timeval * struct timeval *
uc_to2tv(struct timeval *dst, unsigned long ms) uc_ms2tv(struct timeval *dst, unsigned long long ms)
{ {
dst->tv_sec = ms / 1000; dst->tv_sec = ms / 1000;
dst->tv_usec = ms % 1000 * 1000; dst->tv_usec = ms % 1000 * 1000;
+2
View File
@@ -66,6 +66,8 @@ START_TEST (test_bitvec_setall_clearall)
for (i = 0; i < sizeof(unsigned long) * 8; i++) for (i = 0; i < sizeof(unsigned long) * 8; i++)
fail_if(uc_bv_get_bit(v, i) != 0 , "bit %zu is not 0", i); fail_if(uc_bv_get_bit(v, i) != 0 , "bit %zu is not 0", i);
uc_bv_free(v);
END_TEST END_TEST
Suite *bitvec_suite(void) Suite *bitvec_suite(void)
+97
View File
@@ -0,0 +1,97 @@
#include <check.h>
#include <string.h>
#include <ucore/dbuf.h>
START_TEST (test_dbuf)
DBuf buf;
int rc;
rc = uc_dbuf_init(&buf, 10);
fail_if(rc != 0);
fail_if(uc_dbuf_buflen(&buf) != 10);
fail_if(uc_dbuf_remaining(&buf) != 10);
strcpy((char *)buf.end, "12345679");
uc_dbuf_added(&buf, 10);
fail_if(uc_dbuf_len(&buf) != 10);
fail_if(uc_dbuf_remaining(&buf) != 0);
rc = uc_dbuf_ensure(&buf, 110);
fail_if(rc != 0);
fail_if(uc_dbuf_remaining(&buf) != 110);
fail_if(uc_dbuf_buflen(&buf) != 120);
rc = uc_dbuf_ensure(&buf, 5);
fail_if(rc != 0);
strcpy((char *)buf.end, "ABCD");
uc_dbuf_added(&buf, 5);
uc_dbuf_take(&buf, 10);
fail_if(uc_dbuf_remaining(&buf) != 105);
fail_if(uc_dbuf_len(&buf) != 5);
ck_assert_str_eq((char *)buf.start, "ABCD");
uc_dbuf_take(&buf, 5);
fail_if(uc_dbuf_remaining(&buf) != 120);
fail_if(uc_dbuf_buflen(&buf) != 120);
fail_if(uc_dbuf_len(&buf) != 0);
strcpy((char *)buf.end, "EFGH");
uc_dbuf_added(&buf, 5);
uc_dbuf_trim(&buf);
fail_if(uc_dbuf_buflen(&buf) != 5);
fail_if(uc_dbuf_len(&buf) != 5);
uc_dbuf_take(&buf, 1);
rc = uc_dbuf_ensure(&buf, 10);
fail_if(rc != 0);
ck_assert_str_eq((char *)buf.start, "FGH");
uc_dbuf_take(&buf, 1);
uc_dbuf_trim(&buf);
ck_assert_str_eq((char *)buf.start, "GH");
fail_if(uc_dbuf_buflen(&buf) != 3);
fail_if(uc_dbuf_len(&buf) != 3);
uc_dbuf_free(&buf);
END_TEST
START_TEST (test_dbuf_take_fail)
DBuf buf;
int rc;
rc = uc_dbuf_init(&buf, 10);
fail_if(rc != 0);
fail_if(uc_dbuf_buflen(&buf) != 10);
fail_if(uc_dbuf_remaining(&buf) != 10);
strcpy((char *)buf.end, "12345679");
uc_dbuf_added(&buf, 10);
fail_if(uc_dbuf_len(&buf) != 10);
fail_if(uc_dbuf_remaining(&buf) != 0);
rc = uc_dbuf_take(&buf, 11);
fail_if(rc == 0);
uc_dbuf_free(&buf);
END_TEST
Suite *dbuf_suite(void)
{
Suite *s = suite_create("dbuf");
TCase *tc = tcase_create("dbuf tests");
tcase_add_test(tc, test_dbuf);
tcase_add_test(tc, test_dbuf_take_fail);
suite_add_tcase(s, tc);
return s;
}
+14
View File
@@ -164,6 +164,18 @@ START_TEST (test_uc_hex_encode_delim_zero_len)
END_TEST END_TEST
START_TEST (test_uc_hex_decode_lowercase)
char hex[] = "1f";
uint8_t binary[2] = {0x11,0x22};
uint8_t *res;
res = uc_hex_decode(hex, 2, binary);
fail_if(binary[0] != 0x1f);
fail_if(binary[1] != 0x22);
fail_if(res != binary + 1, "binary %p, res %p", &binary[0], res);
END_TEST
Suite *hex_suite(void) Suite *hex_suite(void)
{ {
Suite *s = suite_create("hex"); Suite *s = suite_create("hex");
@@ -185,6 +197,8 @@ Suite *hex_suite(void)
tcase_add_test(tc, test_uc_hex_decode_invalid); tcase_add_test(tc, test_uc_hex_decode_invalid);
tcase_add_test(tc, test_uc_hex_decode_empty_string); tcase_add_test(tc, test_uc_hex_decode_empty_string);
tcase_add_test(tc, test_uc_hex_decode_lowercase);
suite_add_tcase(s, tc); suite_add_tcase(s, tc);
+85
View File
@@ -0,0 +1,85 @@
#include <check.h>
#include <ucore/string.h>
START_TEST (test_human_bytesz_bytes)
char result[128];
char *rc;
rc = uc_human_bytesz(999, result, sizeof result);
fail_if(rc == NULL);
ck_assert_str_eq(result, "999 b");
END_TEST
START_TEST (test_human_bytesz_bytes_0)
char result[128];
char *rc;
rc = uc_human_bytesz(0, result, sizeof result);
fail_if(rc == NULL);
ck_assert_str_eq(result, "0 b");
END_TEST
START_TEST (test_human_bytesz_kilobytes)
char result[128];
char *rc;
rc = uc_human_bytesz(64000, result, sizeof result);
fail_if(rc == NULL);
ck_assert_str_eq(result, "64.00 kB");
END_TEST
START_TEST (test_human_bytesz_megabytes)
char result[128];
char *rc;
rc = uc_human_bytesz(6409000, result, sizeof result);
fail_if(rc == NULL);
ck_assert_str_eq(result, "6.41 MB");
END_TEST
START_TEST (test_human_bytesz_gigabytes)
char result[128];
char *rc;
rc = uc_human_bytesz(126999400000, result, sizeof result);
fail_if(rc == NULL);
ck_assert_str_eq(result, "127.00 GB");
END_TEST
START_TEST (test_human_bytesz_terrabytes)
char result[128];
char *rc;
rc = uc_human_bytesz(12453400030000, result, sizeof result);
fail_if(rc == NULL);
ck_assert_str_eq(result, "12.45 TB");
END_TEST
START_TEST (test_human_bytesz_petabytes)
char result[128];
char *rc;
rc = uc_human_bytesz(~0LL, result, sizeof result);
fail_if(rc == NULL);
ck_assert_str_eq(result, "18446.74 PB");
END_TEST
Suite *human_bytesz_suite(void)
{
Suite *s = suite_create("human_bytesz");
TCase *tc = tcase_create("human_bytesz tests");
tcase_add_test(tc, test_human_bytesz_bytes);
tcase_add_test(tc, test_human_bytesz_bytes_0);
tcase_add_test(tc, test_human_bytesz_kilobytes);
tcase_add_test(tc, test_human_bytesz_megabytes);
tcase_add_test(tc, test_human_bytesz_gigabytes);
tcase_add_test(tc, test_human_bytesz_terrabytes);
tcase_add_test(tc, test_human_bytesz_petabytes);
suite_add_tcase(s, tc);
return s;
}
+50
View File
@@ -50,6 +50,7 @@ START_TEST (test_logfile_location)
dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1); dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1);
fail_if(dest == NULL); fail_if(dest == NULL);
uc_log_add_destination(dest); uc_log_add_destination(dest);
uc_log_add_destination(dest); //adding this twice should do nothing
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1); UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1);
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson 2\n"); UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson 2\n");
@@ -62,6 +63,54 @@ START_TEST (test_logfile_location)
fail_if(st.st_size != 380, "was %ld\n", (long)st.st_size); fail_if(st.st_size != 380, "was %ld\n", (long)st.st_size);
END_TEST END_TEST
START_TEST (test_logfile_delete_destination)
struct uc_log_module m = {
.id = 0,
.short_name = "MOD1",
.long_name = "Module 1",
.log_level = UC_LL_DEBUG,
};
struct uc_log_modules mods = {
.mods = &m,
.cnt = 1,
};
struct stat st;
struct uc_log_destination *dest;
int rc;
uc_log_init(&mods);
dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1);
fail_if(dest == NULL);
uc_log_add_destination(dest);
uc_log_add_destination(dest); //adding this twice should do nothing
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1);
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson 2\n");
UC_LOGF(UC_LL_INFO, 0, "Lorum ipson 3\n");
UC_LOGF(UC_LL_WARNING, 0, "Lorum ipson 4\n");
UC_LOGF(UC_LL_ERROR, 0, "Lorum ipson 5\n");
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s\n", strerror(errno));
fail_if(st.st_size != 380, "was %ld\n", (long)st.st_size);
uc_log_delete_destination(dest);
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1);
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson 2\n");
UC_LOGF(UC_LL_INFO, 0, "Lorum ipson 3\n");
UC_LOGF(UC_LL_WARNING, 0, "Lorum ipson 4\n");
UC_LOGF(UC_LL_ERROR, 0, "Lorum ipson 5\n");
//since we deleted destinatiion, no more logging should appear in the file
rc = stat(FILE_NAME, &st);
fail_if(rc != 0, "stat failed: %s\n", strerror(errno));
fail_if(st.st_size != 380, "was %ld\n", (long)st.st_size);
END_TEST
START_TEST (test_logfile_no_location) START_TEST (test_logfile_no_location)
struct uc_log_module m = { struct uc_log_module m = {
@@ -476,6 +525,7 @@ Suite *logging_suite(void)
TCase *tc2 = tcase_create("ucore_logging2"); TCase *tc2 = tcase_create("ucore_logging2");
tcase_add_test(tc1, test_logfile_location); tcase_add_test(tc1, test_logfile_location);
tcase_add_test(tc1, test_logfile_delete_destination);
tcase_add_test(tc1, test_logfile_no_location); tcase_add_test(tc1, test_logfile_no_location);
tcase_add_test(tc1, test_logfile_loglevel_surpressed_dest); tcase_add_test(tc1, test_logfile_loglevel_surpressed_dest);
tcase_add_test(tc1, test_logfile_loglevel_surpressed_module); tcase_add_test(tc1, test_logfile_loglevel_surpressed_module);
+266
View File
@@ -0,0 +1,266 @@
#include <check.h>
#include <string.h>
#include <ucore/mbuf.h>
START_TEST (test_mbuf_new)
struct MBuf *mbuf;
mbuf = uc_mbuf_new(110);
fail_if(mbuf == NULL);
fail_if(uc_mbuf_len(mbuf) != 0);
fail_if(uc_mbuf_headroom(mbuf) != 0);
fail_if(uc_mbuf_tailroom(mbuf) != 110);
fail_if(mbuf->next != NULL);
fail_if(mbuf->p1 != NULL);
fail_if(mbuf->p2 != NULL);
fail_if(mbuf->p3 != NULL);
fail_if(mbuf->p4 != NULL);
fail_if(mbuf->cookie != NULL);
fail_if(mbuf->head != mbuf->tail);
uc_mbuf_free(mbuf);
END_TEST
START_TEST (test_mbuf_new_inline)
struct MBuf *mbuf;
mbuf = uc_mbuf_new_inline(110);
fail_if(mbuf == NULL);
fail_if(uc_mbuf_len(mbuf) != 0);
fail_if(uc_mbuf_headroom(mbuf) != 0);
fail_if(uc_mbuf_tailroom(mbuf) != 110);
fail_if(mbuf->next != NULL);
fail_if(mbuf->p1 != NULL);
fail_if(mbuf->p2 != NULL);
fail_if(mbuf->p3 != NULL);
fail_if(mbuf->p4 != NULL);
fail_if(mbuf->cookie != NULL);
fail_if(mbuf->head != mbuf->tail);
uc_mbuf_free(mbuf);
END_TEST
START_TEST (test_mbuf_new_headroom)
struct MBuf *mbuf;
mbuf = uc_mbuf_new_hr(110,20);
fail_if(mbuf == NULL);
fail_if(uc_mbuf_len(mbuf) != 0);
fail_if(uc_mbuf_headroom(mbuf) != 20);
fail_if(uc_mbuf_tailroom(mbuf) != 110);
fail_if(mbuf->next != NULL);
fail_if(mbuf->p1 != NULL);
fail_if(mbuf->p2 != NULL);
fail_if(mbuf->p3 != NULL);
fail_if(mbuf->p4 != NULL);
fail_if(mbuf->cookie != NULL);
fail_if(mbuf->head != mbuf->tail);
uc_mbuf_free(mbuf);
END_TEST
START_TEST (test_mbuf_put)
struct MBuf *mbuf;
uint8_t *data;
mbuf = uc_mbuf_new_inline(111);
fail_if(mbuf == NULL);
data = uc_mbuf_put(mbuf, 111);
fail_if(data == NULL);
fail_if(uc_mbuf_len(mbuf) != 111);
fail_if(uc_mbuf_tailroom(mbuf) != 0);
memset(data, 0, 111);
uc_mbuf_free(mbuf);
END_TEST
START_TEST (test_mbuf_put_fail)
struct MBuf *mbuf;
uint8_t *data;
mbuf = uc_mbuf_new_inline(10);
fail_if(mbuf == NULL);
data = uc_mbuf_put(mbuf, 11);
fail_if(data != NULL);
uc_mbuf_free(mbuf);
END_TEST
START_TEST (test_mbuf_push)
struct MBuf *mbuf;
uint8_t *data;
mbuf = uc_mbuf_new_hr(10,1);
fail_if(mbuf == NULL);
data = uc_mbuf_push(mbuf, 1);
fail_if(data == NULL);
fail_if(uc_mbuf_len(mbuf) != 1);
fail_if(uc_mbuf_headroom(mbuf) != 0);
*data = 0;
uc_mbuf_free(mbuf);
END_TEST
START_TEST (test_mbuf_push_fail)
struct MBuf *mbuf;
uint8_t *data;
mbuf = uc_mbuf_new_hr(1,2);
fail_if(mbuf == NULL);
data = uc_mbuf_push(mbuf, 3);
fail_if(data != NULL);
uc_mbuf_free(mbuf);
END_TEST
START_TEST (test_mbuf_pull)
struct MBuf *mbuf;
uint8_t *data1;
uint8_t *data2;
mbuf = uc_mbuf_new_inline(10);
fail_if(mbuf == NULL);
data1 = uc_mbuf_put(mbuf, 10);
fail_if(data1 == NULL);
fail_if(uc_mbuf_tailroom(mbuf) != 0);
fail_if(uc_mbuf_len(mbuf) != 10);
data2 = uc_mbuf_pull(mbuf,10);
fail_if(data2 == NULL);
fail_if(data1 != data2);
fail_if(uc_mbuf_len(mbuf) != 0);
uc_mbuf_free(mbuf);
END_TEST
START_TEST (test_mbuf_pull_fail)
struct MBuf *mbuf;
uint8_t *data1;
uint8_t *data2;
mbuf = uc_mbuf_new_inline(10);
fail_if(mbuf == NULL);
data1 = uc_mbuf_put(mbuf, 10);
fail_if(data1 == NULL);
fail_if(uc_mbuf_len(mbuf) != 10);
data2 = uc_mbuf_pull(mbuf,11);
fail_if(data2 != NULL);
fail_if(uc_mbuf_len(mbuf) != 10);
uc_mbuf_free(mbuf);
END_TEST
START_TEST (test_mbuf_copy)
struct MBuf *mbuf;
uint8_t *data1;
struct MBuf *copy;
mbuf = uc_mbuf_new_inline_hr(10,5);
fail_if(mbuf == NULL);
data1 = uc_mbuf_put(mbuf, 10);
fail_if(data1 == NULL);
strcpy((char*)data1, "123456789");
copy = uc_mbuf_copy_data(mbuf);
fail_if(copy == NULL);
fail_if(uc_mbuf_len(copy) != 10);
fail_if(uc_mbuf_headroom(copy) != 5);
fail_if(memcmp(mbuf->head, copy->head, 10) != 0);
uc_mbuf_free(mbuf);
uc_mbuf_free(copy);
END_TEST
START_TEST (test_mbuf_zero)
struct MBuf *mbuf;
uint8_t *data1;
mbuf = uc_mbuf_new_inline(10);
fail_if(mbuf == NULL);
data1 = uc_mbuf_put(mbuf, 10);
fail_if(data1 == NULL);
strcpy((char*)data1, "123456789");
uc_mbuf_zero(mbuf);
fail_if(memcmp(mbuf->head, "\0\0\0\0\0\0\0\0\0\0", 10) != 0);
uc_mbuf_free(mbuf);
END_TEST
START_TEST (test_mbuf_static)
uint8_t data[1024];
struct MBuf mbuf;
uc_mbuf_init(&mbuf, data, 1000, 24, UC_MBUF_FL_STATIC);
fail_if(uc_mbuf_len(&mbuf) != 0);
fail_if(uc_mbuf_headroom(&mbuf) != 24);
fail_if(uc_mbuf_tailroom(&mbuf) != 1000);
fail_if(mbuf.next != NULL);
fail_if(mbuf.p1 != NULL);
fail_if(mbuf.p2 != NULL);
fail_if(mbuf.p3 != NULL);
fail_if(mbuf.p4 != NULL);
fail_if(mbuf.cookie != NULL);
fail_if(mbuf.head != mbuf.tail);
fail_if(mbuf.head != &data[24]);
uc_mbuf_free(&mbuf);
END_TEST
Suite *mbuf_suite(void)
{
Suite *s = suite_create("mbuf");
TCase *tc = tcase_create("mbuf tests");
tcase_add_test(tc, test_mbuf_new);
tcase_add_test(tc, test_mbuf_new_inline);
tcase_add_test(tc, test_mbuf_new_headroom);
tcase_add_test(tc, test_mbuf_put);
tcase_add_test(tc, test_mbuf_put_fail);
tcase_add_test(tc, test_mbuf_push);
tcase_add_test(tc, test_mbuf_push_fail);
tcase_add_test(tc, test_mbuf_pull);
tcase_add_test(tc, test_mbuf_pull_fail);
tcase_add_test(tc, test_mbuf_copy);
tcase_add_test(tc, test_mbuf_zero);
tcase_add_test(tc, test_mbuf_static);
suite_add_tcase(s, tc);
return s;
}
+63
View File
@@ -91,6 +91,65 @@ START_TEST (test_read_file_boundary)
free(content); free(content);
END_TEST END_TEST
START_TEST (test_read_file_devnull)
char *content;
size_t len = 123;
content = uc_read_file("/dev/null", &len, 1024);
fail_if(content == NULL);
fail_if(len != 0);
free(content);
END_TEST
START_TEST (test_read_file_too_big)
char *content;
const char *filename = "test_read_file_too_big";
size_t len;
ssize_t rc;
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
fail_if(fd == -1);
rc = write(fd, "hello", 5);
fail_if(rc != 5, "rc was %ld", (long)rc);
close(fd);
content = uc_read_file(filename, &len, 4);
fail_if(errno != EMSGSIZE);
fail_if(content != NULL);
unlink(filename);
END_TEST
START_TEST (test_read_file_big)
char *content;
const char *filename = "test_read_file_big";
char buf[4096 * 16];
size_t len;
ssize_t rc;
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
fail_if(fd == -1);
memset(buf, 'a', sizeof buf);
rc = write(fd, buf, sizeof buf);
fail_if(rc != sizeof buf, "rc was %ld", (long)rc);
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);
free(content);
unlink(filename);
END_TEST
Suite *read_file_suite(void) Suite *read_file_suite(void)
{ {
Suite *s = suite_create("read_file"); Suite *s = suite_create("read_file");
@@ -99,6 +158,10 @@ Suite *read_file_suite(void)
tcase_add_test(tc, test_read_file_simple); tcase_add_test(tc, test_read_file_simple);
tcase_add_test(tc, test_read_file_greater_than_max); tcase_add_test(tc, test_read_file_greater_than_max);
tcase_add_test(tc, test_read_file_boundary); tcase_add_test(tc, test_read_file_boundary);
tcase_add_test(tc, test_read_file_devnull);
tcase_add_test(tc, test_read_file_too_big);
tcase_add_test(tc, test_read_file_big);
suite_add_tcase(s, tc); suite_add_tcase(s, tc);
+11 -1
View File
@@ -19,6 +19,11 @@ extern Suite *clock_suite(void);
extern Suite *seq_suite(void); extern Suite *seq_suite(void);
extern Suite *sat_math_suite(void); extern Suite *sat_math_suite(void);
extern Suite *timers_suite(void); extern Suite *timers_suite(void);
extern Suite *mbuf_suite(void);
extern Suite *human_bytesz_suite(void);
extern Suite *dbuf_suite(void);
extern Suite *sprintb_suite(void);
extern Suite *strv_suite(void);
static suite_func suites[] = { static suite_func suites[] = {
bitvec_suite, bitvec_suite,
@@ -33,7 +38,12 @@ static suite_func suites[] = {
clock_suite, clock_suite,
seq_suite, seq_suite,
sat_math_suite, sat_math_suite,
timers_suite timers_suite,
mbuf_suite,
human_bytesz_suite,
dbuf_suite,
sprintb_suite,
strv_suite
}; };
int int
+97
View File
@@ -0,0 +1,97 @@
#include <check.h>
#include <limits.h>
#include <ucore/string.h>
//Note these tests assume
// char 8 bit
// short 16 bit
// int 32 bit
// long long 64 bit
START_TEST (test_sprintb)
char result[128];
char *rc;
rc = uc_sprintb(result, 0);
ck_assert_str_eq(rc, "00000000000000000000000000000000");
rc = uc_sprintb(result, UINT_MAX);
ck_assert_str_eq(rc, "11111111111111111111111111111111");
rc = uc_sprintb(result, 0xE0A14341);
ck_assert_str_eq(rc, "11100000101000010100001101000001");
rc = uc_sprintb(result, 1);
ck_assert_str_eq(rc, "00000000000000000000000000000001");
END_TEST
START_TEST (test_sprintbc)
char result[128];
char *rc;
rc = uc_sprintbc(result, 0);
ck_assert_str_eq(rc, "00000000");
rc = uc_sprintbc(result, UCHAR_MAX);
ck_assert_str_eq(rc, "11111111");
rc = uc_sprintbc(result, 0xE1);
ck_assert_str_eq(rc, "11100001");
rc = uc_sprintbc(result, 1);
ck_assert_str_eq(rc, "00000001");
END_TEST
START_TEST (test_sprintbs)
char result[128];
char *rc;
rc = uc_sprintbs(result, 0);
ck_assert_str_eq(rc, "0000000000000000");
rc = uc_sprintbs(result, USHRT_MAX);
ck_assert_str_eq(rc, "1111111111111111");
rc = uc_sprintbs(result, 0xE0A1);
ck_assert_str_eq(rc, "1110000010100001");
rc = uc_sprintbs(result, 1);
ck_assert_str_eq(rc, "0000000000000001");
END_TEST
START_TEST (test_sprintbll)
char result[128];
char *rc;
rc = uc_sprintbll(result, 0);
ck_assert_str_eq(rc, "0000000000000000000000000000000000000000000000000000000000000000");
rc = uc_sprintbll(result, ULLONG_MAX);
ck_assert_str_eq(rc, "1111111111111111111111111111111111111111111111111111111111111111");
rc = uc_sprintbll(result, 0xE0A14341E0A14341ULL);
ck_assert_str_eq(rc, "1110000010100001010000110100000111100000101000010100001101000001");
rc = uc_sprintbll(result, 1);
ck_assert_str_eq(rc, "0000000000000000000000000000000000000000000000000000000000000001");
END_TEST
Suite *sprintb_suite(void)
{
Suite *s = suite_create("sprintb");
TCase *tc = tcase_create("sprintb tests");
tcase_add_test(tc, test_sprintb);
tcase_add_test(tc, test_sprintbc);
tcase_add_test(tc, test_sprintbs);
tcase_add_test(tc, test_sprintbll);
suite_add_tcase(s, tc);
return s;
}
+91
View File
@@ -0,0 +1,91 @@
#include <check.h>
#include <string.h>
#include <ucore/strvec.h>
START_TEST (test_strv_append)
struct UCStrv strv;
int rc;
uc_strv_init(&strv);
rc = uc_strv_append(&strv, "string");
fail_if(rc != 0);
fail_if(strv.cnt != 1);
ck_assert_str_eq("string", strv.strings[0]);
rc = uc_strv_append(&strv, "string2");
fail_if(rc != 0);
fail_if(strv.cnt != 2);
ck_assert_str_eq("string2", strv.strings[1]);
uc_strv_destroy(&strv);
END_TEST
START_TEST (test_strv_clear)
struct UCStrv strv;
int rc;
uc_strv_init(&strv);
rc = uc_strv_append(&strv, "string");
fail_if(rc != 0);
fail_if(strv.cnt != 1);
uc_strv_clear(&strv);
fail_if(strv.cnt != 0);
uc_strv_destroy(&strv);
END_TEST
START_TEST (test_strv_nocopy)
struct UCStrv strv;
char *str = strdup("string");
int rc;
uc_strv_init(&strv);
rc = uc_strv_append_nocopy(&strv, str);
fail_if(rc != 0);
fail_if(strv.cnt != 1);
fail_if(strv.strings[0] != str);
uc_strv_destroy(&strv);
END_TEST
START_TEST (test_strv_null_terminate)
struct UCStrv strv;
int rc;
uc_strv_init(&strv);
rc = uc_strv_append(&strv, "string");
fail_if(rc != 0);
fail_if(strv.cnt != 1);
rc = uc_strv_null_terminate(&strv);
fail_if(rc != 0);
fail_if(strv.strings[strv.cnt] != NULL);
uc_strv_destroy(&strv);
END_TEST
Suite *strv_suite(void)
{
Suite *s = suite_create("strvec");
TCase *tc = tcase_create("strvec");
tcase_add_test(tc, test_strv_append);
tcase_add_test(tc, test_strv_clear);
tcase_add_test(tc, test_strv_nocopy);
tcase_add_test(tc, test_strv_null_terminate);
suite_add_tcase(s, tc);
return s;
}
+42
View File
@@ -160,6 +160,47 @@ START_TEST (test_timers_remove_from_callback)
END_TEST END_TEST
START_TEST (test_timers_add_remove)
struct UCoreSettableClock clk;
struct TimerTest tt;
struct UCTimers timers;
struct UCTimer timer1;
struct UCTimer timer2;
struct UCTimer timer3;
struct UCTimer timer4;
struct timeval first;
common_init(&clk, &tt, &timers, &timer1);
memset(&timer2, 0, sizeof timer2);
memset(&timer3, 0, sizeof timer2);
memset(&timer4, 0, sizeof timer2);
timer1.callback = timer_test_cb_add;
timer2.callback = timer_test_cb_add;
timer3.callback = timer_test_cb_add;
timer4.callback = timer_test_cb_add;
uc_timers_add(&timers, &timer1, 10, 0);
uc_timers_add(&timers, &timer2, 5 , 0);
uc_timers_add(&timers, &timer3, 15, 1);
uc_timers_add(&timers, &timer4, 15, 1);
fail_if(uc_timers_first(&timers, &first) != 0);
fail_if(first.tv_sec != TEST_TIMER_START + 5);
fail_if(first.tv_usec != 0);
fail_if(uc_timers_count(&timers) != 4);
uc_timers_remove(&timers, &timer1);
uc_timers_remove(&timers, &timer2);
uc_timers_remove(&timers, &timer3);
uc_timers_remove(&timers, &timer4);
fail_if(uc_timers_count(&timers) != 0);
fail_if(uc_timers_first(&timers, &first) == 0);
END_TEST
Suite *timers_suite(void) Suite *timers_suite(void)
{ {
@@ -168,6 +209,7 @@ Suite *timers_suite(void)
tcase_add_test(tc, test_timers_simple); tcase_add_test(tc, test_timers_simple);
tcase_add_test(tc, test_timers_add_from_callback); tcase_add_test(tc, test_timers_add_from_callback);
tcase_add_test(tc, test_timers_remove_from_callback); tcase_add_test(tc, test_timers_remove_from_callback);
tcase_add_test(tc, test_timers_add_remove);
suite_add_tcase(s, tc); suite_add_tcase(s, tc);