/* -*- Mode: C -*-
  ======================================================================
  FILE: regression.c
  CREATOR: eric 03 April 1999
  
  DESCRIPTION:
  
  $Id: regression.c,v 1.19 2005/08/11 00:00:26 tml Exp $
  $Locker:  $

  (C) COPYRIGHT 1999 Eric Busboom 
  http://www.softwarestudio.org

  The contents of this file are subject to the Mozilla Public License
  Version 1.0 (the "License"); you may not use this file except in
  compliance with the License. You may obtain a copy of the License at
  http://www.mozilla.org/MPL/
 
  Software distributed under the License is distributed on an "AS IS"
  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  the License for the specific language governing rights and
  limitations under the License.

  The original author is Eric Busboom
  The original code is regression.c

    
  ======================================================================*/

#include <libical/ical.h>
#include <libicalss/icalss.h>
#include <libicalvcal/icalvcal.h>

#include "regression.h"

#include <assert.h>
#include <string.h> /* for strdup */
#include <stdlib.h> /* for malloc */
#include <stdio.h> /* for printf */
#include <time.h> /* for time() */
#ifndef WIN32
#include <unistd.h> /* for unlink, fork */
#include <sys/wait.h> /* For waitpid */
#include <sys/time.h> /* for select */
#else
#include <Windows.h>
#endif
#include <sys/types.h> /* For wait pid */

#ifdef WIN32
typedef int pid_t;
#define mkdir(path, mode) _mkdir(path)
#endif


/* For GNU libc, strcmp appears to be a macro, so using strcmp in
 assert results in incomprehansible assertion messages. This
 eliminates the problem */

int regrstrcmp(const char* a, const char* b){
    return strcmp(a,b);
}

/* This example creates and minipulates the ical object that appears
 * in rfc 2445, page 137 */

static char str[] = "BEGIN:VCALENDAR\
PRODID:\"-//RDU Software//NONSGML HandCal//EN\"\
VERSION:2.0\
BEGIN:VTIMEZONE\
TZID:America/New_York\
BEGIN:STANDARD\
DTSTART:19981025T020000\
RDATE:19981025T020000\
TZOFFSETFROM:-0400\
TZOFFSETTO:-0500\
TZNAME:EST\
END:STANDARD\
BEGIN:DAYLIGHT\
DTSTART:19990404T020000\
RDATE:19990404T020000\
TZOFFSETFROM:-0500\
TZOFFSETTO:-0400\
TZNAME:EDT\
END:DAYLIGHT\
END:VTIMEZONE\
BEGIN:VEVENT\
DTSTAMP:19980309T231000Z\
UID:guid-1.host1.com\
ORGANIZER;ROLE=CHAIR:MAILTO:mrbig@host.com\
ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:MAILTO:employee-A@host.com\
DESCRIPTION:Project XYZ Review Meeting\
CATEGORIES:MEETING\
CLASS:PUBLIC\
CREATED:19980309T130000Z\
SUMMARY:XYZ Project Review\
DTSTART;TZID=America/New_York:19980312T083000\
DTEND;TZID=America/New_York:19980312T093000\
LOCATION:1CP Conference Room 4350\
END:VEVENT\
BEGIN:BOOGA\
DTSTAMP:19980309T231000Z\
X-LIC-FOO:Booga\
DTSTOMP:19980309T231000Z\
UID:guid-1.host1.com\
END:BOOGA\
END:VCALENDAR";



/* Return a list of all attendees who are required. */
   
static char** get_required_attendees(icalcomponent* event)
{
    icalproperty* p;
    icalparameter* parameter;

    char **attendees;
    int max = 10;
    int c = 0;

    attendees = malloc(max * (sizeof (char *)));

    ok("event is non null", (event != 0));
    int_is("event is a VEVENT", icalcomponent_isa(event), ICAL_VEVENT_COMPONENT);
    
    for(
	p = icalcomponent_get_first_property(event,ICAL_ATTENDEE_PROPERTY);
	p != 0;
	p = icalcomponent_get_next_property(event,ICAL_ATTENDEE_PROPERTY)
	) {
	
	parameter = icalproperty_get_first_parameter(p,ICAL_ROLE_PARAMETER);

	if ( icalparameter_get_role(parameter) == ICAL_ROLE_REQPARTICIPANT) 
	{
	    attendees[c++] = icalmemory_strdup(icalproperty_get_attendee(p));

            if (c >= max) {
                max *= 2; 
                attendees = realloc(attendees, max * (sizeof (char *)));
            }

	}
    }

    return attendees;
}

/* If an attendee has a PARTSTAT of NEEDSACTION or has no PARTSTAT
   parameter, change it to TENTATIVE. */
   
static void update_attendees(icalcomponent* event)
{
    icalproperty* p;
    icalparameter* parameter;


    assert(event != 0);
    assert(icalcomponent_isa(event) == ICAL_VEVENT_COMPONENT);
    
    for(
	p = icalcomponent_get_first_property(event,ICAL_ATTENDEE_PROPERTY);
	p != 0;
	p = icalcomponent_get_next_property(event,ICAL_ATTENDEE_PROPERTY)
	) {
	
	parameter = icalproperty_get_first_parameter(p,ICAL_PARTSTAT_PARAMETER);

	if (parameter == 0) {

	    icalproperty_add_parameter(
		p,
		icalparameter_new_partstat(ICAL_PARTSTAT_TENTATIVE)
		);

	} else if (icalparameter_get_partstat(parameter) == ICAL_PARTSTAT_NEEDSACTION) {

	    icalproperty_remove_parameter_by_ref(p,parameter);
	    
	    icalparameter_free(parameter);

	    icalproperty_add_parameter(
		p,
		icalparameter_new_partstat(ICAL_PARTSTAT_TENTATIVE)
		);
	}

    }
}


void test_values()
{
    icalvalue *v; 
    icalvalue *copy; 

    v = icalvalue_new_caladdress("cap://value/1");

    is("icalvalue_new_caladdress()", 
       icalvalue_get_caladdress(v), "cap://value/1");

    icalvalue_set_caladdress(v,"cap://value/2");

    is("icalvalue_set_caladdress()",
       icalvalue_get_caladdress(v), "cap://value/2");

    is("icalvalue_as_ical_string()",
       icalvalue_as_ical_string(v), "cap://value/2");

    copy = icalvalue_new_clone(v);

    is("icalvalue_new_clone()",
       icalvalue_as_ical_string(copy), "cap://value/2");
    icalvalue_free(v);
    icalvalue_free(copy);


    v = icalvalue_new_boolean(1);
    int_is("icalvalue_new_boolean(1)", icalvalue_get_boolean(v), 1);
    icalvalue_set_boolean(v,2);
    ok("icalvalue_set_boolean(2)", (2 == icalvalue_get_boolean(v)));
    is("icalvalue_as_ical_string()", icalvalue_as_ical_string(v), "2");

    copy = icalvalue_new_clone(v);
    is("icalvalue_new_clone()", icalvalue_as_ical_string(copy), "2");

    icalvalue_free(v);
    icalvalue_free(copy);


    v = icalvalue_new_x("test");
    is("icalvalue_new_x(test)", icalvalue_get_x(v), "test");
    icalvalue_set_x(v, "test2");
    is("icalvalue_set_x(test2)", icalvalue_get_x(v), "test2");
    is("icalvalue_as_ical_string()", icalvalue_as_ical_string(v), "test2");

    copy = icalvalue_new_clone(v);
    is("icalvalue_new_clone()", icalvalue_as_ical_string(copy), "test2");

    icalvalue_free(v);
    icalvalue_free(copy);


    v = icalvalue_new_date(icaltime_from_timet( 1023404802,0));
    is("icalvalue_new_date()", icalvalue_as_ical_string(v), "20020606T230642");
    icalvalue_set_date(v,icaltime_from_timet( 1023404802-3600,0));
    is("icalvalue_set_date()",icalvalue_as_ical_string(v), "20020606T220642");

    copy = icalvalue_new_clone(v);
    is("icalvalue_new_clone()",icalvalue_as_ical_string(v), "20020606T220642");

    icalvalue_free(v);
    icalvalue_free(copy);


    v = icalvalue_new(-1);

    ok("icalvalue_new(-1), Invalid type", (v == NULL));

    if (v!=0) icalvalue_free(v);

    ok("ICAL_BOOLEAN_VALUE",(ICAL_BOOLEAN_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_BOOLEAN)));
    ok("ICAL_UTCOFFSET_VALUE",(ICAL_UTCOFFSET_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_UTCOFFSET)));
    ok("ICAL_RECUR_VALUE", (ICAL_RECUR_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_RECUR)));
    ok("ICAL_CALADDRESS_VALUE",(ICAL_CALADDRESS_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_CALADDRESS)));
    ok("ICAL_PERIOD_VALUE", (ICAL_PERIOD_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_PERIOD)));
    ok("ICAL_BINARY_VALUE",(ICAL_BINARY_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_BINARY)));
    ok("ICAL_TEXT_VALUE",(ICAL_TEXT_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_TEXT)));
    ok("ICAL_DURATION_VALUE",(ICAL_DURATION_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_DURATION)));
    ok("ICAL_INTEGER_VALUE",
       (ICAL_INTEGER_VALUE == icalparameter_value_to_value_kind(ICAL_VALUE_INTEGER)));

    ok("ICAL_URI_VALUE",
       (ICAL_URI_VALUE == icalparameter_value_to_value_kind(ICAL_VALUE_URI)));
    ok("ICAL_FLOAT_VALUE",(ICAL_FLOAT_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_FLOAT)));
    ok("ICAL_X_VALUE",(ICAL_X_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_X)));
    ok("ICAL_DATETIME_VALUE",(ICAL_DATETIME_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_DATETIME)));
    ok("ICAL_DATE_TIME",(ICAL_DATE_VALUE == 
           icalparameter_value_to_value_kind(ICAL_VALUE_DATE)));

    /*    v = icalvalue_new_caladdress(0);

    printf("Bad string: %p\n",v);

    if (v!=0) icalvalue_free(v); */

    icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR, ICAL_ERROR_NONFATAL);
    v = icalvalue_new_from_string(ICAL_RECUR_VALUE,"D2 #0");
    ok("illegal recur value", (v == 0));

    v = icalvalue_new_from_string(ICAL_TRIGGER_VALUE,"Gonk");
    ok("illegal trigger value", (v == 0));

    v = icalvalue_new_from_string(ICAL_REQUESTSTATUS_VALUE,"Gonk");
    ok("illegal requeststatus value", (v == 0));

    icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR, ICAL_ERROR_DEFAULT);
}


void test_properties()
{
    icalproperty *prop;
    icalparameter *param;

    icalproperty *clone;
    char test_cn_str[128] = "";
    char *test_cn_str_good = "A Common Name 1A Common Name 2A Common Name 3A Common Name 4";
    char *test_ical_str_good = "COMMENT;CN=A Common Name 1;CN=A Common Name 2;CN=A Common Name 3;CN=A \n Common Name 4:Another Comment\n";

    prop = icalproperty_vanew_comment(
	"Another Comment",
	icalparameter_new_cn("A Common Name 1"),
	icalparameter_new_cn("A Common Name 2"),
	icalparameter_new_cn("A Common Name 3"),
       	icalparameter_new_cn("A Common Name 4"),
	0); 

    for(param = icalproperty_get_first_parameter(prop,ICAL_ANY_PARAMETER);
	param != 0; 
	param = icalproperty_get_next_parameter(prop,ICAL_ANY_PARAMETER)) {
      const char *str = icalparameter_get_cn(param);
      if (VERBOSE) printf("Prop parameter: %s\n",icalparameter_get_cn(param));
      strcat(test_cn_str, str);
    }    
    is("fetching parameters", test_cn_str, test_cn_str_good);

    if (VERBOSE) printf("Prop value: %s\n",icalproperty_get_comment(prop));
    is("icalproperty_get_comment()", 
       icalproperty_get_comment(prop), "Another Comment");

    if (VERBOSE) printf("As iCAL string:\n %s\n",icalproperty_as_ical_string(prop));
    
    is("icalproperty_as_ical_string()",
       icalproperty_as_ical_string(prop), test_ical_str_good);
    
    clone = icalproperty_new_clone(prop);

    if (VERBOSE) printf("Clone:\n %s\n",icalproperty_as_ical_string(prop));
    is("icalproperty_new_clone()",
       icalproperty_as_ical_string(prop), test_ical_str_good);
    
    icalproperty_free(clone);
    icalproperty_free(prop);

    prop = icalproperty_new(-1);

    ok("test icalproperty_new() with invalid type (-1)",
       (prop == NULL));

    if (prop!=0) icalproperty_free(prop);
}

void test_utf8()
{
    icalproperty *prop;
    char *utf8text = "aáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaá";
    char *test_ical_str_good = "DESCRIPTION:\n"
" aáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaá\n"
" óaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóaáóa\n"
" áóaáóaáóaáóaáóaáóaáóaáóaáóaá\n";

    prop = icalproperty_new_description(utf8text);

    is("icalproperty_as_ical_string()",
       icalproperty_as_ical_string(prop), test_ical_str_good);
    icalproperty_free(prop);
}



void test_parameters()
{
    icalparameter *p;
    int i;
    int enums[] = {ICAL_CUTYPE_INDIVIDUAL,ICAL_CUTYPE_RESOURCE,ICAL_FBTYPE_BUSY,ICAL_PARTSTAT_NEEDSACTION,ICAL_ROLE_NONPARTICIPANT,ICAL_XLICCOMPARETYPE_LESSEQUAL,ICAL_XLICERRORTYPE_MIMEPARSEERROR,-1};

    char* str1 = "A Common Name";

    p = icalparameter_new_cn(str1);

    is("icalparameter_new_cn()", icalparameter_get_cn(p), str1);
    is("icalparameter_as_ical_string()" ,icalparameter_as_ical_string(p),"CN=A Common Name");
    
    icalparameter_free(p);

    p = icalparameter_new_from_string("PARTSTAT=ACCEPTED");
    ok("PARTSTAT_PARAMETER", (icalparameter_isa(p) == ICAL_PARTSTAT_PARAMETER));
    ok("PARTSTAT_ACCEPTED", (icalparameter_get_partstat(p) == ICAL_PARTSTAT_ACCEPTED));
 
    icalparameter_free(p);

    p = icalparameter_new_from_string("ROLE=CHAIR");

    ok("ROLE_PARAMETER", (icalparameter_isa(p) == ICAL_ROLE_PARAMETER));
    ok("ROLE_CHAIR", (icalparameter_get_partstat(p) == ICAL_ROLE_CHAIR));
 
    icalparameter_free(p);

    p = icalparameter_new_from_string("PARTSTAT=X-FOO");
    ok("PARTSTAT_PARAMETER", (icalparameter_isa(p) == ICAL_PARTSTAT_PARAMETER));
    ok("PARTSTAT_X", (icalparameter_get_partstat(p) == ICAL_PARTSTAT_X));
 
    icalparameter_free(p);

    p = icalparameter_new_from_string("X-PARAM=X-FOO");
    ok("X_PARAMETER", (icalparameter_isa(p) == ICAL_X_PARAMETER));
 
    icalparameter_free(p);


    for (i=0;enums[i] != -1; i++){
      if (VERBOSE) printf("%s\n",icalparameter_enum_to_string(enums[i]));
      ok("test paramter enums", 
	 (icalparameter_string_to_enum(icalparameter_enum_to_string(enums[i]))==enums[i]));
    }
}


