use sed instead of grep to get rid of the <?xml...> line
[platform/upstream/libsolv.git] / ext / testcase.c
index 72f9dc8..32547c8 100644 (file)
@@ -58,6 +58,7 @@ static struct jobflags2str {
   { SOLVER_ORUPDATE,  "orupdate" },
   { SOLVER_FORCEBEST, "forcebest" },
   { SOLVER_TARGETED,  "targeted" },
+  { SOLVER_NOTBYUSER, "notbyuser" },
   { SOLVER_SETEV,     "setev" },
   { SOLVER_SETEVR,    "setevr" },
   { SOLVER_SETARCH,   "setarch" },
@@ -97,6 +98,12 @@ static struct solverflags2str {
   { SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES,    "keepexplicitobsoletes", 0 },
   { SOLVER_FLAG_BEST_OBEY_POLICY,           "bestobeypolicy", 0 },
   { SOLVER_FLAG_NO_AUTOTARGET,              "noautotarget", 0 },
+  { SOLVER_FLAG_DUP_ALLOW_DOWNGRADE,        "dupallowdowngrade", 1 },
+  { SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE,       "dupallowarchchange", 1 },
+  { SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE,     "dupallowvendorchange", 1 },
+  { SOLVER_FLAG_DUP_ALLOW_NAMECHANGE,       "dupallownamechange", 1 },
+  { SOLVER_FLAG_KEEP_ORPHANS,               "keeporphans", 0 },
+  { SOLVER_FLAG_BREAK_ORPHANS,              "breakorphans", 0 },
   { 0, 0, 0 }
 };
 
@@ -110,8 +117,11 @@ static struct poolflags2str {
   { POOL_FLAG_OBSOLETEUSESPROVIDES,         "obsoleteusesprovides", 0 },
   { POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES, "implicitobsoleteusesprovides", 0 },
   { POOL_FLAG_OBSOLETEUSESCOLORS,           "obsoleteusescolors", 0 },
+  { POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS,   "implicitobsoleteusescolors", 0 },
   { POOL_FLAG_NOINSTALLEDOBSOLETES,         "noinstalledobsoletes", 0 },
   { POOL_FLAG_HAVEDISTEPOCH,                "havedistepoch", 0 },
+  { POOL_FLAG_NOOBSOLETESMULTIVERSION,      "noobsoletesmultiversion", 0 },
+  { POOL_FLAG_ADDFILEPROVIDESFILTERED,      "addfileprovidesfiltered", 0 },
   { 0, 0, 0 }
 };
 
@@ -122,6 +132,7 @@ static struct disttype2str {
   { DISTTYPE_RPM,  "rpm" },
   { DISTTYPE_DEB,  "deb" },
   { DISTTYPE_ARCH, "arch" },
+  { DISTTYPE_HAIKU, "haiku" },
   { 0, 0 }
 };
 
@@ -283,21 +294,14 @@ pool_isknownarch(Pool *pool, Id id)
   return 1;
 }
 
-Id
-testcase_str2dep(Pool *pool, char *s)
+static Id
+testcase_str2dep_simple(Pool *pool, const char **sp)
 {
-  char *n, *a;
-  Id id;
+  const char *s = *sp;
+  const char *n, *a;
+  Id id, evr;
   int flags;
 
-  if ((n = strchr(s, '|')) != 0)
-    {    
-      id = testcase_str2dep(pool, n + 1);
-      *n = 0; 
-      id = pool_rel2id(pool, testcase_str2dep(pool, s), id, REL_OR, 1);
-      *n = '|'; 
-      return id;
-    }
   while (*s == ' ' || *s == '\t')
     s++;
   n = s;
@@ -307,9 +311,9 @@ testcase_str2dep(Pool *pool, char *s)
        {
          while (*s && *s != ')')
            s++;
+         continue;
        }
-      else
-        s++;
+      s++;
     }
   if ((a = strchr(n, '.')) != 0 && a + 1 < s && s[-1] != ')')
     {
@@ -322,32 +326,105 @@ testcase_str2dep(Pool *pool, char *s)
       else
         id = pool_strn2id(pool, n, s - n, 1);
     }
+  else if (s - n > 4 && s[-4] == ':' && !strncmp(s - 4, ":any", 4))
+    {
+      id = pool_strn2id(pool, n, s - n - 4, 1);
+      id = pool_rel2id(pool, id, ARCH_ANY, REL_MULTIARCH, 1);
+    }
   else
     id = pool_strn2id(pool, n, s - n, 1);
   if (!*s)
-    return id;
+    {
+      *sp = s;
+      return id;
+    }
   while (*s == ' ' || *s == '\t')
     s++;
   flags = 0;
+  if (*s == '!' && s[1] == '=')        /* support != as synonym for <> */
+    {
+      flags = REL_LT | REL_GT;
+      s += 2;
+    }
   for (;;s++)
