add libc testcase.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1061 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
bernard.xiong@gmail.com 2010-11-18 11:31:54 +00:00
parent 019b654201
commit d9cb84f484
15 changed files with 1575 additions and 0 deletions

8
examples/libc/SConscript Normal file
View File

@ -0,0 +1,8 @@
Import('env')
src_local = Glob('*.c')
# The set of source files associated with this SConscript file.
obj = env.Object(src_local)
Return('obj')

56
examples/libc/dirent.c Normal file
View File

@ -0,0 +1,56 @@
/*
* dirent.c
*
* Created on: 2010-11-17
* Author: bernard
*/
#include <stdio.h>
#include <stdlib.h>
#include <finsh.h>
#include <dirent.h>
int libc_dirent()
{
DIR * dirp;
long int save3 = 0;
long int cur;
int i = 0;
int result = 0;
struct dirent *dp;
dirp = opendir("/");
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
{
/* save position 3 (after fourth entry) */
if (i++ == 3)
save3 = telldir(dirp);
printf("%s\n", dp->d_name);
/* stop at 400 (just to make sure dirp->__offset and dirp->__size are
scrambled */
if (i == 400)
break;
}
printf("going back past 4-th entry...\n");
/* go back to saved entry */
seekdir(dirp, save3);
/* Check whether telldir equals to save3 now. */
cur = telldir(dirp);
if (cur != save3)
{
printf("seekdir (d, %ld); telldir (d) == %ld\n", save3, cur);
result = 1;
}
/* print remaining files (3-last) */
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
printf("%s\n", dp->d_name);
closedir(dirp);
return result;
}
FINSH_FUNCTION_EXPORT(libc_dirent, dirent test for libc);

18
examples/libc/env.c Normal file
View File

@ -0,0 +1,18 @@
/*
* env.c
*
* Created on: 2010-11-17
* Author: bernard
*/
#include <stdio.h>
#include <stdlib.h>
#include <finsh.h>
int libc_env()
{
printf("PATH=%s\n", getenv("PATH"));
putenv("foo=bar");
printf("foo=%s\n", getenv("foo"));
return 0;
}
FINSH_FUNCTION_EXPORT(libc_env, get/set_env test);

37
examples/libc/ex1.c Normal file
View File

@ -0,0 +1,37 @@
/* Creates two threads, one printing 10000 "a"s, the other printing
10000 "b"s.
Illustrates: thread creation, thread joining. */
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
#include "pthread.h"
static void *process(void * arg)
{
int i;
printf("Starting process %s\n", (char *)arg);
for (i = 0; i < 10000; i++)
write(1, (char *) arg, 1);
return NULL;
}
#define sucfail(r) (r != 0 ? "failed" : "succeeded")
int libc_ex1(void)
{
int pret, ret = 0;
pthread_t th_a, th_b;
void *retval;
ret += (pret = pthread_create(&th_a, NULL, process, (void *)"a"));
printf("create a %s %d\n", sucfail(pret), pret);
ret += (pret = pthread_create(&th_b, NULL, process, (void *)"b"));
printf("create b %s %d\n", sucfail(pret), pret);
ret += (pret = pthread_join(th_a, &retval));
printf("join a %s %d\n", sucfail(pret), pret);
ret += (pret = pthread_join(th_b, &retval));
printf("join b %s %d\n", sucfail(pret), pret);
return ret;
}
#include <finsh.h>
FINSH_FUNCTION_EXPORT(libc_ex1, example 1 for libc);

114
examples/libc/ex2.c Normal file
View File

@ -0,0 +1,114 @@
/* The classic producer-consumer example.
Illustrates mutexes and conditions.
All integers between 0 and 9999 should be printed exactly twice,
once to the right of the arrow and once to the left. */
#include <stdio.h>
#include "pthread.h"
#define BUFFER_SIZE 16
/* Circular buffer of integers. */
struct prodcons {
int buffer[BUFFER_SIZE]; /* the actual data */
pthread_mutex_t lock; /* mutex ensuring exclusive access to buffer */
int readpos, writepos; /* positions for reading and writing */
pthread_cond_t notempty; /* signaled when buffer is not empty */
pthread_cond_t notfull; /* signaled when buffer is not full */
};
/* Initialize a buffer */
static void init(struct prodcons * b)
{
pthread_mutex_init(&b->lock, NULL);
pthread_cond_init(&b->notempty, NULL);
pthread_cond_init(&b->notfull, NULL);
b->readpos = 0;
b->writepos = 0;
}
/* Store an integer in the buffer */
static void put(struct prodcons * b, int data)
{
pthread_mutex_lock(&b->lock);
/* Wait until buffer is not full */
while ((b->writepos + 1) % BUFFER_SIZE == b->readpos) {
pthread_cond_wait(&b->notfull, &b->lock);
/* pthread_cond_wait reacquired b->lock before returning */
}
/* Write the data and advance write pointer */
b->buffer[b->writepos] = data;
b->writepos++;
if (b->writepos >= BUFFER_SIZE) b->writepos = 0;
/* Signal that the buffer is now not empty */
pthread_cond_signal(&b->notempty);
pthread_mutex_unlock(&b->lock);
}
/* Read and remove an integer from the buffer */
static int get(struct prodcons * b)
{
int data;
pthread_mutex_lock(&b->lock);
/* Wait until buffer is not empty */
while (b->writepos == b->readpos) {
pthread_cond_wait(&b->notempty, &b->lock);
}
/* Read the data and advance read pointer */
data = b->buffer[b->readpos];
b->readpos++;
if (b->readpos >= BUFFER_SIZE) b->readpos = 0;
/* Signal that the buffer is now not full */
pthread_cond_signal(&b->notfull);
pthread_mutex_unlock(&b->lock);
return data;
}
/* A test program: one thread inserts integers from 1 to 10000,
the other reads them and prints them. */
#define OVER (-1)
struct prodcons buffer;
static void * producer(void * data)
{
int n;
for (n = 0; n < 10000; n++) {
printf("%d --->\n", n);
put(&buffer, n);
}
put(&buffer, OVER);
return NULL;
}
static void * consumer(void * data)
{
int d;
while (1) {
d = get(&buffer);
if (d == OVER) break;
printf("---> %d\n", d);
}
return NULL;
}
int libc_ex2(void)
{
pthread_t th_a, th_b;
void * retval;
init(&buffer);
/* Create the threads */
pthread_create(&th_a, NULL, producer, 0);
pthread_create(&th_b, NULL, consumer, 0);
/* Wait until producer and consumer finish. */
pthread_join(th_a, &retval);
pthread_join(th_b, &retval);
return 0;
}
#include <finsh.h>
FINSH_FUNCTION_EXPORT(libc_ex2, example 2 for libc);

