'lb.harvester' => [ qw// ],
'lb.yaim' => [ qw/yaim_core:R/ ],
'lb.glite-LB' => [ qw/fetchcrl:R gpt:R gip_release:R gip_service:R bdii:R glite_version:R glite_info_templates:R glue_schema:R/ ],
- 'lbjp-common.db' => [ qw/mysql:B mysql-devel:B postgresql:B/ ],
+ 'lbjp-common.db' => [ qw/mysql:B mysql-devel:B postgresql:B cppunit:B/ ],
'lbjp-common.log' => [ qw/log4c/ ],
'lbjp-common.maildir' => [ qw// ],
'lbjp-common.server-bones' => [ qw// ],
CC=gcc
-VPATH=${top_srcdir}/interface:${top_srcdir}/src:${top_srcdir}/examples
+VPATH=${top_srcdir}/interface:${top_srcdir}/src:${top_srcdir}/examples:${top_srcdir}/test
DEBUG:=-g -O0 -W -Wall
LDFLAGS:=-L${stagedir}/${libdir} ${COVERAGE_FLAGS}
COMPILE:=libtool --mode=compile ${CC} ${CFLAGS}
+COMPILEXX:=libtool --mode=compile ${CXX} ${CFLAGS}
LINK:=libtool --mode=link ${CC} -rpath ${stagedir}/${libdir} ${LDFLAGS}
+LINKXX:=libtool --mode=link ${CXX} -rpath ${stagedir}/${libdir} ${LDFLAGS}
INSTALL:=libtool --mode=install install
EXT_LIBS:=-lglite_lbu_trio -lglite_lbu_log -lpthread ${DL_LIBS}
db_expire: db_expire.lo libglite_lbu_dbtest.la
${LINK} -o $@ $+ ${EXT_LIBS}
+timezone: timezone.lo libglite_lbu_db.la
+ ${LINKXX} -o $@ $+ ${TEST_LIBS} ${EXT_LIBS}
+
compile: libglite_lbu_db.la
-check:
- -echo No checks here yet.
+check: timezone
+ ./timezone
test_coverage:
-mkdir coverage
clean:
rm -rvf *.o *.lo *.loT .libs lib* *.c *.h *.dox C/ CPP/
rm -rvf log.xml project/ rpmbuild/ RPMS/ tgz/
- rm -rvf db_expire db_test db_test_mysql db_test_psql
+ rm -rvf db_expire db_test db_test_mysql db_test_psql timezone
db-mysql.o db-mysql.lo: db-mysql.c
${COMPILE} ${MYSQL_CPPFLAGS} -c $<
db_test_psql.o db_test_psql.lo: db_test.c
${COMPILE} -DPSQL_BACKEND=1 -c $< -o $@
+timezone.o timezone.lo: timezone.cpp
+ ${COMPILEXX} -c $< -o $@ ${TEST_INC}
+
%.o %.lo: %.c
${COMPILE} -c $<
'lb.harvester' => [ qw// ],
'lb.yaim' => [ qw/yaim_core:R/ ],
'lb.glite-LB' => [ qw/fetchcrl:R gpt:R gip_release:R gip_service:R bdii:R glite_version:R glite_info_templates:R glue_schema:R/ ],
- 'lbjp-common.db' => [ qw/mysql:B mysql-devel:B postgresql:B/ ],
+ 'lbjp-common.db' => [ qw/mysql:B mysql-devel:B postgresql:B cppunit:B/ ],
'lbjp-common.log' => [ qw/log4c/ ],
'lbjp-common.maildir' => [ qw// ],
'lbjp-common.server-bones' => [ qw// ],
}
+static time_t tm2time(struct tm *tm) {
+ static struct tm tm_last = { tm_year:0, tm_mon:0 };
+ static time_t t = (time_t)-1;
+ static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+ char *tz;
+
+ pthread_mutex_lock(&lock);
+ if (tm->tm_year == tm_last.tm_year && tm->tm_mon == tm_last.tm_mon) {
+ t = t + (tm->tm_sec - tm_last.tm_sec)
+ + (tm->tm_min - tm_last.tm_min) * 60
+ + (tm->tm_hour - tm_last.tm_hour) * 3600
+ + (tm->tm_mday - tm_last.tm_mday) * 86400;
+ memcpy(&tm_last, tm, sizeof tm_last);
+ } else {
+ tz = getenv("TZ");
+ if (tz) tz = strdup(tz);
+ setenv("TZ", "UTC", 1);
+ tzset();
+
+ t = mktime(tm);
+ memcpy(&tm_last, tm, sizeof tm_last);
+
+ if (tz) setenv("TZ", tz, 1);
+ else unsetenv("TZ");
+ free(tz);
+ tzset();
+ }
+ pthread_mutex_unlock(&lock);
+
+ return t;
+}
+
+
time_t glite_lbu_StrToTime(const char *str) {
struct tm tm;
- char *tz;
- time_t t;
memset(&tm,0,sizeof(tm));
- tz = getenv("TZ");
- setenv("TZ", "UTC", 1);
- tzset();
-
sscanf(str,"%4d-%02d-%02d %02d:%02d:%02d",
&tm.tm_year,&tm.tm_mon,&tm.tm_mday,
&tm.tm_hour,&tm.tm_min,&tm.tm_sec);
tm.tm_year -= 1900;
tm.tm_mon--;
- t = mktime(&tm);
-
- if (tz) setenv("TZ", tz, 1);
- else unsetenv("TZ");
- tzset();
- return t;
+ return tm2time(&tm);
}
double glite_lbu_StrToTimestamp(const char *str) {
struct tm tm;
- double sec, t;
- char *tz;
+ double sec;
memset(&tm,0,sizeof(tm));
- tz = getenv("TZ");
- setenv("TZ", "UTC", 1);
- tzset();
-
sscanf(str,"%4d-%02d-%02d %02d:%02d:%lf",
&tm.tm_year,&tm.tm_mon,&tm.tm_mday,
&tm.tm_hour,&tm.tm_min,&sec);
tm.tm_mon--;
tm.tm_sec = sec;
- t = (sec - tm.tm_sec) + mktime(&tm);
-
- if (tz) setenv("TZ", tz, 1);
- else unsetenv("TZ");
- tzset();
-
- return t;
+ return (sec - tm.tm_sec) + tm2time(&tm);
}
--- /dev/null
+/*
+Copyright (c) Members of the EGEE Collaboration. 2004-2010.
+See http://www.eu-egee.org/partners for details on the copyright holders.
+
+Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+#include <cmath>
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+#include "db.h"
+
+#define zoneCheck(tmp) {\
+ (tmp) = getenv("TZ"); \
+ if (tz == NULL) CPPUNIT_ASSERT((tmp) == NULL);\
+ else CPPUNIT_ASSERT((tmp) != NULL && strcmp(tz, (tmp)) == 0);\
+}
+
+static struct {
+ time_t t;
+ const char *db;
+} data[] = {
+ // year of tiger (and day +, day -)
+ {t:1266142830, db:"2010-02-14 10:20:30"},
+ {t:1266142830-24*3600, db:"2010-02-13 10:20:30"},
+ {t:1266142830+24*3600, db:"2010-02-15 10:20:30"},
+
+ // two months later (and day +, day -)
+ {t:1271240430, db:"2010-04-14 10:20:30"},
+ {t:1271240430-24*3600, db:"2010-04-13 10:20:30"},
+ {t:1271240430+24*3600, db:"2010-04-15 10:20:30"},
+};
+
+class ZoneTest: public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ZoneTest);
+ CPPUNIT_TEST(testInitialZoneCheck);
+ CPPUNIT_TEST(testTimeZone3);
+ CPPUNIT_TEST(testTimeZoneNULL);
+ CPPUNIT_TEST(testTimeZoneUTC);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+
+ void setUp() {
+ tz0 = getenv("TZ");
+ }
+
+ void tearDown() {
+ if (tz0) setenv("TZ", tz0, 1);
+ else unsetenv("TZ");
+ }
+
+ void testInitialZoneCheck() {
+ char *tz2;
+
+ zoneCheck(tz2);
+ }
+
+ void testTimeZone3() {
+ tz = "Tst 3:00";
+ setenv("TZ", tz, 1);
+ tzset();
+ testInitialZoneCheck();
+ convertCheck();
+ }
+
+ void testTimeZoneNULL() {
+ tz = NULL;
+ unsetenv("TZ");
+ tzset();
+ testInitialZoneCheck();
+ convertCheck();
+ }
+
+ void testTimeZoneUTC() {
+ tz = "UTC";
+ setenv("TZ", tz, 1);
+ tzset();
+ testInitialZoneCheck();
+ convertCheck();
+ }
+
+private:
+
+const char *tz0, *tz;
+
+void convertCheck() {
+ char *tz2;
+
+ time_t tt;
+ double st_d;
+ char *st_str, *st_dbstr, *t_dbstr;
+
+ char *s;
+ time_t t;
+ double d;
+ size_t i;
+
+ for (i = 0; i < sizeof(data)/sizeof(data[0]); i++) {
+ tt = data[i].t;
+ st_d = tt + 0.013;
+ asprintf(&t_dbstr, "'%s'", data[i].db);
+ asprintf(&st_str, "%s.013", data[i].db);
+ asprintf(&st_dbstr, "'%s.013'", data[i].db);
+
+ glite_lbu_TimeToStr(tt, &s);
+ CPPUNIT_ASSERT(s != NULL);
+ CPPUNIT_ASSERT(strcmp(s, t_dbstr) == 0);
+ free(s);
+ zoneCheck(tz2);
+
+ glite_lbu_TimestampToStr(st_d, &s);
+ CPPUNIT_ASSERT(s != NULL);
+ CPPUNIT_ASSERT(strncmp(s, st_dbstr, 24) == 0);
+ free(s);
+ zoneCheck(tz2);
+
+ t = glite_lbu_StrToTime(data[i].db);
+ CPPUNIT_ASSERT(t == tt);
+ zoneCheck(tz2);
+
+ d = glite_lbu_StrToTimestamp(st_str);
+ CPPUNIT_ASSERT(round(1000 * d) == round(1000 * st_d));
+ zoneCheck(tz2);
+
+ free(st_str);
+ free(st_dbstr);
+ free(t_dbstr);
+ }
+}
+
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION( ZoneTest );
+
+int
+main ()
+{
+ CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
+ CppUnit::TextUi::TestRunner runner;
+
+ runner.addTest(suite);
+ return runner.run() ? 0 : 1;
+}