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