char *good_child = 
"BEGIN:VEVENT\n"
"VERSION:2.0\n"
"DESCRIPTION:This is an event\n"
"COMMENT;CN=A Common Name 1;CN=A Common Name 2;CN=A Common Name 3;CN=A \n"
" Common Name 4:Another Comment\n"
"X-LIC-ERROR;X-LIC-ERRORTYPE=COMPONENT-PARSE-ERROR:This is only a test\n"
"END:VEVENT\n";

void test_components()
{
    icalcomponent* c;
    icalcomponent* child;

    c = icalcomponent_vanew(
	ICAL_VCALENDAR_COMPONENT,
	icalproperty_new_version("2.0"),
	icalproperty_new_prodid("-//RDU Software//NONSGML HandCal//EN"),
	icalproperty_vanew_comment(
	    "A Comment",
	    icalparameter_new_cn("A Common Name 1"),
	    0),
	icalcomponent_vanew(
	    ICAL_VEVENT_COMPONENT,
	    icalproperty_new_version("2.0"),
	    icalproperty_new_description("This is an event"),
	    icalproperty_vanew_comment(
		"Another Comment",
		icalparameter_new_cn("A Common Name 1"),
		icalparameter_new_cn("A Common Name 2"),
		icalparameter_new_cn("A Common Name 3"),
		icalparameter_new_cn("A Common Name 4"),
		0),
	    icalproperty_vanew_xlicerror(
		"This is only a test",
		icalparameter_new_xlicerrortype(ICAL_XLICERRORTYPE_COMPONENTPARSEERROR),
		0),
	    
	    0
	    ),
	0
	);

    if (VERBOSE) 
      printf("Original Component:\n%s\n\n",icalcomponent_as_ical_string(c));

    child = icalcomponent_get_first_component(c,ICAL_VEVENT_COMPONENT);
    
    ok("test icalcomponent_get_first_component()",
       (child != NULL));

    if (VERBOSE)
      printf("Child Component:\n%s\n\n",icalcomponent_as_ical_string(child));

    is("test results of child component", 
       icalcomponent_as_ical_string(child), good_child);

    icalcomponent_free(c);
}


void test_memory()
{
    size_t bufsize = 256;
    int i;
    char *p;

    char S1[] = "1) When in the Course of human events, ";
    char S2[] = "2) it becomes necessary for one people to dissolve the political bands which have connected them with another, ";
    char S3[] = "3) and to assume among the powers of the earth, ";
    char S4[] = "4) the separate and equal station to which the Laws of Nature and of Nature's God entitle them, ";
    char S5[] = "5) a decent respect to the opinions of mankind requires that they ";
    char S6[] = "6) should declare the causes which impel them to the separation. ";
    char S7[] = "7) We hold these truths to be self-evident, ";
    char S8[] = "8) that all men are created equal, ";

/*    char S9[] = "9) that they are endowed by their Creator with certain unalienable Rights, ";
    char S10[] = "10) that among these are Life, Liberty, and the pursuit of Happiness. ";
    char S11[] = "11) That to secure these rights, Governments are instituted among Men, ";
    char S12[] = "12) deriving their just powers from the consent of the governed. "; 
*/


    char *f, *b1, *b2, *b3, *b4, *b5, *b6, *b7, *b8;

#define BUFSIZE 1024

    f = icalmemory_new_buffer(bufsize);
    p = f;
    b1 = icalmemory_tmp_buffer(BUFSIZE);
    strcpy(b1, S1);
    icalmemory_append_string(&f, &p, &bufsize, b1);

    b2 = icalmemory_tmp_buffer(BUFSIZE);
    strcpy(b2, S2);
    icalmemory_append_string(&f, &p, &bufsize, b2);

    b3 = icalmemory_tmp_buffer(BUFSIZE);
    strcpy(b3, S3);
    icalmemory_append_string(&f, &p, &bufsize, b3);

    b4 = icalmemory_tmp_buffer(BUFSIZE);
    strcpy(b4, S4);
    icalmemory_append_string(&f, &p, &bufsize, b4);

    b5 = icalmemory_tmp_buffer(BUFSIZE);
    strcpy(b5, S5);
    icalmemory_append_string(&f, &p, &bufsize, b5);

    b6 = icalmemory_tmp_buffer(BUFSIZE);
    strcpy(b6, S6);
    icalmemory_append_string(&f, &p, &bufsize, b6);

    b7 = icalmemory_tmp_buffer(BUFSIZE);
    strcpy(b7, S7);
    icalmemory_append_string(&f, &p, &bufsize, b7);

    b8 = icalmemory_tmp_buffer(BUFSIZE);
    strcpy(b8, S8);
    icalmemory_append_string(&f, &p, &bufsize, b8);


    if (VERBOSE) {
      printf("1: %p %s \n",b1,b1);
      printf("2: %p %s\n",b2,b2);
      printf("3: %p %s\n",b3,b3);
      printf("4: %p %s\n",b4,b4);
      printf("5: %p %s\n",b5,b5);
      printf("6: %p %s\n",b6,b6);
      printf("7: %p %s\n",b7,b7);
      printf("8: %p %s\n",b8,b8);
      
      
      printf("Final: %s\n", f);
      
      printf("Final buffer size: %d\n",bufsize);
    }

    ok("final buffer size == 806", (bufsize == 806));

    free(f);
    
    bufsize = 4;

    f = icalmemory_new_buffer(bufsize);

    memset(f,0,bufsize);
    p = f;

    icalmemory_append_char(&f, &p, &bufsize, 'a');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);

    icalmemory_append_char(&f, &p, &bufsize, 'b');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'c');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'd');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'e');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'f');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'g');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'h');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'i');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'j');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'a');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'b');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'c');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'd');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'e');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'f');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'g');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'h');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'i');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
    icalmemory_append_char(&f, &p, &bufsize, 'j');
    if (VERBOSE) printf("Char-by-Char buffer: %s\n", f);
 
	free(f);
  
    for(i=0; i<100; i++){
	f = icalmemory_tmp_buffer(bufsize);
	
	assert(f!=0);

	memset(f,0,bufsize);
	sprintf(f,"%d",i);
    }
}


void test_dirset()
{
    icalcomponent *c;
    icalgauge *gauge;
    icalerrorenum error;
    icalcomponent *next, *itr;
    icalset* cluster;
    icalset *s, *s2;
    struct icalperiodtype rtime;
    int i;
    int count = 0;

    mkdir("store", 0755);
    mkdir("store-new", 0755);

    s = icaldirset_new("store");
    s2 = icaldirset_new("store-new");

    ok("opening 'store' dirset", s!=NULL);
    ok("opening 'store-new' dirset", s2!=NULL);

    rtime.start = icaltime_from_timet( time(0),0);

    cluster = icalfileset_new("clusterin.vcd");

    if (cluster == 0){
	printf("Failed to create cluster: %s\n",icalerror_strerror(icalerrno));
    }

#define NUMCOMP 4

    /* Duplicate every component in the cluster NUMCOMP times */

    icalerror_clear_errno();

    for (i = 1; i<NUMCOMP+1; i++){

	/*rtime.start.month = i%12;*/
	rtime.start.month = i;
	rtime.end = rtime.start;
	rtime.end.hour++;
	
	for (itr = icalfileset_get_first_component(cluster);
	     itr != 0;
	     itr = icalfileset_get_next_component(cluster)){
	    icalcomponent *clone;
	    icalproperty *p;

	    
	    if(icalcomponent_isa(itr) != ICAL_VEVENT_COMPONENT){
		continue;
	    }

	    
	    /* Change the dtstart and dtend times in the component
               pointed to by Itr*/

	    clone = icalcomponent_new_clone(itr);
	    assert(icalerrno == ICAL_NO_ERROR);
	    assert(clone !=0);

	    /* DTSTART*/
	    p = icalcomponent_get_first_property(clone,ICAL_DTSTART_PROPERTY);
	    assert(icalerrno  == ICAL_NO_ERROR);

	    if (p == 0){
		p = icalproperty_new_dtstart(rtime.start);
		icalcomponent_add_property(clone,p);
	    } else {
		icalproperty_set_dtstart(p,rtime.start);
	    }
	    assert(icalerrno  == ICAL_NO_ERROR);

	    /* DTEND*/
	    p = icalcomponent_get_first_property(clone,ICAL_DTEND_PROPERTY);
	    assert(icalerrno  == ICAL_NO_ERROR);

	    if (p == 0){
		p = icalproperty_new_dtstart(rtime.end);
		icalcomponent_add_property(clone,p);
	    } else {
		icalproperty_set_dtstart(p,rtime.end);
	    }
	    assert(icalerrno  == ICAL_NO_ERROR);
	    
	    printf("\n----------\n%s\n---------\n",icalcomponent_as_ical_string(clone));

	    error = icaldirset_add_component(s,clone);
	    
	    assert(icalerrno  == ICAL_NO_ERROR);
	}
    }
    
    gauge = icalgauge_new_from_sql("SELECT * FROM VEVENT WHERE VEVENT.SUMMARY = 'Submit Income Taxes' OR VEVENT.SUMMARY = 'Bastille Day Party'", 0);

    icaldirset_select(s,gauge);

    for(c = icaldirset_get_first_component(s); c != 0; c = icaldirset_get_next_component(s)){
	printf("Got one! (%d)\n", count++);
	
	if (c != 0){
	    printf("%s", icalcomponent_as_ical_string(c));;
	    if (icaldirset_add_component(s2,c) == 0){
		printf("Failed to write!\n");
	    }
	    icalcomponent_free(c);
	} else {
	    printf("Failed to get component\n");
	}
    }


    icalset_free(s2);

    for(c = icaldirset_get_first_component(s); 
	c != 0; 
	c =  next){
	
	next = icaldirset_get_next_component(s);

	if (c != 0){
	    /*icaldirset_remove_component(s,c);*/
	    printf("%s", icalcomponent_as_ical_string(c));;
	} else {
	    printf("Failed to get component\n");
	}
    }

    icalset_free(s);
    icalset_free(cluster);
}


void test_compare()
{
    icalvalue *v1, *v2;

    v1 = icalvalue_new_caladdress("cap://value/1");
    v2 = icalvalue_new_clone(v1);

    ok("compare value and clone", 
       (icalvalue_compare(v1,v2) == ICAL_XLICCOMPARETYPE_EQUAL));

    icalvalue_free(v1);
    icalvalue_free(v2);

    v1 = icalvalue_new_caladdress("A");
    v2 = icalvalue_new_caladdress("B");

    ok("test compare of A and B results in LESS",
       (icalvalue_compare(v1,v2) == ICAL_XLICCOMPARETYPE_LESS));
	   
    ok("test compare of B and A results in GREATER",
       (icalvalue_compare(v2,v1) == ICAL_XLICCOMPARETYPE_GREATER));

    icalvalue_free(v1);
    icalvalue_free(v2);

    v1 = icalvalue_new_caladdress("B");
    v2 = icalvalue_new_caladdress("A");

    ok("test compare of caladdress A and B results in GREATER",
       (icalvalue_compare(v1,v2) == ICAL_XLICCOMPARETYPE_GREATER));
    
    icalvalue_free(v1);
    icalvalue_free(v2);

    v1 = icalvalue_new_integer(5);
    v2 = icalvalue_new_integer(5);

    ok("test compare of 5 and 5 results in EQUAL", 
       (icalvalue_compare(v1,v2) == ICAL_XLICCOMPARETYPE_EQUAL));

    icalvalue_free(v1);
    icalvalue_free(v2);

    v1 = icalvalue_new_integer(5);
    v2 = icalvalue_new_integer(10);

    ok("test compare of 5 and 10 results in LESS",
       (icalvalue_compare(v1,v2) == ICAL_XLICCOMPARETYPE_LESS));
	   
    ok("test compare of 10 and 5 results in GREATER",
       (icalvalue_compare(v2,v1) == ICAL_XLICCOMPARETYPE_GREATER));

    icalvalue_free(v1);
    icalvalue_free(v2);
}


void test_restriction()
{
    icalcomponent *comp;
    struct icaltimetype atime = icaltime_from_timet( time(0),0);
    int valid; 

    struct icaldatetimeperiodtype rtime;

    char *str;

    rtime.period.start = icaltime_from_timet( time(0),0);
    rtime.period.end = icaltime_from_timet( time(0),0);
    rtime.period.end.hour++;
    rtime.time = icaltime_null_time();

    comp = 
	icalcomponent_vanew(
	    ICAL_VCALENDAR_COMPONENT,
	    icalproperty_new_version("2.0"),
	    icalproperty_new_prodid("-//RDU Software//NONSGML HandCal//EN"),
	    icalproperty_new_method(ICAL_METHOD_REQUEST),
	    icalcomponent_vanew(
		ICAL_VTIMEZONE_COMPONENT,
		icalproperty_new_tzid("America/New_York"),
		icalcomponent_vanew(
		    ICAL_XDAYLIGHT_COMPONENT,
		    icalproperty_new_dtstart(atime),
		    icalproperty_new_rdate(rtime),
		    icalproperty_new_tzoffsetfrom(-4.0),
		    icalproperty_new_tzoffsetto(-5.0),
		    icalproperty_new_tzname("EST"),
		    0
		    ),
		icalcomponent_vanew(
		    ICAL_XSTANDARD_COMPONENT,
		    icalproperty_new_dtstart(atime),
		    icalproperty_new_rdate(rtime),
		    icalproperty_new_tzoffsetfrom(-5.0),
		    icalproperty_new_tzoffsetto(-4.0),
		    icalproperty_new_tzname("EST"),
		    0
		    ),
		0
		),
	    icalcomponent_vanew(
		ICAL_VEVENT_COMPONENT,
		icalproperty_new_dtstamp(atime),
		icalproperty_new_uid("guid-1.host1.com"),
		icalproperty_vanew_organizer(
		    "mrbig@host.com",
		    icalparameter_new_role(ICAL_ROLE_CHAIR),
		    0
		    ),
		icalproperty_vanew_attendee(
		    "employee-A@host.com",
		    icalparameter_new_role(ICAL_ROLE_REQPARTICIPANT),
		    icalparameter_new_rsvp(ICAL_RSVP_TRUE),
		    icalparameter_new_cutype(ICAL_CUTYPE_GROUP),
		    0
		    ),
		icalproperty_new_description("Project XYZ Review Meeting"),
		icalproperty_new_categories("MEETING"),
		icalproperty_new_class(ICAL_CLASS_PUBLIC),
		icalproperty_new_created(atime),
		icalproperty_new_summary("XYZ Project Review"),
                /*		icalproperty_new_dtstart(
		    atime,
		    icalparameter_new_tzid("America/New_York"),
		    0
		    ),*/
		icalproperty_vanew_dtend(
		    atime,
		    icalparameter_new_tzid("America/New_York"),
		    0
		    ),
		icalproperty_new_location("1CP Conference Room 4350"),
		0
		),
	    0
	    );

    valid = icalrestriction_check(comp);
    
    ok("icalrestriction_check() == 0", (valid==0));
    
    str = icalcomponent_as_ical_string(comp);

    icalcomponent_free(comp);

}

