Imported Upstream version 0.7.19
[platform/upstream/libsolv.git] / tools / testsolv.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <getopt.h>
5
6 #include "pool.h"
7 #include "repo.h"
8 #include "solver.h"
9 #include "selection.h"
10 #include "solverdebug.h"
11 #include "testcase.h"
12
13 static struct resultflags2str {
14   Id flag;
15   const char *str;
16 } resultflags2str[] = {
17   { TESTCASE_RESULT_TRANSACTION,        "transaction" },
18   { TESTCASE_RESULT_PROBLEMS,           "problems" },
19   { TESTCASE_RESULT_ORPHANED,           "orphaned" },
20   { TESTCASE_RESULT_RECOMMENDED,        "recommended" },
21   { TESTCASE_RESULT_UNNEEDED,           "unneeded" },
22   { TESTCASE_RESULT_ALTERNATIVES,       "alternatives" },
23   { TESTCASE_RESULT_RULES,              "rules" },
24   { TESTCASE_RESULT_GENID,              "genid" },
25   { TESTCASE_RESULT_REASON,             "reason" },
26   { TESTCASE_RESULT_CLEANDEPS,          "cleandeps" },
27   { TESTCASE_RESULT_JOBS,               "jobs" },
28   { 0, 0 }
29 };
30
31 static void
32 usage(int ex)
33 {
34   fprintf(ex ? stderr : stdout, "Usage: testsolv <testcase>\n");
35   exit(ex);
36 }
37
38 struct reportsolutiondata {
39   int count;
40   char *result;
41 };
42
43 static int
44 reportsolutioncb(Solver *solv, void *cbdata)
45 {
46   struct reportsolutiondata *sd = cbdata;
47   char *res;
48
49   sd->count++;
50   res = testcase_solverresult(solv, TESTCASE_RESULT_TRANSACTION);
51   if (*res)
52     {
53       char prefix[64];
54       char *p2, *p = res;
55       sprintf(prefix, "callback%d:", sd->count);
56       while ((p2 = strchr(p, '\n')) != 0)
57         {
58           char c = p2[1];
59           p2[1] = 0;
60           sd->result = solv_dupappend(sd->result, prefix, p);
61           p2[1] = c;
62           p = p2 + 1;
63         }
64     }
65   solv_free(res);
66   return 0;
67 }
68
69 static void
70 free_considered(Pool *pool)
71 {
72   if (pool->considered)
73     {
74       map_free(pool->considered);
75       pool->considered = solv_free(pool->considered);
76     }
77 }
78
79 int
80 main(int argc, char **argv)
81 {
82   Pool *pool;
83   Queue job;
84   Queue solq;
85   Solver *solv, *reusesolv = 0;
86   char *result = 0;
87   int resultflags = 0;
88   int debuglevel = 0;
89   int writeresult = 0;
90   char *writetestcase = 0;
91   int multijob = 0;
92   int rescallback = 0;
93   int c;
94   int ex = 0;
95   const char *list = 0;
96   int list_with_deps = 0;
97   FILE *fp;
98   const char *p;
99
100   queue_init(&solq);
101   while ((c = getopt(argc, argv, "vmrhL:l:s:T:")) >= 0)
102     {
103       switch (c)
104       {
105         case 'v':
106           debuglevel++;
107           break;
108         case 'r':
109           writeresult++;
110           break;
111         case 'm':
112           rescallback = 1;
113           break;
114         case 'h':
115           usage(0);
116           break;
117         case 'l':
118           list = optarg;
119           list_with_deps = 0;
120           break;
121         case 'L':
122           list = optarg;
123           list_with_deps = 1;
124           break;
125         case 's':
126           if ((p = strchr(optarg, ':')))
127             queue_push2(&solq, atoi(optarg), atoi(p + 1));
128           else
129             queue_push2(&solq, 1, atoi(optarg));
130           break;
131         case 'T':
132           writetestcase = optarg;
133           break;
134         default:
135           usage(1);
136           break;
137       }
138     }
139   if (optind == argc)
140     usage(1);
141   for (; optind < argc; optind++)
142     {
143       pool = pool_create();
144       pool_setdebuglevel(pool, debuglevel);
145       /* report all errors */
146       pool_setdebugmask(pool, pool->debugmask | SOLV_ERROR);
147
148       fp = fopen(argv[optind], "r");
149       if (!fp)
150         {
151           perror(argv[optind]);
152           exit(0);
153         }
154       while (!feof(fp))
155         {
156           queue_init(&job);
157           result = 0;
158           resultflags = 0;
159           solv = testcase_read(pool, fp, argv[optind], &job, &result, &resultflags);
160           if (!solv)
161             {
162               free_considered(pool);
163               pool_free(pool);
164               queue_free(&job);
165               exit(resultflags == 77 ? 77 : 1);
166             }
167           if (reusesolv)
168             {
169               solver_free(solv);
170               solv = reusesolv;
171               reusesolv = 0;
172             }
173           if (!multijob && !feof(fp))
174             multijob = 1;
175
176           if (multijob)
177             printf("test %d:\n", multijob++);
178           if (list)
179             {
180               Id p = 0;
181               int selflags = SELECTION_NAME|SELECTION_PROVIDES|SELECTION_CANON|SELECTION_DOTARCH|SELECTION_REL|SELECTION_GLOB|SELECTION_FLAT;
182               if (*list == '/')
183                 selflags |= SELECTION_FILELIST;
184               queue_empty(&job);
185               if (list_with_deps)
186                 p = testcase_str2solvid(pool, list);
187               if (p)
188                 queue_push2(&job, SOLVER_SOLVABLE, p);
189               else
190                 selection_make(pool, &job, list, selflags);
191               if (!job.elements)
192                 printf("No match\n");
193               else
194                 {
195                   Queue q;
196                   int i;
197                   queue_init(&q);
198                   selection_solvables(pool, &job, &q);
199                   for (i = 0; i < q.count; i++)
200                     {
201                       printf("  - %s\n", testcase_solvid2str(pool, q.elements[i]));
202                       if (list_with_deps)
203                         {
204                           int j, k;
205                           const char *vendor;
206                           static Id deps[] = {
207                             SOLVABLE_PROVIDES, SOLVABLE_REQUIRES, SOLVABLE_CONFLICTS, SOLVABLE_OBSOLETES,
208                             SOLVABLE_RECOMMENDS, SOLVABLE_SUGGESTS, SOLVABLE_SUPPLEMENTS, SOLVABLE_ENHANCES,
209                             SOLVABLE_PREREQ_IGNOREINST,
210                             0
211                           };
212                           vendor = pool_lookup_str(pool, q.elements[i], SOLVABLE_VENDOR);
213                           if (vendor)
214                             printf("    %s: %s\n", pool_id2str(pool, SOLVABLE_VENDOR), vendor);
215                           for (j = 0; deps[j]; j++)
216                             {
217                               Queue dq;
218                               queue_init(&dq);
219                               pool_lookup_idarray(pool, q.elements[i], deps[j], &dq);
220                               if (dq.count)
221                                 printf("    %s:\n", pool_id2str(pool, deps[j]));
222                               for (k = 0; k < dq.count; k++)
223                                 printf("      %s\n", pool_dep2str(pool, dq.elements[k]));
224                               queue_free(&dq);
225                             }
226                         }
227                     }
228                   queue_free(&q);
229                 }
230             }
231           else if (result || writeresult)
232             {
233               char *myresult, *resultdiff;
234               struct reportsolutiondata reportsolutiondata;
235               memset(&reportsolutiondata, 0, sizeof(reportsolutiondata));
236               if (rescallback)
237                 {
238                   solv->solution_callback = reportsolutioncb;
239                   solv->solution_callback_data = &reportsolutiondata;
240                 }
241               solver_solve(solv, &job);
242               solv->solution_callback = 0;
243               solv->solution_callback_data = 0;
244               if ((resultflags & ~TESTCASE_RESULT_REUSE_SOLVER) == 0)
245                 resultflags |= TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS;
246               myresult = testcase_solverresult(solv, resultflags);
247               if (rescallback && reportsolutiondata.result)
248                 {
249                   reportsolutiondata.result = solv_dupjoin(reportsolutiondata.result, myresult, 0);
250                   solv_free(myresult);
251                   myresult = reportsolutiondata.result;
252                 }
253               if (writeresult)
254                 {
255                   if (*myresult)
256                     {
257                       if (writeresult > 1)
258                         {
259                           const char *p;
260                           int i;
261                           
262                           printf("result ");
263                           p = "%s";
264                           for (i = 0; resultflags2str[i].str; i++)
265                             if ((resultflags & resultflags2str[i].flag) != 0)
266                               {
267                                 printf(p, resultflags2str[i].str);
268                                 p = ",%s";
269                               }
270                           printf(" <inline>\n");
271                           p = myresult;
272                           while (*p)
273                             {
274                               const char *p2 = strchr(p, '\n');
275                               p2 = p2 ? p2 + 1 : p + strlen(p);
276                               printf("#>%.*s", (int)(p2 - p), p);
277                               p = p2;
278                             }
279                         }
280                       else
281                         printf("%s", myresult);
282                     }
283                 }
284               else
285                 {
286                   resultdiff = testcase_resultdiff(result, myresult);
287                   if (resultdiff)
288                     {
289                       printf("Results differ:\n%s", resultdiff);
290                       ex = 1;
291                       solv_free(resultdiff);
292                     }
293                 }
294               solv_free(result);
295               solv_free(myresult);
296             }
297           else
298             {
299               int pcnt = solver_solve(solv, &job);
300               if (writetestcase)
301                 testcase_write(solv, writetestcase, resultflags, 0, 0);
302               if (pcnt && solq.count)
303                 {
304                   int i, taken = 0;
305                   for (i = 0; i < solq.count; i += 2)
306                     {
307                       if (solq.elements[i] > 0 && solq.elements[i] <= pcnt)
308                         if (solq.elements[i + 1] > 0 && solq.elements[i + 1] <=  solver_solution_count(solv, solq.elements[i]))
309                           {
310                             printf("problem %d: taking solution %d\n", solq.elements[i], solq.elements[i + 1]);
311                             solver_take_solution(solv, solq.elements[i], solq.elements[i + 1], &job);
312                             taken = 1;
313                           }
314                     }
315                   if (taken)
316                     pcnt = solver_solve(solv, &job);
317                 }
318               if (pcnt)
319                 {
320                   int problem, solution, scnt;
321                   printf("Found %d problems:\n", pcnt);
322                   for (problem = 1; problem <= pcnt; problem++)
323                     {
324                       printf("Problem %d:\n", problem);
325 #if 1
326                       solver_printprobleminfo(solv, problem);
327 #else
328                       {
329                         Queue pq;
330                         int j;
331                         queue_init(&pq);
332                         solver_findallproblemrules(solv, problem, &pq);
333                         for (j = 0; j < pq.count; j++)
334                           solver_printproblemruleinfo(solv, pq.elements[j]);
335                         queue_free(&pq);
336                       }
337 #endif
338                       printf("\n");
339                       scnt = solver_solution_count(solv, problem);
340                       for (solution = 1; solution <= scnt; solution++)
341                         {
342                           printf("Solution %d:\n", solution);
343                           solver_printsolution(solv, problem, solution);
344                           printf("\n");
345                         }
346                     }
347                 }
348               else
349                 {
350                   Transaction *trans = solver_create_transaction(solv);
351                   printf("Transaction summary:\n\n");
352                   transaction_print(trans);
353                   transaction_free(trans);
354                 }
355             }
356           queue_free(&job);
357           if ((resultflags & TESTCASE_RESULT_REUSE_SOLVER) != 0 && !feof(fp))
358             reusesolv = solv;
359           else
360             solver_free(solv);
361         }
362       if (reusesolv)
363         solver_free(reusesolv);
364       free_considered(pool);
365       pool_free(pool);
366       fclose(fp);
367     }
368   queue_free(&solq);
369   exit(ex);
370 }