improve guessing of appdata.xml file name
[platform/upstream/libsolv.git] / tools / patchcheck.c
index b900d06..6a5c3f7 100644 (file)
@@ -1,6 +1,13 @@
 /* vim: sw=2 et
  */
 
+/*
+ * Copyright (c) 2009, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
 #define _GNU_SOURCE
 
 #include <stdio.h>
 #include "evr.h"
 #include "poolarch.h"
 #include "repo_solv.h"
+#ifdef ENABLE_SUSEREPO
 #include "repo_susetags.h"
+#endif
+#ifdef ENABLE_RPMMD
 #include "repo_updateinfoxml.h"
 #include "repo_rpmmd.h"
+#endif
 #include "solver.h"
 #include "solverdebug.h"
 
-static ssize_t
-cookie_gzread(void *cookie, char *buf, size_t nbytes)
-{
-  return gzread((gzFile *)cookie, buf, nbytes);
-}
-
-static int
-cookie_gzclose(void *cookie)
-{
-  return gzclose((gzFile *)cookie);
-}
-
-FILE *
-myfopen(const char *fn)
-{
-  cookie_io_functions_t cio;
-  char *suf;
-  gzFile *gzf;
-
-  if (!fn)
-    return 0;
-  suf = strrchr(fn, '.');
-  if (!suf || strcmp(suf, ".gz") != 0)
-    return fopen(fn, "r");
-  gzf = gzopen(fn, "r");
-  if (!gzf)
-    return 0;
-  memset(&cio, 0, sizeof(cio));
-  cio.read = cookie_gzread;
-  cio.close = cookie_gzclose;
-  return  fopencookie(gzf, "r", cio);
-}
+#include "solv_xfopen.h"
 
 void
 showproblems(Solver *solv, Solvable *s, Queue *cand, Queue *badguys)
@@ -63,7 +43,7 @@ showproblems(Solver *solv, Solvable *s, Queue *cand, Queue *badguys)
 
   queue_init(&rids);
   queue_init(&rinfo);
-  printf("can't install %s:\n", solvable2str(pool, s));
+  printf("can't install %s:\n", pool_solvable2str(pool, s));
   while ((problem = solver_next_problem(solv, problem)) != 0)
     {
       solver_findallproblemrules(solv, problem, &rids);
@@ -82,13 +62,13 @@ showproblems(Solver *solv, Solvable *s, Queue *cand, Queue *badguys)
              dep = rinfo.elements[k + 3];
              switch (rinfo.elements[k])
                {
-               case SOLVER_PROBLEM_DISTUPGRADE_RULE:
+               case SOLVER_RULE_DISTUPGRADE:
                  break;
-               case SOLVER_PROBLEM_INFARCH_RULE:
-                 printf("  %s has inferior architecture\n", solvid2str(pool, source));
+               case SOLVER_RULE_INFARCH:
+                 printf("  %s has inferior architecture\n", pool_solvid2str(pool, source));
                  break;
-               case SOLVER_PROBLEM_UPDATE_RULE:
-                 printf("  update rule for %s\n", solvid2str(pool, source));
+               case SOLVER_RULE_UPDATE:
+                 printf("  update rule for %s\n", pool_solvid2str(pool, source));
                  if (badguys)
                    queue_pushunique(badguys, source);
                  if (!cand)
@@ -112,19 +92,22 @@ showproblems(Solver *solv, Solvable *s, Queue *cand, Queue *badguys)
                        cand->elements[l] = -source;
                      }
                  break;
-               case SOLVER_PROBLEM_JOB_RULE:
+               case SOLVER_RULE_JOB:
+               case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM:
+               case SOLVER_RULE_JOB_UNKNOWN_PACKAGE:
+               case SOLVER_RULE_JOB_UNSUPPORTED:
                  break;
-               case SOLVER_PROBLEM_RPM_RULE:
+               case SOLVER_RULE_RPM:
                  printf("  some dependency problem\n");
                  break;
-               case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP:
-                 printf("  nothing provides requested %s\n", dep2str(pool, dep));
+               case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP:
+                 printf("  nothing provides requested %s\n", pool_dep2str(pool, dep));
                  break;
-               case SOLVER_PROBLEM_NOT_INSTALLABLE:
-                 printf("  package %s is not installable\n", solvid2str(pool, source));
+               case SOLVER_RULE_RPM_NOT_INSTALLABLE:
+                 printf("  package %s is not installable\n", pool_solvid2str(pool, source));
                  break;
-               case SOLVER_PROBLEM_NOTHING_PROVIDES_DEP:
-                 printf("  nothing provides %s needed by %s\n", dep2str(pool, dep), solvid2str(pool, source));
+               case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP:
+                 printf("  nothing provides %s needed by %s\n", pool_dep2str(pool, dep), pool_solvid2str(pool, source));
                  if (ISRELDEP(dep))
                    {
                      Reldep *rd = GETRELDEP(pool, dep);
@@ -132,24 +115,24 @@ showproblems(Solver *solv, Solvable *s, Queue *cand, Queue *badguys)
                        {
                          Id rp, rpp;
                          FOR_PROVIDES(rp, rpp, rd->name)
-                           printf("    (we have %s)\n", solvid2str(pool, rp));
+                           printf("    (we have %s)\n", pool_solvid2str(pool, rp));
                        }
                    }
                  break;
-               case SOLVER_PROBLEM_SAME_NAME:
-                 printf("  cannot install both %s and %s\n", solvid2str(pool, source), solvid2str(pool, target));
+               case SOLVER_RULE_RPM_SAME_NAME:
+                 printf("  cannot install both %s and %s\n", pool_solvid2str(pool, source), pool_solvid2str(pool, target));
                  break;
-               case SOLVER_PROBLEM_PACKAGE_CONFLICT:
-                 printf("  package %s conflicts with %s provided by %s\n", solvid2str(pool, source), dep2str(pool, dep), solvid2str(pool, target));
+               case SOLVER_RULE_RPM_PACKAGE_CONFLICT:
+                 printf("  package %s conflicts with %s provided by %s\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep), pool_solvid2str(pool, target));
                  break;
-               case SOLVER_PROBLEM_PACKAGE_OBSOLETES:
-                 printf("  package %s obsoletes %s provided by %s\n", solvid2str(pool, source), dep2str(pool, dep), solvid2str(pool, target));
+               case SOLVER_RULE_RPM_PACKAGE_OBSOLETES:
+                 printf("  package %s obsoletes %s provided by %s\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep), pool_solvid2str(pool, target));
                  break;
-               case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE:
-                 printf("  package %s requires %s, but none of the providers can be installed\n", solvid2str(pool, source), dep2str(pool, dep));
+               case SOLVER_RULE_RPM_PACKAGE_REQUIRES:
+                 printf("  package %s requires %s, but none of the providers can be installed\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep));
                  break;
-               case SOLVER_PROBLEM_SELF_CONFLICT:
-                 printf("  package %s conflicts with %s provided by itself\n", solvid2str(pool, source), dep2str(pool, dep));
+               case SOLVER_RULE_RPM_SELF_CONFLICT:
+                 printf("  package %s conflicts with %s provided by itself\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep));
                  break;
                }
            }
@@ -163,19 +146,23 @@ void
 toinst(Solver *solv, Repo *repo, Repo *instrepo)
 {
   Pool *pool = solv->pool;
+  Queue q;
   int k;
   Id p;
 
-  for (k = 0; k < solv->decisionq.count; k++)
+  queue_init(&q);
+  solver_get_decisionqueue(solv, &q);
+  for (k = 0; k < q.count; k++)
     {
-      p = solv->decisionq.elements[k];
+      p = q.elements[k];
       if (p < 0 || p == SYSTEMSOLVABLE)
        continue;
 
-     /* printf(" toinstall %s\n", solvid2str(pool, p));*/
+     /* printf(" toinstall %s\n", pool_solvid2str(pool, p));*/
       /* oh my! */
       pool->solvables[p].repo = instrepo;
     }