void test_calendar()
{
    icalcomponent *comp;
    icalset *c;
    icalset *s;
    icalcalendar* calendar;
    icalerrorenum error;
    struct icaltimetype atime = icaltime_from_timet( time(0),0);

    mkdir("calendar", 0755);
    mkdir("calendar/booked", 0755);

    calendar = icalcalendar_new("calendar");

    comp = icalcomponent_vanew(ICAL_VCALENDAR_COMPONENT,
	icalcomponent_vanew(
	ICAL_VEVENT_COMPONENT,
	icalproperty_new_version("2.0"),
	icalproperty_new_description("This is an event"),
	icalproperty_new_dtstart(atime),
	icalproperty_vanew_comment(
	    "Another Comment",
	    icalparameter_new_cn("A Common Name 1"),
	    icalparameter_new_cn("A Common Name 2"),
	    icalparameter_new_cn("A Common Name 3"),
		icalparameter_new_cn("A Common Name 4"),
	    0),
	icalproperty_vanew_xlicerror(
	    "This is only a test",
	    icalparameter_new_xlicerrortype(ICAL_XLICERRORTYPE_COMPONENTPARSEERROR),
	    0),
	
	0),0);
    
    s = icalcalendar_get_booked(calendar);

    error = icaldirset_add_component(s,comp);
    
    ok("Adding Component to dirset", (error == ICAL_NO_ERROR));

    c = icalcalendar_get_properties(calendar);

    error = icalfileset_add_component(c,icalcomponent_new_clone(comp));

    ok("Adding Clone Component to dirset", (error == ICAL_NO_ERROR));

    icalcalendar_free(calendar);

    ok("icalcalendar test", (1));
}


void test_increment(void);

void print_occur(struct icalrecurrencetype recur, struct icaltimetype start)
{
    struct icaltimetype next;
    icalrecur_iterator* ritr;
	
    time_t tt = icaltime_as_timet(start);

    printf("#### %s\n",icalrecurrencetype_as_string(&recur));
    printf("#### %s\n",ctime(&tt ));
    
    for(ritr = icalrecur_iterator_new(recur,start),
	    next = icalrecur_iterator_next(ritr); 
	!icaltime_is_null_time(next);
	next = icalrecur_iterator_next(ritr)){
	
	tt = icaltime_as_timet(next);
	
	printf("  %s",ctime(&tt ));		
	
    }

    icalrecur_iterator_free(ritr);
}

void test_recur()
{
   struct icalrecurrencetype rt;
   struct icaltimetype start;
   time_t array[25];
   int i;

   rt = icalrecurrencetype_from_string("FREQ=MONTHLY;UNTIL=19971224T000000Z;INTERVAL=1;BYDAY=TU,2FR,3SA");
   start = icaltime_from_string("19970905T090000Z");

   if (VERBOSE) print_occur(rt,start);   

   if (VERBOSE) printf("\n  Using icalrecur_expand_recurrence\n");

   icalrecur_expand_recurrence("FREQ=MONTHLY;UNTIL=19971224T000000Z;INTERVAL=1;BYDAY=TU,2FR,3SA",
			       icaltime_as_timet(start),
			       25,
			       array);

   for(i =0; array[i] != 0 && i < 25 ; i++){
     if (VERBOSE) printf("  %s",ctime(&(array[i])));
   }

   
/*    test_increment();*/

}


void test_expand_recurrence(){

    time_t arr[10];
    time_t now = 931057385;
    int i, numfound = 0;
    icalrecur_expand_recurrence( "FREQ=MONTHLY;BYDAY=MO,WE", now,
                                 5, arr );

    if (VERBOSE) printf("Start %s",ctime(&now) );

    for (i=0; i<5; i++) {
      numfound++;
      if (VERBOSE) printf("i=%d  %s\n", i, ctime(&arr[i]) );
    }
    int_is("Get an array of 5 items", numfound, 5);
}



enum byrule {
    NO_CONTRACTION = -1,
    BY_SECOND = 0,
    BY_MINUTE = 1,
    BY_HOUR = 2,
    BY_DAY = 3,
    BY_MONTH_DAY = 4,
    BY_YEAR_DAY = 5,
    BY_WEEK_NO = 6,
    BY_MONTH = 7,
    BY_SET_POS
};

void icalrecurrencetype_test()
{
    icalvalue *v = icalvalue_new_from_string(
	ICAL_RECUR_VALUE,
	"FREQ=YEARLY;UNTIL=20060101T000000;INTERVAL=2;BYDAY=SU,WE;BYSECOND=15,30; BYMONTH=1,6,11");

    struct icalrecurrencetype r = icalvalue_get_recur(v);
    struct icaltimetype t = icaltime_from_timet( time(0), 0);
    struct icaltimetype next;
    time_t tt;

    struct icalrecur_iterator_impl* itr 
	= (struct icalrecur_iterator_impl*) icalrecur_iterator_new(r,t);

    do {

	next = icalrecur_iterator_next(itr);
	tt = icaltime_as_timet(next);

	printf("%s",ctime(&tt ));		

    } while( ! icaltime_is_null_time(next));

    icalvalue_free(v);

    icalrecur_iterator_free(itr);
 
}

/* From Federico Mena Quintero <federico@ximian.com>    */
void test_recur_parameter_bug(){

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
 
#include <stdio.h>
#include <stdlib.h>
#include <libical/ical.h>
 
    static const char test_icalcomp_str[] =
"BEGIN:VEVENT\n"
"RRULE;X-EVOLUTION-ENDDATE=20030209T081500:FREQ=DAILY;COUNT=10;INTERVAL=6\n"
"END:VEVENT\n";
  
    icalcomponent *icalcomp;
    icalproperty *prop;
    struct icalrecurrencetype recur;
    int n_errors;
    char *str;

    icalcomp = icalparser_parse_string ((char *) test_icalcomp_str);
    ok("icalparser_parse_string()",(icalcomp!=NULL));
    assert(icalcomp!=NULL);
    
    str = icalcomponent_as_ical_string(icalcomp);
    is("parsed matches original", str, (char*)test_icalcomp_str);
    if (VERBOSE) printf("%s\n\n",str);

    n_errors = icalcomponent_count_errors (icalcomp);
    int_is("no parse errors", n_errors, 0);

    if (n_errors) {
	icalproperty *p;
	
	for (p = icalcomponent_get_first_property (icalcomp,
						   ICAL_XLICERROR_PROPERTY);
	     p;
	     p = icalcomponent_get_next_property (icalcomp,
						  ICAL_XLICERROR_PROPERTY)) {
	    const char *str;
	    
	    str = icalproperty_as_ical_string (p);
	    fprintf (stderr, "error: %s\n", str);
	}
    }
    
    prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
    ok("get RRULE property", (prop!=NULL));
    assert(prop!=NULL);
    
    recur = icalproperty_get_rrule (prop);
    
    if (VERBOSE) printf("%s\n",icalrecurrencetype_as_string(&recur));

    icalcomponent_free(icalcomp);
}


void test_duration()
{
    struct icaldurationtype d;

    d = icaldurationtype_from_string("PT8H30M");
    if (VERBOSE) printf("%s\n",icaldurationtype_as_ical_string(d));
    int_is("PT8H30M", icaldurationtype_as_int(d), 30600);
    
    d = icaldurationtype_from_string("-PT8H30M");
    if (VERBOSE) printf("%s\n",icaldurationtype_as_ical_string(d));
    int_is("-PT8H30M", icaldurationtype_as_int(d), -30600);

    d = icaldurationtype_from_string("PT10H10M10S");
    if (VERBOSE) printf("%s\n",icaldurationtype_as_ical_string(d));
    int_is("PT10H10M10S", icaldurationtype_as_int(d), 36610);

    d = icaldurationtype_from_string("P7W");
    if (VERBOSE) printf("%s\n",icaldurationtype_as_ical_string(d));
    int_is("P7W", icaldurationtype_as_int(d), 4233600);

    d = icaldurationtype_from_string("P2DT8H30M");
    if (VERBOSE) printf("%s\n",icaldurationtype_as_ical_string(d));
    int_is("P2DT8H30M", icaldurationtype_as_int(d), 203400);

    icalerror_errors_are_fatal = 0;

    /* Test conversion of bad input */

    d = icaldurationtype_from_int(1314000);
    if (VERBOSE) printf("%s %d\n",icaldurationtype_as_ical_string(d),
			icaldurationtype_as_int(d));
    is("1314000", icaldurationtype_as_ical_string(d), "P15DT5H");

    d = icaldurationtype_from_string("P2W1DT5H");
    if (VERBOSE) printf("%s %d\n",icaldurationtype_as_ical_string(d),
			icaldurationtype_as_int(d));
    int_is("P15DT5H", icaldurationtype_as_int(d), 0);

    d = icaldurationtype_from_string("P-2DT8H30M");
    if (VERBOSE) printf("%s\n",icaldurationtype_as_ical_string(d));
    int_is("P-2DT8H30M", icaldurationtype_as_int(d), 0);

    d = icaldurationtype_from_string("P7W8H");
    if (VERBOSE) printf("%s\n",icaldurationtype_as_ical_string(d));
    int_is("P7W8H", icaldurationtype_as_int(d), 0);

    d = icaldurationtype_from_string("T10H");
    if (VERBOSE) printf("%s\n",icaldurationtype_as_ical_string(d));
    int_is("T10H", icaldurationtype_as_int(d), 0);

    icalerror_errors_are_fatal = 1;

    d = icaldurationtype_from_int(4233600);
    if (VERBOSE) printf("%s\n",icaldurationtype_as_ical_string(d));
    is("P7W",
	icaldurationtype_as_ical_string(d), "P7W");

    d = icaldurationtype_from_int(4424400);
    if (VERBOSE) printf("%s\n",icaldurationtype_as_ical_string(d));
    is("P51DT5H",
	icaldurationtype_as_ical_string(d), "P51DT5H");
}


void test_period()
{
    struct icalperiodtype p;
    icalvalue *v;
    char *str;

    str = "19971015T050000Z/PT8H30M";
    p = icalperiodtype_from_string(str);
    is(str, icalperiodtype_as_ical_string(p),str);


    str = "19971015T050000Z/19971015T060000Z";
    p = icalperiodtype_from_string(str);
    is(str, icalperiodtype_as_ical_string(p),str);


    str = "19970101T120000/PT3H";

    v = icalvalue_new_from_string(ICAL_PERIOD_VALUE,str);
    is(str, icalvalue_as_ical_string(v), str);

    icalvalue_free(v);
}


void test_strings(){
    icalvalue *v;

    v = icalvalue_new_text("foo;bar;bats");
    if (VERBOSE)
      printf("%s\n",icalvalue_as_ical_string(v));

    is("test encoding of 'foo;bar;bats'", 
       "foo\\;bar\\;bats", icalvalue_as_ical_string(v));

    icalvalue_free(v);


    v = icalvalue_new_text("foo\\;b\nar\\;ba\tts");
    if (VERBOSE)
      printf("%s\n",icalvalue_as_ical_string(v));
    
    is("test encoding of 'foo\\\\;b\\nar\\\\;ba\\tts'", 
       "foo\\\\\\;b\\nar\\\\\\;ba\\tts", icalvalue_as_ical_string(v));
    
    icalvalue_free(v);
}


void test_requeststat()
{
    icalproperty *p;
    icalrequeststatus s;
    struct icalreqstattype st, st2;
    char temp[1024];
    
    s = icalenum_num_to_reqstat(2,1);
    
    ok("icalenum_num_to_reqstat(2,1)",(s == ICAL_2_1_FALLBACK_STATUS));
    
    ok("icalenum_reqstat_major()",(icalenum_reqstat_major(s) == 2));
    ok("icalenum_reqstat_minor()",(icalenum_reqstat_minor(s) == 1));
    
    is ("icalenum_reqstat_desc() -> 2.1", icalenum_reqstat_desc(s),
	"Success but fallback taken  on one or more property  values.");
    
    st.code = s;
    st.debug = "booga";
    st.desc = 0;
    
    is("icalreqstattype_as_string()",
       icalreqstattype_as_string(st), 
       "2.1;Success but fallback taken  on one or more property  values.;booga");
    
    st.desc = " A non-standard description";
    
    is("icalreqstattype_as_string() w/ non standard description",
       icalreqstattype_as_string(st),
       "2.1; A non-standard description;booga");
    
    st.desc = 0;
    
    sprintf(temp,"%s\n",icalreqstattype_as_string(st));
    
    
    st2 = icalreqstattype_from_string("2.1;Success but fallback taken  on one or more property  values.;booga");
    
    /*    printf("%d --  %d --  %s -- %s\n",*/
    ok("icalenum_reqstat_major()",(icalenum_reqstat_major(st2.code) == 2));
    ok("icalenum_reqstat_minor()",(icalenum_reqstat_minor(st2.code) == 1));
    is("icalenum_reqstat_desc",
       icalenum_reqstat_desc(st2.code),
       "Success but fallback taken  on one or more property  values.");
    
    st2 = icalreqstattype_from_string("2.1;Success but fallback taken  on one or more property  values.;booga");
    if (VERBOSE) printf("%s\n",icalreqstattype_as_string(st2));
    
    st2 = icalreqstattype_from_string("2.1;Success but fallback taken  on one or more property  values.;");
    if (VERBOSE) printf("%s\n",icalreqstattype_as_string(st2));
    
    st2 = icalreqstattype_from_string("2.1;Success but fallback taken  on one or more property  values.");
    if (VERBOSE) printf("%s\n",icalreqstattype_as_string(st2));
    
    st2 = icalreqstattype_from_string("2.1;");
    if (VERBOSE) printf("%s\n",icalreqstattype_as_string(st2));

    is("st2 test again",
       icalreqstattype_as_string(st2),
       "2.1;Success but fallback taken  on one or more property  values.");
    
    st2 = icalreqstattype_from_string("2.1");
    is("st2 test #3",
       icalreqstattype_as_string(st2),
       "2.1;Success but fallback taken  on one or more property  values.");
    
    p = icalproperty_new_from_string("REQUEST-STATUS:2.1;Success but fallback taken  on one or more property  values.;booga");

    is("icalproperty_new_from_string()",
       icalproperty_as_ical_string(p),
       "REQUEST-STATUS:2.1;Success but fallback taken  on one or more property  \n values.;booga\n");

    icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL);
    st2 = icalreqstattype_from_string("16.4");
    
    ok("test unknown code", (st2.code == ICAL_UNKNOWN_STATUS));
    
    st2 = icalreqstattype_from_string("1.");
    
    ok("test malformed code", (st2.code == ICAL_UNKNOWN_STATUS));
    icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_DEFAULT);

    icalproperty_free(p);
}


void test_dtstart(){
    
    struct icaltimetype tt,tt2;
    
    icalproperty *p;
    

    tt = icaltime_from_string("19970101");

    int_is("19970101 is a date", tt.is_date, 1);

    p = icalproperty_new_dtstart(tt);

    if (VERBOSE) printf("%s\n",icalvalue_kind_to_string(icalvalue_isa(icalproperty_get_value(p))));

    ok("ICAL_DATE_VALUE", (icalvalue_isa(icalproperty_get_value(p))==ICAL_DATE_VALUE));

    tt2 = icalproperty_get_dtstart(p);
    int_is("converted date is date", tt2.is_date, 1);

    if (VERBOSE) printf("%s\n",icalproperty_as_ical_string(p));

    tt = icaltime_from_string("19970101T103000");

    int_is("19970101T103000 is not a date", tt.is_date, 0);

    icalproperty_free(p);

    p = icalproperty_new_dtstart(tt);

    if (VERBOSE) printf("%s\n",icalvalue_kind_to_string(icalvalue_isa(icalproperty_get_value(p))));
    ok("ICAL_DATETIME_VALUE", (icalvalue_isa(icalproperty_get_value(p))==ICAL_DATETIME_VALUE));

    tt2 = icalproperty_get_dtstart(p);
    int_is("converted datetime is not date", tt2.is_date, 0);

    if (VERBOSE) printf("%s\n",icalproperty_as_ical_string(p));

    icalproperty_free(p);
}