154
examples/libc/ex3.c Normal file
View File

@ -0,0 +1,154 @@
/* Multi-thread searching.
Illustrates: thread cancellation, cleanup handlers. */
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pthread.h>
/* Defines the number of searching threads */
#define NUM_THREADS 5
/* Function prototypes */
void *search(void *);
void print_it(void *);
/* Global variables */
pthread_t threads[NUM_THREADS];
pthread_mutex_t lock;
int tries;
volatile int started;
int libc_ex3()
{
int i;
int pid;
/* create a number to search for */
pid = getpid();
printf("Searching for the number = %d...\n", pid);
/* Initialize the mutex lock */
pthread_mutex_init(&lock, NULL);
/* Create the searching threads */
for (started=0; started<NUM_THREADS; started++)
pthread_create(&threads[started], NULL, search, (void *)pid);
/* Wait for (join) all the searching threads */
for (i=0; i<NUM_THREADS; i++)
pthread_join(threads[i], NULL);
printf("It took %d tries to find the number.\n", tries);
/* Exit the program */
return 0;
}
#include <finsh.h>
FINSH_FUNCTION_EXPORT(libc_ex3, example 5 for libc);
/* This is the cleanup function that is called
when the threads are cancelled */
void print_it(void *arg)
{
int *try = (int *) arg;
pthread_t tid;
/* Get the calling thread's ID */
tid = pthread_self();
/* Print where the thread was in its search when it was cancelled */
printf("Thread %lx was canceled on its %d try.\n", tid, *try);
}
/* This is the search routine that is executed in each thread */
void *search(void *arg)
{
int num = (int) arg;
int i, j, ntries;
pthread_t tid;
/* get the calling thread ID */
tid = pthread_self();
/* use the thread ID to set the seed for the random number generator */
/* Since srand and rand are not thread-safe, serialize with lock */
/* Try to lock the mutex lock --
if locked, check to see if the thread has been cancelled
if not locked then continue */
while (pthread_mutex_trylock(&lock) == EBUSY)
pthread_testcancel();
srand((int)tid);
i = rand() & 0xFFFFFF;
pthread_mutex_unlock(&lock);
ntries = 0;
/* Set the cancellation parameters --
- Enable thread cancellation
- Defer the action of the cancellation */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
while (started < NUM_THREADS)
sched_yield ();
/* Push the cleanup routine (print_it) onto the thread
cleanup stack. This routine will be called when the
thread is cancelled. Also note that the pthread_cleanup_push
call must have a matching pthread_cleanup_pop call. The
push and pop calls MUST be at the same lexical level
within the code */
/* Pass address of `ntries' since the current value of `ntries' is not
the one we want to use in the cleanup function */
pthread_cleanup_push(print_it, (void *)&ntries);
/* Loop forever */
while (1) {
i = (i + 1) & 0xFFFFFF;
ntries++;
/* Does the random number match the target number? */
if (num == i) {
/* Try to lock the mutex lock --
if locked, check to see if the thread has been cancelled
if not locked then continue */
while (pthread_mutex_trylock(&lock) == EBUSY)
pthread_testcancel();
/* Set the global variable for the number of tries */
tries = ntries;
printf("Thread %lx found the number!\n", tid);
/* Cancel all the other threads */
for (j=0; j<NUM_THREADS; j++)
if (threads[j] != tid) pthread_cancel(threads[j]);
/* Break out of the while loop */
break;
}
/* Every 100 tries check to see if the thread has been cancelled. */
if (ntries % 100 == 0) {
pthread_testcancel();
}
}
/* The only way we can get here is when the thread breaks out
of the while loop. In this case the thread that makes it here
has found the number we are looking for and does not need to run
the thread cleanup function. This is why the pthread_cleanup_pop
function is called with a 0 argument; this will pop the cleanup
function off the stack without executing it */
pthread_cleanup_pop(0);
return((void *)0);
}

