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