void do_test_time(char* zone)
{
    struct icaltimetype ictt, icttutc, icttzone, icttdayl, 
	icttla, icttny,icttphoenix, icttlocal, icttnorm;
    time_t tt,tt2, tt_p200;
    int offset_tz;
    icalvalue *v;
    short day_of_week,start_day_of_week, day_of_year;
    icaltimezone *azone, *utczone;
    char msg[256];

    icalerror_errors_are_fatal = 0;

    azone = icaltimezone_get_builtin_timezone(zone);
    utczone = icaltimezone_get_utc_timezone();

    /* Test new API */
    if (VERBOSE) printf("\n---> From time_t \n");

    tt = 1025127869;		/* stick with a constant... */

    if (VERBOSE) printf("Orig        : %s\n",ical_timet_string(tt));
    if (VERBOSE) printf("\nicaltime_from_timet(tt,0) (DEPRECATED)\n");

    ictt = icaltime_from_timet(tt, 0);

    is("icaltime_from_timet(1025127869) as UTC", ictt_as_string(ictt),
       "2002-06-26 21:44:29 (floating)");

    ictt = icaltime_from_timet_with_zone(tt, 0, NULL);
    is("Floating time from time_t",
       ictt_as_string(ictt), "2002-06-26 21:44:29 (floating)");

    ictt = icaltime_from_timet_with_zone(tt, 0, azone);
    ok("icaltime_from_timet_with_zone(tt,0,zone) as zone", 
       strncmp(ictt_as_string(ictt), "2002-06-26 21:44:29", 19)==0);

    ictt = icaltime_from_timet_with_zone(tt, 0, utczone);

    is("icaltime_from_timet_with_zone(tt,0,utc)", ictt_as_string(ictt),
       "2002-06-26 21:44:29 Z UTC");

    if (VERBOSE) printf("\n---> Convert from floating \n");

    ictt = icaltime_from_timet_with_zone(tt, 0, NULL);
    icttutc = icaltime_convert_to_zone(ictt, utczone);

    is("Convert from floating to UTC",
       ictt_as_string(icttutc),
       "2002-06-26 21:44:29 Z UTC");
	   
    icttzone = icaltime_convert_to_zone(ictt, azone);

    ok("Convert from floating to zone",
       (strncmp(ictt_as_string(icttzone), "2002-06-26 21:44:29", 19)==0));

    tt2 = icaltime_as_timet(icttzone);

    if (VERBOSE) printf("\n---> Convert from UTC \n");

    ictt = icaltime_from_timet_with_zone(tt, 0, utczone);
    icttutc = icaltime_convert_to_zone(ictt, utczone);

    is("Convert from UTC to UTC",
       ictt_as_string(icttutc),
       "2002-06-26 21:44:29 Z UTC");

    icttzone = icaltime_convert_to_zone(ictt, azone);

    ok("Convert from UTC to zone (test year/mon only..)",
       (strncmp(ictt_as_string(icttzone), "2002-06-26 21:44:29", 7)==0));

    tt2 = icaltime_as_timet(icttzone);

    if (VERBOSE) printf("No conversion: %s\n", ical_timet_string(tt2));

    ok("No conversion at all (test year/mon only)",
       (strncmp(ical_timet_string(tt2), "2002-06-26 21:44:29 Z",7) == 0));

    tt2 = icaltime_as_timet_with_zone(icttzone, utczone);
    if (VERBOSE) printf("Back to UTC  : %s\n", ical_timet_string(tt2));

    ok("test time conversion routines",(tt==tt2));

    if (VERBOSE) printf("\n---> Convert from zone \n");
    ictt = icaltime_from_timet_with_zone(tt, 0, azone);
    icttzone = icaltime_convert_to_zone(ictt, azone);

    if (VERBOSE)
    printf("To zone      : %s\n", ictt_as_string(icttzone));
    icttutc = icaltime_convert_to_zone(ictt, utczone);

    if (VERBOSE)
    printf("To UTC      : %s\n", ictt_as_string(icttutc));
    tt2 = icaltime_as_timet(icttutc);

    if (VERBOSE)
    printf("No conversion: %s\n", ical_timet_string(tt2));

    tt2 = icaltime_as_timet_with_zone(icttutc, azone);

    if (VERBOSE)
    printf("Back to zone  : %s\n", ical_timet_string(tt2));

    ok("test time conversion, round 2", (tt==tt2));

    ictt = icaltime_from_string("20001103T183030Z");

    tt = icaltime_as_timet(ictt);

    ok("test icaltime -> time_t for 20001103T183030Z", (tt==973276230)); 
    /* Fri Nov  3 10:30:30 PST 2000 in PST 
       Fri Nov  3 18:30:30 PST 2000 in UTC */
    
    if (VERBOSE) {
    printf(" Normalize \n");
    printf("Orig (ical) : %s\n", ictt_as_string(ictt));
    }
    icttnorm = ictt;
    icttnorm.second -= 60 * 60 * 24 * 5;
    icttnorm = icaltime_normalize(icttnorm);

    if (VERBOSE) 
      printf("-5d in sec  : %s\n", ictt_as_string(icttnorm));
    icttnorm.day += 60;
    icttnorm = icaltime_normalize(icttnorm);

    if (VERBOSE) 
      printf("+60 d       : %s\n", ictt_as_string(icttnorm));

    /** add test case here.. **/

    if (VERBOSE) 
    printf("\n As time_t \n");

    tt2 = icaltime_as_timet(ictt);

    if (VERBOSE) {
      printf("20001103T183030Z (timet): %s\n",ical_timet_string(tt2));
      printf("20001103T183030Z        : %s\n",ictt_as_string(ictt));
    }

    /** this test is bogus **/
    ok("test normalization", (tt2 == tt));

    icttlocal = icaltime_convert_to_zone(ictt, azone);
    tt2 = icaltime_as_timet(icttlocal);
    if (VERBOSE) {
      printf("20001103T183030  (timet): %s\n",ical_timet_string(tt2));
      printf("20001103T183030         : %s\n",ictt_as_string(icttlocal));
    }

    offset_tz = -icaltimezone_get_utc_offset_of_utc_time(azone, &ictt, 0); /* FIXME */
    if (VERBOSE)
      printf("offset_tz               : %d\n",offset_tz);

    ok("test utc offset", (tt-tt2 == offset_tz));

    /* FIXME with the new API, it's not very useful */
    icttlocal = ictt;
    icaltimezone_convert_time(&icttlocal,
	icaltimezone_get_utc_timezone(),
	icaltimezone_get_builtin_timezone(zone));

    if (VERBOSE)
      printf("As local    : %s\n", ictt_as_string(icttlocal));

    if (VERBOSE) printf("\n Convert to and from lib c \n");

    if (VERBOSE) printf("System time is: %s\n",ical_timet_string(tt));

    v = icalvalue_new_datetime(ictt);

    if (VERBOSE) 
      printf("System time from libical: %s\n",icalvalue_as_ical_string(v));

    icalvalue_free(v);

    tt2 = icaltime_as_timet(ictt);

    if (VERBOSE)
    printf("Converted back to libc: %s\n",ical_timet_string(tt2));
    
    if (VERBOSE) printf("\n Incrementing time  \n");

    icttnorm = ictt;

    icttnorm.year++;
    tt2 = icaltime_as_timet(icttnorm);
    if (VERBOSE)
    printf("Add a year: %s\n",ical_timet_string(tt2));

    icttnorm.month+=13;
    tt2 = icaltime_as_timet(icttnorm);
    if (VERBOSE)
    printf("Add 13 months: %s\n",ical_timet_string(tt2));

    icttnorm.second+=90;
    tt2 = icaltime_as_timet(icttnorm);
    if (VERBOSE)
    printf("Add 90 seconds: %s\n",ical_timet_string(tt2));

    if (VERBOSE) printf("\n Day Of week \n");

    day_of_week = icaltime_day_of_week(ictt);
    start_day_of_week = icaltime_start_doy_of_week(ictt);
    day_of_year = icaltime_day_of_year(ictt);

    sprintf(msg, "Testing day of week %d", day_of_week);
    int_is(msg, day_of_week, 6);

    sprintf(msg, "Testing day of year %d",day_of_year);
    int_is(msg, day_of_year, 308);

    sprintf(msg, "Week started on doy of %d", start_day_of_week);
    int_is(msg, start_day_of_week , 303);

    if (VERBOSE) printf("\n TimeZone Conversions \n");

/*
    icttla = ictt;
    icaltimezone_convert_time(&icttla,
			      icaltimezone_get_utc_timezone(),
			      lazone);
*/
    icttla = icaltime_convert_to_zone(ictt,
	icaltimezone_get_builtin_timezone("America/Los_Angeles"));

    int_is("Converted hour in America/Los_Angeles is 10", icttla.hour, 10);

    icttutc = icaltime_convert_to_zone(icttla,icaltimezone_get_utc_timezone());

    ok("America/Los_Angeles local time is 2000-11-03 10:30:30",
       (strncmp(ictt_as_string(icttla), "2000-11-03 10:30:30", 19)==0));

    ok("Test conversion back to UTC",(icaltime_compare(icttutc, ictt) == 0)); 

    icttny  = icaltime_convert_to_zone(ictt,
	icaltimezone_get_builtin_timezone("America/New_York"));

    icttphoenix = icaltime_convert_to_zone(ictt,
	icaltimezone_get_builtin_timezone("America/Phoenix"));

    if (VERBOSE) {
    printf("Orig (ctime): %s\n", ical_timet_string(tt) );
    printf("Orig (ical) : %s\n", ictt_as_string(ictt));
    printf("UTC         : %s\n", ictt_as_string(icttutc));
    printf("Los Angeles : %s\n", ictt_as_string(icttla));
    printf("Phoenix     : %s\n", ictt_as_string(icttphoenix));
    printf("New York    : %s\n", ictt_as_string(icttny));
    }
    /** @todo Check results for Phoenix here?... **/

    /* Daylight savings test for New York */
    if (VERBOSE) {
    printf("\n Daylight Savings \n");

    printf("Orig (ctime): %s\n", ical_timet_string(tt) );
    printf("Orig (ical) : %s\n", ictt_as_string(ictt));
    printf("NY          : %s\n", ictt_as_string(icttny));
    }

    ok("Converted time in zone America/New_York is 2000-11-03 13:30:30",
       (strncmp(ictt_as_string(icttny),"2000-11-03 13:30:30",19)==0));

    tt_p200 = tt +  200 * 24 * 60 * 60 ; /* Add 200 days */

    icttdayl = icaltime_from_timet_with_zone(tt_p200,0,
	icaltimezone_get_utc_timezone());
    icttny = icaltime_convert_to_zone(icttdayl,
	icaltimezone_get_builtin_timezone("America/New_York"));

    if (VERBOSE) {
    printf("Orig +200d  : %s\n", ical_timet_string(tt_p200) );
    printf("NY+200D     : %s\n", ictt_as_string(icttny));
    }

    ok("Converted time +200d in zone America/New_York is 2001-05-22 14:30:30",
       (strncmp(ictt_as_string(icttny),"2001-05-22 14:30:30",19)==0));


    /* Daylight savings test for Los Angeles */

    icttla = icaltime_convert_to_zone(ictt,
	icaltimezone_get_builtin_timezone("America/Los_Angeles"));

    if (VERBOSE) {
    printf("\nOrig (ctime): %s\n", ical_timet_string(tt) );
    printf("Orig (ical) : %s\n", ictt_as_string(ictt));
    printf("LA          : %s\n", ictt_as_string(icttla));
    }

    ok("Converted time in zone America/Los_Angeles is 2000-11-03 10:30:30",
       (strncmp(ictt_as_string(icttla),"2000-11-03 10:30:30",19)==0));

    
    icttla = icaltime_convert_to_zone(icttdayl,
	icaltimezone_get_builtin_timezone("America/Los_Angeles"));

    if (VERBOSE) {
    printf("Orig +200d  : %s\n", ical_timet_string(tt_p200) );
    printf("LA+200D     : %s\n", ictt_as_string(icttla));
    }

    ok("Converted time +200d in zone America/Los_Angeles is 2001-05-22 11:30:30",
       (strncmp(ictt_as_string(icttla),"2001-05-22 11:30:30",19)==0));


    icalerror_errors_are_fatal = 1;
}

void test_iterators()
{
    icalcomponent *c,*inner,*next;
    icalcompiter i;
    char vevent_list[64] = "";
    char remaining_list[64] = "";

    char *vevent_list_good = "12347";
    char *remaining_list_good = "568910";

    int nomore = 1;
    
    c= icalcomponent_vanew(
	ICAL_VCALENDAR_COMPONENT,
	icalcomponent_vanew(ICAL_VEVENT_COMPONENT,
			    icalproperty_new_version("1"),0),
	icalcomponent_vanew(ICAL_VEVENT_COMPONENT,
			    icalproperty_new_version("2"),0),
	icalcomponent_vanew(ICAL_VEVENT_COMPONENT,
			    icalproperty_new_version("3"),0),
	icalcomponent_vanew(ICAL_VEVENT_COMPONENT,
			    icalproperty_new_version("4"),0),
	icalcomponent_vanew(ICAL_VTODO_COMPONENT,
			    icalproperty_new_version("5"),0),
	icalcomponent_vanew(ICAL_VJOURNAL_COMPONENT,
			    icalproperty_new_version("6"),0),
	icalcomponent_vanew(ICAL_VEVENT_COMPONENT,
			    icalproperty_new_version("7"),0),
	icalcomponent_vanew(ICAL_VJOURNAL_COMPONENT,
			    icalproperty_new_version("8"),0),
	icalcomponent_vanew(ICAL_VJOURNAL_COMPONENT,
			    icalproperty_new_version("9"),0),
	icalcomponent_vanew(ICAL_VJOURNAL_COMPONENT,
			    icalproperty_new_version("10"),0),
	0);
   
    /* List all of the VEVENTS */

    for(i = icalcomponent_begin_component(c,ICAL_VEVENT_COMPONENT);
	icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
	
	icalcomponent *this = icalcompiter_deref(&i);

	icalproperty *p = 
	    icalcomponent_get_first_property(this,
					     ICAL_VERSION_PROPERTY);
	const char* s = icalproperty_get_version(p);

	strcat(vevent_list, s);
    }
    is("iterate through VEVENTS in a component", 
       vevent_list, vevent_list_good);

    /* Delete all of the VEVENTS */
    /* reset iterator */
    icalcomponent_get_first_component(c,ICAL_VEVENT_COMPONENT);

    while((inner=icalcomponent_get_current_component(c)) != 0 ){
	if(icalcomponent_isa(inner) == ICAL_VEVENT_COMPONENT){
	    icalcomponent_remove_component(c,inner);
		icalcomponent_free(inner);
	} else {
	    icalcomponent_get_next_component(c,ICAL_VEVENT_COMPONENT);
	}
    }

    /* List all remaining components */
    for(inner = icalcomponent_get_first_component(c,ICAL_ANY_COMPONENT); 
	inner != 0; 
	inner = icalcomponent_get_next_component(c,ICAL_ANY_COMPONENT)){
	

	icalproperty *p = 
	    icalcomponent_get_first_property(inner,ICAL_VERSION_PROPERTY);

	const char* s = icalproperty_get_version(p);	

	strcat(remaining_list, s);
    }

    is("iterate through remaining components", 
       remaining_list, remaining_list_good);

    
    /* Remove all remaining components */
    for(inner = icalcomponent_get_first_component(c,ICAL_ANY_COMPONENT); 
	inner != 0; 
	inner = next){

	icalcomponent *this;
	icalproperty *p;
	const char* s;
	next = icalcomponent_get_next_component(c,ICAL_ANY_COMPONENT);

	p=icalcomponent_get_first_property(inner,ICAL_VERSION_PROPERTY);
	s = icalproperty_get_version(p);	

	icalcomponent_remove_component(c,inner);

	this = icalcomponent_get_current_component(c);

	if(this != 0){
	    p=icalcomponent_get_first_property(this,ICAL_VERSION_PROPERTY);
	    s = icalproperty_get_version(p);	
	}

	icalcomponent_free(inner);
    }


    /* List all remaining components */
    for(inner = icalcomponent_get_first_component(c,ICAL_ANY_COMPONENT); 
	inner != 0; 
	inner = icalcomponent_get_next_component(c,ICAL_ANY_COMPONENT)){
	
	icalproperty *p = 
	    icalcomponent_get_first_property(inner,ICAL_VERSION_PROPERTY);

	const char* s = icalproperty_get_version(p);	

	if (s)
	  nomore = 0;
    }

    ok("test if any components remain after deleting the rest", 
       nomore == 1);
    
	icalcomponent_free(c);
}


