default type plugin, including tests
authorAleš Křenek <ljocha@ics.muni.cz>
Wed, 11 Oct 2006 17:40:28 +0000 (17:40 +0000)
committerAleš Křenek <ljocha@ics.muni.cz>
Wed, 11 Oct 2006 17:40:28 +0000 (17:40 +0000)
org.glite.jp.common/Makefile
org.glite.jp.common/interface/attr.h
org.glite.jp.common/interface/context.h
org.glite.jp.common/interface/strmd5.h
org.glite.jp.common/src/attr.c
org.glite.jp.common/src/strmd5.c
org.glite.jp.common/test/base64_test.cpp [new file with mode: 0644]
org.glite.jp.common/test/type_test.cpp [new file with mode: 0644]

index 177a143..c0aa6b0 100644 (file)
@@ -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:
 
index 6ae2cb5..6badff7 100644 (file)
@@ -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
index 40ae2eb..75a71a3 100644 (file)
@@ -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
index 4ca27a2..c354e6d 100755 (executable)
@@ -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 */
index 47c2891..42a5cc6 100644 (file)
@@ -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;
 }
 
index 7a35fb1..b07593f 100755 (executable)
@@ -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 (file)
index 0000000..55a41c1
--- /dev/null
@@ -0,0 +1,75 @@
+#include <assert.h>
+#include <fstream>
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/XmlOutputter.h>
+#include <cppunit/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+
+#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 (file)
index 0000000..8669637
--- /dev/null
@@ -0,0 +1,184 @@
+#include <assert.h>
+#include <fstream>
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/XmlOutputter.h>
+#include <cppunit/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+
+#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 ;
+}
+
+
+