108
examples/libc/ex4.c Normal file
View File

@ -0,0 +1,108 @@
/* Making a library function that uses static variables thread-safe.
Illustrates: thread-specific data, pthread_once(). */
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
/* This is a typical example of a library function that uses
static variables to accumulate results between calls.
Here, it just returns the concatenation of all string arguments
that were given to it. */
#if 0
char * str_accumulate(char * s)
{
static char accu[1024] = { 0 };
strcat(accu, s);
return accu;
}
#endif
/* Of course, this cannot be used in a multi-threaded program
because all threads store "accu" at the same location.
So, we'll use thread-specific data to have a different "accu"
for each thread. */
/* Key identifying the thread-specific data */
static pthread_key_t str_key;
/* "Once" variable ensuring that the key for str_alloc will be allocated
exactly once. */
static pthread_once_t str_alloc_key_once = PTHREAD_ONCE_INIT;
/* Forward functions */
static void str_alloc_key(void);
static void str_alloc_destroy_accu(void * accu);
/* Thread-safe version of str_accumulate */
char * str_accumulate(const char * s)
{
char * accu;
/* Make sure the key is allocated */
pthread_once(&str_alloc_key_once, str_alloc_key);
/* Get the thread-specific data associated with the key */
accu = (char *) pthread_getspecific(str_key);
/* It's initially NULL, meaning that we must allocate the buffer first. */
if (accu == NULL) {
accu = malloc(1024);
if (accu == NULL) return NULL;
accu[0] = 0;
/* Store the buffer pointer in the thread-specific data. */
pthread_setspecific(str_key, (void *) accu);
printf("Thread %lx: allocating buffer at %p\n", pthread_self(), accu);
}
/* Now we can use accu just as in the non thread-safe code. */
strcat(accu, s);
return accu;
}
/* Function to allocate the key for str_alloc thread-specific data. */
static void str_alloc_key(void)
{
pthread_key_create(&str_key, str_alloc_destroy_accu);
printf("Thread %lx: allocated key %d\n", pthread_self(), str_key);
}
/* Function to free the buffer when the thread exits. */
/* Called only when the thread-specific data is not NULL. */
static void str_alloc_destroy_accu(void * accu)
{
printf("Thread %lx: freeing buffer at %p\n", pthread_self(), accu);
free(accu);
}
/* Test program */
static void *process(void * arg)
{
char *res;
res = str_accumulate("Result of ");
res = str_accumulate((char *) arg);
res = str_accumulate(" thread");
printf("Thread %lx: \"%s\"\n", pthread_self(), res);
return NULL;
}
int libc_ex4()
{
char * res;
pthread_t th1, th2;
// res = str_accumulate("Result of ");
pthread_create(&th1, NULL, process, (void *) "first");
pthread_create(&th2, NULL, process, (void *) "second");
// res = str_accumulate("initial thread");
printf("Thread %lx: \"%s\"\n", pthread_self(), res);
pthread_join(th1, NULL);
pthread_join(th2, NULL);
}
#include <finsh.h>
FINSH_FUNCTION_EXPORT(libc_ex4, example 4 for libc);

105
examples/libc/ex5.c Normal file
View File

@ -0,0 +1,105 @@
/* The classic producer-consumer example, implemented with semaphores.
All integers between 0 and 9999 should be printed exactly twice,
once to the right of the arrow and once to the left. */
#include <stdio.h>
#include "pthread.h"
#include "semaphore.h"
#define BUFFER_SIZE 16
/* Circular buffer of integers. */
struct prodcons {
int buffer[BUFFER_SIZE]; /* the actual data */
int readpos, writepos; /* positions for reading and writing */
sem_t sem_read; /* number of elements available for reading */
sem_t sem_write; /* number of locations available for writing */
};
/* Initialize a buffer */
void init(struct prodcons * b)
{
sem_init(&b->sem_write, 0, BUFFER_SIZE - 1);
sem_init(&b->sem_read, 0, 0);
b->readpos = 0;
b->writepos = 0;
}
/* Store an integer in the buffer */
void put(struct prodcons * b, int data)
{
/* Wait until buffer is not full */
sem_wait(&b->sem_write);
/* Write the data and advance write pointer */
b->buffer[b->writepos] = data;
b->writepos++;
if (b->writepos >= BUFFER_SIZE) b->writepos = 0;
/* Signal that the buffer contains one more element for reading */
sem_post(&b->sem_read);
}
/* Read and remove an integer from the buffer */
int get(struct prodcons * b)
{
int data;
/* Wait until buffer is not empty */
sem_wait(&b->sem_read);
/* Read the data and advance read pointer */
data = b->buffer[b->readpos];
b->readpos++;
if (b->readpos >= BUFFER_SIZE) b->readpos = 0;
/* Signal that the buffer has now one more location for writing */
sem_post(&b->sem_write);
return data;
}
/* A test program: one thread inserts integers from 1 to 10000,
the other reads them and prints them. */
#define OVER (-1)
struct prodcons buffer;
static void *producer(void * data)
{
int n;
for (n = 0; n < 10000; n++) {
printf("%d --->\n", n);
put(&buffer, n);
}
put(&buffer, OVER);
return NULL;
}
static void *consumer(void * data)
{
int d;
while (1) {
d = get(&buffer);
if (d == OVER) break;
printf("---> %d\n", d);
}
return NULL;
}
int libc_ex5(void)
{
pthread_t th_a, th_b;
void * retval;
init(&buffer);
/* Create the threads */
pthread_create(&th_a, NULL, producer, 0);
pthread_create(&th_b, NULL, consumer, 0);
/* Wait until producer and consumer finish. */
pthread_join(th_a, &retval);
pthread_join(th_b, &retval);
return 0;
}
#include <finsh.h>
FINSH_FUNCTION_EXPORT(libc_ex5, example 5 for libc);