void test_time()
{
    char  *zones[6] = { "America/Los_Angeles","America/New_York","Europe/London","Asia/Shanghai", NULL};
    
    int i;

    do_test_time(0);

    for(i = 0; zones[i] != NULL; i++){

      if (VERBOSE) printf(" ######### Timezone: %s ############\n",zones[i]);
        
	do_test_time(zones[i]);

    } 

}


void test_icalset()
{
    icalcomponent *c; 

    icalset* f = icalset_new_file("2446.ics");
    icalset* d = icalset_new_dir("outdir");

    assert(f!=0);
    assert(d!=0);

    for(c = icalset_get_first_component(f);
	c != 0;
	c = icalset_get_next_component(f)){

	icalcomponent *clone; 

	clone = icalcomponent_new_clone(c);

	icalset_add_component(d,clone);

	printf(" class %d\n",icalclassify(c,0,"user"));

    }

	icalset_free(f);
	icalset_free(d);
}


icalcomponent* icalclassify_find_overlaps(icalset* set, icalcomponent* comp);

void test_overlaps()
{
    icalcomponent *cset,*c;
    icalset *set;
    time_t tm1 = 973378800; /*Sat Nov  4 23:00:00 UTC 2000,
			      Sat Nov  4 15:00:00 PST 2000 */
    time_t tm2 = 973382400; /*Sat Nov  5 00:00:00 UTC 2000 
			      Sat Nov  4 16:00:00 PST 2000 */

    time_t hh = 1800; /* one half hour */
    icalfileset_options options = {O_RDONLY, 0644, 0};

    set = icalset_new(ICAL_FILE_SET, TEST_DATADIR "/overlaps.ics", &options);

    c = icalcomponent_vanew(
	ICAL_VEVENT_COMPONENT,
	icalproperty_vanew_dtstart(icaltime_from_timet(tm1-hh,0),0),
	icalproperty_vanew_dtend(icaltime_from_timet(tm2-hh,0),0),
	0
	);

    cset =  icalclassify_find_overlaps(set,c);
    ok("TODO find overlaps 1", (cset != NULL));

    if (VERBOSE && cset) printf("%s\n",icalcomponent_as_ical_string(cset));

    if (cset) icalcomponent_free(cset);
    if (c)    icalcomponent_free(c);


    c = icalcomponent_vanew(
	ICAL_VEVENT_COMPONENT,
	icalproperty_vanew_dtstart(icaltime_from_timet(tm1-hh,0),0),
	icalproperty_vanew_dtend(icaltime_from_timet(tm2,0),0),
	0
	);

    cset =  icalclassify_find_overlaps(set,c);

    ok("TODO find overlaps 1", cset != NULL);
    if (VERBOSE && cset) printf("%s\n",icalcomponent_as_ical_string(cset));

    if (cset) icalcomponent_free(cset);
    if (c)    icalcomponent_free(c);

    c = icalcomponent_vanew(
	ICAL_VEVENT_COMPONENT,
	icalproperty_vanew_dtstart(icaltime_from_timet(tm1+5*hh,0),0),
	icalproperty_vanew_dtend(icaltime_from_timet(tm2+5*hh,0),0),
	0
	);

    cset =  icalclassify_find_overlaps(set,c);
    ok("TODO find overlaps 1", cset != NULL);
    if (VERBOSE && cset) printf("%s\n",icalcomponent_as_ical_string(cset));

    if (set)  icalset_free(set);
    if (cset) icalcomponent_free(cset);
    if (c)    icalcomponent_free(c);
}



void test_fblist()
{
    icalspanlist *sl, *new_sl;
    icalfileset_options options = {O_RDONLY, 0644, 0};
    icalset *set = icalset_new(ICAL_FILE_SET, TEST_DATADIR "/spanlist.ics", &options);
    struct icalperiodtype period;
    icalcomponent *comp;
    int * foo;
    int i;

    sl = icalspanlist_new(set,
		     icaltime_from_string("19980101T000000Z"),
		     icaltime_from_string("19980108T000000Z"));
		
    ok("open ../../test-data/spanlist.ics", (set!=NULL));
    assert(set!=NULL);

    if (VERBOSE) printf("Restricted spanlist\n");
    if (VERBOSE) icalspanlist_dump(sl);

    period= icalspanlist_next_free_time(sl,
		    icaltime_from_string("19970801T120000"));

    is("Next Free time start 19970801T120000", icaltime_as_ical_string(period.start), "19970801T120000");
    is("Next Free time end   19980101T000000", icaltime_as_ical_string(period.end), "19980101T000000");

    period= icalspanlist_next_free_time(sl, period.end);

    is("Next Free time start 19980101T010000", icaltime_as_ical_string(period.start), "19980101T010000");
    is("Next Free time end   19980102T010000", icaltime_as_ical_string(period.end), "19980102T010000");
 
    if (VERBOSE) printf("%s\n",
	   icalcomponent_as_ical_string(icalspanlist_as_vfreebusy(sl,
								  "a@foo.com",
								  "b@foo.com")
					));

    foo = icalspanlist_as_freebusy_matrix(sl,3600);
    
    for (i=0; foo[i] != -1; i++); /* find number entries */

    int_is("Calculating freebusy hourly matrix", i, (7*24));

    if (VERBOSE) {
      for (i=0; foo[i] != -1; i++) {
	printf("%d", foo[i]);
	if ((i % 24) == 23)
	  printf("\n");
      }
      printf("\n\n");
    }


    free(foo);

    foo = icalspanlist_as_freebusy_matrix(sl,3600*24);

    ok("Calculating daily freebusy matrix", (foo!=NULL));

    {
      char out_str[80] = "";
      char *strp = out_str;

      for (i=0; foo[i]!=-1; i++){
	sprintf(strp, "%d", foo[i]);
	strp++;
      }
      is("Checking freebusy validity", out_str, "1121110");
    }
    if (VERBOSE) {
      for (i=0; foo[i] != -1; i++) {
	printf("%d", foo[i]);
	if ((i % 7) == 6)
	  printf("\n");
      }
      printf("\n\n");
    }
    free(foo);

    icalspanlist_free(sl);


    if (VERBOSE) printf("Unrestricted spanlist\n");

    sl = icalspanlist_new(set,
			  icaltime_from_string("19970324T120000Z"),
			  icaltime_null_time());

    ok("add 19970324T120000Z to spanlist", (sl!=NULL));

    if (VERBOSE) printf("Restricted spanlist\n");
    if (VERBOSE) icalspanlist_dump(sl);

    period= icalspanlist_next_free_time(sl,
				      icaltime_from_string("19970801T120000Z"));


    is("Next Free time start 19980101T010000", 
       icaltime_as_ical_string(period.start),
       "19980101T010000");

    is("Next Free time end   19980102T010000", 
       icaltime_as_ical_string(period.end), 
       "19980102T010000");

    comp = icalspanlist_as_vfreebusy(sl, "a@foo.com", "b@foo.com");

    ok("Calculating VFREEBUSY component", (comp != NULL));
    if (VERBOSE) printf("%s\n", icalcomponent_as_ical_string(comp));

    new_sl = icalspanlist_from_vfreebusy(comp);

    ok("Calculating spanlist from generated VFREEBUSY component", 
       (new_sl != NULL));

    if (VERBOSE) icalspanlist_dump(new_sl);

    if (sl) icalspanlist_free(sl);
    if (new_sl) icalspanlist_free(new_sl);
    if (comp) icalcomponent_free(comp);

    icalset_free(set);
}


void test_convenience(){
    icalcomponent *c;
    int duration;
    struct icaltimetype tt;

    c = icalcomponent_vanew(
	ICAL_VCALENDAR_COMPONENT,
	icalcomponent_vanew(
	    ICAL_VEVENT_COMPONENT,
	    icalproperty_new_dtstart(icaltime_from_string("19970801T120000")),
	    icalproperty_new_dtend(icaltime_from_string("19970801T130000")),
	    0
	    ),
	0);

    if (VERBOSE) printf("\n%s\n", icalcomponent_as_ical_string(c));

    duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60;

    is("Start is 1997-08-01 12:00:00 (floating)",
       ictt_as_string(icalcomponent_get_dtstart(c)), "1997-08-01 12:00:00 (floating)");
    is("End is 1997-08-01 13:00:00 (floating)",
       ictt_as_string(icalcomponent_get_dtend(c)), "1997-08-01 13:00:00 (floating)");
    ok("Duration is 60 m", (duration == 60));

    icalcomponent_free(c);

    c = icalcomponent_vanew(
	ICAL_VCALENDAR_COMPONENT,
	icalcomponent_vanew(
	    ICAL_VEVENT_COMPONENT,
	    icalproperty_new_dtstart(icaltime_from_string("19970801T120000Z")),
	    icalproperty_new_duration(icaldurationtype_from_string("PT1H30M")),
	    0
	    ),
	0);

    if (VERBOSE) printf("\n%s\n", icalcomponent_as_ical_string(c));

    duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60;

    is("Start is 1997-08-01 12:00:00 Z UTC",
       ictt_as_string(icalcomponent_get_dtstart(c)), "1997-08-01 12:00:00 Z UTC");
    is("End is 1997-08-01 13:30:00 Z UTC",
       ictt_as_string(icalcomponent_get_dtend(c)), "1997-08-01 13:30:00 Z UTC");
    ok("Duration is 90 m", (duration == 90));

    icalcomponent_free(c);

    icalerror_errors_are_fatal = 0;

    c = icalcomponent_vanew(
	ICAL_VCALENDAR_COMPONENT,
	icalcomponent_vanew(
	    ICAL_VEVENT_COMPONENT,
	    icalproperty_new_dtstart(icaltime_from_string("19970801T120000")),
	    icalproperty_new_dtend(icaltime_from_string("19970801T130000")),
	    0
	    ),
	0);

    icalcomponent_set_duration(c,icaldurationtype_from_string("PT1H30M"));

    if (VERBOSE) printf("\n%s\n", icalcomponent_as_ical_string(c));

    duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60;

    is("Start is 1997-08-01 12:00:00 (floating)",
	ictt_as_string(icalcomponent_get_dtstart(c)),
	"1997-08-01 12:00:00 (floating)");
    is("End is 1997-08-01 13:00:00 (floating)",
	ictt_as_string(icalcomponent_get_dtend(c)),
	"1997-08-01 13:00:00 (floating)");
    ok("Duration is 60 m", (duration == 60));

    icalcomponent_free(c);

    c = icalcomponent_vanew(
	ICAL_VCALENDAR_COMPONENT,
	icalcomponent_vanew(
	    ICAL_VEVENT_COMPONENT,
	    icalproperty_new_dtstart(icaltime_from_string("19970801T120000Z")),
	    icalproperty_new_duration(icaldurationtype_from_string("PT1H30M")),
	    0
	    ),
	0);

    icalcomponent_set_dtend(c,icaltime_from_string("19970801T133000Z"));

    if (VERBOSE) printf("\n%s\n", icalcomponent_as_ical_string(c));


    duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60;

    ok("Start is 1997-08-01 12:00:00 Z UTC",
       (0 == strcmp("1997-08-01 12:00:00 Z UTC", ictt_as_string(icalcomponent_get_dtstart(c)))));
    ok("End is 1997-08-01 13:30:00 Z UTC",
       (0 == strcmp("1997-08-01 13:30:00 Z UTC", ictt_as_string(icalcomponent_get_dtend(c)))));
    ok("Duration is 90 m", (duration == 90));

    icalerror_errors_are_fatal = 1;

    icalcomponent_free(c);

    c = icalcomponent_vanew(
	ICAL_VCALENDAR_COMPONENT,
	icalcomponent_vanew(
	    ICAL_VEVENT_COMPONENT,
	    0
	    ),
	0);

    icalcomponent_set_dtstart(c,icaltime_from_string("19970801T120000Z"));
    icalcomponent_set_dtend(c,icaltime_from_string("19970801T133000Z"));

    if (VERBOSE) printf("\n%s\n", icalcomponent_as_ical_string(c));


    duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60;

    ok("Start is 1997-08-01 12:00:00 Z UTC",
       (0 == strcmp("1997-08-01 12:00:00 Z UTC", ictt_as_string(icalcomponent_get_dtstart(c)))));
    ok("End is 1997-08-01 13:30:00 Z UTC",
       (0 == strcmp("1997-08-01 13:30:00 Z UTC", ictt_as_string(icalcomponent_get_dtend(c)))));
    ok("Duration is 90 m", (duration == 90));

    icalcomponent_free(c);

    c = icalcomponent_vanew(
	ICAL_VCALENDAR_COMPONENT,
	icalcomponent_vanew(
	    ICAL_VEVENT_COMPONENT,
	    0
	    ),
	0);


    icalcomponent_set_dtstart(c,icaltime_from_string("19970801T120000Z"));
    icalcomponent_set_duration(c,icaldurationtype_from_string("PT1H30M"));

    if (VERBOSE) printf("\n%s\n", icalcomponent_as_ical_string(c));


    duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60;

    ok("Start is 1997-08-01 12:00:00 Z UTC",
       (0 == strcmp("1997-08-01 12:00:00 Z UTC", ictt_as_string(icalcomponent_get_dtstart(c)))));
    ok("End is 1997-08-01 13:30:00 Z UTC",
       (0 == strcmp("1997-08-01 13:30:00 Z UTC", ictt_as_string(icalcomponent_get_dtend(c)))));
    ok("Duration is 90 m", (duration == 90));

    icalcomponent_free(c);

    c = icalcomponent_vanew(
	ICAL_VCALENDAR_COMPONENT,
	icalcomponent_vanew(
	    ICAL_VEVENT_COMPONENT,
	    0
	    ),
    0);

    tt = icaltime_from_string("19970801T120000");
    icaltime_set_timezone(&tt,
	icaltimezone_get_builtin_timezone("Europe/Rome"));
    icalcomponent_set_dtstart(c,tt);

    if (VERBOSE) printf("\n%s\n", icalcomponent_as_ical_string(c));

    icalcomponent_set_duration(c,icaldurationtype_from_string("PT1H30M"));
    duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60;

    ok("Start is 1997-08-01 12:00:00 /softwarestudio.org/Olson_20010626_2/Europe/Rome",
       (0 == strcmp("1997-08-01 12:00:00 /softwarestudio.org/Olson_20010626_2/Europe/Rome", ictt_as_string(icalcomponent_get_dtstart(c)))));
    ok("End is 1997-08-01 13:30:00 /softwarestudio.org/Olson_20010626_2/Europe/Rome",
       (0 == strcmp("1997-08-01 13:30:00 /softwarestudio.org/Olson_20010626_2/Europe/Rome", ictt_as_string(icalcomponent_get_dtend(c)))));
    ok("Duration is 90 m", (duration == 90));

    icalcomponent_free(c);
}

