From f3fe5f327d0238aaf32c8bff0152d25d84a3b581 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ale=C5=A1=20K=C5=99enek?= Date: Wed, 11 Oct 2006 17:40:28 +0000 Subject: [PATCH] default type plugin, including tests --- org.glite.jp.common/Makefile | 19 +++- org.glite.jp.common/interface/attr.h | 8 ++ org.glite.jp.common/interface/context.h | 8 ++ org.glite.jp.common/interface/strmd5.h | 8 ++ org.glite.jp.common/src/attr.c | 131 ++++++++++++++++------ org.glite.jp.common/src/strmd5.c | 10 +- org.glite.jp.common/test/base64_test.cpp | 75 +++++++++++++ org.glite.jp.common/test/type_test.cpp | 184 +++++++++++++++++++++++++++++++ 8 files changed, 399 insertions(+), 44 deletions(-) create mode 100644 org.glite.jp.common/test/base64_test.cpp create mode 100644 org.glite.jp.common/test/type_test.cpp diff --git a/org.glite.jp.common/Makefile b/org.glite.jp.common/Makefile index 177a143..c0aa6b0 100644 --- a/org.glite.jp.common/Makefile +++ b/org.glite.jp.common/Makefile @@ -31,6 +31,8 @@ DEBUG:=-g -O0 CFLAGS:=${DEBUG} -I. -I${top_srcdir}/interface -I${stagedir}/include \ ${GLOBUSINC} +LDFLAGS:=-L${globus_prefix}/lib + offset=0 version_info:=-version-info ${shell \ perl -e '$$,=":"; @F=split "\\.","${version}"; print $$F[0]+$$F[1]+${offset},$$F[2],$$F[1]' } @@ -52,18 +54,27 @@ TRIO_OBJS:=escape.o trio.o strio.o TRIO_LIB:=libglite_jp_trio.la TRIO_LOBJS:=${TRIO_OBJS:.o=.lo} +TEST_LIBS:=-L${cppunit}/lib -lcppunit -ldl +TEST_INC:=-I${cppunit}/include + + default all: compile -compile: ${commonlib} ${TRIO_LIB} +compile: ${commonlib} ${TRIO_LIB} ${commonlib}: ${OBJS} - ${LINK} -o $@ ${OBJS} + ${LINK} -o $@ ${OBJS} -lcrypto_${nothrflavour} ${TRIO_LIB}: ${TRIO_LOBJS} ${LINK} ${version_info} -o $@ ${TRIO_LOBJS} -lm -check: - -echo nothing yet +check: base64_test type_test + ./base64_test base64_test.xml + ./type_test type_test.xml + +type_test base64_test: %: %.cpp compile + ${CXX} -c ${CFLAGS} ${TEST_INC} $< + ${LINKXX} -o $@ $@.o ${commonlib} ${TRIO_LIB} ${TEST_LIBS} doc: diff --git a/org.glite.jp.common/interface/attr.h b/org.glite.jp.common/interface/attr.h index 6ae2cb5..6badff7 100644 --- a/org.glite.jp.common/interface/attr.h +++ b/org.glite.jp.common/interface/attr.h @@ -1,6 +1,10 @@ #ifndef __GLITE_JP_ATTR #define __GLITE_JP_ATTR +#ifdef __cplusplus +extern "C" { +#endif + void glite_jp_attrval_free(glite_jp_attrval_t *,int); void glite_jp_attrval_copy(glite_jp_attrval_t *,const glite_jp_attrval_t *); @@ -20,5 +24,9 @@ const char *glite_jp_attrval_db_type_index(glite_jp_context_t ctx,const char *at time_t glite_jp_attr2time(const char *); char * glite_jp_time2attr(time_t); +#ifdef __cplusplus +}; +#endif + #endif diff --git a/org.glite.jp.common/interface/context.h b/org.glite.jp.common/interface/context.h index 40ae2eb..75a71a3 100644 --- a/org.glite.jp.common/interface/context.h +++ b/org.glite.jp.common/interface/context.h @@ -1,6 +1,10 @@ #ifndef __GLITE_JP_CONTEXT #define __GLITE_JP_CONTEXT +#ifdef __cplusplus +extern "C" { +#endif + int glite_jp_init_context(glite_jp_context_t *); void glite_jp_free_context(glite_jp_context_t); void glite_jp_free_query_rec(glite_jp_query_rec_t *); @@ -15,4 +19,8 @@ int glite_jp_add_deferred(glite_jp_context_t,int (*)(glite_jp_context_t,void *), int glite_jp_run_deferred(glite_jp_context_t); +#ifdef __cplusplus +}; +#endif + #endif diff --git a/org.glite.jp.common/interface/strmd5.h b/org.glite.jp.common/interface/strmd5.h index 4ca27a2..c354e6d 100755 --- a/org.glite.jp.common/interface/strmd5.h +++ b/org.glite.jp.common/interface/strmd5.h @@ -1,6 +1,10 @@ #ifndef _GLITE_STRMD5_H #define _GLITE_STRMD5_H +#ifdef __cplusplus +extern "C" { +#endif + #ident "$Header$" /* Compute MD5 sum of the first argument. @@ -28,5 +32,9 @@ char *str2md5base64(const char *src); int base64_encode(const void *enc, int enc_size, char *out, int out_max_size); int base64_decode(const char *enc,char *out,int out_size); +#ifdef __cplusplus +}; +#endif + #endif /* _GLITE_STRMD5_H */ diff --git a/org.glite.jp.common/src/attr.c b/org.glite.jp.common/src/attr.c index 47c2891..42a5cc6 100644 --- a/org.glite.jp.common/src/attr.c +++ b/org.glite.jp.common/src/attr.c @@ -47,49 +47,118 @@ static int fb_cmp(void *ctx,const glite_jp_attrval_t *a,const glite_jp_attrval_t return 0; } +/* XXX: depends on specific definition of glite_jp_attr_orig_t */ +static char orig_char[] = "ASUF"; + +/* XXX: don't allocate memory, don't grow more than twice */ +static int escape_colon(const char *in, char *out) +{ + int i,o; + + for (i=o=0; in[i]; i++) switch (in[i]) { + case ':': out[o++] = '\\'; out[o++] = ':'; break; + case '\\': out[o++] = '\\'; out[o++] = '\\'; break; + default: out[o++] = in[i]; break; + } + out[o] = 0; + return o; +} + +/* XXX: read until unescaped colon is found + * allocates output */ +static char * unescape_colon(const char *in,int *rd) +{ + int i,o; + char *out; + + for (i=o=0; in[i] && in[i] != ':'; i++,o++) + if (in[i] == '\\') i++; + + out = malloc(o+1); + + for (i=o=0; in[i] && in[i] != ':'; i++) + if (in[i] == '\\') out[o++] = in[++i]; + else out[o++] = in[i]; + + out[o] = 0; + *rd = i; + return out; +} + static char * fb_to_db_full(void *ctx,const glite_jp_attrval_t *attr) { - char *db; - if (attr->binary) { - int osize = attr->size * 4/3 + 6; - db = malloc(osize); - db[0] = 'B'; db[1] = ':'; - osize = base64_encode(attr->value,attr->size,db+2,osize-3); - assert(osize >= 0); - db[osize] = 0; + + int vsize = attr->binary ? attr->size * 4/3 + 6 : strlen(attr->value)+1, + len; + + /* 4x: + \0 + ASUF + BS + %12d */ + char *db = malloc(19 + (attr->origin_detail ? 2*strlen(attr->origin_detail) : 0) + vsize); + + if (attr->origin < 0 || attr->origin > GLITE_JP_ATTR_ORIG_FILE) { + free(db); return NULL; } - else { - db = malloc(strlen(attr->value)+3); - db[0] = 'S'; db[1] = ':'; - strcpy(db+2,attr->value); + len = sprintf(db,"%c:%d:%c:",attr->binary ? 'B' : 'S', + attr->timestamp,orig_char[attr->origin]); + + if (attr->origin_detail) len += escape_colon(attr->origin_detail,db+len); + db[len++] = ':'; + + if (attr->binary) { + vsize = base64_encode(attr->value,attr->size,db+len,vsize-1); + if (vsize < 0) { free(db); return NULL; } + db[len+vsize] = 0; } + else strcpy(db+len,attr->value); + return db; } static char * fb_to_db_index(void *ctx,const glite_jp_attrval_t *attr,int len) { - char *db = fb_to_db_full(ctx,attr); - if (len < strlen(db)) db[len] = 0; - return db; + char *s; + +/* XXX: binary values not really handled. Though the formal semantics is not broken */ + if (attr->binary) return strdup("XXX"); + + s = strdup(attr->value); + if (len < strlen(s)) s[len] = 0; + return s; } -int fb_from_db(void *ctx,const char *str,glite_jp_attrval_t *attr) -{ - int osize; - switch (str[0]) { - case 'B': - attr->value = malloc(osize = strlen(str) * 3/4 + 4); - attr->size = base64_decode(str,str+2,osize); - assert(attr->size >= 0); - attr->binary = 1; - break; - case 'S': - attr->value = strdup(str + 2); - attr->size = 0; - attr->binary = 0; - break; - default: return EINVAL; +static int fb_from_db(void *ctx,const char *str,glite_jp_attrval_t *attr) +{ + int p = 2; + char *colon,*cp; + + if (str[0] != 'B' && str[0] != 'S') return EINVAL; + attr->binary = str[0] == 'B'; + cp = attr->value = strdup(str); + + colon = strchr(cp+p,':'); + if (!colon) return EINVAL; + + *colon++ = 0; + attr->timestamp = (time_t) atol(cp+p); + p = colon-cp; + + for (attr->origin = GLITE_JP_ATTR_ORIG_ANY; orig_char[attr->origin] && orig_char[attr->origin] != cp[p]; attr->origin++); + if (!orig_char[attr->origin]) return EINVAL; + + p += 2; + if (cp[p] == ':') attr->origin_detail = NULL; + else { + int r; + attr->origin_detail = unescape_colon(cp+p,&r); + p += r; } + if (cp[p++] != ':') return EINVAL; + + if (attr->binary) { + attr->size = base64_decode(str+p,attr->value,strlen(str)); + if (attr->size < 0) return EINVAL; + } + else strcpy(attr->value,str+p); + return 0; } diff --git a/org.glite.jp.common/src/strmd5.c b/org.glite.jp.common/src/strmd5.c index 7a35fb1..b07593f 100755 --- a/org.glite.jp.common/src/strmd5.c +++ b/org.glite.jp.common/src/strmd5.c @@ -67,7 +67,7 @@ int base64_decode(const char *enc,char *out,int max_out_size) } while (*enc && *enc != '=') { - bits << 6; + bits <<= 6; bits |= b64r[*enc++]; shift += 6; @@ -79,14 +79,6 @@ int base64_decode(const char *enc,char *out,int max_out_size) } } - /* XXX: will it ever happen? */ - if (shift) { - if (out_size >= max_out_size) return -1; - bits <<= 8-shift; - *out = bits & 0xff; - out_size++; - } - return out_size; } diff --git a/org.glite.jp.common/test/base64_test.cpp b/org.glite.jp.common/test/base64_test.cpp new file mode 100644 index 0000000..55a41c1 --- /dev/null +++ b/org.glite.jp.common/test/base64_test.cpp @@ -0,0 +1,75 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "strmd5.h" + +class Base64Test: public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(Base64Test); + CPPUNIT_TEST(test); + CPPUNIT_TEST_SUITE_END(); +public: + void test(); +}; + +void Base64Test::test() +{ + int i; + unsigned char in[2000], b[4000], out[2000]; + + srandom(0xDEAD); + in[0] = 'x'; + for (i=1; i<2000; i++) { + char s[20]; + int len; + sprintf(s,"%d",i); + in[i] = random() % 256; + + std::cerr << '.'; + + base64_encode(in,i,(char *) b,sizeof b); + len = base64_decode((const char *) b,(char *) out,sizeof out); + + CPPUNIT_ASSERT_MESSAGE(std::string("len"),i == len); + CPPUNIT_ASSERT_MESSAGE(std::string(s),!memcmp(in,out,i)); + } + std::cerr << std::endl; +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Base64Test); + + +int main (int argc,const char *argv[]) +{ + CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest(); + + assert(argc == 2); + std::ofstream xml(argv[1]); + + CppUnit::TestResult controller; + CppUnit::TestResultCollector result; + controller.addListener( &result ); + + CppUnit::TestRunner runner; + runner.addTest(suite); + runner.run(controller); + + CppUnit::XmlOutputter xout( &result, xml ); + CppUnit::CompilerOutputter tout( &result, std::cout); + xout.write(); + tout.write(); + + return result.wasSuccessful() ? 0 : 1 ; +} + + + diff --git a/org.glite.jp.common/test/type_test.cpp b/org.glite.jp.common/test/type_test.cpp new file mode 100644 index 0000000..8669637 --- /dev/null +++ b/org.glite.jp.common/test/type_test.cpp @@ -0,0 +1,184 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "types.h" +#include "attr.h" +#include "context.h" + + +class TypePluginTest: public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(TypePluginTest); + CPPUNIT_TEST(simple); + CPPUNIT_TEST(binary); + CPPUNIT_TEST(origin); + CPPUNIT_TEST(origin2); + CPPUNIT_TEST(index); + CPPUNIT_TEST_SUITE_END(); +public: + void simple(); + void binary(); + void origin(); + void origin2(); + void index(); +}; + +void TypePluginTest::simple() +{ + glite_jp_context_t ctx; + + glite_jp_attrval_t attr = { + "myattr", + "short string", + 0,0, + GLITE_JP_ATTR_ORIG_USER, + NULL, + 0 + },attr2; + + char *db; + + glite_jp_init_context(&ctx); + attr.timestamp = time(NULL); + + db = glite_jp_attrval_to_db_full(ctx,&attr); + + CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db); + std::cerr << db << std::endl; + + glite_jp_attrval_from_db(ctx,db,&attr2); + CPPUNIT_ASSERT_MESSAGE(std::string("value"),!strcmp(attr.value,attr2.value)); + CPPUNIT_ASSERT_MESSAGE(std::string("origin"),attr.origin == attr2.origin); + CPPUNIT_ASSERT_MESSAGE(std::string("timestamp"),attr.timestamp == attr2.timestamp); +} + +void TypePluginTest::binary() +{ + glite_jp_context_t ctx; + + glite_jp_attrval_t attr = { + "myattr", + NULL, + 1,1000, + GLITE_JP_ATTR_ORIG_USER, + NULL, + 0 + },attr2; + + char *db; + + glite_jp_init_context(&ctx); + attr.timestamp = time(NULL); + attr.value = (char *) malloc(attr.size); + + db = glite_jp_attrval_to_db_full(ctx,&attr); + + CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db); + std::cerr << db << std::endl; + + glite_jp_attrval_from_db(ctx,db,&attr2); + CPPUNIT_ASSERT_MESSAGE(std::string("size"),attr.size == attr2.size); + CPPUNIT_ASSERT_MESSAGE(std::string("value"),!memcmp(attr.value,attr2.value,attr.size)); +} + +void TypePluginTest::origin() +{ + glite_jp_context_t ctx; + + glite_jp_attrval_t attr = { + "myattr", + NULL, + 0,0, + GLITE_JP_ATTR_ORIG_USER, + NULL, + 0 + },attr2; + + char *db; + + glite_jp_init_context(&ctx); + attr.timestamp = time(NULL); + attr.value = "origin test"; + attr.origin_detail = "simple origin"; + + db = glite_jp_attrval_to_db_full(ctx,&attr); + + CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db); + std::cerr << db << std::endl; + + glite_jp_attrval_from_db(ctx,db,&attr2); + CPPUNIT_ASSERT_MESSAGE(std::string("origin detail"),!strcmp(attr.origin_detail,attr2.origin_detail)); +} + +void TypePluginTest::origin2() +{ + glite_jp_context_t ctx; + + glite_jp_attrval_t attr = { + "myattr", + NULL, + 0,0, + GLITE_JP_ATTR_ORIG_USER, + NULL, + 0 + },attr2; + + char *db; + + glite_jp_init_context(&ctx); + attr.timestamp = time(NULL); + attr.value = "origin:test"; + attr.origin_detail = "ftp://some.server:1234/ugly \\file"; + + db = glite_jp_attrval_to_db_full(ctx,&attr); + + CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db); + std::cerr << db << std::endl; + + glite_jp_attrval_from_db(ctx,db,&attr2); + CPPUNIT_ASSERT_MESSAGE(std::string("origin detail"),!strcmp(attr.origin_detail,attr2.origin_detail)); + CPPUNIT_ASSERT_MESSAGE(std::string("value"),!strcmp(attr.value,attr2.value)); +} + +void TypePluginTest::index() +{ + /* TODO: check monotonity */ +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TypePluginTest); + + +int main (int argc,const char *argv[]) +{ + CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest(); + + assert(argc == 2); + std::ofstream xml(argv[1]); + + CppUnit::TestResult controller; + CppUnit::TestResultCollector result; + controller.addListener( &result ); + + CppUnit::TestRunner runner; + runner.addTest(suite); + runner.run(controller); + + CppUnit::XmlOutputter xout( &result, xml ); + CppUnit::CompilerOutputter tout( &result, std::cout); + xout.write(); + tout.write(); + + return result.wasSuccessful() ? 0 : 1 ; +} + + + -- 1.8.2.3