Commit 99e80d6e authored by Not Zed's avatar Not Zed Committed by Michael Zucci

Add tests.

2000-11-24  Not Zed  <NotZed@HelixCode.com>

	* Makefile.am (SUBDIRS): Add tests.

	* camel-mime-filter-basic.c (filter): Well, I'll add the extra
	bytes here too, lathough not strictly needed, might save a
	re-malloc when we get to complete().

	* camel-mime-filter-charset.c (filter): Make sure we have room if
	we only convert very short data.
	(complete): and here too.

	* tests/Makefile.am: Initial test harness & tests.  Requires gcc
	for this.

	* camel-internet-address.c (d): Turn off debug.

	* camel-charset-map.c (camel_charset_step): Oops, & masks for set
	intersection, not | them.  Dunno how this got even close to
	working.

2000-11-23  Not Zed  <NotZed@HelixCode.com>

	* camel-mime-filter-basic.c (filter): For base64 encoding, the
	output size for 0, 1, or 2 bytes of input can exceed input*2, so
	make sure we account for that as well.
	(complete): And here.
	(complete): Similarly for qp encoding, if we have a trailing
	space, we need some extra bytes (not needed for 'filter()', as any
	such bytes are stored in state/save).

	* camel-mime-utils.c (quoted_decode_step): Removed fixme not required.
	(quoted_encode_close): Dont append a trailing afterall.  Otherwise
	a pass through the encode/decode will grow the message each time.