37
examples/libc/ex6.c Normal file
View File

@ -0,0 +1,37 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define usleep rt_thread_sleep
static void *test_thread(void *v_param) {
return NULL;
}
int libc_ex6(void) {
unsigned long count;
setvbuf(stdout, NULL, _IONBF, 0);
for (count = 0; count < 2000; ++count) {
pthread_t thread;
int status;
status = pthread_create(&thread, NULL, test_thread, NULL);
if (status != 0) {
printf("status = %d, count = %lu: %s\n", status, count, strerror(
errno));
return 1;
} else {
printf("count = %lu\n", count);
}
/* pthread_detach (thread); */
pthread_join(thread, NULL);
usleep(10);
}
return 0;
}
#include <finsh.h>
FINSH_FUNCTION_EXPORT(libc_ex6, example 6 for libc);

101
examples/libc/ex7.c Normal file
View File

@ -0,0 +1,101 @@
/* ex7
*
* Test case that illustrates a timed wait on a condition variable.
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
#define usleep rt_thread_sleep
/* Our event variable using a condition variable contruct. */
typedef struct {
pthread_mutex_t mutex;
pthread_cond_t cond;
int flag;
} event_t;
/* Global event to signal main thread the timeout of the child thread. */
event_t main_event;
static void *test_thread(void *ms_param) {
int status = 0;
event_t foo;
struct timespec time;
struct timeval now;
long ms = (long) ms_param;
/* initialize cond var */
pthread_cond_init(&foo.cond, NULL);
pthread_mutex_init(&foo.mutex, NULL);
foo.flag = 0;
/* set the time out value */
printf("waiting %ld ms ...\n", ms);
gettimeofday(&now, NULL);
time.tv_sec = now.tv_sec + ms / 1000 + (now.tv_usec + (ms % 1000) * 1000)
/ 1000000;
time.tv_nsec = ((now.tv_usec + (ms % 1000) * 1000) % 1000000) * 1000;
/* Just use this to test the time out. The cond var is never signaled. */
pthread_mutex_lock(&foo.mutex);
while (foo.flag == 0 && status != ETIMEDOUT) {
status = pthread_cond_timedwait(&foo.cond, &foo.mutex, &time);
}
pthread_mutex_unlock(&foo.mutex);
/* post the main event */
pthread_mutex_lock(&main_event.mutex);
main_event.flag = 1;
pthread_cond_signal(&main_event.cond);
pthread_mutex_unlock(&main_event.mutex);
/* that's it, bye */
return (void*) status;
}
int libc_ex7(void) {
unsigned long count;
setvbuf(stdout, NULL, _IONBF, 0);
/* initialize main event cond var */
pthread_cond_init(&main_event.cond, NULL);
pthread_mutex_init(&main_event.mutex, NULL);
main_event.flag = 0;
for (count = 0; count < 20; ++count) {
pthread_t thread;
int status;
/* pass down the milli-second timeout in the void* param */
status = pthread_create(&thread, NULL, test_thread, (void*) (count
* 100));
if (status != 0) {
printf("status = %d, count = %lu: %s\n", status, count, strerror(
errno));
return 1;
} else {
/* wait for the event posted by the child thread */
pthread_mutex_lock(&main_event.mutex);
while (main_event.flag == 0) {
pthread_cond_wait(&main_event.cond, &main_event.mutex);
}
main_event.flag = 0;
pthread_mutex_unlock(&main_event.mutex);
printf("count = %lu\n", count);
}
usleep(10);
}
return 0;
}
#include <finsh.h>
FINSH_FUNCTION_EXPORT(libc_ex7, example 7 for libc);

516
examples/libc/file.c Normal file
View File