void test_time_parser()
{
    struct icaltimetype tt;

    icalerror_errors_are_fatal = 0;

    tt = icaltime_from_string("19970101T1000");
    ok("19970101T1000 is null time", icaltime_is_null_time(tt));

    tt = icaltime_from_string("19970101X100000");
    ok("19970101X100000 is null time", icaltime_is_null_time(tt));

    tt = icaltime_from_string("19970101T100000");
    ok("19970101T100000 is valid", !icaltime_is_null_time(tt));

    if (VERBOSE) printf("%s\n",icaltime_as_ctime(tt));

    tt = icaltime_from_string("19970101T100000Z");

    ok("19970101T100000Z is valid" , !icaltime_is_null_time(tt));
    if (VERBOSE) printf("%s\n",icaltime_as_ctime(tt));

    tt = icaltime_from_string("19970101");
    ok("19970101 is valid", (!icaltime_is_null_time(tt)));

    if (VERBOSE) printf("%s\n",icaltime_as_ctime(tt));

    icalerror_errors_are_fatal = 1;
}

void test_recur_parser()
{
  struct icalrecurrencetype rt; 
  char *str;

  str = "FREQ=YEARLY;UNTIL=20000131T090000Z;INTERVAL=1;BYDAY=-1TU,3WE,-4FR,SA,SU;BYYEARDAY=34,65,76,78;BYMONTH=1,2,3,4,8";
  rt = icalrecurrencetype_from_string(str);
  is(str, icalrecurrencetype_as_string(&rt), str);

  str = "FREQ=DAILY;COUNT=3;INTERVAL=1;BYDAY=-1TU,3WE,-4FR,SA,SU;BYYEARDAY=34,65,76,78;BYMONTH=1,2,3,4,8";
  
  rt = icalrecurrencetype_from_string(str);
  is(str, icalrecurrencetype_as_string(&rt), str);
}

char* ical_strstr(const char *haystack, const char *needle){
    return strstr(haystack,needle);
}

void test_start_of_week()
{
    struct icaltimetype tt2;
    struct icaltimetype tt1 = icaltime_from_string("19900110");
    int dow, doy,start_dow;

    do{
        tt1 = icaltime_normalize(tt1);

        doy = icaltime_start_doy_of_week(tt1);
        dow = icaltime_day_of_week(tt1);

        tt2 = icaltime_from_day_of_year(doy,tt1.year);
        start_dow = icaltime_day_of_week(tt2);

        if(doy == 1){
	  char msg[128];
	  sprintf(msg, "%s", ictt_as_string(tt1));
	  int_is(msg, start_dow, 1);
        }

        if(start_dow != 1){ /* Sunday is 1 */
            printf("failed: Start of week (%s) is not a Sunday \n for %s (doy=%d,dow=%d)\n",ictt_as_string(tt2), ictt_as_string(tt1),dow,start_dow);
        }


        assert(start_dow == 1);


        tt1.day+=1;
        
    } while(tt1.year < 2010);
}

void test_doy()
{
    struct icaltimetype tt1, tt2;
    short doy,doy2;
    char msg[128];

    doy = -1;

    tt1 = icaltime_from_string("19900101");

    if (VERBOSE) printf("Test icaltime_day_of_year() agreement with mktime\n");

    do{
        struct tm stm;

        tt1 = icaltime_normalize(tt1);

        stm.tm_sec = tt1.second;
        stm.tm_min = tt1.minute;
        stm.tm_hour = tt1.hour;
        stm.tm_mday = tt1.day;
        stm.tm_mon = tt1.month-1;
        stm.tm_year = tt1.year-1900;
        stm.tm_isdst = -1;

        mktime(&stm);

        doy = icaltime_day_of_year(tt1);

        doy2 = stm.tm_yday+1;

	if (doy == 1) {
	  /** show some test cases **/
	  sprintf(msg, "Year %d - mktime() compare", tt1.year);
	  int_is(msg, doy,doy2);
	}

        if (doy != doy2){
	  printf("Failed for %s (%d,%d)\n",ictt_as_string(tt1),doy,doy2);
        }
	assert(doy == doy2);

        tt1.day+=1;
        
    } while(tt1.year < 2010);
    
    if (VERBOSE) printf("\nTest icaltime_day_of_year() agreement with icaltime_from_day_of_year()\n");

    tt1 = icaltime_from_string("19900101");

    do{      
        if(doy == 1){
	  /** show some test cases **/
	  sprintf(msg, "Year %d - icaltime_day_of_year() compare", tt1.year);
	  int_is(msg, doy,doy2);
        }

        doy = icaltime_day_of_year(tt1);
        tt2 = icaltime_from_day_of_year(doy,tt1.year);
        doy2 = icaltime_day_of_year(tt2);

        assert(doy2 == doy);
        assert(icaltime_compare(tt1,tt2) == 0);

        tt1.day+=1;
        tt1 = icaltime_normalize(tt1);
        
    } while(tt1.year < 2010);


    tt1 = icaltime_from_string("19950301");
    doy = icaltime_day_of_year(tt1);
    tt2 = icaltime_from_day_of_year(doy,1995);
    if(VERBOSE) printf("%d %s %s\n",doy, icaltime_as_ctime(tt1),icaltime_as_ctime(tt2));

    ok("test 19950301", (tt2.day == 1 && tt2.month == 3));
    ok("day of year == 60", (doy == 60));

    tt1 = icaltime_from_string("19960301");
    doy = icaltime_day_of_year(tt1);
    tt2 = icaltime_from_day_of_year(doy,1996);
    if (VERBOSE) printf("%d %s %s\n",doy, icaltime_as_ctime(tt1),icaltime_as_ctime(tt2));
    ok("test 19960301", (tt2.day == 1 && tt2.month == 3));
    ok("day of year == 61", (doy == 61));

    tt1 = icaltime_from_string("19970301");
    doy = icaltime_day_of_year(tt1);
    tt2 = icaltime_from_day_of_year(doy,1997);
    if (VERBOSE) printf("%d %s %s\n",doy, icaltime_as_ctime(tt1),icaltime_as_ctime(tt2));

    ok("test 19970301", (tt2.day == 1 && tt2.month == 3));
    ok("day of year == 60", (doy == 60));

}

void test_x(){

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
 
#include <stdio.h>
#include <stdlib.h>
#include <libical/ical.h>
 
    static const char test_icalcomp_str[] =
"BEGIN:VEVENT\r\n"
"RRULE\r\n"
" ;X-EVOLUTION-ENDDATE=20030209T081500\r\n"
" :FREQ=DAILY;COUNT=10;INTERVAL=6\r\n"
"X-COMMENT;X-FOO=BAR: Booga\r\n"
"END:VEVENT\r\n";
  
    icalcomponent *icalcomp;
    icalproperty *prop;
    struct icalrecurrencetype recur;
    int n_errors;
    
    icalcomp = icalparser_parse_string ((char *) test_icalcomp_str);
    assert(icalcomp!=NULL);
    
    if (VERBOSE) printf("%s\n\n",icalcomponent_as_ical_string(icalcomp));

    n_errors = icalcomponent_count_errors (icalcomp);
    int_is("icalparser_parse_string()", n_errors,0);

    if (n_errors) {
      /** NOT USED **/
	icalproperty *p;
	
	for (p = icalcomponent_get_first_property (icalcomp,
						   ICAL_XLICERROR_PROPERTY);
	     p;
	     p = icalcomponent_get_next_property (icalcomp,
						  ICAL_XLICERROR_PROPERTY)) {
	    const char *str;
	    
	    str = icalproperty_as_ical_string (p);
	    fprintf (stderr, "error: %s\n", str);
	}
    }
    
    prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
    ok("get RRULE property", (prop != NULL));
    assert(prop!=NULL);
    
    recur = icalproperty_get_rrule (prop);
    
    if (VERBOSE) printf("%s\n",icalrecurrencetype_as_string(&recur));

    icalcomponent_free(icalcomp);

}

void test_gauge_sql() {
    icalgauge *g;
    char* str;
    
    str= "SELECT DTSTART,DTEND,COMMENT FROM VEVENT,VTODO WHERE VEVENT.SUMMARY = 'Bongoa' AND SEQUENCE < 5";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=NULL));
    if (VERBOSE) icalgauge_dump(g);

    icalgauge_free(g);

    str="SELECT * FROM VEVENT,VTODO WHERE VEVENT.SUMMARY = 'Bongoa' AND SEQUENCE < 5 OR METHOD != 'CREATE'";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=NULL));
    if (VERBOSE) icalgauge_dump(g);

    icalgauge_free(g);

    str="SELECT * FROM VEVENT WHERE SUMMARY == 'BA301'";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=NULL));    
    if (VERBOSE) icalgauge_dump(g);

    icalgauge_free(g);

    str="SELECT * FROM VEVENT WHERE SUMMARY == 'BA301'";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=NULL));    
    if (VERBOSE) icalgauge_dump(g);

    icalgauge_free(g);

    str="SELECT * FROM VEVENT WHERE LOCATION == '104 Forum'";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=NULL));    
    if (VERBOSE) icalgauge_dump(g);

    icalgauge_free(g);
}


void test_gauge_compare() {
    icalgauge *g;
    icalcomponent *c;
    char* str;

    /* Equality */

    c =  icalcomponent_vanew(ICAL_VCALENDAR_COMPONENT,
	      icalcomponent_vanew(ICAL_VEVENT_COMPONENT,
		  icalproperty_new_dtstart(
		      icaltime_from_string("20000101T000002")),0),0);

    g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART = '20000101T000002'", 0);

    ok("SELECT * FROM VEVENT WHERE DTSTART = '20000101T000002'", (c!=0 && g!=0));
    assert(c!=0);
    assert(g!=0);

    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);


    g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART = '20000101T000001'", 0);

    ok("SELECT * FROM VEVENT WHERE DTSTART = '20000101T000001'\n", (g!=0));

    assert(g!=0);
    int_is("compare",icalgauge_compare(g,c), 0);

    icalgauge_free(g);

    g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART != '20000101T000003'", 0);

    ok("SELECT * FROM VEVENT WHERE DTSTART != '20000101T000003'\n", (c!=0 && g!=0));


    assert(g!=0);
    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);


    /* Less than */

    g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART < '20000101T000003'", 0);

    ok("SELECT * FROM VEVENT WHERE DTSTART < '20000101T000003'", (c!=0 && g!=0));

    int_is("compare",icalgauge_compare(g,c), 1);

    assert(g!=0);
    icalgauge_free(g);

    g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART < '20000101T000002'", 0);

    ok("SELECT * FROM VEVENT WHERE DTSTART < '20000101T000002'\n", (g!=0));


    assert(g!=0);
    int_is("compare",icalgauge_compare(g,c), 0);

    icalgauge_free(g);

    /* Greater than */

    g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART > '20000101T000001'", 0);

    ok("SELECT * FROM VEVENT WHERE DTSTART > '20000101T000001'\n", (g!=0));


    assert(g!=0);
    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);

    g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART > '20000101T000002'", 0);

    ok("SELECT * FROM VEVENT WHERE DTSTART > '20000101T000002'\n", (g!=0));


    assert(g!=0);
    int_is("compare",icalgauge_compare(g,c), 0);


    icalgauge_free(g);


    /* Greater than or Equal to */

    g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART >= '20000101T000002'", 0);

    ok("SELECT * FROM VEVENT WHERE DTSTART >= '20000101T000002'\n", (g!=0));


    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);

    g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART >= '20000101T000003'", 0);

    ok("SELECT * FROM VEVENT WHERE DTSTART >= '20000101T000003'\n", (g!=0));


    int_is("compare",icalgauge_compare(g,c), 0);

    icalgauge_free(g);

    /* Less than or Equal to */

    g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART <= '20000101T000002'", 0);

    ok("SELECT * FROM VEVENT WHERE DTSTART <= '20000101T000002'\n", (g!=0));


    assert(g!=0);
    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);

    g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART <= '20000101T000001'", 0);

    ok("SELECT * FROM VEVENT WHERE DTSTART <= '20000101T000001'\n", (g!=0));


    int_is("compare",icalgauge_compare(g,c), 0);

    icalgauge_free(g);

    icalcomponent_free(c);

    /* Combinations */

    c =  icalcomponent_vanew(ICAL_VCALENDAR_COMPONENT,
	      icalcomponent_vanew(ICAL_VEVENT_COMPONENT,
		  icalproperty_new_dtstart(
		      icaltime_from_string("20000102T000000")),0),0);


    str =  "SELECT * FROM VEVENT WHERE DTSTART > '20000101T000000' and DTSTART < '20000103T000000'";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=0));
    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);

    str =  "SELECT * FROM VEVENT WHERE DTSTART > '20000101T000000' and DTSTART < '20000102T000000'";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=0));
    int_is("compare",icalgauge_compare(g,c), 0);

    icalgauge_free(g);

    str =  "SELECT * FROM VEVENT WHERE DTSTART > '20000101T000000' or DTSTART < '20000102T000000'";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=0));
    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);


    icalcomponent_free(c);

    /* Combinations, non-cannonical component */

    c = icalcomponent_vanew(ICAL_VEVENT_COMPONENT,
		  icalproperty_new_dtstart(
		      icaltime_from_string("20000102T000000")),0);


    str =  "SELECT * FROM VEVENT WHERE DTSTART > '20000101T000000' and DTSTART < '20000103T000000'";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=0));
    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);

    str =  "SELECT * FROM VEVENT WHERE DTSTART > '20000101T000000' and DTSTART < '20000102T000000'";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=0));
    int_is("compare",icalgauge_compare(g,c), 0);

    icalgauge_free(g);

    str =  "SELECT * FROM VEVENT WHERE DTSTART > '20000101T000000' or DTSTART < '20000102T000000'";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=0));
    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);
    icalcomponent_free(c);


    /* Complex comparisions */

    c =  icalcomponent_vanew(
	ICAL_VCALENDAR_COMPONENT,
	icalproperty_new_method(ICAL_METHOD_REQUEST),
	icalcomponent_vanew(
	    ICAL_VEVENT_COMPONENT,
	    icalproperty_new_dtstart(
		icaltime_from_string("20000101T000002")),
	    icalproperty_new_comment("foo"),
	    icalcomponent_vanew(
		ICAL_VALARM_COMPONENT,
		icalproperty_new_dtstart(
		    icaltime_from_string("20000101T120000")),
		
		0),
	    0),
	0);
    
    
    str = "SELECT * FROM VEVENT WHERE VALARM.DTSTART = '20000101T120000'";

    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=0));
    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);

    str = "SELECT * FROM VEVENT WHERE COMMENT = 'foo'";
    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=0));
    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);
	
    str = "SELECT * FROM VEVENT WHERE COMMENT = 'foo' AND  VALARM.DTSTART = '20000101T120000'";
    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=0));
    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);

    str = "SELECT * FROM VEVENT WHERE COMMENT = 'bar' AND  VALARM.DTSTART = '20000101T120000'";
    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=0));
    int_is("compare",icalgauge_compare(g,c), 0);

    icalgauge_free(g);

    str = "SELECT * FROM VEVENT WHERE COMMENT = 'bar' or  VALARM.DTSTART = '20000101T120000'";
    g = icalgauge_new_from_sql(str, 0);
    ok(str, (g!=0));
    int_is("compare",icalgauge_compare(g,c), 1);

    icalgauge_free(g);

    icalcomponent_free(c);

}