+  queue_free(&q);
 }
 
 void
@@ -186,7 +173,7 @@ dump_instrepo(Repo *instrepo, Pool *pool)
 
   printf("instrepo..\n");
   FOR_REPO_SOLVABLES(instrepo, p, s)
-    printf("  %s\n", solvable2str(pool, s));
+    printf("  %s\n", pool_solvable2str(pool, s));
   printf("done.\n");
 }
 
@@ -205,7 +192,8 @@ void
 usage(char** argv)
 {
 
-  printf("%s: <arch> <patchnameprefix> [repos] [--updaterepos] [repos]...\n"
+  printf("%s: <arch> <patchnameprefix>  [--install-available] [repos] [--updaterepos] [repos]...\n"
+      "\t --install-available: installation repository is available during update\n"
       "\t repos: repository ending in\n"
       "\t\tpackages, packages.gz, primary.xml.gz, updateinfo.xml.gz or .solv\n",
       argv[0]);
@@ -213,25 +201,305 @@ usage(char** argv)
   exit(1);
 }
 
+typedef struct {
+  int updatestart;
+  int shown;
+  int status;
+  int install_available;
+  Repo *repo;
+  Repo *instrepo;
+} context_t;
+
+#define SHOW_PATCH(c) if (!(c)->shown++) printf("%s:\n", pool_solvable2str(pool, s));
+#define PERF_DEBUGGING 0
+static Pool *pool;
+
+void
+test_all_old_patches_included(context_t *c, Id pid)
+{
+  Id p, pp;
+  Id con, *conp;
+  Solvable *s = pool->solvables + pid;
+  /* Test 1: are all old patches included */
+  FOR_PROVIDES(p, pp, s->name)
+    {
+      Solvable *s2 = pool->solvables + p;
+      Id con2, *conp2;
+
+      if (!s2->conflicts)
+        continue;
+      if (pool_evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE) <= 0)
+        continue;
+      conp2 = s2->repo->idarraydata + s2->conflicts;
+      while ((con2 = *conp2++) != 0)
+        {
+          Reldep *rd2, *rd;
+          if (!ISRELDEP(con2))
+            continue;
+          rd2 = GETRELDEP(pool, con2);
+          conp = s->repo->idarraydata + s->conflicts;
+          while ((con = *conp++) != 0)
+            {
+              if (!ISRELDEP(con))
+                continue;
+              rd = GETRELDEP(pool, con);
+              if (rd->name == rd2->name)
+                break;
+            }
+          if (!con)
+            {
+              SHOW_PATCH(c);
+              printf("  %s contained %s\n", pool_solvable2str(pool, s2), pool_dep2str(pool, rd2->name));
+            }
+          else
+           {
+             if (pool_evrcmp(pool, rd->evr, rd2->evr, EVRCMP_COMPARE) < 0)
+               {
+                 SHOW_PATCH(c);
+                 printf("  %s required newer version %s-%s of %s-%s\n",
+                     pool_solvable2str(pool, s2), pool_dep2str(pool, rd2->name), pool_dep2str(pool, rd2->evr),
+                     pool_dep2str(pool, rd->name), pool_dep2str(pool, rd->evr));
+               }
+           }
+
+        }
+    }
+}
+
+void
+test_all_packages_installable(context_t *c, Id pid)
+{
+  Solver *solv;
+  Queue job;
+  Id p, pp;
+  Id con, *conp;
+  unsigned int now, solver_runs;
+  int i;
+  Solvable *s = pool->solvables + pid;
+
+  queue_init(&job);
+
+  now = solv_timems(0);
+  solver_runs = 0;
+
+  conp = s->repo->idarraydata + s->conflicts;
+  while ((con = *conp++) != 0)
+    {
+      FOR_PROVIDES(p, pp, con)
+        {
+          queue_empty(&job);
+          queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_WEAK);
+          queue_push(&job, p);
+
+          /* also set up some minimal system */
+          queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
+          queue_push(&job, pool_str2id(pool, "rpm", 1));
+          queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
+          queue_push(&job, pool_str2id(pool, "aaa_base", 1));
+
+          solv = solver_create(pool);
+          /* solver_set_flag(solv, SOLVER_FLAG_IGNORE_RECOMMENDED, 1); */
+          ++solver_runs;
+          if (solver_solve(solv, &job))
+            {
+              c->status = 1;
+              printf("error installing original package\n");
+              showproblems(solv, s, 0, 0);
+            }
+          toinst(solv, c->repo, c->instrepo);
+          solver_free(solv);
+
+#if 0
+          dump_instrepo(instrepo, pool);
+
+#endif
+          if (!c->install_available)
+            {
+              queue_empty(&job);
+              for (i = 1; i < c->updatestart; i++)
+                {
+                  if (pool->solvables[i].repo != c->repo || i == pid)
+                    continue;
+                  queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE);
+                  queue_push(&job, i);
+                }
+            }
+          queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE);
+          queue_push(&job, pid);
+          solv = solver_create(pool);
+          /* solver_set_flag(solv, SOLVER_FLAG_IGNORE_RECOMMENDED, 1); */
+          ++solver_runs;
+          if (solver_solve(solv, &job))
+            {
+              c->status = 1;
+              showproblems(solv, s, 0, 0);
+            }
+          frominst(solv, c->repo, c->instrepo);
+          solver_free(solv);
+        }
+    }
+
+  if (PERF_DEBUGGING)
+    printf("  test_all_packages_installable took %d ms in %d runs\n", solv_timems(now), solver_runs);
+}
+
+void
+test_can_upgrade_all_packages(context_t *c, Id pid)
+{
+  Solver *solv;
+  Id p;
+  Id con, *conp;
+  Queue job;
+  Queue cand;
+  Queue badguys;
+  int i, j;
+  unsigned int now, solver_runs;
+  Solvable *s = pool->solvables + pid;
+
+  queue_init(&job);
+  queue_init(&cand);
+  queue_init(&badguys);
+
+  now = solv_timems(0);
+  solver_runs = 0;
+
+  /* Test 3: can we upgrade all packages? */
+  for (p = 1; p < pool->nsolvables; p++)
+    {
+      Solvable *s = pool->solvables + p;
+      if (!s->repo)
+        continue;
+      if (strchr(pool_id2str(pool, s->name), ':'))
+        continue;      /* only packages, please */
+      if (!pool_installable(pool, s))
+        continue;
+      queue_push(&cand, p);
+    }
+  while (cand.count)
+    {
+      solv = solver_create(pool);
+      queue_empty(&job);
+      for (i = 0; i < badguys.count; i++)
+        {
+          queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE|SOLVER_WEAK);
+          queue_push(&job, badguys.elements[i]);
+        }
+      conp = s->repo->idarraydata + s->conflicts;
+      while ((con = *conp++) != 0)
+        {
+          queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
+          queue_push(&job, con);
+        }
+      for (i = 0; i < cand.count; i++)
+        {
+          p = cand.elements[i];
+          queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_WEAK);
+          queue_push(&job, p);
+        }
+      ++solver_runs;
+      solver_solve(solv, &job);
+#if 0
+      solver_printdecisions(solv);
+#endif
+      /* put packages into installed repo and prune them from cand */
+      toinst(solv, c->repo, c->instrepo);
+      for (i = 0; i < cand.count; i++)
+        {
+          p = cand.elements[i];
+          if (p > 0 && solver_get_decisionlevel(solv, p) > 0)
+            cand.elements[i] = -p;     /* drop candidate */
+        }
+      solver_free(solv);
+
+      /* now the interesting part: test patch */
+      queue_empty(&job);
+      if (!c->install_available)
+        {
+          for (i = 1; i < c->updatestart; i++)
+            {
+              if (pool->solvables[i].repo != c->repo || i == pid)
+                continue;
+              queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE);
+              queue_push(&job, i);
+            }
+        }
+      queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE);
+      queue_push(&job, pid);
+      solv = solver_create(pool);
+      solver_set_flag(solv, SOLVER_FLAG_IGNORE_RECOMMENDED, 1);
+      ++solver_runs;
+      if (solver_solve(solv, &job))
+        {
+          c->status = 1;
+          showproblems(solv, s, &cand, &badguys);
+        }
+      frominst(solv, c->repo, c->instrepo);
+      solver_free(solv);
+      /* now drop all negative elements from cand */
+      for (i = j = 0; i < cand.count; i++)
+        {
+          if (cand.elements[i] < 0)
+            continue;
+          cand.elements[j++] = cand.elements[i];
+        }
+      if (i == j)
+        break; /* no progress */
+      cand.count = j;
+    }
+  if (PERF_DEBUGGING)
+    printf("  test_can_upgrade_all_packages took %d ms in %d runs\n", solv_timems(now), solver_runs);
+}
+
+void
+test_no_ga_package_fulfills_dependency(context_t *c, Id pid)
+{
+  Id con, *conp;
+  Solvable *s = pool->solvables + pid;
+
+  /* Test 4: no GA package fulfills patch dependency */
+  conp = s->repo->idarraydata + s->conflicts;
+  while ((con = *conp++) != 0)
+    {
+      Reldep *rd;
+      Id rp, rpp;
+
+      if (!ISRELDEP(con))
+        continue;
+      rd = GETRELDEP(pool, con);
+      FOR_PROVIDES(rp, rpp, rd->name)
+        {
+          Solvable *s2 = pool_id2solvable(pool, rp);
+          if (rp < c->updatestart
+              && pool_evrcmp(pool, rd->evr, s2->evr, EVRCMP_COMPARE) < 0
+              && pool_match_nevr_rel(pool, s2, rd->name)
+             )
+            {
+              SHOW_PATCH(c);
+              printf("  conflict %s < %s satisfied by non-updated package %s\n",
+                  pool_dep2str(pool, rd->name), pool_dep2str(pool, rd->evr), pool_solvable2str(pool, s2));
+              break;
+            }
+        }
+    }
+}
+
 int
 main(int argc, char **argv)
 {
-  Pool *pool;
   char *arch, *mypatch;
   const char *pname;
-  int l;
+  int l, r;
   FILE *fp;
-  int i, j;
-  Queue job;
-  Queue cand;
-  Queue badguys;
+  int i;
   Id pid, p, pp;
-  Id con, *conp;
-  Solver *solv;
-  Repo *repo, *instrepo;
-  int status = 0;
   int tests = 0;
-  int updatestart = 0;
+  context_t c;
+  static const char* langs[] = {"en"};
+
+  c.install_available = 0;
+  c.updatestart = 0;
+  c.status = 0;
 
   if (argc <= 3)
     usage(argv);
@@ -239,7 +507,6 @@ main(int argc, char **argv)
   arch = argv[1];
   pool = pool_create();
   pool_setarch(pool, arch);
-  static const char* langs[] = {"en"};
   pool_set_languages(pool, langs, 1);
 
 #if 0
@@ -248,42 +515,59 @@ main(int argc, char **argv)
 
   mypatch = argv[2];
 
-  repo = repo_create(pool, 0);
-  instrepo = repo_create(pool, 0);
+  c.repo = repo_create(pool, 0);
+  c.instrepo = repo_create(pool, 0);
   for (i = 3; i < argc; i++)
     {
       if (!strcmp(argv[i], "--updaterepos"))
        {
-         updatestart = pool->nsolvables;
+         c.updatestart = pool->nsolvables;
          continue;
        }
+
+      if (!strcmp(argv[i], "--install-available"))
+       {
+         c.install_available = 1;
+         continue;
+       }
       l = strlen(argv[i]);
       if (!strcmp(argv[i], "-"))
         fp = stdin;
-      else if ((fp = myfopen(argv[i])) == 0)
+      else if ((fp = solv_xfopen(argv[i], 0)) == 0)
         {
           perror(argv[i]);
           exit(1);
         }
-      if (l >= 8 && !strcmp(argv[i] + l - 8, "packages"))
+      r = 0;
+      if (0)
+       {
+       }
+#ifdef ENABLE_SUSEREPO
+      else if (l >= 8 && !strcmp(argv[i] + l - 8, "packages"))
         {
-          repo_add_susetags(repo, fp, 0, 0, 0);
+          r = repo_add_susetags(c.repo, fp, 0, 0, 0);
         }
       else if (l >= 11 && !strcmp(argv[i] + l - 11, "packages.gz"))
         {
-          repo_add_susetags(repo, fp, 0, 0, 0);
+          r = repo_add_susetags(c.repo, fp, 0, 0, 0);
         }
+#endif
+#ifdef ENABLE_RPMMD
       else if (l >= 14 && !strcmp(argv[i] + l - 14, "primary.xml.gz"))
         {
-          repo_add_rpmmd(repo, fp, 0, 0);
+          r = repo_add_rpmmd(c.repo, fp, 0, 0);
         }
       else if (l >= 17 && !strcmp(argv[i] + l - 17, "updateinfo.xml.gz"))
        {
-          repo_add_updateinfoxml(repo, fp, 0);
+          r = repo_add_updateinfoxml(c.repo, fp, 0);
        }
-      else if (repo_add_solv(repo, fp))
+#endif
+      else
+       r = repo_add_solv(c.repo, fp, 0);
+      if (r)
         {
-          fprintf(stderr, "could not add repo %s\n", argv[i]);
+          fprintf(stderr, "could not add repo %s: %s\n", argv[i], pool_errstr(pool));
           exit(1);
         }
       if (fp != stdin)
@@ -293,27 +577,24 @@ main(int argc, char **argv)
   pool_addfileprovides(pool);
 
   /* bad hack ahead: clone repo */
-  instrepo->idarraydata = repo->idarraydata;
-  instrepo->idarraysize = repo->idarraysize;
-  instrepo->start = repo->start;
-  instrepo->end = repo->end;
-  instrepo->nsolvables = repo->nsolvables;     /* sic! */
-  instrepo->lastoff = repo->lastoff;   /* sic! */
-  pool_set_installed(pool, instrepo);
+  c.instrepo->idarraydata = c.repo->idarraydata;
+  c.instrepo->idarraysize = c.repo->idarraysize;
+  c.instrepo->start = c.repo->start;
+  c.instrepo->end = c.repo->end;
+  c.instrepo->nsolvables = c.repo->nsolvables; /* sic! */
+  pool_set_installed(pool, c.instrepo);
   pool_createwhatprovides(pool);
 
-  queue_init(&job);
-  queue_init(&cand);
-  queue_init(&badguys);
-
   for (pid = 1; pid < pool->nsolvables; pid++)
     {
-      Solvable *s = pool->solvables + pid;
+      Solvable *s;
+      c.shown = 0;
+      s = pool->solvables + pid;
       if (!s->repo)
         continue;
       if (!pool_installable(pool, s))
         continue;
-      pname = id2str(pool, s->name);
+      pname = pool_id2str(pool, s->name);
       if (strncmp(pname, "patch:", 6) != 0)
        continue;
 
@@ -326,7 +607,7 @@ main(int argc, char **argv)
              l = strlen(pname + 6);
              if (mypatch[l] != '-')
                continue;
-             if (strcmp(mypatch + l + 1, id2str(pool, s->evr)) != 0)
+             if (strcmp(mypatch + l + 1, pool_id2str(pool, s->evr)) != 0)
                continue;
            }
        }
@@ -335,7 +616,7 @@ main(int argc, char **argv)
          FOR_PROVIDES(p, pp, s->name)
            {
              Solvable *s2 = pool->solvables + p;
-             if (evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE) < 0)
+             if (pool_evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE) < 0)
                break;
            }
          if (p) {
@@ -348,197 +629,14 @@ main(int argc, char **argv)
        continue;
 
 #if 0
-      printf("testing patch %s-%s\n", pname + 6, id2str(pool, s->evr));
+      printf("testing patch %s-%s\n", pname + 6, pool_id2str(pool, s->evr));
 #endif
 
-      if (1) {
-
-      /* Test 1: are all old patches included */
-      FOR_PROVIDES(p, pp, s->name)
-        {
-         Solvable *s2 = pool->solvables + p;
-         Id con2, *conp2;
-         int shown = 0;
-
-         if (evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE) <= 0)
-           continue;
-         if (!s2->conflicts)
-           continue;
-         conp2 = s2->repo->idarraydata + s2->conflicts;
-          while ((con2 = *conp2++) != 0)
-           {
-             Reldep *rd2;
-             if (!ISRELDEP(con2))
-               continue;
-             rd2 = GETRELDEP(pool, con2);
-             conp = s->repo->idarraydata + s->conflicts;
-             while ((con = *conp++) != 0)
-               {
-                 Reldep *rd;
-                 if (!ISRELDEP(con))
-                   continue;
-                 rd = GETRELDEP(pool, con);
-                 if (rd->name == rd2->name)
-                   break;
-               }
-             if (!con)
-               {
-                 if (!shown++)
-                   printf("%s:\n", solvable2str(pool, s));
-                 printf("  %s contained %s\n", solvable2str(pool, s2), dep2str(pool, rd2->name));
-               }
-           }
-       }
-      }
-
-      if (1) {
-
-      /* Test 2: are the packages installable */
-      conp = s->repo->idarraydata + s->conflicts;
-      while ((con = *conp++) != 0)
-       {
-         FOR_PROVIDES(p, pp, con)
-           {
-             queue_empty(&job);
-             queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_WEAK);
-             queue_push(&job, p);
-
-             /* also set up some minimal system */
-             queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
-             queue_push(&job, str2id(pool, "rpm", 1));
-             queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
-             queue_push(&job, str2id(pool, "aaa_base", 1));
-
-             solv = solver_create(pool);
-             solv->dontinstallrecommended = 0;
-             solver_solve(solv, &job);
-             if (solv->problems.count)
-               {
-                 status = 1;
-                  printf("error installing original package\n");
-                 showproblems(solv, s, 0, 0);
-               }
-             toinst(solv, repo, instrepo);
-             solver_free(solv);
-
-#if 0
-              dump_instrepo(instrepo, pool);
-
-#endif
-#if 1
-             queue_empty(&job);
-             for (i = 1; i < updatestart; i++)
-               {
-                 if (pool->solvables[i].repo != repo || i == pid)
-                   continue;
-                 queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE);
-                 queue_push(&job, i);
-               }
-             queue_push(&job, SOLVER_INSTALL_SOLVABLE);
-             queue_push(&job, pid);
-             solv = solver_create(pool);
-             /*solv->dontinstallrecommended = 1;*/
-             solver_solve(solv, &job);
-             if (solv->problems.count)
-               {
-                 status = 1;
-                 showproblems(solv, s, 0, 0);
-               }
-             frominst(solv, repo, instrepo);
-             solver_free(solv);
-#endif
-           }
-       }
-      }
-
-      if (1) {
-
-      /* Test 3: can we upgrade all packages? */
-      queue_empty(&cand);
-      queue_empty(&badguys);
-      for (p = 1; p < pool->nsolvables; p++)
-       {
-         Solvable *s = pool->solvables + p;
-          if (!s->repo)
-           continue;
-          if (strchr(id2str(pool, s->name), ':'))
-           continue;   /* only packages, please */
-         if (!pool_installable(pool, s))
-           continue;
-         queue_push(&cand, p);
-       }
-      while (cand.count)
-       {
-         solv = solver_create(pool);
-         queue_empty(&job);
-         for (i = 0; i < badguys.count; i++)
-           {
-             queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE|SOLVER_WEAK);
-             queue_push(&job, badguys.elements[i]);
-           }
-         conp = s->repo->idarraydata + s->conflicts;
-          while ((con = *conp++) != 0)
-           {
-             queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
-             queue_push(&job, con);
-           }
-         for (i = 0; i < cand.count; i++)
-           {
-             p = cand.elements[i];
-             queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_WEAK);
-             queue_push(&job, p);
-           }
-         solver_solve(solv, &job);
-#if 0
-         solver_printdecisions(solv);
-#endif
-         /* put packages into installed repo and prune them from cand */
-          toinst(solv, repo, instrepo);
-         for (i = 0; i < cand.count; i++)
-           {
-             p = cand.elements[i];
-             if (p > 0 && solv->decisionmap[p] > 0)
-               cand.elements[i] = -p;  /* drop candidate */
-           }
-         solver_free(solv);
-
-         /* now the interesting part: test patch */
-         queue_empty(&job);
-#if 0
-         for (i = 1; i < updatestart; i++)
-           {
-             if (pool->solvables[i].repo != repo || i == pid)
-               continue;
-             queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE);
-             queue_push(&job, i);
-           }
-#endif
-         queue_push(&job, SOLVER_INSTALL_SOLVABLE);
-         queue_push(&job, pid);
-         solv = solver_create(pool);
-         solv->dontinstallrecommended = 1;
-         solver_solve(solv, &job);
-
-         if (solv->problems.count)
-           {
-             status = 1;
-             showproblems(solv, s, &cand, &badguys);
-           }
-          frominst(solv, repo, instrepo);
-         solver_free(solv);
-         /* now drop all negative elements from cand */
-         for (i = j = 0; i < cand.count; i++)
-           {
-             if (cand.elements[i] < 0)
-               continue;
-             cand.elements[j++] = cand.elements[i];
-           }
-         if (i == j)
-           break;      /* no progress */
-         cand.count = j;
-       }
-      }
+      test_all_old_patches_included(&c, pid);
+      test_all_packages_installable(&c, pid);
+      test_can_upgrade_all_packages(&c, pid);
+      test_no_ga_package_fulfills_dependency(&c, pid);
     }
 
-  exit(status);
+  exit(c.status);
 }