[pacman-dev] [PATCH 10/10] wip: config parser unit test
Andrew Gregory
andrew.gregory.8 at gmail.com
Sat Apr 26 19:57:03 EDT 2014
Just a quick-n-dirty test to demonstrate the reworked parser. Obviously
not suitable to be committed.
Only modified conf.c to allow parsing the config without also
initializing alpm.
Can be run with `make check` in test/unit/pacman/.
---
src/pacman/conf.c | 81 +++++++++++----------
test/unit/pacman/config.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++
test/unit/pacman/tap.h | 123 ++++++++++++++++++++++++++++++++
3 files changed, 342 insertions(+), 36 deletions(-)
create mode 100644 test/unit/pacman/config.c
create mode 100644 test/unit/pacman/tap.h
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 5449b92..09daeb4 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -679,6 +679,7 @@ static int register_repo(config_repo_t *repo)
*/
static int setup_libalpm(void)
{
+ setup_libalpm();
int ret = 0;
alpm_errno_t err;
alpm_handle_t *handle;
@@ -686,25 +687,6 @@ static int setup_libalpm(void)
pm_printf(ALPM_LOG_DEBUG, "setup_libalpm called\n");
- /* Configure root path first. If it is set and dbpath/logfile were not
- * set, then set those as well to reside under the root. */
- if(config->rootdir) {
- char path[PATH_MAX];
- if(!config->dbpath) {
- snprintf(path, PATH_MAX, "%s/%s", config->rootdir, DBPATH + 1);
- config->dbpath = strdup(path);
- }
- if(!config->logfile) {
- snprintf(path, PATH_MAX, "%s/%s", config->rootdir, LOGFILE + 1);
- config->logfile = strdup(path);
- }
- } else {
- config->rootdir = strdup(ROOTDIR);
- if(!config->dbpath) {
- config->dbpath = strdup(DBPATH);
- }
- }
-
/* initialize library */
handle = alpm_initialize(config->rootdir, config->dbpath, &err);
if(!handle) {
@@ -722,7 +704,6 @@ static int setup_libalpm(void)
alpm_option_set_questioncb(handle, cb_question);
alpm_option_set_progresscb(handle, cb_progress);
- config->logfile = config->logfile ? config->logfile : strdup(LOGFILE);
ret = alpm_option_set_logfile(handle, config->logfile);
if(ret != 0) {
pm_printf(ALPM_LOG_ERROR, _("problem setting logfile '%s' (%s)\n"),
@@ -730,9 +711,6 @@ static int setup_libalpm(void)
return ret;
}
- /* Set GnuPG's home directory. This is not relative to rootdir, even if
- * rootdir is defined. Reasoning: gpgdir contains configuration data. */
- config->gpgdir = config->gpgdir ? config->gpgdir : strdup(GPGDIR);
ret = alpm_option_set_gpgdir(handle, config->gpgdir);
if(ret != 0) {
pm_printf(ALPM_LOG_ERROR, _("problem setting gpgdir '%s' (%s)\n"),
@@ -749,18 +727,12 @@ static int setup_libalpm(void)
alpm_option_set_default_siglevel(handle, config->siglevel);
-#define SLMERGE(l, m) if(m) { l = (l & (m)) | (config->siglevel & ~(m)); }
- SLMERGE(config->localfilesiglevel, config->localfilesiglevel_mask);
- SLMERGE(config->remotefilesiglevel, config->remotefilesiglevel_mask);
alpm_option_set_local_file_siglevel(handle, config->localfilesiglevel);
alpm_option_set_remote_file_siglevel(handle, config->remotefilesiglevel);
for(i = config->repos; i; i = alpm_list_next(i)) {
- config_repo_t *repo = i->data;
- SLMERGE(repo->siglevel, repo->siglevel_mask);
- register_repo(repo);
+ register_repo(i->data);
}
-#undef SLMERGE
if(config->xfercommand) {
alpm_option_set_fetchcb(handle, download_with_xfercommand);
@@ -980,6 +952,42 @@ static int _parse_directive(const char *file, int linenum, const char *name,
}
}
+static void finalize_config(void)
+{
+ /* Configure root path first. If it is set and dbpath/logfile were not
+ * set, then set those as well to reside under the root. */
+ if(config->rootdir) {
+ char path[PATH_MAX];
+ if(!config->dbpath) {
+ snprintf(path, PATH_MAX, "%s/%s", config->rootdir, DBPATH + 1);
+ config->dbpath = strdup(path);
+ }
+ if(!config->logfile) {
+ snprintf(path, PATH_MAX, "%s/%s", config->rootdir, LOGFILE + 1);
+ config->logfile = strdup(path);
+ }
+ } else {
+ config->rootdir = strdup(ROOTDIR);
+ if(!config->dbpath) {
+ config->dbpath = strdup(DBPATH);
+ }
+ }
+ config->logfile = config->logfile ? config->logfile : strdup(LOGFILE);
+ /* Set GnuPG's home directory. This is not relative to rootdir, even if
+ * rootdir is defined. Reasoning: gpgdir contains configuration data. */
+ config->gpgdir = config->gpgdir ? config->gpgdir : strdup(GPGDIR);
+
+#define SLMERGE(l, m) if(m) { l = (l & (m)) | (config->siglevel & ~(m)); }
+ SLMERGE(config->localfilesiglevel, config->localfilesiglevel_mask);
+ SLMERGE(config->remotefilesiglevel, config->remotefilesiglevel_mask);
+ alpm_list_t *i;
+ for(i = config->repos; i; i = alpm_list_next(i)) {
+ config_repo_t *repo = i->data;
+ SLMERGE(repo->siglevel, repo->siglevel_mask);
+ }
+#undef SLMERGE
+}
+
/** Parse a configuration file.
* @param file path to the config file
* @return 0 on success, non-zero on error
@@ -994,12 +1002,13 @@ int parseconfig(const char *file)
return ret;
}
pm_printf(ALPM_LOG_DEBUG, "config: finished parsing %s\n", file);
- if((ret = setup_libalpm())) {
- return ret;
- }
- alpm_list_free_inner(config->repos, (alpm_list_fn_free) config_repo_free);
- alpm_list_free(config->repos);
- config->repos = NULL;
+ finalize_config();
+ /*if((ret = setup_libalpm())) {*/
+ /*return ret;*/
+ /*}*/
+ /*alpm_list_free_inner(config->repos, (alpm_list_fn_free) config_repo_free);*/
+ /*alpm_list_free(config->repos);*/
+ /*config->repos = NULL;*/
return ret;
}
diff --git a/test/unit/pacman/config.c b/test/unit/pacman/config.c
new file mode 100644
index 0000000..9f5aa54
--- /dev/null
+++ b/test/unit/pacman/config.c
@@ -0,0 +1,174 @@
+#include <string.h>
+#include <stdlib.h>
+
+#define CONFFILE "/etc/pacman.conf"
+#define DBPATH "/var/lib/pacman/"
+#define LOGFILE "/var/log/pacman.log"
+#define ROOTDIR "/"
+#define GPGDIR "/etc/pacman.d/gnupg/"
+#define CACHEDIR "/var/cache/pacman/pkg"
+
+#include "pacman/conf.c"
+#include "pacman/ini.c"
+#include "pacman/util.c"
+#include "pacman/callback.c"
+
+#include "tap.h"
+
+int main(int argc, char **argv) {
+ alpm_list_t *i;
+ char temp_path1[] = "pu_config_test_XXXXXX";
+ char temp_path2[] = "pu_config_test_XXXXXX";
+ int fd1 = mkstemp(temp_path1);
+ int fd2 = mkstemp(temp_path2);
+ FILE *stream1 = fdopen(fd1, "r+");
+ FILE *stream2 = fdopen(fd2, "r+");
+ fprintf(stream2,
+ "\n"
+ "SigLevel = DatabaseNever\n"
+ "");
+ fprintf(stream1,
+ "\n"
+ "[options]\n"
+ "#RootDir = /root1\n"
+ "RootDir = /root2\n"
+ "DBPath = /dbpath1/ \n"
+ "DBPath = /dbpath2/ \n"
+ "CacheDir=/cachedir\n"
+ "GPGDir =gpgdir\n"
+ "LogFile= /logfile #ignore me\n"
+ " HoldPkg = holdpkga holdpkgb \n"
+ "IgnorePkg = ignorepkga\n"
+ "IgnorePkg = ignorepkgb\n"
+ " IgnoreGroup = ignoregroupa ignoregroupb \n"
+ "Architecture = i686\n"
+ "NoUpgrade = /tmp/noupgrade*\n"
+ "NoExtract = /tmp/noextract*\n"
+ "CleanMethod = KeepInstalled KeepCurrent\n"
+ "UseSyslog\n"
+ "Color\n"
+ "UseDelta\n"
+ "TotalDownload\n"
+ "CheckSpace\n"
+ "VerbosePkgLists\n"
+ "XferCommand = xfercommand\n"
+
+ "LocalFileSigLevel = PackageNever\n"
+ "SigLevel = PackageOptional DatabaseRequired PackageTrustedOnly\n"
+ "RemoteFileSigLevel = PackageTrustAll\n"
+
+ "[core]\n"
+ "SigLevel = PackageRequired\n"
+ "Server = $repo:$arch\n"
+
+ "[extra]\n"
+ "Include = %s\n"
+ "",
+ temp_path2);
+
+ fclose(stream1);
+ fclose(stream2);
+
+ tap_plan(37);
+
+ if((config = config_new()) == NULL) {
+ tap_bail("config_new failed");
+ }
+ parseconfig(temp_path1);
+
+ tap_is_str(config->rootdir, "/root2", "RootDir");
+ tap_is_str(config->dbpath, "/dbpath1/", "DBPath");
+ tap_is_str(config->gpgdir, "gpgdir", "DPGDir");
+ tap_is_str(config->logfile, "/logfile", "LogFile");
+ tap_is_str(config->arch, "i686", "Arch");
+ tap_is_str(config->xfercommand, "xfercommand", "Include XferCommand");
+
+ tap_ok(config->usesyslog, "UseSyslog");
+ tap_ok(config->color, "Color");
+ tap_ok(config->totaldownload, "TotalDownload");
+ tap_ok(config->checkspace, "CheckSpace");
+ tap_ok(config->verbosepkglists, "VerbosePkgLists");
+
+#define is_list_exhausted(l, name) do { \
+ tap_ok(l == NULL, name " exhausted"); \
+ if(l) { \
+ tap_diag("remaining elements:"); \
+ while(l) { \
+ tap_diag(l->data); \
+ l = alpm_list_next(l); \
+ } \
+ } \
+ } while(0)
+
+
+#define is_str_list(l, str, desc) do { \
+ if(l) { \
+ tap_is_str(l->data, str, desc); \
+ l = alpm_list_next(l); \
+ } else { \
+ tap_ok(l != NULL, desc); \
+ } \
+ } while(0)
+
+ i = config->ignorepkg;
+ is_str_list(i, "ignorepkga", "IgnorePkg a");
+ is_str_list(i, "ignorepkgb", "IgnorePkg b");
+ is_list_exhausted(i, "ignorepkg");
+
+ i = config->ignoregrp;
+ is_str_list(i, "ignoregroupa", "IgnoreGroup a");
+ is_str_list(i, "ignoregroupb", "IgnoreGroup b");
+ is_list_exhausted(i, "ignoregroup");
+
+ i = config->noupgrade;
+ is_str_list(i, "/tmp/noupgrade*", "NoUpgrade");
+ is_list_exhausted(i, "noupgrade");
+
+ i = config->noextract;
+ is_str_list(i, "/tmp/noextract*", "NoExtract");
+ is_list_exhausted(i, "noextract");
+
+ i = config->cachedirs;
+ is_str_list(i, "/cachedir", "CacheDir");
+ is_list_exhausted(i, "cachedir");
+
+ i = config->holdpkg;
+ is_str_list(i, "holdpkga", "HoldPkg a");
+ is_str_list(i, "holdpkgb", "HoldPkg b");
+ is_list_exhausted(i, "holdpkgs");
+#undef tap_is_str_list
+
+ tap_is_float(config->deltaratio, 0.7, 0.0001, "UseDelta (default)");
+
+ alpm_siglevel_t base = ALPM_SIG_PACKAGE
+ | ALPM_SIG_PACKAGE_OPTIONAL
+ | ALPM_SIG_DATABASE;
+ alpm_siglevel_t local = base & ~(ALPM_SIG_PACKAGE);
+ alpm_siglevel_t remote = base
+ | ALPM_SIG_PACKAGE_MARGINAL_OK
+ | ALPM_SIG_PACKAGE_UNKNOWN_OK;
+ alpm_siglevel_t core = base & ~(ALPM_SIG_PACKAGE_OPTIONAL);
+ alpm_siglevel_t extra = base & ~(ALPM_SIG_DATABASE);
+
+ tap_is_int(config->siglevel, base, "SigLevel");
+ tap_is_int(config->localfilesiglevel, local, "LocalFileSigLevel");
+ tap_is_int(config->remotefilesiglevel, remote, "RemoteFileSigLevel");
+
+ i = config->repos;
+ config_repo_t *repo = i->data;
+ tap_is_str(repo->name, "core", "core name");
+ tap_is_int(repo->siglevel, core, "core siglevel");
+ tap_is_str(repo->servers->data, "$repo:$arch", "core server");
+ tap_ok(repo->servers->next == NULL, "core server count");
+
+ i = alpm_list_next(i);
+ repo = i->data;
+ tap_is_str(repo->name, "extra", "extra name");
+ tap_is_int(repo->siglevel, extra, "extra siglevel");
+ tap_ok(repo->servers == NULL, "extra server count");
+
+ unlink(temp_path1);
+ unlink(temp_path2);
+
+ return tap_tests_failed();
+}
diff --git a/test/unit/pacman/tap.h b/test/unit/pacman/tap.h
new file mode 100644
index 0000000..e670909
--- /dev/null
+++ b/test/unit/pacman/tap.h
@@ -0,0 +1,123 @@
+#include <math.h>
+#include <stdarg.h>
+
+int _tap_tests_run = 0;
+int _tap_tests_failed = 0;
+
+const char *_tap_todo = NULL;
+
+void tap_todo(const char *reason)
+{
+ _tap_todo = reason;
+}
+
+void tap_ok(int success, const char *description, ...)
+{
+ const char *result;
+ if(success) {
+ result = "ok";
+ if(_tap_todo) ++_tap_tests_failed;
+ } else {
+ result = "not ok";
+ if(!_tap_todo) ++_tap_tests_failed;
+ }
+
+ printf("%s %d", result, ++_tap_tests_run);
+
+ if(description) {
+ va_list args;
+ fputs(" - ", stdout);
+ va_start(args, description);
+ vprintf(description, args);
+ va_end(args);
+ }
+
+ if(_tap_todo) {
+ fputs(" # TODO", stdout);
+ if(*_tap_todo) {
+ fputc(' ', stdout);
+ fputs(_tap_todo, stdout);
+ }
+ }
+
+ fputc('\n', stdout);
+}
+
+void tap_bail(const char *format, ...)
+{
+ va_list args;
+ fputs("Bail out! ", stdout);
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ fputc('\n', stdout);
+}
+
+void tap_diag(const char *format, ...)
+{
+ va_list args;
+ fputs(" # ", stdout);
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ fputc('\n', stdout);
+}
+
+void tap_is_float(float got, float expected, float delta,
+ const char *description)
+{
+ float diff = fabs(expected - got);
+ int match = diff < delta;
+ tap_ok(match, description);
+ if(!match) {
+ tap_diag("expected '%f'", expected);
+ tap_diag("got '%f'", got);
+ tap_diag("delta '%f'", diff);
+ tap_diag("allowed '%f'", delta);
+ }
+}
+
+void tap_is_int(int got, int expected, const char *description)
+{
+ int match = got == expected;
+ tap_ok(match, description);
+ if(!match) {
+ tap_diag("expected '%d'", expected);
+ tap_diag("got '%d'", got);
+ }
+}
+
+void tap_is_str(const char *got, const char *expected, const char *description)
+{
+ int match;
+ if(got && expected) {
+ match = (strcmp(got, expected) == 0);
+ } else {
+ match = (got == expected);
+ }
+ tap_ok(match, description);
+ if(!match) {
+ tap_diag("expected '%s'", expected);
+ tap_diag("got '%s'", got);
+ }
+}
+
+void tap_plan(int test_count)
+{
+ printf("1..%d\n", test_count);
+}
+
+void tap_done_testing(void)
+{
+ tap_plan(_tap_tests_run);
+}
+
+int tap_tests_run(void)
+{
+ return _tap_tests_run;
+}
+
+int tap_tests_failed(void)
+{
+ return _tap_tests_failed;
+}
--
1.9.2
More information about the pacman-dev
mailing list