icalcomponent* make_component(int i){

    icalcomponent *c;

    struct icaltimetype t = icaltime_from_string("20000101T120000Z");

    t.day += i;

    icaltime_normalize(t);

    c =  icalcomponent_vanew(
	ICAL_VCALENDAR_COMPONENT,
	icalproperty_new_method(ICAL_METHOD_REQUEST),
	icalcomponent_vanew(
	    ICAL_VEVENT_COMPONENT,
	    icalproperty_new_dtstart(t),
	    0),
	0);

    assert(c != 0);

    return c;

}
void test_fileset()
{
    icalset *fs;
    icalcomponent *c;
    int i;
    int comp_count = 0;
    char *path = "test_fileset.ics";
    icalgauge  *g = icalgauge_new_from_sql(
	"SELECT * FROM VEVENT WHERE DTSTART > '20000103T120000Z' AND DTSTART <= '20000106T120000Z'", 0);

    ok("icalgauge_new_from_sql()", (g!=NULL));

    unlink(path);

    fs = icalfileset_new(path);
    
    ok("icalfileset_new()", (fs!=NULL));
    assert(fs != 0);

    for (i = 0; i!= 10; i++){
	c = make_component(i);
	icalfileset_add_component(fs,c);
    }

    icalfileset_commit(fs);

    icalset_free(fs);
    /** reopen fileset.ics **/
    fs = icalfileset_new(path);

    if (VERBOSE) printf("== No Selections \n");

    comp_count = 0;
    for (c = icalfileset_get_first_component(fs);
	 c != 0;
	 c = icalfileset_get_next_component(fs)){
	struct icaltimetype t = icalcomponent_get_dtstart(c);
	comp_count++;
	if (VERBOSE) printf("%s\n",icaltime_as_ctime(t));
    }
    int_is("icalfileset get components",comp_count, 10);

    icalfileset_select(fs,g);

    if (VERBOSE) printf("\n== DTSTART > '20000103T120000Z' AND DTSTART <= '20000106T120000Z' \n");

    comp_count = 0;
    for (c = icalfileset_get_first_component(fs);
	 c != 0;
	 c = icalfileset_get_next_component(fs)){
	struct icaltimetype t = icalcomponent_get_dtstart(c);
	comp_count++;
	if (VERBOSE) printf("%s\n",icaltime_as_ctime(t));
    }
    int_is("icalfileset get components with gauge",comp_count, 3);

    icalset_free(fs);

	/*icalgauge_free(g);*/
    
}

void microsleep(int us)
{
#ifndef WIN32
    struct timeval tv;

    tv.tv_sec = 0;
    tv.tv_usec = us;

    select(0,0,0,0,&tv);
#else
	Sleep(us);
#endif
}


void test_file_locks()
{
#ifndef WIN32
    pid_t pid;
    char *path = "test_fileset_locktest.ics";
    icalset *fs;
    icalcomponent *c, *c2;
    struct icaldurationtype d;
    int i;
    int final,sec;

    icalerror_clear_errno();

    unlink(path);

    fs = icalfileset_new(path);

    if(icalfileset_get_first_component(fs)==0){
	c = make_component(0);
	
	d = icaldurationtype_from_int(1);
	
	icalcomponent_set_duration(c,d);
	
	icalfileset_add_component(fs,c);
	
	c2 = icalcomponent_new_clone(c);
	
	icalfileset_add_component(fs,c2);
	
	icalfileset_commit(fs);
    }
    
    icalset_free(fs);
    
    assert(icalerrno == ICAL_NO_ERROR);
    
    pid = fork();
    
    assert(pid >= 0);
    
    if(pid == 0){
	/*child*/
	int i;

	microsleep(rand()/(RAND_MAX/100));

	for(i = 0; i< 50; i++){
	    fs = icalfileset_new(path);


	    assert(fs != 0);

	    c = icalfileset_get_first_component(fs);

	    assert(c!=0);
	   
	    d = icalcomponent_get_duration(c);
	    d = icaldurationtype_from_int(icaldurationtype_as_int(d)+1);
	    
	    icalcomponent_set_duration(c,d);
	    icalcomponent_set_summary(c,"Child");	  
  
	    c2 = icalcomponent_new_clone(c);
	    icalcomponent_set_summary(c2,"Child");
	    icalfileset_add_component(fs,c2);

	    icalfileset_mark(fs);
	    icalfileset_commit(fs);

	    icalset_free(fs);

	    microsleep(rand()/(RAND_MAX/20));


	}

	exit(0);

    } else {
	/* parent */
	int i;
	
	for(i = 0; i< 50; i++){
	    fs = icalfileset_new(path);

	    assert(fs != 0);

	    c = icalfileset_get_first_component(fs);
	    
	    assert(c!=0);

	    d = icalcomponent_get_duration(c);
	    d = icaldurationtype_from_int(icaldurationtype_as_int(d)+1);
	    
	    icalcomponent_set_duration(c,d);
	    icalcomponent_set_summary(c,"Parent");

	    c2 = icalcomponent_new_clone(c);
	    icalcomponent_set_summary(c2,"Parent");
	    icalfileset_add_component(fs,c2);

	    icalfileset_mark(fs);
	    icalfileset_commit(fs);
	    icalset_free(fs);

	    putc('.',stdout);
	    fflush(stdout);

	}
    }

    assert(waitpid(pid,0,0)==pid);
	

    fs = icalfileset_new(path);
    
    i=1;

    c = icalfileset_get_first_component(fs);
    final = icaldurationtype_as_int(icalcomponent_get_duration(c));
    for (c = icalfileset_get_next_component(fs);
	 c != 0;
	 c = icalfileset_get_next_component(fs)){
	struct icaldurationtype d = icalcomponent_get_duration(c);
	sec = icaldurationtype_as_int(d);

	/*printf("%d,%d ",i,sec);*/
	assert(i == sec);
	i++;
    }

    printf("\nFinal: %d\n",final);

    
    assert(sec == final);
#endif
}

void test_action()
{
    icalcomponent *c;
    icalproperty *p;
    char *str;

    static const char test_icalcomp_str[] =
"BEGIN:VEVENT\n"
"ACTION:EMAIL\n"
"ACTION:PROCEDURE\n"
"ACTION:AUDIO\n"
"ACTION:FUBAR\n"
"END:VEVENT\n";

     
    c = icalparser_parse_string ((char *) test_icalcomp_str);

    ok("icalparser_parse_string(), ACTIONS", (c!=NULL));
    assert(c!=0);
    
    str = icalcomponent_as_ical_string(c);
    is("icalcomponent_as_ical_string()", str, ((char*) test_icalcomp_str));
    if (VERBOSE) printf("%s\n\n",str);

    p = icalcomponent_get_first_property(c,ICAL_ACTION_PROPERTY);

    ok("ICAL_ACTION_EMAIL", (icalproperty_get_action(p) == ICAL_ACTION_EMAIL));

    p = icalcomponent_get_next_property(c,ICAL_ACTION_PROPERTY);

    ok("ICAL_ACTION_PROCEDURE", (icalproperty_get_action(p) == ICAL_ACTION_PROCEDURE));

    p = icalcomponent_get_next_property(c,ICAL_ACTION_PROPERTY);

    ok("ICAL_ACTION_AUDIO", (icalproperty_get_action(p) == ICAL_ACTION_AUDIO));

    p = icalcomponent_get_next_property(c,ICAL_ACTION_PROPERTY);

    ok("ICAL_ACTION_X", (icalproperty_get_action(p) == ICAL_ACTION_X));
    is("ICAL_ACTION -> FUBAR", icalvalue_get_x(icalproperty_get_value(p)), "FUBAR");
    icalcomponent_free(c);
}

        

void test_trigger()
{

    struct icaltriggertype tr;
    icalcomponent *c;
    icalproperty *p;
    const char* str;
    
    static const char test_icalcomp_str[] =
"BEGIN:VEVENT\n"
"TRIGGER;VALUE=DATE-TIME:19980403T120000\n"
"TRIGGER;VALUE=DURATION:-PT15M\n"
"TRIGGER;VALUE=DATE-TIME:19980403T120000\n"
"TRIGGER;VALUE=DURATION:-PT15M\n"
"END:VEVENT\n";
  
    
    c = icalparser_parse_string ((char *) test_icalcomp_str);
    ok("icalparser_parse_string()", (c!= NULL));
    assert(c!=NULL);
    
    is("parsed triggers", icalcomponent_as_ical_string(c), (char*)test_icalcomp_str);

    for(p = icalcomponent_get_first_property(c,ICAL_TRIGGER_PROPERTY);
	p != 0;
	p = icalcomponent_get_next_property(c,ICAL_TRIGGER_PROPERTY)){
	tr = icalproperty_get_trigger(p);

	if(!icaltime_is_null_time(tr.time)){
	  if (VERBOSE) printf("value=DATE-TIME:%s\n", icaltime_as_ical_string(tr.time));
	} else {
	  if (VERBOSE) printf("value=DURATION:%s\n", icaldurationtype_as_ical_string(tr.duration));
	}   
    }

    icalcomponent_free(c);

    /* Trigger, as a DATETIME */
    tr.duration = icaldurationtype_null_duration();
    tr.time = icaltime_from_string("19970101T120000");
    p = icalproperty_new_trigger(tr);
    str = icalproperty_as_ical_string(p);

    is("TRIGGER;VALUE=DATE-TIME:19970101T120000", str, "TRIGGER;VALUE=DATE-TIME:19970101T120000\n");
    icalproperty_free(p);

    /* TRIGGER, as a DURATION */
    tr.time = icaltime_null_time();
    tr.duration = icaldurationtype_from_string("P3DT3H50M45S");
    p = icalproperty_new_trigger(tr);
    str = icalproperty_as_ical_string(p);
    
    is("TRIGGER;VALUE=DURATION:P3DT3H50M45S", str, "TRIGGER;VALUE=DURATION:P3DT3H50M45S\n");
    icalproperty_free(p);

    /* TRIGGER, as a DATETIME, VALUE=DATETIME*/
    tr.duration = icaldurationtype_null_duration();
    tr.time = icaltime_from_string("19970101T120000");
    p = icalproperty_new_trigger(tr);
    icalproperty_add_parameter(p,icalparameter_new_value( ICAL_VALUE_DATETIME));
    str = icalproperty_as_ical_string(p);

    is("TRIGGER;VALUE=DATE-TIME:19970101T120000", str, "TRIGGER;VALUE=DATE-TIME:19970101T120000\n");
    icalproperty_free(p);

    /*TRIGGER, as a DURATION, VALUE=DATETIME */
    tr.time = icaltime_null_time();
    tr.duration = icaldurationtype_from_string("P3DT3H50M45S");
    p = icalproperty_new_trigger(tr);
    icalproperty_add_parameter(p,icalparameter_new_value( ICAL_VALUE_DATETIME ));

    str = icalproperty_as_ical_string(p);
    
    is("TRIGGER;VALUE=DURATION:P3DT3H50M45S", str, "TRIGGER;VALUE=DURATION:P3DT3H50M45S\n");
    icalproperty_free(p);

    /* TRIGGER, as a DATETIME, VALUE=DURATION*/
    tr.duration = icaldurationtype_null_duration();
    tr.time = icaltime_from_string("19970101T120000");
    p = icalproperty_new_trigger(tr);
    icalproperty_add_parameter(p,icalparameter_new_value( ICAL_VALUE_DURATION));
    str = icalproperty_as_ical_string(p);

    is("TRIGGER;VALUE=DATE-TIME:19970101T120000", str, "TRIGGER;VALUE=DATE-TIME:19970101T120000\n");
    icalproperty_free(p);

    /*TRIGGER, as a DURATION, VALUE=DURATION */
    tr.time = icaltime_null_time();
    tr.duration = icaldurationtype_from_string("P3DT3H50M45S");
    p = icalproperty_new_trigger(tr);
    icalproperty_add_parameter(p,icalparameter_new_value( ICAL_VALUE_DURATION));

    str = icalproperty_as_ical_string(p);
    
    is("TRIGGER;VALUE=DURATION:P3DT3H50M45S", str, "TRIGGER;VALUE=DURATION:P3DT3H50M45S\n");
    icalproperty_free(p);


   /* TRIGGER, as a DATETIME, VALUE=BINARY  */
    tr.duration = icaldurationtype_null_duration();
    tr.time = icaltime_from_string("19970101T120000");
    p = icalproperty_new_trigger(tr);
    icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_BINARY));
    str = icalproperty_as_ical_string(p);

    is("TRIGGER;VALUE=DATE-TIME:19970101T120000", str, "TRIGGER;VALUE=DATE-TIME:19970101T120000\n");
    icalproperty_free(p);

    /*TRIGGER, as a DURATION, VALUE=BINARY   */
    tr.time = icaltime_null_time();
    tr.duration = icaldurationtype_from_string("P3DT3H50M45S");
    p = icalproperty_new_trigger(tr);
    icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_BINARY));

    str = icalproperty_as_ical_string(p);
    
    is("TRIGGER;VALUE=DURATION:P3DT3H50M45S", str, "TRIGGER;VALUE=DURATION:P3DT3H50M45S\n");
    icalproperty_free(p);
}


