Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

check_list.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * check_list.c - check that gwlib/list.c works
00059  */
00060  
00061 #include <string.h>
00062 #include <unistd.h>
00063 #include <signal.h>
00064 
00065 #include "gwlib/gwlib.h"
00066 
00067 #define NUM_PRODUCERS (4)
00068 #define NUM_CONSUMERS (4)
00069 #define NUM_ITEMS_PER_PRODUCER (1*1000)
00070 
00071 struct producer_info {
00072     List *list;
00073     long start_index;
00074     long id;
00075 };
00076 
00077 
00078 static char received[NUM_PRODUCERS * NUM_ITEMS_PER_PRODUCER];
00079 
00080 
00081 typedef struct {
00082     long producer;
00083     long num;
00084     long index;
00085 } Item;
00086 
00087 
00088 static Item *new_item(long producer, long num, long index) {
00089     Item *item;
00090     
00091     item = gw_malloc(sizeof(Item));
00092     item->producer = producer;
00093     item->num = num;
00094     item->index = index;
00095     return item;
00096 }
00097 
00098 
00099 static void producer(void *arg) {
00100     long i, index;
00101     long id;
00102     struct producer_info *info;
00103 
00104     info = arg;
00105 
00106     id = gwthread_self();
00107     index = info->start_index;
00108     for (i = 0; i < NUM_ITEMS_PER_PRODUCER; ++i, ++index)
00109         gwlist_produce(info->list, new_item(id, i, index));
00110     gwlist_remove_producer(info->list);
00111 }
00112 
00113 static void consumer(void *arg) {
00114     List *list;
00115     Item *item;
00116     
00117     list = arg;
00118     for (;;) {
00119         item = gwlist_consume(list);
00120         if (item == NULL)
00121             break;
00122         received[item->index] = 1;
00123         gw_free(item);
00124     }
00125 }
00126 
00127 
00128 static void init_received(void) {
00129     memset(received, 0, sizeof(received));
00130 }
00131 
00132 
00133 static void main_for_producer_and_consumer(void) {
00134     List *list;
00135     int i;
00136     Item *item;
00137     struct producer_info tab[NUM_PRODUCERS];
00138     long p, n, index;
00139     int errors;
00140     
00141     list = gwlist_create();
00142     init_received();
00143     
00144     for (i = 0; i < NUM_PRODUCERS; ++i) {
00145             tab[i].list = list;
00146         tab[i].start_index = i * NUM_ITEMS_PER_PRODUCER;
00147             gwlist_add_producer(list);
00148         tab[i].id = gwthread_create(producer, tab + i);
00149     }
00150     for (i = 0; i < NUM_CONSUMERS; ++i)
00151         gwthread_create(consumer, list);
00152     
00153         gwthread_join_every(producer);
00154         gwthread_join_every(consumer);
00155 
00156     while (gwlist_len(list) > 0) {
00157         item = gwlist_get(list, 0);
00158         gwlist_delete(list, 0, 1);
00159         warning(0, "main: %ld %ld %ld", (long) item->producer, 
00160                 item->num, item->index);
00161     }
00162     
00163     errors = 0;
00164     for (p = 0; p < NUM_PRODUCERS; ++p) {
00165         for (n = 0; n < NUM_ITEMS_PER_PRODUCER; ++n) {
00166             index = p * NUM_ITEMS_PER_PRODUCER + n;
00167             if (!received[index]) {
00168                 error(0, "Not received: producer=%ld "
00169                          "item=%ld index=%ld", 
00170                      tab[p].id, n, index);
00171                 errors = 1;
00172             }
00173         }
00174     }
00175     
00176     if (errors)
00177         panic(0, "Not all messages were received.");
00178 }
00179 
00180 
00181 static int compare_cstr(void *item, void *pat) {
00182         /* Remove a macro definition of strcmp to prevent warnings from
00183      * a broken version in the glibc libary. */
00184     #undef strcmp
00185     return strcmp(item, pat) == 0;
00186 }
00187 
00188 
00189 static void main_for_list_add_and_delete(void) {
00190     static char *items[] = {
00191         "one",
00192         "two",
00193         "three",
00194     };
00195     int num_items = sizeof(items) / sizeof(items[0]);
00196     int num_repeats = 3;
00197     int i, j;
00198     char *p;
00199     List *list;
00200 
00201     list = gwlist_create();
00202     
00203     for (j = 0; j < num_repeats; ++j)
00204         for (i = 0; i < num_items; ++i)
00205             gwlist_append(list, items[i]);
00206     gwlist_delete_matching(list, items[0], compare_cstr);
00207     for (i = 0; i < gwlist_len(list); ++i) {
00208         p = gwlist_get(list, i);
00209         if (strcmp(p, items[0]) == 0)
00210             panic(0, "list contains `%s' after deleting it!",
00211                 items[0]);
00212     }
00213     
00214     for (i = 0; i < num_items; ++i)
00215         gwlist_delete_equal(list, items[i]);
00216     if (gwlist_len(list) != 0)
00217         panic(0, "list is not empty after deleting everything");
00218     
00219     gwlist_destroy(list, NULL);
00220 }
00221 
00222 
00223 static void main_for_extract(void) {
00224     static char *items[] = {
00225         "one",
00226         "two",
00227         "three",
00228     };
00229     int num_items = sizeof(items) / sizeof(items[0]);
00230     int num_repeats = 3;
00231     int i, j;
00232     char *p;
00233     List *list, *extracted;
00234 
00235     list = gwlist_create();
00236     
00237     for (j = 0; j < num_repeats; ++j)
00238         for (i = 0; i < num_items; ++i)
00239             gwlist_append(list, items[i]);
00240 
00241     for (j = 0; j < num_items; ++j) {
00242         extracted = gwlist_extract_matching(list, items[j], 
00243                     compare_cstr);
00244         if (extracted == NULL)
00245             panic(0, "no extracted elements, should have!");
00246         for (i = 0; i < gwlist_len(list); ++i) {
00247             p = gwlist_get(list, i);
00248             if (strcmp(p, items[j]) == 0)
00249                 panic(0, "list contains `%s' after "
00250                          "extracting it!",
00251                     items[j]);
00252         }
00253         for (i = 0; i < gwlist_len(extracted); ++i) {
00254             p = gwlist_get(extracted, i);
00255             if (strcmp(p, items[j]) != 0)
00256                 panic(0, 
00257                   "extraction returned wrong element!");
00258         }
00259         gwlist_destroy(extracted, NULL);
00260     }
00261     
00262     if (gwlist_len(list) != 0)
00263         panic(0, "list is not empty after extracting everything");
00264     
00265     gwlist_destroy(list, NULL);
00266 }
00267 
00268 
00269 int main(void) {
00270     gwlib_init();
00271     log_set_output_level(GW_INFO);
00272     main_for_list_add_and_delete();
00273     main_for_extract();
00274     main_for_producer_and_consumer();
00275     gwlib_shutdown();
00276     return 0;
00277 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.