-    {  
+    {
       if (*s == '<')
-        flags |= REL_LT;
+       flags |= REL_LT;
       else if (*s == '=')
-        flags |= REL_EQ;
+       flags |= REL_EQ;
       else if (*s == '>')
-        flags |= REL_GT;
+       flags |= REL_GT;
       else
-        break;
+       break;
     }
   if (!flags)
-    return id;
+    {
+      *sp = s;
+      return id;
+    }
   while (*s == ' ' || *s == '\t')
     s++;
   n = s;
   while (*s && *s != ' ' && *s != '\t')
     s++;
-  return pool_rel2id(pool, id, pool_strn2id(pool, n, s - n, 1), flags, 1);
+  evr = pool_strn2id(pool, n, s - n, 1);
+  if (*s == ' ' && !strcmp(s, " compat >= "))
+    {
+      s += 11;
+      while (*s == ' ' || *s == '\t')
+       s++;
+      n = s;
+      while (*s && *s != ' ' && *s != '\t')
+       s++;
+      evr = pool_rel2id(pool, evr, pool_strn2id(pool, n, s - n, 1), REL_COMPAT, 1);
+    }
+  *sp = s;
+  return pool_rel2id(pool, id, evr, flags, 1);
+}
+
+static Id
+testcase_str2dep_complex(Pool *pool, const char **sp)
+{
+  const char *s = *sp;
+  Id id;
+#ifdef ENABLE_COMPLEX_DEPS
+  while (*s == ' ' || *s == '\t')
+    s++;
+  if (*s == '(')
+    {
+      s++;
+      id = testcase_str2dep_complex(pool, &s);
+      if (*s == ')')
+       s++;
+      while (*s == ' ' || *s == '\t')
+       s++;
+    }
+  else
+#endif
+    id = testcase_str2dep_simple(pool, &s);
+  if (*s == '|')
+    {
+      s++;
+      id = pool_rel2id(pool, id, testcase_str2dep_complex(pool, &s), REL_OR, 1);
+    }
+  else if (*s == '&')
+    {
+      s++;
+      id = pool_rel2id(pool, id, testcase_str2dep_complex(pool, &s), REL_AND, 1);
+    }
+  else if (*s == 'I' && s[1] == 'F' && (s[2] == ' ' || s[2] == '\t'))
+    {
+      s += 2;
+      id = pool_rel2id(pool, id, testcase_str2dep_complex(pool, &s), REL_COND, 1);
+    }
+  *sp = s;
+  return id;
+}
+
+Id
+testcase_str2dep(Pool *pool, const char *s)
+{
+  return testcase_str2dep_complex(pool, &s);
 }
 
 const char *
@@ -383,8 +460,8 @@ testcase_solvid2str(Pool *pool, Id p)
   n = pool_id2str(pool, s->name);
   e = pool_id2str(pool, s->evr);
   a = pool_id2str(pool, s->arch);
-  str = pool_alloctmpspace(pool, strlen(n) + strlen(e) + strlen(a) + 3); 
-  sprintf(str, "%s-%s.%s", n, e, a); 
+  str = pool_alloctmpspace(pool, strlen(n) + strlen(e) + strlen(a) + 3);
+  sprintf(str, "%s-%s.%s", n, e, a);
   if (!s->repo)
     return pool_tmpappend(pool, str, "@", 0);
   if (s->repo->name)