@ -0,0 +1,516 @@
/*
* fstat.c
*
* Created on: 2010-11-17
* Author: bernard
*/
#include <stdio.h>
#include <stdlib.h>
#include <finsh.h>
#include <errno.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
const char* text = "this is a test string\n";
void libc_fstat()
{
int fd;
struct stat s;
fd = open("/tmp/tt.txt", O_WRONLY | O_CREAT, 0);
if (fd < 0)
{
printf("open failed\n");
return;
}
write(fd, text, strlen(text) + 1);
printf("begin: %d\n", lseek(fd, 0, SEEK_SET));
printf("end: %d\n", lseek(fd, 0, SEEK_END));
printf("fstat result: %d\n", fstat(fd, &s));
close(fd);
}
FINSH_FUNCTION_EXPORT(libc_fstat, fstat test for libc);
void libc_lseek()
{
int fd;
fd = open("/tmp/tt.txt", O_WRONLY | O_CREAT, 0);
if (fd < 0)
{
printf("open failed\n");
return;
}
write(fd, text, strlen(text) + 1);
printf("begin: %d\n", lseek(fd, 0, SEEK_SET));
printf("end: %d\n", lseek(fd, 0, SEEK_END));
close(fd);
}
FINSH_FUNCTION_EXPORT(libc_lseek, lseek test for libc);
void sleep(int tick)
{
rt_thread_sleep(tick);
}
int libc_fseek(void)
{
const char *tmpdir;
char *fname;
int fd;
FILE *fp;
const char outstr[] = "hello world!\n";
char strbuf[sizeof outstr];
char buf[200];
struct stat st1;
struct stat st2;
int result = 0;
tmpdir = getenv("TMPDIR");
if (tmpdir == NULL || tmpdir[0] == '\0')
tmpdir = "/tmp";
asprintf(&fname, "%s/tst-fseek.XXXXXX", tmpdir);
if (fname == NULL)
{
fprintf(stderr, "cannot generate name for temporary file: %s\n",
strerror(errno));
return 1;
}
/* Create a temporary file. */
fd = mkstemp(fname);
if (fd == -1)
{
fprintf(stderr, "cannot open temporary file: %s\n", strerror(errno));
return 1;
}
fp = fdopen(fd, "w+");
if (fp == NULL)
{
fprintf(stderr, "cannot get FILE for temporary file: %s\n", strerror(
errno));
return 1;
}
setbuffer(fp, strbuf, sizeof(outstr) - 1);
if (fwrite(outstr, sizeof(outstr) - 1, 1, fp) != 1)
{
printf("%d: write error\n", __LINE__);
result = 1;
goto out;
}
/* The EOF flag must be reset. */
if (fgetc(fp) != EOF)
{
printf("%d: managed to read at end of file\n", __LINE__);
result = 1;
}
else if (!feof(fp))
{
printf("%d: EOF flag not set\n", __LINE__);
result = 1;
}
if (fseek(fp, 0, SEEK_CUR) != 0)
{
printf("%d: fseek(fp, 0, SEEK_CUR) failed\n", __LINE__);
result = 1;
}
else if (feof(fp))
{
printf("%d: fseek() didn't reset EOF flag\n", __LINE__);
result = 1;
}
/* Do the same for fseeko(). */
if (fgetc(fp) != EOF)
{
printf("%d: managed to read at end of file\n", __LINE__);
result = 1;
}
else if (!feof(fp))
{
printf("%d: EOF flag not set\n", __LINE__);
result = 1;
}
if (fseeko(fp, 0, SEEK_CUR) != 0)
{
printf("%d: fseek(fp, 0, SEEK_CUR) failed\n", __LINE__);
result = 1;
}
else if (feof(fp))
{
printf("%d: fseek() didn't reset EOF flag\n", __LINE__);
result = 1;
}
/* Go back to the beginning of the file: absolute. */
if (fseek(fp, 0, SEEK_SET) != 0)
{
printf("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__);
result = 1;
}
else if (fflush(fp) != 0)
{
printf("%d: fflush() failed\n", __LINE__);
result = 1;
}
else if (lseek(fd, 0, SEEK_CUR) != 0)
{
int pos = lseek(fd, 0, SEEK_CUR);
printf("%d: lseek() returned different position, pos %d\n", __LINE__,
pos);
result = 1;
}
else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
{
printf("%d: fread() failed\n", __LINE__);
result = 1;
}
else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
{
printf("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__);
result = 1;
}
/* Now with fseeko. */
if (fseeko(fp, 0, SEEK_SET) != 0)
{
printf("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__);
result = 1;
}
else if (fflush(fp) != 0)
{
printf("%d: fflush() failed\n", __LINE__);
result = 1;
}
else if (lseek(fd, 0, SEEK_CUR) != 0)
{
printf("%d: lseek() returned different position\n", __LINE__);
result = 1;
}
else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
{
printf("%d: fread() failed\n", __LINE__);
result = 1;
}
else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
{
printf("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__);
result = 1;
}
/* Go back to the beginning of the file: relative. */
if (fseek(fp, -((int) sizeof(outstr) - 1), SEEK_CUR) != 0)
{
printf("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__);
result = 1;
}
else if (fflush(fp) != 0)
{
printf("%d: fflush() failed\n", __LINE__);
result = 1;
}
else if (lseek(fd, 0, SEEK_CUR) != 0)
{
printf("%d: lseek() returned different position\n", __LINE__);
result = 1;
}
else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
{
printf("%d: fread() failed\n", __LINE__);
result = 1;
}
else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
{
printf("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__);
result = 1;
}
/* Now with fseeko. */
if (fseeko(fp, -((int) sizeof(outstr) - 1), SEEK_CUR) != 0)
{
printf("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__);
result = 1;
}
else if (fflush(fp) != 0)
{
printf("%d: fflush() failed\n", __LINE__);
result = 1;
}
else if (lseek(fd, 0, SEEK_CUR) != 0)
{
printf("%d: lseek() returned different position\n", __LINE__);
result = 1;
}
else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
{
printf("%d: fread() failed\n", __LINE__);
result = 1;
}
else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
{
printf("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__);
result = 1;
}
/* Go back to the beginning of the file: from the end. */
if (fseek(fp, -((int) sizeof(outstr) - 1), SEEK_END) != 0)
{
printf("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__);
result = 1;
}
else if (fflush(fp) != 0)
{
printf("%d: fflush() failed\n", __LINE__);
result = 1;
}
else if (lseek(fd, 0, SEEK_CUR) != 0)
{
printf("%d: lseek() returned different position\n", __LINE__);
result = 1;
}
else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
{
printf("%d: fread() failed\n", __LINE__);
result = 1;
}
else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
{
printf("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__);
result = 1;
}
/* Now with fseeko. */
if (fseeko(fp, -((int) sizeof(outstr) - 1), SEEK_END) != 0)
{
printf("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__);
result = 1;
}
else if (fflush(fp) != 0)
{
printf("%d: fflush() failed\n", __LINE__);
result = 1;
}
else if (lseek(fd, 0, SEEK_CUR) != 0)
{
printf("%d: lseek() returned different position\n", __LINE__);
result = 1;
}
else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
{
printf("%d: fread() failed\n", __LINE__);
result = 1;
}
else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
{
printf("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__);
result = 1;
}
if (fwrite(outstr, sizeof(outstr) - 1, 1, fp) != 1)
{
printf("%d: write error 2\n", __LINE__);
result = 1;
goto out;
}
if (fwrite(outstr, sizeof(outstr) - 1, 1, fp) != 1)
{
printf("%d: write error 3\n", __LINE__);
result = 1;
goto out;
}
if (fwrite(outstr, sizeof(outstr) - 1, 1, fp) != 1)
{
printf("%d: write error 4\n", __LINE__);
result = 1;
goto out;
}
if (fwrite(outstr, sizeof(outstr) - 1, 1, fp) != 1)
{
printf("%d: write error 5\n", __LINE__);
result = 1;
goto out;
}
if (fputc('1', fp) == EOF || fputc('2', fp) == EOF)
{
printf("%d: cannot add characters at the end\n", __LINE__);
result = 1;
goto out;
}
/* Check the access time. */
if (fstat(fd, &st1) < 0)
{
printf("%d: fstat64() before fseeko() failed\n\n", __LINE__);
result = 1;
}
else
{
sleep(1);
if (fseek(fp, -(2 + 2 * (sizeof(outstr) - 1)), SEEK_CUR) != 0)
{
printf("%d: fseek() after write characters failed\n", __LINE__);
result = 1;
goto out;
}
else
{
time_t t;
/* Make sure the timestamp actually can be different. */
sleep(1);
t = time(NULL);
if (fstat(fd, &st2) < 0)
{
printf("%d: fstat64() after fseeko() failed\n\n", __LINE__);
result = 1;
}
if (st1.st_ctime >= t)
{
printf("%d: st_ctime not updated\n", __LINE__);
result = 1;
}
if (st1.st_mtime >= t)
{
printf("%d: st_mtime not updated\n", __LINE__);
result = 1;
}
if (st1.st_ctime >= st2.st_ctime)
{
printf("%d: st_ctime not changed\n", __LINE__);
result = 1;
}
if (st1.st_mtime >= st2.st_mtime)
{
printf("%d: st_mtime not changed\n", __LINE__);
result = 1;
}
}
}
if (fread(buf, 1, 2 + 2 * (sizeof(outstr) - 1), fp) != 2 + 2
* (sizeof(outstr) - 1))
{
printf("%d: reading 2 records plus bits failed\n", __LINE__);
result = 1;
}
else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0 || memcmp(
&buf[sizeof(outstr) - 1], outstr, sizeof(outstr) - 1) != 0 || buf[2
* (sizeof(outstr) - 1)] != '1' || buf[2 * (sizeof(outstr) - 1) + 1]
!= '2')
{
printf("%d: reading records failed\n", __LINE__);
result = 1;
}
else if (ungetc('9', fp) == EOF)
{
printf("%d: ungetc() failed\n", __LINE__);
result = 1;
}
else if (fseek(fp, -(2 + 2 * (sizeof(outstr) - 1)), SEEK_END) != 0)
{
printf("%d: fseek after ungetc failed\n", __LINE__);
result = 1;
}
else if (fread(buf, 1, 2 + 2 * (sizeof(outstr) - 1), fp) != 2 + 2
* (sizeof(outstr) - 1))
{
printf("%d: reading 2 records plus bits failed\n", __LINE__);
result = 1;
}
else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0 || memcmp(
&buf[sizeof(outstr) - 1], outstr, sizeof(outstr) - 1) != 0 || buf[2
* (sizeof(outstr) - 1)] != '1')
{
printf("%d: reading records for the second time failed\n", __LINE__);
result = 1;
}
else if (buf[2 * (sizeof(outstr) - 1) + 1] == '9')
{
printf("%d: unget character not ignored\n", __LINE__);
result = 1;
}
else if (buf[2 * (sizeof(outstr) - 1) + 1] != '2')
{
printf("%d: unget somehow changed character\n", __LINE__);
result = 1;
}
fclose(fp);
fp = fopen(fname, "r");
if (fp == NULL)
{
printf("%d: fopen() failed\n\n", __LINE__);
result = 1;
}
else if (fstat(fileno(fp), &st1) < 0)
{
printf("%d: fstat64() before fseeko() failed\n\n", __LINE__);
result = 1;
}
else if (fseeko(fp, 0, SEEK_END) != 0)
{
printf("%d: fseeko(fp, 0, SEEK_END) failed\n", __LINE__);
result = 1;
}
else if (ftello(fp) != st1.st_size)
{
printf("%d: fstat64 st_size %zd ftello %zd\n", __LINE__,
(size_t) st1.st_size, (size_t) ftello(fp));
result = 1;
}
else
printf("%d: SEEK_END works\n", __LINE__);
if (fp != NULL)
fclose(fp);
fp = fopen(fname, "r");
if (fp == NULL)
{
printf("%d: fopen() failed\n\n", __LINE__);
result = 1;
}
else if (fstat(fileno(fp), &st1) < 0)
{
printf("%d: fstat64() before fgetc() failed\n\n", __LINE__);
result = 1;
}
else if (fgetc(fp) == EOF)
{
printf("%d: fgetc() before fseeko() failed\n\n", __LINE__);
result = 1;
}
else if (fseeko(fp, 0, SEEK_END) != 0)
{
printf("%d: fseeko(fp, 0, SEEK_END) failed\n", __LINE__);
result = 1;
}
else if (ftello(fp) != st1.st_size)
{
printf("%d: fstat64 st_size %zd ftello %zd\n", __LINE__,
(size_t) st1.st_size, (size_t) ftello(fp));
result = 1;
}
else
printf("%d: SEEK_END works\n", __LINE__);
if (fp != NULL)
fclose(fp);
out: unlink(fname);
return result;
}
FINSH_FUNCTION_EXPORT(libc_fseek, lseek test for libc);

54
examples/libc/memory.c Normal file
View File

@ -0,0 +1,54 @@
/*
* memory.c
*
* Created on: 2010-11-17
* Author: bernard
*/
#include <stdio.h>
#include <stdlib.h>
#include <finsh.h>
#include <errno.h>
static int errors = 0;
static void merror(const char *msg)
{
++errors;
printf("Error: %s\n", msg);
}
int libc_mem(void)
{
void *p;
int save;
errno = 0;
p = malloc(-1);
save = errno;
if (p != NULL)
merror("malloc (-1) succeeded.");
if (p == NULL && save != ENOMEM)
merror("errno is not set correctly");
p = malloc(10);
if (p == NULL)
merror("malloc (10) failed.");
/* realloc (p, 0) == free (p). */
p = realloc(p, 0);
if (p != NULL)
merror("realloc (p, 0) failed.");
p = malloc(0);
if (p == NULL)
merror("malloc (0) failed.");
p = realloc(p, 0);
if (p != NULL)
merror("realloc (p, 0) failed.");
return errors != 0;
}
FINSH_FUNCTION_EXPORT(libc_mem, memory test for libc);

200
examples/libc/printf.c Normal file
View File

@ -0,0 +1,200 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/fcntl.h>
#include <finsh.h>
char * format[] = {
"%",
"%0.",
"%.0",
"%+0.",
"%+.0",
"%.5",
"%+.5",
"%2.5",
"%22.5",
"%022.5",
"%#022.5",
"%-#022.5",
"%+#022.5",
"%-22.5",
"%+22.5",
"%--22.5",
"%++22.5",
"%+-22.5",
"%-+22.5",
"%-#022.5",
"%-#22.5",
"%-2.22",
"%+2.22",
"%-#02.22",
"%-#2.22",
"%-1.5",
"%1.5",
"%-#01.5",
"%-#1.5",
"%-#.5",
"%-#1.",
"%-#.",
NULL
};
static void
intchk (const char *fmt)
{
(void) printf("%15s :, \"", fmt);
(void) printf(fmt, 0);
(void) printf("\", \"");
(void) printf(fmt, 123);
(void) printf("\", \"");
(void) printf(fmt, -18);
(void) printf("\"\n");
}
static void
fltchk (const char *fmt)
{
(void) printf("%15s :, \"", fmt);
(void) printf(fmt, 0.0);
(void) printf("\", \"");
(void) printf(fmt, 123.0001);
(void) printf("\", \"");
(void) printf(fmt, -18.0002301);
(void) printf("\"\n");
}
int printf_test()
{
char buf[256];
int i;
printf("%s\n\n", "# vim:syntax=off:");
/* integers */
for(i=0;format[i];i++) {
strcpy(buf, format[i]);
strcat(buf, "d");
intchk(buf);
}
/* floats */
for(i=0;format[i];i++) {
strcpy(buf, format[i]);
strcat(buf, "f");
fltchk(buf);
}
/* hexa */
for(i=0;format[i];i++) {
strcpy(buf, format[i]);
strcat(buf, "x");
intchk(buf);
}
printf("#%.4x %4x#\n", 4, 88);
printf("#%4x#\n",4);
printf("#%#22.8x#\n",1234567);
printf("#%+2i#\n",18);
printf("#%i#\n",18);
printf("#%llu#\n",4294967297ULL);
printf("#%#x#\n",44444);
printf("#%-8i#\n",33);
printf("#%i#\n",18);
printf("#%d#\n",18);
printf("#%u#\n",18);
printf("#%lu#\n",18);
printf("#%li#\n",18);
printf("#%-+#06d#\n", -123);
printf("#%-+#6d#\n", -123);
printf("#%+#06d#\n", -123);
printf("#%06d#\n", -123);
printf("#%+15s#\n","ABCDEF");
/* from ncurses make_keys */
printf("{ %4d, %-*.*s },\t/* %s */\n", 139, 16, 16, "KEY_A1", "key_a1");
printf("{ %4d, %-*.*s },\t/* %s */\n", 139, 16, 2, "KEY_A1", "key_a1");
printf("{ %4d, %-*.*s },\t/* %s */\n", 139, 2, 16, "KEY_A1", "key_a1");
printf("{ %4d, %-*.*s },\t/* %s */\n", 139, 16, 0, "KEY_A1", "key_a1");
printf("{ %4d, %-*.*s },\t/* %s */\n", 139, 0, 16, "KEY_A1", "key_a1");
printf("{ %4d, %-*.*s },\t/* %s */\n", 139, 0, 0, "KEY_A1", "key_a1");
printf("{ %4d, %*.*s },\t/* %s */\n", 139, 16, 16, "KEY_A1", "key_a1");
printf("{ %4d, %*.*s },\t/* %s */\n", 139, 16, 2, "KEY_A1", "key_a1");
printf("{ %4d, %*.*s },\t/* %s */\n", 139, 2, 16, "KEY_A1", "key_a1");
printf("{ %4d, %*.*s },\t/* %s */\n", 139, 16, 0, "KEY_A1", "key_a1");
printf("{ %4d, %*.*s },\t/* %s */\n", 139, 0, 16, "KEY_A1", "key_a1");
printf("{ %4d, %*.*s },\t/* %s */\n", 139, 0, 0, "KEY_A1", "key_a1");
printf("%*.*f\n", 0, 16, 0.0);
printf("%*.*f\n", 16, 16, 0.0);
printf("%*.*f\n", 2, 2, -0.0);
printf("%*.*f\n", 20, 0, -123.123);
printf("%*.*f\n", 10, 0, +123.123);
i = printf("\"%s\"\n","A");
printf("%i\n", i);
/* from glibc's tst-printf.c */
{
char buf[20];
char buf2[512];
int i;
printf ("snprintf (\"%%30s\", \"foo\") == %d, \"%.*s\"\n",
snprintf (buf, sizeof (buf), "%30s", "foo"), (int) sizeof (buf),
buf);
memset(buf2,0,sizeof(buf));
i=snprintf(buf2, 256, "%.9999u", 10);
printf("%i %i\n",i,strlen(buf2));
printf ("snprintf (\"%%.999999u\", 10) == %d\n",
snprintf(buf2, sizeof(buf2), "%.999999u", 10));
}
return 0;
}
void libc_printf()
{
printf("stdout test!!\n");
fprintf(stdout, "fprintf test!!\n");
fprintf(stderr, "fprintf test!!\n");
puts("puts test!!\n");
putc('1', stderr);
putc('2', stderr);
putc('\n', stderr);
printf_test();
}
FINSH_FUNCTION_EXPORT(libc_printf, printf test in libc);
void libc_dprintf()
{
int fd;
fd = open("/dev/console", O_WRONLY, 0);
if (fd >0)
{
dprintf(fd, "fd:%d printf test!!\n", fd);
close(fd);
}
}
FINSH_FUNCTION_EXPORT(libc_dprintf, dprintf test);
void libc_fdopen()
{
int fd;
FILE* fp;
fd = open("/dev/console", O_WRONLY, 0);
if (fd >0)
{
fp = fdopen(fd, "w");
fprintf(fp, "fdopen test, fd %d!!\n", fileno(fp));
fclose(fp);
}
}
FINSH_FUNCTION_EXPORT(libc_fdopen, fdopen test);

43
examples/libc/rand.c Normal file
View File

@ -0,0 +1,43 @@
/*
* rand.c
*
* Created on: 2010-11-17
* Author: bernard
*/
#include <stdio.h>
#include <stdlib.h>
#include <finsh.h>
int libc_rand(void)
{
int i1, i2;
int j1, j2;
/* The C standard says that "If rand is called before any calls to
srand have been made, the same sequence shall be generated as
when srand is first called with a seed value of 1." */
i1 = rand();
i2 = rand();
srand(1);
j1 = rand();
j2 = rand();
if (i1 < 0 || i2 < 0 || j1 < 0 || j2 < 0)
{
puts("Test FAILED!");
}
if (j1 == i1 && j2 == i2)
{
puts("Test succeeded.");
return 0;
}
else
{
if (j1 != i1)
printf("%d != %d\n", j1, i1);
if (j2 != i2)
printf("%d != %d\n", j2, i2);
puts("Test FAILED!");
return 1;
}
}
FINSH_FUNCTION_EXPORT(libc_rand, rand test for libc);

24
examples/libc/time.c Normal file
View File

@ -0,0 +1,24 @@
/*
* time.c
*
* Created on: 2010-11-17
* Author: bernard
*/
#include <stdio.h>
#include <stdlib.h>
#include <finsh.h>
int speed()
{
int i;
time_t t;
printf("%d\n", time(0));
for (i = 0; i < 10000000; ++i)
t = time(0);
printf("%d\n", time(0));
return 0;
}
FINSH_FUNCTION_EXPORT(speed, speed test);