svn path=/trunk/; revision=6656
parent a7e18523
2000-11-24 Not Zed <NotZed@HelixCode.com>
* Makefile.am (SUBDIRS): Add tests.
* camel-mime-filter-basic.c (filter): Well, I'll add the extra
bytes here too, lathough not strictly needed, might save a
re-malloc when we get to complete().
* camel-mime-filter-charset.c (filter): Make sure we have room if
we only convert very short data.
(complete): and here too.
* tests/Makefile.am: Initial test harness & tests. Requires gcc
for this.
* camel-internet-address.c (d): Turn off debug.
* camel-charset-map.c (camel_charset_step): Oops, & masks for set
intersection, not | them. Dunno how this got even close to
working.
2000-11-23 Not Zed <NotZed@HelixCode.com>
* camel-mime-filter-basic.c (filter): For base64 encoding, the
output size for 0, 1, or 2 bytes of input can exceed input*2, so
make sure we account for that as well.
(complete): And here.
(complete): Similarly for qp encoding, if we have a trailing
space, we need some extra bytes (not needed for 'filter()', as any
such bytes are stored in state/save).
* camel-mime-utils.c (quoted_decode_step): Removed fixme not required.
(quoted_encode_close): Dont append a trailing afterall. Otherwise
a pass through the encode/decode will grow the message each time.
2000-11-22 Radek Doulik <rodo@helixcode.com>
* camel-mime-utils.c (header_msgid_generate): check for return
......
## Process this file with automake to produce Makefile.in
SUBDIRS = providers
SUBDIRS = providers tests
libcamelincludedir = $(includedir)/camel
providerdir = $(libdir)/evolution/camel-providers/$(VERSION)
......
......@@ -231,7 +231,7 @@ camel_charset_step(CamelCharset *c, const char *in, int len)
}
inptr = newinptr;
if (c<=0xffff) {
mask |= charset_mask(c);
mask &= charset_mask(c);
if (c>=128 && c<256)
level = MAX(level, 1);
......
......@@ -23,7 +23,7 @@
#include <stdio.h>
#define d(x) x
#define d(x)
static int internet_decode (CamelAddress *, const char *raw);
static char * internet_encode (CamelAddress *);
......
......@@ -98,23 +98,27 @@ complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out,
switch(f->type) {
case CAMEL_MIME_FILTER_BASIC_BASE64_ENC:
/* wont go to more than 2x size (overly conservative) */
camel_mime_filter_set_size(mf, len*2, FALSE);
camel_mime_filter_set_size(mf, len*2+6, FALSE);
newlen = base64_encode_close(in, len, TRUE, mf->outbuf, &f->state, &f->save);
g_assert(newlen <= len*2+6);
break;
case CAMEL_MIME_FILTER_BASIC_QP_ENC:
/* *4 is definetly more than needed ... */
camel_mime_filter_set_size(mf, len*4, FALSE);
camel_mime_filter_set_size(mf, len*4+4, FALSE);
newlen = quoted_encode_close(in, len, mf->outbuf, &f->state, &f->save);
g_assert(newlen <= len*4+4);
break;
case CAMEL_MIME_FILTER_BASIC_BASE64_DEC:
/* output can't possibly exceed the input size */
camel_mime_filter_set_size(mf, len, FALSE);
camel_mime_filter_set_size(mf, len, FALSE);
newlen = base64_decode_step(in, len, mf->outbuf, &f->state, &f->save);
g_assert(newlen <= len);
break;
case CAMEL_MIME_FILTER_BASIC_QP_DEC:
/* output can't possibly exceed the input size */
camel_mime_filter_set_size(mf, len, FALSE);
newlen = quoted_decode_step(in, len, mf->outbuf, &f->state, &f->save);
g_assert(newlen <= len);
break;
default:
g_warning("unknown type %d in CamelMimeFilterBasic", f->type);
......@@ -142,23 +146,27 @@ filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, s
switch(f->type) {
case CAMEL_MIME_FILTER_BASIC_BASE64_ENC:
/* wont go to more than 2x size (overly conservative) */
camel_mime_filter_set_size(mf, len*2, FALSE);
camel_mime_filter_set_size(mf, len*2+6, FALSE);
newlen = base64_encode_step(in, len, TRUE, mf->outbuf, &f->state, &f->save);
g_assert(newlen <= len*2+6);
break;
case CAMEL_MIME_FILTER_BASIC_QP_ENC:
/* *4 is overly conservative, but will do */
camel_mime_filter_set_size(mf, len*4, FALSE);
camel_mime_filter_set_size(mf, len*4+4, FALSE);
newlen = quoted_encode_step(in, len, mf->outbuf, &f->state, &f->save);
g_assert(newlen <= len*4+4);
break;
case CAMEL_MIME_FILTER_BASIC_BASE64_DEC:
/* output can't possibly exceed the input size */
camel_mime_filter_set_size(mf, len, FALSE);
newlen = base64_decode_step(in, len, mf->outbuf, &f->state, &f->save);
g_assert(newlen <= len);
break;
case CAMEL_MIME_FILTER_BASIC_QP_DEC:
/* output can't possibly exceed the input size */
camel_mime_filter_set_size(mf, len, FALSE);
newlen = quoted_decode_step(in, len, mf->outbuf, &f->state, &f->save);
g_assert(newlen <= len);
break;
default:
g_warning("unknown type %d in CamelMimeFilterBasic", f->type);
......
......@@ -96,7 +96,7 @@ complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out,
/* FIXME: there's probably a safer way to size this ...? */
/* We could always resize if we run out of room in outbuf (but it'd be nice not
to have to) */
camel_mime_filter_set_size(mf, len*5, FALSE);
camel_mime_filter_set_size(mf, len*5+16, FALSE);
inbuf = in;
inlen = len;
outbuf = mf->outbuf;
......@@ -160,7 +160,7 @@ filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, s
}
/* FIXME: there's probably a safer way to size this ...? */
camel_mime_filter_set_size(mf, len*5, FALSE);
camel_mime_filter_set_size(mf, len*5+16, FALSE);
inbuf = in;
inlen = len;
outbuf = mf->outbuf;
......
......@@ -114,7 +114,7 @@ simple_data_wrapper_construct_from_parser(CamelDataWrapper *dw, CamelMimeParser
start = camel_mime_parser_tell(mp) + seekable_source->bound_start;
}
while ( camel_mime_parser_step(mp, &buf, &len) != HSCAN_BODY_END ) {
d(printf("appending o/p data: %.*s\n", len, buf));
d(printf("appending o/p data: %d: %.*s\n", len, len, buf));
if (buffer) {
if (buffer->len > 20480 && seekable_source) {
/* is this a 'big' message? Yes? We dont want to convert it all then.*/
......@@ -132,7 +132,9 @@ simple_data_wrapper_construct_from_parser(CamelDataWrapper *dw, CamelMimeParser
if (buffer) {
CamelStream *mem;
d(printf("Small message part, kept in memory!\n"));
mem = camel_stream_mem_new_with_byte_array(buffer);
camel_data_wrapper_construct_from_stream (dw, mem);
camel_object_unref ((CamelObject *)mem);
......
......@@ -285,6 +285,11 @@ base64_encode_close(unsigned char *in, int inlen, gboolean break_lines, unsigned
c1 = ((unsigned char *)save)[1];
c2 = ((unsigned char *)save)[2];
d(printf("mode = %d\nc1 = %c\nc2 = %c\n",
(int)((char *)save)[0],
(int)((char *)save)[1],
(int)((char *)save)[2]));
switch (((char *)save)[0]) {
case 2:
......@@ -560,10 +565,6 @@ quoted_encode_close(unsigned char *in, int len, unsigned char *out, int *state,
}
}
/* hmm, not sure if this should really be added here, we dont want
to add it to the content, afterall ...? */
*outptr++ = '\n';
*save = 0;
*state = -1;
......@@ -677,7 +678,6 @@ quoted_decode_step(unsigned char *in, int len, unsigned char *out, int *savestat
case 0:
while (inptr<inend) {
c = *inptr++;
/* FIXME: use a specials table to avoid 3 comparisons for the common case */
if (c=='=') {
state = 1;
break;
......
SUBDIRS = lib \
message
#!/usr/bin/perl
# Generate 'documents' in different encodings, from po files
if ($#ARGV < 0) {
print "Usage: gendoc.pl pofile pofile ...\n";
exit 1;
}
$fmt = "| fmt -u ";
sub read_msgstr()
{
my $str = "";
while (<IN>) {
if (m/^msgstr \"(.*)\"/) {
$str = $1;
if ($str eq "") {
while (<IN>) {
if (m/\"(.*)\"/) {
$str .= $1;
} else {
last;
}
}
}
return $str;
}
}
return "";
}
$unknown = "x-unknown-1";
foreach $name (@ARGV) {
if ($name =~ m@([^/]*).po$@) {
$poname = $1;
open IN,"<$name";
$header = read_msgstr;
if ($header =~ /Content-Type:.*charset=([-a-zA-Z0-9]*)/i) {
$charset = $1;
} else {
$charset = $unknown++;
}
print "Building $poname.$charset.txt from $name\n";
open OUT,"$fmt > $poname.$charset.txt";
while (!eof(IN)) {
$msg = read_msgstr;
# de-escape
$msg =~ s/\\n/\n/gso;
$msg =~ s/\\t/\t/gso;
$msg =~ s/\\(.)/$1/gso;
print OUT $msg." ";
}
close OUT;
close IN;
} else {
printf("ignoring $name, probably not intended\n");
}
}
#!/usr/bin/perl
# Generate 'documents' in different encodings, from po files
if ($#ARGV < 0) {
print "Usage: genline.pl pofile pofile ...\n";
exit 1;
}
sub read_msgstr()
{
my $str = "";
while (<IN>) {
if (m/^msgstr \"(.*)\"/) {
$str = $1;
if ($str eq "") {
while (<IN>) {
if (m/\"(.*)\"/) {
$str .= $1;
} else {
last;
}
}
}
return $str;
}
}
return "";
}
$unknown = "x-unknown-1";
open OUT, ">test-lines.h";
print OUT <<END;
struct _l {
char *type;
char *line;
} test_lines[] = {
END
foreach $name (@ARGV) {
if ($name =~ m@([^/]*).po$@) {
$poname = $1;
open IN,"<$name";
$header = read_msgstr;
if ($header =~ /Content-Type:.*charset=([-a-zA-Z0-9]*)/i) {
$charset = $1;
} else {
$charset = $unknown++;
}
while (!eof(IN)) {
$msg = read_msgstr;
if (length($msg) > 60 && length($msg) < 160) {
print OUT "\t{ \"$charset\", \"$msg\" },\n";
last;
}
# $msg =~ s/\\n/\n/gso;
# $msg =~ s/\\t/\t/gso;
# $msg =~ s/\\(.)/$1/gso;
# print OUT $msg." ";
}
close IN;
} else {
printf("ignoring $name, probably not intended\n");
}
}
print OUT "};\n";
close OUT;
check_LIBRARIES = libcameltest.a
libcameltest_a_SOURCES = \
camel-test.c camel-test.h \
messages.c messages.h \
addresses.c addresses.h
#include "addresses.h"
#include "camel-test.h"
void
test_address_compare(CamelInternetAddress *addr, CamelInternetAddress *addr2)
{
const char *r1, *r2, *a1, *a2;
char *e1, *e2, *f1, *f2;
int j;
check(camel_address_length(CAMEL_ADDRESS(addr)) == camel_address_length(CAMEL_ADDRESS(addr2)));
for (j=0;j<camel_address_length(CAMEL_ADDRESS(addr));j++) {
check(camel_internet_address_get(addr, j, &r1, &a1) == TRUE);
check(camel_internet_address_get(addr2, j, &r2, &a2) == TRUE);
check(string_equal(r1, r2));
check(strcmp(a1, a2) == 0);
}
check(camel_internet_address_get(addr, j, &r1, &a1) == FALSE);
check(camel_internet_address_get(addr2, j, &r2, &a2) == FALSE);
e1 = camel_address_encode(CAMEL_ADDRESS(addr));
e2 = camel_address_encode(CAMEL_ADDRESS(addr2));
if (camel_address_length(CAMEL_ADDRESS(addr)) == 0)
check(e1 == NULL && e2 == NULL);
else
check(e1 != NULL && e2 != NULL);
if (e1 != NULL) {
check_msg(string_equal(e1, e2), "e1 = '%s' e2 = '%s'", e1, e2);
test_free(e1);
test_free(e2);
}
f1 = camel_address_format(CAMEL_ADDRESS(addr));
f2 = camel_address_format(CAMEL_ADDRESS(addr2));
if (camel_address_length(CAMEL_ADDRESS(addr)) == 0)
check(f1 == NULL && f2 == NULL);
else
check(f1 != NULL && f2 != NULL);
if (f1 != NULL) {
check_msg(string_equal(f1, f2), "f1 = '%s' f2 = '%s'", f1, f2);
test_free(f1);
test_free(f2);
}
}
#include <camel/camel-internet-address.h>
/* addresses.c */
void test_address_compare(CamelInternetAddress *addr, CamelInternetAddress *addr2);
#include "camel-test.h"
#include <stdio.h>
#include <signal.h>
struct _stack {
struct _stack *next;
char *what;
};
static int setup;
static struct _stack *state;
static struct _stack *nonfatal;
static int ok;
int camel_test_verbose;
static void die(int sig)
{
static indie = 0;
struct _stack *node;
if (!indie) {
indie = 1;
printf("\n\nReceived fatal signal %d\n", sig);
node = state;
if (node) {
printf("Current action:\n");
while (node) {
printf("\t%s\n", node->what);
node = node->next;
}
}
}
_exit(1);
}
void camel_test_init(int argc, char **argv)
{
void camel_init(void);
int i;
setup = 1;
camel_init();
/* yeah, we do need ot thread init, even though camel isn't compiled with enable threads */
g_thread_init(NULL);
signal(SIGSEGV, die);
signal(SIGABRT, die);
/* default, just say what, how well we did, unless fail, then abort */
camel_test_verbose = 1;
for (i=0;i<argc;i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'v':
camel_test_verbose = strlen(argv[i]);
break;
case 'q':
camel_test_verbose = 0;
break;
}
}
}
}
void camel_test_start(const char *what)
{
if (!setup)
camel_test_init(0, 0);
ok = 1;
if (camel_test_verbose > 0) {
printf("Test: %s ... ", what);
fflush(stdout);
}
}
void camel_test_push(const char *what, ...)
{
struct _stack *node;
va_list ap;
char *text;
va_start(ap, what);
text = g_strdup_vprintf(what, ap);
va_end(ap);
if (camel_test_verbose > 3)
printf("Start step: %s\n", text);
node = g_malloc(sizeof(*node));
node->what = text;
node->next = state;
state = node;
}
void camel_test_pull(void)
{
struct _stack *node;
g_assert(state);
if (camel_test_verbose > 3)
printf("Finish step: %s\n", state->what);
node = state;
state = node->next;
g_free(node->what);
g_free(node);
}
void camel_test_fail(const char *why, ...)
{
struct _stack *node;
va_list ap;
char *text;
va_start(ap, why);
text = g_strdup_vprintf(why, ap);
va_end(ap);
if ((nonfatal == NULL && camel_test_verbose > 0)
|| (nonfatal && camel_test_verbose > 1)) {
printf("Failed: %s\n", text);
}
g_free(text);
if ((nonfatal == NULL && camel_test_verbose > 0)
|| (nonfatal && camel_test_verbose > 2)) {
node = state;
if (node) {
printf("Current action:\n");
while (node) {
printf("\t%s\n", node->what);
node = node->next;
}
}
}
if (nonfatal == NULL) {
exit(1);
} else {
ok=0;
if (camel_test_verbose > 1) {
printf("Known problem (ignored): %s\n", nonfatal->what);
}
}
}
void camel_test_nonfatal(const char *why, ...)
{
struct _stack *node;
va_list ap;
char *text;
va_start(ap, why);
text = g_strdup_vprintf(why, ap);
va_end(ap);
if (camel_test_verbose>3)
printf("Start nonfatal: %s\n", text);
node = g_malloc(sizeof(*node));
node->what = text;
node->next = nonfatal;
nonfatal = node;
}
/* dont ask me why but the compiler just can't seem to find the prototypes for this */
void camel_test_fatal()
{
struct _stack *node;
g_assert(nonfatal);
if (camel_test_verbose>3)
printf("Finish nonfatal: %s\n", nonfatal->what);
node = nonfatal;
nonfatal = node->next;
g_free(node->what);
g_free(node);
}
void camel_test_end(void)
{
if (camel_test_verbose > 0) {
if (ok)
printf("Ok\n");
else
printf("Partial success\n");
}
fflush(stdout);
}
/* compare strings, ignore whitespace though */
int string_equal(const char *a, const char *b)
{
const char *ap, *bp;
int cmp;
ap = a;
bp = b;
while (*ap && *bp) {
while (*ap == ' ' || *ap == '\n' || *ap == '\t')
ap++;
while (*bp == ' ' || *bp == '\n' || *bp == '\t')
bp++;
a = ap;
b = bp;
while (*ap && *ap != ' ' && *ap != '\n' && *ap != '\t')
ap++;
while (*bp && *bp != ' ' && *bp != '\n' && *bp != '\t')
bp++;
if (ap - a != bp - a
&& ap - 1 > 0
&& memcmp(a, b, ap-a) != 0) {
return 0;
}
}
return 1;
}
/* some utilities for testing */
#include "config.h"
#include <stdlib.h>
#include <glib.h>
/* perform a check assertion */
#define check(x) do {if (!(x)) { camel_test_fail("%s", #x); } } while (0)
#define check_msg(x, y, z...) do {if (!(x)) { camel_test_fail("%s\n\t" #y, #x, ##z); } } while (0)
#define check_count(object, expected) do { \
if (CAMEL_OBJECT(object)->ref_count != expected) { \
camel_test_fail("%s->ref_count != %s\n\tref_count = %d", #object, #expected, CAMEL_OBJECT(object)->ref_count); \
} \
} while (0)
#define check_unref(object, expected) do { \
check_count(object, expected); \
camel_object_unref(CAMEL_OBJECT(object)); \
if (expected == 1) { \
object = NULL; \
} \
} while (0)
#define test_free(mem) (g_free(mem), mem=NULL)
#define push camel_test_push
#define pull camel_test_pull
void camel_test_init(int argc, char **argv);
/* start/finish a new test */
void camel_test_start(const char *what);
void camel_test_end(void);
/* start/finish a new test part */
void camel_test_push(const char *what, ...);
void camel_test_pull(void);
/* fail a test, with a reason why */
void camel_test_fail(const char *why, ...);
/* Set whether a failed test quits. May be nested, but must be called in nonfatal/fatal pairs */
void camel_test_nonfatal(const char *why, ...);
void camel_test_fatal();
/* utility functions */
/* compare strings, ignore whitespace though */
int string_equal(const char *a, const char *b);
#include "messages.h"
#include "camel-test.h"
#include <camel/camel-mime-message.h>
#include <camel/camel-stream-fs.h>
#include <camel/camel-stream-mem.h>
CamelMimeMessage *
test_message_create_simple(void)
{
CamelMimeMessage *msg;
CamelInternetAddress *addr;
msg = camel_mime_message_new();
addr = camel_internet_address_new();
camel_internet_address_add(addr, "Michael Zucchi", "zed@nowhere.com");
camel_mime_message_set_from(msg, addr);
camel_address_remove((CamelAddress *)addr, -1);
camel_internet_address_add(addr, "POSTMASTER", "POSTMASTER@somewhere.net");
camel_mime_message_set_recipients(msg, CAMEL_RECIPIENT_TYPE_TO, addr);
camel_address_remove((CamelAddress *)addr, -1);
camel_internet_address_add(addr, "Michael Zucchi", "zed@nowhere.com");
camel_mime_message_set_recipients(msg, CAMEL_RECIPIENT_TYPE_CC, addr);
check_unref(addr, 1);
camel_mime_message_set_subject(msg, "Simple message subject");