18dfcfe1c87bad0f21b8378e3cd821c3bad5eeca
[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 int
70 main(int argc, char **argv)
71 {
72   Pool *pool;
73   Queue job;
74   Queue solq;
75   Solver *solv, *reusesolv = 0;
76   char *result = 0;
77   int resultflags = 0;
78   int debuglevel = 0;
79   int writeresult = 0;
80   char *writetestcase = 0;
81   int multijob = 0;
82   int rescallback = 0;
83   int c;
84   int ex = 0;
85   const char *list = 0;
86   int list_with_deps = 0;
87   FILE *fp;
88   const char *p;
89
90   queue_init(&solq);
91   while ((c = getopt(argc, argv, "vmrhL:l:s:T:")) >= 0)
92     {
93       switch (c)
94       {
95         case 'v':
96           debuglevel++;
97           break;
98         case 'r':
99           writeresult++;
100           break;
101         case 'm':
102           rescallback = 1;
103           break;
104         case 'h':
105           usage(0);
106           break;
107         case 'l':
108           list = optarg;
109           list_with_deps = 0;
110           break;
111         case 'L':
112           list = optarg;
113           list_with_deps = 1;
114           break;
115         case 's':
116           if ((p = strchr(optarg, ':')))
117             queue_push2(&solq, atoi(optarg), atoi(p + 1));
118           else
119             queue_push2(&solq, 1, atoi(optarg));
120           break;
121         case 'T':
122           writetestcase = optarg;
123           break;
124         default:
125           usage(1);
126           break;
127       }
128     }
129   if (optind == argc)
130     usage(1);
131   for (; optind < argc; optind++)
132     {
133       pool = pool_create();
134       pool_setdebuglevel(pool, debuglevel);
135       /* report all errors */
136       pool_setdebugmask(pool, pool->debugmask | SOLV_ERROR);
137
138       fp = fopen(argv[optind], "r");
139       if (!fp)
140         {
141           perror(argv[optind]);
142           exit(0);
143         }
144       while (!feof(fp))
145         {
146           queue_init(&job);
147           result = 0;
148           resultflags = 0;
149           solv = testcase_read(pool, fp, argv[optind], &job, &result, &resultflags);
150           if (!solv)
151             {
152               pool_free(pool);
153               exit(resultflags == 77 ? 77 : 1);
154             }
155           if (reusesolv)
156             {
157               solver_free(solv);
158               solv = reusesolv;
159               reusesolv = 0;
160             }
161           if (!multijob && !feof(fp))
162             multijob = 1;
163
164           if (multijob)
165             printf("test %d:\n", multijob++);
166           if (list)
167             {
168               Id p = 0;
169               int selflags = SELECTION_NAME|SELECTION_PROVIDES|SELECTION_CANON|SELECTION_DOTARCH|SELECTION_REL|SELECTION_GLOB|SELECTION_FLAT;
170               if (*list == '/')
171                 selflags |= SELECTION_FILELIST;
172               queue_empty(&job);
173               if (list_with_deps)
174                 p = testcase_str2solvid(pool, list);
175               if (p)
176                 queue_push2(&job, SOLVER_SOLVABLE, p);
177               else
178                 selection_make(pool, &job, list, selflags);
179               if (!job.elements)
180                 printf("No match\n");
181               else
182                 {
183                   Queue q;
184                   int i;
185                   queue_init(&q);
186                   selection_solvables(pool, &job, &q);
187                   for (i = 0; i < q.count; i++)
188                     {
189                       printf("  - %s\n", testcase_solvid2str(pool, q.elements[i]));
190                       if (list_with_deps)
191                         {
192                           int j, k;
193                           const char *vendor;
194                           static Id deps[] = {
195                             SOLVABLE_PROVIDES, SOLVABLE_REQUIRES, SOLVABLE_CONFLICTS, SOLVABLE_OBSOLETES,
196                             SOLVABLE_RECOMMENDS, SOLVABLE_SUGGESTS, SOLVABLE_SUPPLEMENTS, SOLVABLE_ENHANCES,
197                             SOLVABLE_PREREQ_IGNOREINST,
198                             0
199                           };
200                           vendor = pool_lookup_str(pool, q.elements[i], SOLVABLE_VENDOR);
201                           if (vendor)
202                             printf("    %s: %s\n", pool_id2str(pool, SOLVABLE_VENDOR), vendor);
203                           for (j = 0; deps[j]; j++)
204                             {
205                               Queue dq;
206                               queue_init(&dq);
207                               pool_lookup_idarray(pool, q.elements[i], deps[j], &dq);
208                               if (dq.count)
209                                 printf("    %s:\n", pool_id2str(pool, deps[j]));
210                               for (k = 0; k < dq.count; k++)
211                                 printf("      %s\n", pool_dep2str(pool, dq.elements[k]));
212                               queue_free(&dq);
213                             }
214                         }
215                     }
216                   queue_free(&q);
217                 }
218             }
219           else if (result || writeresult)
220             {
221               char *myresult, *resultdiff;
222               struct reportsolutiondata reportsolutiondata;
223               memset(&reportsolutiondata, 0, sizeof(reportsolutiondata));
224               if (rescallback)
225                 {
226                   solv->solution_callback = reportsolutioncb;
227                   solv->solution_callback_data = &reportsolutiondata;
228                 }
229               solver_solve(solv, &job);
230               solv->solution_callback = 0;
231               solv->solution_callback_data = 0;
232               if ((resultflags & ~TESTCASE_RESULT_REUSE_SOLVER) == 0)
233                 resultflags |= TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS;
234               myresult = testcase_solverresult(solv, resultflags);
235               if (rescallback && reportsolutiondata.result)
236                 {
237                   reportsolutiondata.result = solv_dupjoin(reportsolutiondata.result, myresult, 0);
238                   solv_free(myresult);
239                   myresult = reportsolutiondata.result;
240                 }
241               if (writeresult)
242                 {
243                   if (*myresult)
244                     {
245                       if (writeresult > 1)
246                         {
247                           const char *p;
248                           int i;
249                           
250                           printf("result ");
251                           p = "%s";
252                           for (i = 0; resultflags2str[i].str; i++)
253                             if ((resultflags & resultflags2str[i].flag) != 0)
254                               {
255                                 printf(p, resultflags2str[i].str);
256                                 p = ",%s";
257                               }
258                           printf(" <inline>\n");
259                           p = myresult;
260                           while (*p)
261                             {
262                               const char *p2 = strchr(p, '\n');
263                               p2 = p2 ? p2 + 1 : p + strlen(p);
264                               printf("#>%.*s", (int)(p2 - p), p);
265                               p = p2;
266                             }
267                         }
268                       else
269                         printf("%s", myresult);
270                     }
271                 }
272               else
273                 {
274                   resultdiff = testcase_resultdiff(result, myresult);
275                   if (resultdiff)
276                     {
277                       printf("Results differ:\n%s", resultdiff);
278                       ex = 1;
279                       solv_free(resultdiff);
280                     }
281                 }
282               solv_free(result);
283               solv_free(myresult);
284             }
285           else
286             {
287               int pcnt = solver_solve(solv, &job);
288               if (writetestcase)
289                 testcase_write(solv, writetestcase, resultflags, 0, 0);
290               if (pcnt && solq.count)
291                 {
292                   int i, taken = 0;
293                   for (i = 0; i < solq.count; i += 2)
294                     {
295                       if (solq.elements[i] > 0 && solq.elements[i] <= pcnt)
296                         if (solq.elements[i + 1] > 0 && solq.elements[i + 1] <=  solver_solution_count(solv, solq.elements[i]))
297                           {
298                             printf("problem %d: taking solution %d\n", solq.elements[i], solq.elements[i + 1]);
299                             solver_take_solution(solv, solq.elements[i], solq.elements[i + 1], &job);
300                             taken = 1;
301                           }
302                     }
303                   if (taken)
304                     pcnt = solver_solve(solv, &job);
305                 }
306               if (pcnt)
307                 {
308                   int problem, solution, scnt;
309                   printf("Found %d problems:\n", pcnt);
310                   for (problem = 1; problem <= pcnt; problem++)
311                     {
312                       printf("Problem %d:\n", problem);
313 #if 1
314                       solver_printprobleminfo(solv, problem);
315 #else
316                       {
317                         Queue pq;
318                         int j;
319                         queue_init(&pq);
320                         solver_findallproblemrules(solv, problem, &pq);
321                         for (j = 0; j < pq.count; j++)
322                           solver_printproblemruleinfo(solv, pq.elements[j]);
323                         queue_free(&pq);
324                       }
325 #endif
326                       printf("\n");
327                       scnt = solver_solution_count(solv, problem);
328                       for (solution = 1; solution <= scnt; solution++)
329                         {
330                           printf("Solution %d:\n", solution);
331                           solver_printsolution(solv, problem, solution);
332                           printf("\n");
333                         }
334                     }
335                 }
336               else
337                 {
338                   Transaction *trans = solver_create_transaction(solv);
339                   printf("Transaction summary:\n\n");
340                   transaction_print(trans);
341                   transaction_free(trans);
342                 }
343             }
344           queue_free(&job);
345           if ((resultflags & TESTCASE_RESULT_REUSE_SOLVER) != 0 && !feof(fp))
346             reusesolv = solv;
347           else
348             solver_free(solv);
349         }
350       if (reusesolv)
351         solver_free(reusesolv);
352       pool_free(pool);
353       fclose(fp);
354     }
355   queue_free(&solq);
356   exit(ex);
357 }