@@ -1017,15 +1094,15 @@ finish_solvable(Pool *pool, Repodata *data, Solvable *s, char *filelist, int nfi
   if (nfilelist)
     {
       int l;
-      Id did; 
-      for (l = 0; l < nfilelist; l += strlen(filelist + l) + 1) 
+      Id did;
+      for (l = 0; l < nfilelist; l += strlen(filelist + l) + 1)
        {
          char *p = strrchr(filelist + l, '/');
-         if (!p) 
+         if (!p)
            continue;
-         *p++ = 0; 
+         *p++ = 0;
          did = repodata_str2dir(data, filelist + l, 1);
-         p[-1] = '/'; 
+         p[-1] = '/';
          if (!did)
            did = repodata_str2dir(data, "/", 1);
          repodata_add_dirstr(data, s - pool->solvables, SOLVABLE_FILELIST, did, p);
@@ -1075,7 +1152,7 @@ testcase_add_testtags(Repo *repo, FILE *fp, int flags)
       linep += strlen(linep);
       if (linep == line || linep[-1] != '\n')
        continue;
-      *--linep = 0;
+      linep[-1] = 0;
       linep = line + intag;
       if (intag)
        {
@@ -1306,7 +1383,7 @@ testcase_ruleid(Solver *solv, Id rid)
   Strqueue sq;
   Queue q;
   int i;
-  void *chk;
+  Chksum *chk;
   const unsigned char *md5;
   int md5l;
   const char *s;
@@ -1339,7 +1416,7 @@ testcase_problemid(Solver *solv, Id problem)
 {
   Strqueue sq;
   Queue q;
-  void *chk;
+  Chksum *chk;
   const unsigned char *md5;
   int i, md5l;
   const char *s;
@@ -1366,7 +1443,7 @@ static const char *
 testcase_solutionid(Solver *solv, Id problem, Id solution)
 {
   Id intid;
-  void *chk;
+  Chksum *chk;
   const unsigned char *md5;
   int md5l;
   const char *s;
@@ -1526,16 +1603,26 @@ testcase_solverresult(Solver *solv, int resultflags)
 
   if ((resultflags & TESTCASE_RESULT_UNNEEDED) != 0)
     {
-      Queue q;
+      Queue q, qf;
 
       queue_init(&q);
+      queue_init(&qf);
       solver_get_unneeded(solv, &q, 0);
-      for (i = 0; i < q.count; i++)
+      solver_get_unneeded(solv, &qf, 1);
+      for (i = j = 0; i < q.count; i++)
        {
-         s = pool_tmpjoin(pool, "unneeded ", testcase_solvid2str(pool, q.elements[i]), 0);
+         /* we rely on qf containing a subset of q in the same order */
+         if (j < qf.count && q.elements[i] == qf.elements[j])
+           {
+             s = pool_tmpjoin(pool, "unneeded_filtered ", testcase_solvid2str(pool, q.elements[i]), 0);
+             j++;
+           }
+         else
+           s = pool_tmpjoin(pool, "unneeded ", testcase_solvid2str(pool, q.elements[i]), 0);
          strqueue_push(&sq, s);
        }
       queue_free(&q);
+      queue_free(&qf);
     }
 
   strqueue_sort(&sq);
@@ -1715,6 +1802,7 @@ testcase_write(Solver *solv, char *dir, int resultflags, const char *testcasenam
              pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n");
              solv_free(result);
              strqueue_free(&sq);
+             fclose(fp);
              return 0;
            }
          if (fclose(fp))
@@ -1739,6 +1827,7 @@ testcase_write(Solver *solv, char *dir, int resultflags, const char *testcasenam
     {
       pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n");
       strqueue_free(&sq);
+      fclose(fp);
       return 0;
     }
   if (fclose(fp))
@@ -1758,7 +1847,7 @@ read_inline_file(FILE *fp, char **bufp, char **bufpp, int *buflp)
   char *result = solv_malloc(1024);
   char *rp = result;
   int resultl = 1024;
-  
+
   for (;;)
     {
       size_t rl;
@@ -1813,7 +1902,7 @@ read_file(FILE *fp)
   char *result = solv_malloc(1024);
   char *rp = result;
   int resultl = 1024;
-  
+
   for (;;)
     {
       size_t rl;
@@ -1977,6 +2066,7 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp,
 #if 0
              else if (!strcmp(repotype, "helix"))
                {
+                 extern int repo_add_helix(Repo *repo, FILE *fp, int flags);
                  repo_add_helix(repo, rfp, 0);
                  fclose(rfp);
                }
@@ -2006,10 +2096,12 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp,
              pool_debug(pool, SOLV_ERROR, "testcase_read: system: cannot change disttype to '%s'\n", pieces[2]);
 #endif
            }
-         if (strcmp(pieces[1], "unset") != 0)
-           pool_setarch(pool, pieces[1]);
-         else
+         if (strcmp(pieces[1], "unset") == 0)
            pool_setarch(pool, 0);
+         else if (pieces[1][0] == ':')
+           pool_setarchpolicy(pool, pieces[1] + 1);
+         else
+           pool_setarch(pool, pieces[1]);
          if (npieces > 3)
            {
              Repo *repo = testcase_str2repo(pool, pieces[3]);
@@ -2101,22 +2193,26 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp,
          for (i = 1; i < npieces; i++)
            testcase_setsolverflags(solv, pieces[i]);
         }
-      else if (!strcmp(pieces[0], "result") && npieces > 2)
+      else if (!strcmp(pieces[0], "result") && npieces > 1)
        {
          char *result = 0;
          int resultflags = str2resultflags(pool, pieces[1]);
-         const char *rdata = pool_tmpjoin(pool, testcasedir, pieces[2], 0);
-         if (!strcmp(pieces[2], "<inline>"))
-           result = read_inline_file(fp, &buf, &bufp, &bufl);
-         else
+         const char *rdata;
+         if (npieces > 2)
            {
-              FILE *rfp = fopen(rdata, "r");
-             if (!rfp)
-               pool_debug(pool, SOLV_ERROR, "testcase_read: could not open '%s'\n", rdata);
+             rdata = pool_tmpjoin(pool, testcasedir, pieces[2], 0);
+             if (!strcmp(pieces[2], "<inline>"))
+               result = read_inline_file(fp, &buf, &bufp, &bufl);
              else
                {
-                 result = read_file(rfp);
-                 fclose(rfp);
+                 FILE *rfp = fopen(rdata, "r");
+                 if (!rfp)
+                   pool_debug(pool, SOLV_ERROR, "testcase_read: could not open '%s'\n", rdata);
+                 else
+                   {
+                     result = read_file(rfp);
+                     fclose(rfp);
+                   }
                }
            }
          if (resultp)