Move get_next_tag() to lib/edit.c and add unittest for it.
bacula/src/lib/bsock_test
bacula/src/lib/bsockcore_test
bacula/src/lib/crc32_test
+bacula/src/lib/edit_test
bacula/src/lib/flist_test
bacula/src/lib/output_test
bacula/src/lib/sellist_test
$(RANLIB) $@
libbacsql.la: Makefile $(LIBBACSQL_LOBJS)
- @echo "Making $@ ..."
+ @echo "Making $@ ..."
$(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBACSQL_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBACSQL_LT_RELEASE) $(DB_LIBS)
libbaccats.la: Makefile cats_null.lo
# and it also includes system headers.
# `semi'-automatic since dependencies are generated at distribution time.
-depend:
+depend:
@$(MV) Makefile Makefile.bak
@$(SED) "/^# DO NOT DELETE:/,$$ d" Makefile.bak > Makefile
@$(ECHO) "# DO NOT DELETE: nice dependency list follows" >> Makefile
-/*
+/*
Bacula(R) - The Network Backup Solution
Copyright (C) 2000-2020 Kern Sibbald
This notice must be preserved when any source code is
conveyed and/or propagated.
- Bacula(R) is a registered trademark of Kern Sibbald.
-*/
-/*
- * Generic catalog class methods.
- *
- * Note: at one point, this file was assembled from parts of other files
- * by a programmer, and other than "wrapping" in a class, which is a trivial
- * change for a C++ programmer, nothing substantial was done, yet all the
- * code was recommitted under this programmer's name. Consequently, we
- * undo those changes here.
- */
-
-#include "bacula.h"
-
-#if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL
-
-#include "cats.h"
+ Bacula(R) is a registered trademark of Kern Sibbald.
+*/
+/*
+ * Generic catalog class methods.
+ *
+ * Note: at one point, this file was assembled from parts of other files
+ * by a programmer, and other than "wrapping" in a class, which is a trivial
+ * change for a C++ programmer, nothing substantial was done, yet all the
+ * code was recommitted under this programmer's name. Consequently, we
+ * undo those changes here.
+ */
+
+#include "bacula.h"
+
+#if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL
+
+#include "cats.h"
static int dbglvl=100;
-
+
void append_filter(POOLMEM **buf, char *cond)
{
if (*buf[0] != '\0') {
pm_strcat(buf, cond);
}
-bool BDB::bdb_match_database(const char *db_driver, const char *db_name,
- const char *db_address, int db_port)
-{
- BDB *mdb = this;
- bool match;
-
- if (db_driver) {
- match = strcasecmp(mdb->m_db_driver, db_driver) == 0 &&
- bstrcmp(mdb->m_db_name, db_name) &&
- bstrcmp(mdb->m_db_address, db_address) &&
- mdb->m_db_port == db_port &&
- mdb->m_dedicated == false;
- } else {
- match = bstrcmp(mdb->m_db_name, db_name) &&
- bstrcmp(mdb->m_db_address, db_address) &&
- mdb->m_db_port == db_port &&
- mdb->m_dedicated == false;
- }
- return match;
-}
-
-BDB *BDB::bdb_clone_database_connection(JCR *jcr, bool mult_db_connections)
-{
- BDB *mdb = this;
- /*
- * See if its a simple clone e.g. with mult_db_connections set to false
- * then we just return the calling class pointer.
- */
- if (!mult_db_connections) {
- mdb->m_ref_count++;
- return mdb;
- }
-
- /*
- * A bit more to do here just open a new session to the database.
- */
- return db_init_database(jcr, mdb->m_db_driver, mdb->m_db_name,
+bool BDB::bdb_match_database(const char *db_driver, const char *db_name,
+ const char *db_address, int db_port)
+{
+ BDB *mdb = this;
+ bool match;
+
+ if (db_driver) {
+ match = strcasecmp(mdb->m_db_driver, db_driver) == 0 &&
+ bstrcmp(mdb->m_db_name, db_name) &&
+ bstrcmp(mdb->m_db_address, db_address) &&
+ mdb->m_db_port == db_port &&
+ mdb->m_dedicated == false;
+ } else {
+ match = bstrcmp(mdb->m_db_name, db_name) &&
+ bstrcmp(mdb->m_db_address, db_address) &&
+ mdb->m_db_port == db_port &&
+ mdb->m_dedicated == false;
+ }
+ return match;
+}
+
+BDB *BDB::bdb_clone_database_connection(JCR *jcr, bool mult_db_connections)
+{
+ BDB *mdb = this;
+ /*
+ * See if its a simple clone e.g. with mult_db_connections set to false
+ * then we just return the calling class pointer.
+ */
+ if (!mult_db_connections) {
+ mdb->m_ref_count++;
+ return mdb;
+ }
+
+ /*
+ * A bit more to do here just open a new session to the database.
+ */
+ return db_init_database(jcr, mdb->m_db_driver, mdb->m_db_name,
mdb->m_db_user, mdb->m_db_password, mdb->m_db_address,
mdb->m_db_port, mdb->m_db_socket,
mdb->m_db_ssl_mode, mdb->m_db_ssl_key,
mdb->m_db_ssl_cert, mdb->m_db_ssl_ca,
mdb->m_db_ssl_capath, mdb->m_db_ssl_cipher,
true, mdb->m_disabled_batch_insert);
-}
-
-const char *BDB::bdb_get_engine_name(void)
-{
- BDB *mdb = this;
- switch (mdb->m_db_driver_type) {
- case SQL_DRIVER_TYPE_MYSQL:
- return "MySQL";
- case SQL_DRIVER_TYPE_POSTGRESQL:
- return "PostgreSQL";
- case SQL_DRIVER_TYPE_SQLITE3:
- return "SQLite3";
- default:
- return "Unknown";
- }
-}
-
-/*
- * Lock database, this can be called multiple times by the same
- * thread without blocking, but must be unlocked the number of
- * times it was locked using db_unlock().
- */
-void BDB::bdb_lock(const char *file, int line)
-{
- int errstat;
- BDB *mdb = this;
-
- if ((errstat = rwl_writelock_p(&mdb->m_lock, file, line)) != 0) {
- berrno be;
- e_msg(file, line, M_FATAL, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
- errstat, be.bstrerror(errstat));
- }
-}
-
-/*
- * Unlock the database. This can be called multiple times by the
- * same thread up to the number of times that thread called
- * db_lock()/
- */
-void BDB::bdb_unlock(const char *file, int line)
-{
- int errstat;
- BDB *mdb = this;
-
- if ((errstat = rwl_writeunlock(&mdb->m_lock)) != 0) {
- berrno be;
- e_msg(file, line, M_FATAL, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
- errstat, be.bstrerror(errstat));
- }
-}
-
-bool BDB::bdb_sql_query(const char *query, int flags)
-{
- bool retval;
- BDB *mdb = this;
-
- bdb_lock();
- retval = sql_query(query, flags);
- if (!retval) {
- Mmsg(mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror());
- }
- bdb_unlock();
- return retval;
-}
-
-void BDB::print_lock_info(FILE *fp)
-{
- BDB *mdb = this;
- if (mdb->m_lock.valid == RWLOCK_VALID) {
- fprintf(fp, "\tRWLOCK=%p w_active=%i w_wait=%i\n",
- &mdb->m_lock, mdb->m_lock.w_active, mdb->m_lock.w_wait);
- }
-}
-
-/* Parse stream of tags, return next one from the stream (it will be null terminated,
- * original buffer will be changed) */
-static char *get_next_tag(char **buf)
+}
+
+const char *BDB::bdb_get_engine_name(void)
{
- char *p = *buf;
- char *tmp = p;
- skip_nonspaces(&p);
- skip_spaces(&p);
- char *c = strpbrk(tmp, " ");
- if (c) {
- *c = '\0';
- } else {
- Dmsg0(dbglvl, "No tag found!\n");
- return NULL;
+ BDB *mdb = this;
+ switch (mdb->m_db_driver_type) {
+ case SQL_DRIVER_TYPE_MYSQL:
+ return "MySQL";
+ case SQL_DRIVER_TYPE_POSTGRESQL:
+ return "PostgreSQL";
+ case SQL_DRIVER_TYPE_SQLITE3:
+ return "SQLite3";
+ default:
+ return "Unknown";
}
- *buf = p;
+}
+
+/*
+ * Lock database, this can be called multiple times by the same
+ * thread without blocking, but must be unlocked the number of
+ * times it was locked using db_unlock().
+ */
+void BDB::bdb_lock(const char *file, int line)
+{
+ int errstat;
+ BDB *mdb = this;
- Dmsg1(dbglvl, "Found tag: %s\n", tmp);
- return tmp;
+ if ((errstat = rwl_writelock_p(&mdb->m_lock, file, line)) != 0) {
+ berrno be;
+ e_msg(file, line, M_FATAL, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
+ errstat, be.bstrerror(errstat));
+ }
+}
+
+/*
+ * Unlock the database. This can be called multiple times by the
+ * same thread up to the number of times that thread called
+ * db_lock()/
+ */
+void BDB::bdb_unlock(const char *file, int line)
+{
+ int errstat;
+ BDB *mdb = this;
+
+ if ((errstat = rwl_writeunlock(&mdb->m_lock)) != 0) {
+ berrno be;
+ e_msg(file, line, M_FATAL, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
+ errstat, be.bstrerror(errstat));
+ }
}
+bool BDB::bdb_sql_query(const char *query, int flags)
+{
+ bool retval;
+ BDB *mdb = this;
+
+ bdb_lock();
+ retval = sql_query(query, flags);
+ if (!retval) {
+ Mmsg(mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror());
+ }
+ bdb_unlock();
+ return retval;
+}
+
+void BDB::print_lock_info(FILE *fp)
+{
+ BDB *mdb = this;
+ if (mdb->m_lock.valid == RWLOCK_VALID) {
+ fprintf(fp, "\tRWLOCK=%p w_active=%i w_wait=%i\n",
+ &mdb->m_lock, mdb->m_lock.w_active, mdb->m_lock.w_wait);
+ }
+}
bool OBJECT_DBR::parse_plugin_object_string(char **obj_str)
{
robj_r->object_len, robj_r->object);
}
-#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL */
+#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL */
$(RMF) base64.o
$(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) base64.c
+edit_test: Makefile libbac.la edit.c unittests.o
+ $(RMF) edit.o
+ $(CXX) -DTEST_PROGRAM $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) edit.c
+ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L. -o $@ edit.o unittests.o $(DLIB) -lbac -lm $(LIBS) $(OPENSSL_LIBS)
+ $(LIBTOOL_INSTALL) $(INSTALL_PROGRAM) $@ $(DESTDIR)$(sbindir)/
+ $(RMF) edit.o
+ $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) edit.c
+
flist_test: Makefile libbac.la flist.c unittests.o
$(RMF) flist.o
$(CXX) -DTEST_PROGRAM $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) flist.c
$(RMF) org_lib_crc32.o
$(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) org_lib_crc32.c
-
bee_crc32_test: Makefile libbac.la bee_lib_crc32.c unittests.o
$(RMF) bee_lib_crc32.o
$(CXX) -DTEST_PROGRAM $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) bee_lib_crc32.c
bsnprintf_test: Makefile libbac.la bsnprintf.c unittests.o
$(RMF) bsnprintf.o
- $(CXX) -DTEST_PROGRAM $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) -Wno-format-truncation bsnprintf.c
+ $(CXX) -DTEST_PROGRAM $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) -Wno-format-truncation bsnprintf.c
$(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L. -o $@ bsnprintf.o unittests.o $(DLIB) -lbac -lm $(LIBS) $(OPENSSL_LIBS)
$(LIBTOOL_INSTALL) $(INSTALL_PROGRAM) $@ $(DESTDIR)$(sbindir)/
$(RMF) bsnprintf.o
* Check if Bacula Resoure Name is valid
*/
/*
- * Check if the Volume/resource name has legal characters
+ * Check if the Volume name has legal characters
* If ua is non-NULL send the message
*/
bool is_name_valid(const char *name, POOLMEM **msg, const char *accept)
}
if (len == 0) {
if (msg) {
- Mmsg(msg, _("Name must be at least one character long.\n"));
+ Mmsg(msg, _("Volume name must be at least one character long.\n"));
}
return false;
}
return buf;
}
+/* Parse stream of tags, return next one from the stream (it will be null terminated,
+ * original buffer will be changed) */
+char *get_next_tag(char **buf)
+{
+ char *tmp = NULL;
+
+ if (**buf != '\0') {
+ char *p = *buf;
+ tmp = p;
+ p = strchr(*buf, ' ');
+ if (p != NULL){
+ *p++ = '\0';
+ *buf = p;
+ } else {
+ *buf += strlen(tmp);
+ }
+ Dmsg1(900, "Found tag: %s\n", tmp);
+ } else {
+ Dmsg0(900, "No tag found!\n");
+ }
+
+ return tmp;
+}
+
+// #define TEST_PROGRAM
+
#ifdef TEST_PROGRAM
+#include "unittests.h"
+
void d_msg(const char*, int, int, const char*, ...)
{}
-int main(int argc, char *argv[])
+
+// this is a test vector
+// /@kubernetes/ kubernetes:^Ans=plugintest^Adebug^Averify_ssl=0 Container PVCs Kubernetes^APersistent^AVolume^AClaim 5368709120 U 5
+char __po_log1[] = {
+ 0x2f, 0x40, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73,
+ 0x2f, 0x20, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73,
+ 0x3a, 0x01, 0x6e, 0x73, 0x3d, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x74,
+ 0x65, 0x73, 0x74, 0x01, 0x64, 0x65, 0x62, 0x75, 0x67, 0x01, 0x76, 0x65,
+ 0x72, 0x69, 0x66, 0x79, 0x5f, 0x73, 0x73, 0x6c, 0x3d, 0x30, 0x20, 0x43,
+ 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x20, 0x50, 0x56, 0x43,
+ 0x73, 0x20, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73,
+ 0x01, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x01,
+ 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x01, 0x43, 0x6c, 0x61, 0x69, 0x6d,
+ 0x20, 0x20, 0x20, 0x35, 0x33, 0x36, 0x38, 0x37, 0x30, 0x39, 0x31, 0x32,
+ 0x30, 0x20, 0x55, 0x20, 0x35, 0x00
+};
+unsigned int __po_log1_len = sizeof(__po_log1);
+int __po_log1_nr = 10;
+
+// ASD 123
+char __po_log2[] = {0x41, 0x53, 0x44, 0x20, 0x20, 0x31, 0x32, 0x33, 0x00, 0x00};
+unsigned int __po_log2_len = sizeof(__po_log2);
+
+struct _edit_utime_vect
{
- char *str[] = {"3", "3n", "3 hours", "3.5 day", "3 week", "3 m", "3 q", "3 years"};
- utime_t val;
- char buf[100];
- char outval[100];
-
- for (int i=0; i<8; i++) {
- strcpy(buf, str[i]);
- if (!duration_to_utime(buf, &val)) {
- printf("Error return from duration_to_utime for in=%s\n", str[i]);
- continue;
+ const char *in;
+ const utime_t val;
+ const char *outval;
+};
+
+_edit_utime_vect __testvect1[] =
+{
+ { "3", 3, "3 secs"},
+ { "3n", 180, "3 mins "},
+ { "3 hours", 10800, "3 hours "},
+ { "3.5 day", 302400, "3 days 12 hours "},
+ { "3 week", 1814400, "21 days "},
+ { "3 m", 7776000, "3 months "},
+ { "3 q", 23587200, "9 months 3 days "},
+ { "3 years", 94608000, "3 years "},
+ { "23587201", 23587201, "9 months 3 days 1 sec"},
+ { NULL, 0, NULL},
+};
+
+int main()
+{
+ Unittests unittest("text_edit_tests");
+
+ {
+ utime_t val;
+ char buf[100];
+ char outval[100];
+
+ for (int i=0; __testvect1[i].in != NULL; i++) {
+ strcpy(buf, __testvect1[i].in);
+ POOL_MEM label;
+ Mmsg(label, "duration_to_utime %s", __testvect1[i].in);
+ bool status = duration_to_utime(buf, &val);
+ ok(status, label.c_str());
+ if (status){
+ edit_utime(val, outval, sizeof(outval));
+ ok(val == __testvect1[i].val, "checking val");
+ ok(strcmp(outval, __testvect1[i].outval) == 0, "checking outval");
+ }
+ // printf("outval='%s'\n", outval);
+ }
+ }
+
+ {
+ char *testvect = __po_log2;
+ char **obj_str = &testvect;
+
+ char *fname = get_next_tag(obj_str);
+ ok(fname != NULL, "checking first tag");
+ ok(strcmp(fname, "ASD") == 0, "checking first tag value");
+
+ char *empty = get_next_tag(obj_str);
+ ok(empty != NULL, "checking empty tag");
+ ok(strlen(empty) == 0, "checking empty value tag");
+
+ char *last = get_next_tag(obj_str);
+ ok(last != NULL, "checking last tag");
+ ok(strcmp(last, "123") == 0, "checking last tag value");
+ ok(obj_str != NULL, "checking obj_str");
+ ok(*obj_str != NULL, "checking obj_str ptr");
+ ok(**obj_str == 0, "checking obj_str char");
+
+ char *afterlast = get_next_tag(obj_str);
+ ok(afterlast == NULL, "checking no tags");
+ }
+
+ {
+ char *testvect = __po_log1;
+ char **obj_str = &testvect;
+
+ for (int a = 0; a < __po_log1_nr; a++){
+ char *tag = get_next_tag(obj_str);
+ POOL_MEM label;
+ Mmsg(label, "checking tag %d", a);
+ ok(tag != NULL, label.c_str());
}
- edit_utime(val, outval);
- printf("in=%s val=%" lld " outval=%s\n", str[i], val, outval);
+ ok(get_next_tag(obj_str) == NULL, "checking the last");
}
+
+ return report();
}
+
#endif
#define EXTRA_VALID_RESOURCE_CHAR_GLOB EXTRA_VALID_RESOURCE_CHAR "[]*?"
bool is_name_valid (const char *name, POOLMEM **msg);
bool is_name_valid (const char *name, POOLMEM **msg, const char *accept);
+char *get_next_tag(char **buf);
/* jcr.c (most definitions are in src/jcr.h) */
void init_last_jobs_list();
--- /dev/null
+#!/bin/sh
+#
+# Copyright (C) 2000-2015 Kern Sibbald
+# License: BSD 2-Clause; see file LICENSE-FOSS
+#
+# This is an alist unit test
+#
+. scripts/regress-utils.sh
+do_regress_unittest "edit_test" "src/lib"