void test_rdate()
{

    struct icaldatetimeperiodtype dtp;
    icalproperty *p;
    const char* str;
    struct icalperiodtype period;

    period.start = icaltime_from_string("19970101T120000");
    period.end = icaltime_null_time();
    period.duration = icaldurationtype_from_string("PT3H10M15S");

    /* RDATE, as DATE-TIME */
    dtp.time = icaltime_from_string("19970101T120000");
    dtp.period = icalperiodtype_null_period();
    p = icalproperty_new_rdate(dtp);
    str = icalproperty_as_ical_string(p);

    is("RDATE as DATE-TIME",
       "RDATE;VALUE=DATE-TIME:19970101T120000\n",str);
    icalproperty_free(p); 

    /* RDATE, as PERIOD */
    dtp.time = icaltime_null_time();
    dtp.period = period;
    p = icalproperty_new_rdate(dtp);

    str = icalproperty_as_ical_string(p);
    is("RDATE, as PERIOD", "RDATE;VALUE=PERIOD:19970101T120000/PT3H10M15S\n",str);
    icalproperty_free(p); 

    /* RDATE, as DATE-TIME, VALUE=DATE-TIME */
    dtp.time = icaltime_from_string("19970101T120000");
    dtp.period = icalperiodtype_null_period();
    p = icalproperty_new_rdate(dtp);
    icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_DATETIME));
    str = icalproperty_as_ical_string(p);

    is("RDATE, as DATE-TIME, VALUE=DATE-TIME",
       "RDATE;VALUE=DATE-TIME:19970101T120000\n",str);
    icalproperty_free(p); 


    /* RDATE, as PERIOD, VALUE=DATE-TIME */
    dtp.time = icaltime_null_time();
    dtp.period = period;
    p = icalproperty_new_rdate(dtp);
    icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_DATETIME));
    str = icalproperty_as_ical_string(p);
    is("RDATE, as PERIOD, VALUE=DATE-TIME",
       "RDATE;VALUE=PERIOD:19970101T120000/PT3H10M15S\n",str);
    icalproperty_free(p); 


    /* RDATE, as DATE-TIME, VALUE=PERIOD */
    dtp.time = icaltime_from_string("19970101T120000");
    dtp.period = icalperiodtype_null_period();
    p = icalproperty_new_rdate(dtp);
    icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_PERIOD));
    str = icalproperty_as_ical_string(p);

    is("RDATE, as DATE-TIME, VALUE=PERIOD",
       "RDATE;VALUE=DATE-TIME:19970101T120000\n",str);
    icalproperty_free(p); 


    /* RDATE, as PERIOD, VALUE=PERIOD */
    dtp.time = icaltime_null_time();
    dtp.period = period;
    p = icalproperty_new_rdate(dtp);
    icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_PERIOD));
    str = icalproperty_as_ical_string(p);

    is("RDATE, as PERIOD, VALUE=PERIOD",
       "RDATE;VALUE=PERIOD:19970101T120000/PT3H10M15S\n",str);
    icalproperty_free(p); 


    /* RDATE, as DATE-TIME, VALUE=BINARY */
    dtp.time = icaltime_from_string("19970101T120000");
    dtp.period = icalperiodtype_null_period();
    p = icalproperty_new_rdate(dtp);
    icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_BINARY));
    str = icalproperty_as_ical_string(p);
    
    is("RDATE, as DATE-TIME, VALUE=BINARY",
       "RDATE;VALUE=DATE-TIME:19970101T120000\n",str);
    icalproperty_free(p); 


    /* RDATE, as PERIOD, VALUE=BINARY */
    dtp.time = icaltime_null_time();
    dtp.period = period;
    p = icalproperty_new_rdate(dtp);
    icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_BINARY));
    str = icalproperty_as_ical_string(p);

    is("RDAE, as PERIOD, VALUE=BINARY",
       "RDATE;VALUE=PERIOD:19970101T120000/PT3H10M15S\n",str);
    icalproperty_free(p); 
}


void test_langbind()
{
    icalcomponent *c, *inner; 
    icalproperty *p;
    char *test_str_parsed;
    static const char test_str[] =
"BEGIN:VEVENT\n"
"ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:MAILTO:employee-A@host.com\n"
"COMMENT: Comment that \n spans a line\n"
"COMMENT: Comment with \"quotable\" \'characters\' and other \t bad magic \n things \f Yeah.\n"
"DTSTART:19970101T120000\n"
"DTSTART:19970101T120000Z\n"
"DTSTART:19970101\n"
"DURATION:P3DT4H25M\n"
"FREEBUSY:19970101T120000/19970101T120000\n"
"FREEBUSY:19970101T120000/P3DT4H25M\n"
"END:VEVENT\n";

    static const char *test_str_parsed_good = 
"BEGIN:VEVENT\n"
"ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:MAILTO:\n"
" employee-A@host.com\n"
"COMMENT: Comment that spans a line\n"
"COMMENT: Comment with \\\"quotable\\\" 'characters' and other \\t bad magic \n"
" things \\f Yeah.\n"
"DTSTART:19970101T120000\n"
"DTSTART:19970101T120000Z\n"
"DTSTART;VALUE=DATE:19970101\n"
"DURATION:P3DT4H25M\n"
"FREEBUSY:19970101T120000/19970101T120000\n"
"FREEBUSY:19970101T120000/P3DT4H25M\n"
"END:VEVENT\n";

    if (VERBOSE) printf("%s\n",test_str);

    c = icalparser_parse_string(test_str);

    ok("icalparser_parse_string()", (c!=NULL));
    assert(c != NULL);

    test_str_parsed = icalcomponent_as_ical_string(c);

    is("parsed version with bad chars, etc",
       test_str_parsed,
       test_str_parsed_good);

    
    inner = icalcomponent_get_inner(c);

    for(
	p = icallangbind_get_first_property(inner,"ANY");
	p != 0;
	p = icallangbind_get_next_property(inner,"ANY")
	) { 

      const char *str = icallangbind_property_eval_string(p,":");
      /** TODO add tests **/
      if (VERBOSE) printf("%s\n",str);
    }


    p = icalcomponent_get_first_property(inner,ICAL_ATTENDEE_PROPERTY);

    icalproperty_set_parameter_from_string(p,"CUTYPE","INDIVIDUAL");

    is ("Set attendee parameter",
	icalproperty_as_ical_string(p),
	"ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=INDIVIDUAL:MAILTO:\n"
	" employee-A@host.com\n");
 
    icalproperty_set_value_from_string(p,"mary@foo.org","TEXT");

    is ("Set attendee parameter value",
	icalproperty_as_ical_string(p),
	"ATTENDEE;VALUE=TEXT;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=INDIVIDUAL:\n"
" mary@foo.org\n");

	icalcomponent_free(c);
}

void test_property_parse()
{
    icalproperty *p;
    const char *str;

    p= icalproperty_new_from_string(
                         "ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:MAILTO:employee-A@host.com");

    ok("icalproperty_from_string(), ATTENDEE", (p != 0));
    assert (p !=  0);

    str = icalproperty_as_ical_string(p);
    if (VERBOSE) printf("%s\n",str);

    icalproperty_free(p);

    p= icalproperty_new_from_string("DTSTART:19970101T120000Z\n");

    ok("icalproperty_from_string(), simple DTSTART", (p != 0));
    assert (p !=  0);

    str = icalproperty_as_ical_string(p);
    if (VERBOSE) printf("%s\n",str);
    
    icalproperty_free(p);

}


void test_value_parameter() 
{

    icalcomponent *c;
    icalproperty *p;
    icalparameter *param;
    
    static const char test_icalcomp_str[] =
"BEGIN:VEVENT\n"
"DTSTART;VALUE=DATE-TIME:19971123T123000\n"
"DTSTART;VALUE=DATE:19971123\n"
"DTSTART;VALUE=FOO:19971123T123000\n"
"END:VEVENT\n";
     
    c = icalparser_parse_string ((char *) test_icalcomp_str);
    ok("icalparser_parse_string()", (c != NULL));
    if (!c) {
	exit (EXIT_FAILURE);
    }

    if (VERBOSE) printf("%s",icalcomponent_as_ical_string(c));

    p = icalcomponent_get_first_property(c,ICAL_DTSTART_PROPERTY);
    param = icalproperty_get_first_parameter(p,ICAL_VALUE_PARAMETER);
    
    ok("icalproperty_get_value()", (icalparameter_get_value(param) == ICAL_VALUE_DATETIME));

    p = icalcomponent_get_next_property(c,ICAL_DTSTART_PROPERTY);
    param = icalproperty_get_first_parameter(p,ICAL_VALUE_PARAMETER);
    ok("icalproperty_get_first_parameter()",(icalparameter_get_value(param) == ICAL_VALUE_DATE));

    icalcomponent_free(c);
}


void test_x_parameter()
{
    icalproperty *p;

    p= icalproperty_new_from_string(
       "COMMENT;X-A=1;X-B=2: This is a note");

    if (VERBOSE) printf("%s\n",icalproperty_as_ical_string(p));

    ok("COMMENT property",(icalproperty_isa(p) == ICAL_COMMENT_PROPERTY));
    is("COMMENT parses param", icalproperty_get_comment(p)," This is a note");

    icalproperty_set_parameter_from_string(p,"X-LIES", "no");
    icalproperty_set_parameter_from_string(p,"X-LAUGHS", "big");
    icalproperty_set_parameter_from_string(p,"X-TRUTH", "yes");
    icalproperty_set_parameter_from_string(p,"X-HUMOUR", "bad");

    if (VERBOSE) printf("%s\n",icalproperty_as_ical_string(p));

    is("Check X-LIES", icalproperty_get_parameter_as_string(p, "X-LIES"), "no");
    is("Check X-LAUGHS", icalproperty_get_parameter_as_string(p, "X-LAUGHS"), "big");
    is("Check X-TRUTH", icalproperty_get_parameter_as_string(p, "X-TRUTH"), "yes");
    is("Check X-HUMOUR", icalproperty_get_parameter_as_string(p, "X-HUMOUR"), "bad");

    icalproperty_free(p);
}



void test_x_property() 
{
    icalproperty *p;
    
    p= icalproperty_new_from_string(
       "X-LIC-PROPERTY: This is a note");

    if (VERBOSE && p) printf("%s\n",icalproperty_as_ical_string(p));

    ok("x-property is correct kind",(icalproperty_isa(p) == ICAL_X_PROPERTY));
    is("icalproperty_get_x_name() works",
       icalproperty_get_x_name(p),"X-LIC-PROPERTY");
    is("icalproperty_get_x() works",
       icalproperty_get_x(p)," This is a note");

    icalproperty_free(p);
}

void test_utcoffset()
{
    icalproperty *p;

    p = icalproperty_new_from_string("TZOFFSETFROM:-001608");
    ok("parse TZOOFSETFROM:-001608", (p!=NULL));

    if (VERBOSE && p) printf("%s\n",icalproperty_as_ical_string(p));

    if (p) icalproperty_free(p);
}

void test_attach()
{
    icalcomponent *c;

    static const char test_icalcomp_str[] =
"BEGIN:VEVENT\n"
"ATTACH:CID:jsmith.part3.960817T083000.xyzMain@host1.com\n"
"ATTACH:FMTTYPE=application/postscript;ftp://xyzCorp.com/pub/reports/r-960812.ps\n"
"END:VEVENT\n";

    c = icalparser_parse_string ((char *) test_icalcomp_str);
    ok("parse simple attachment", (c != NULL));

    if (VERBOSE) printf("%s",icalcomponent_as_ical_string(c));

    if (c) icalcomponent_free(c);
}


void test_vcal(void)
{
  VObject *vcal = 0;
  icalcomponent *comp;
  char* file = TEST_DATADIR "/user-cal.vcf";

  vcal = Parse_MIME_FromFileName(file);
    
  ok("Parsing " TEST_DATADIR "/user-cal.vcf", (vcal != 0));

  comp = icalvcal_convert(vcal);

  ok("Converting to ical component", (comp != 0));
  
  if (VERBOSE && comp)
    printf("%s\n",icalcomponent_as_ical_string(comp));

  if (comp) icalcomponent_free(comp);
  if (vcal) deleteVObject(vcal);
}

int main(int argc, char *argv[])
{
    int c;
    extern char *optarg;
    extern int optopt;
    int errflg=0;
    char* program_name = strrchr(argv[0],'/');
    int do_test = 0;
    int do_header = 0;

    set_zone_directory("../../zoneinfo");
    putenv("TZ=");

    test_start(0);


#ifndef WIN32
    while ((c = getopt(argc, argv, "lvq")) != -1) {
      switch (c) {
      case 'v': {
	VERBOSE = 1;
	break;
      }
      case 'q': {
	QUIET = 1;
	break;
      }
      case 'l': {
	do_header = 1;;
      }
      case '?': {
	errflg++;
      }
      }
    } 
    if (optind < argc) {
      do_test = atoi(argv[argc-1]);
    }
#else
    if (argc>1)
      do_test = atoi(argv[2]);

#endif
    
    
    test_run("Test time parser functions", test_time_parser, do_test, do_header);
    test_run("Test time", test_time, do_test, do_header);
    test_run("Test day of Year", test_doy, do_test, do_header);
    test_run("Test duration", test_duration, do_test, do_header);
    test_run("Test period",      test_period, do_test, do_header);
    test_run("Test DTSTART",      test_dtstart, do_test, do_header);
    test_run("Test day of year of week start",      test_start_of_week, do_test, do_header);
    test_run("Test recur parser",      test_recur_parser, do_test, do_header);
    test_run("Test recur", test_recur, do_test, do_header);
    test_run("Test Recurring Events File", test_recur_file, do_test, do_header);
    test_run("Test parameter bug", test_recur_parameter_bug, do_test, do_header);
    test_run("Test Array Expansion", test_expand_recurrence, do_test, do_header);
    test_run("Test Free/Busy lists", test_fblist, do_test, do_header);
    test_run("Test Overlaps", test_overlaps, do_test, do_header);
    
    test_run("Test Span", test_icalcomponent_get_span, do_test, do_header);
    test_run("Test Gauge SQL", test_gauge_sql, do_test, do_header);
    test_run("Test Gauge Compare", test_gauge_compare, do_test, do_header);
    test_run("Test File Set", test_fileset, do_test, do_header);
    test_run("Test File Set (Extended)", test_fileset_extended, do_test, do_header);
    test_run("Test Dir Set", test_dirset, do_test, do_header);
    test_run("Test Dir Set (Extended)", test_dirset_extended, do_test, do_header);
    
    test_run("Test File Locks", test_file_locks, do_test, do_header);
    test_run("Test X Props and Params", test_x, do_test, do_header);
    test_run("Test Trigger", test_trigger, do_test, do_header);
    test_run("Test Restriction", test_restriction, do_test, do_header);
    test_run("Test RDATE", test_rdate, do_test, do_header);
    test_run("Test language binding", test_langbind, do_test, do_header);
    test_run("Test property parser", test_property_parse, do_test, do_header);
    test_run("Test Action", test_action, do_test, do_header);
    test_run("Test Value Parameter", test_value_parameter, do_test, do_header);
    test_run("Test X property", test_x_property, do_test, do_header);
    test_run("Test X parameter", test_x_parameter, do_test, do_header);
    test_run("Test request status", test_requeststat, do_test, do_header);
    test_run("Test UTC-OFFSET", test_utcoffset, do_test, do_header);
    test_run("Test Values", test_values, do_test, do_header);
    test_run("Test Parameters", test_parameters, do_test, do_header);
    test_run("Test Properties", test_properties, do_test, do_header);
    test_run("Test Components", test_components, do_test, do_header);
    test_run("Test Convenience", test_convenience, do_test, do_header);
    test_run("Test classify ", test_classify, do_test, do_header);
    test_run("Test Iterators", test_iterators, do_test, do_header);
    test_run("Test strings", test_strings, do_test, do_header);
    test_run("Test Compare", test_compare, do_test, do_header);
    test_run("Create Simple Component", create_simple_component, do_test, do_header);
    test_run("Create Components", create_new_component, do_test, do_header);
    test_run("Create Components with vaargs", create_new_component_with_va_args, do_test, do_header);
    test_run("Test Memory", test_memory, do_test, do_header);
    test_run("Test Attachment", test_attach, do_test, do_header);
    test_run("Test icalcalendar", test_calendar, do_test, do_header);
    test_run("Test Dirset", test_dirset, do_test, do_header);
    test_run("Test vCal to iCal conversion", test_vcal, do_test, do_header);
    test_run("Test UTF-8 Handling", test_utf8, do_test, do_header);

    /** OPTIONAL TESTS go here... **/

#ifdef WITH_CXX_BINDINGS
    test_run("Test C++ API", test_cxx, do_test, do_header);
#endif

#ifdef WITH_BDB
    test_run("Test BDB Set", test_bdbset, do_test, do_header);
#endif


    icaltimezone_free_builtin_timezones();
    icalmemory_free_ring();
    free_zone_directory();

    test_end();

    return 0;
}


