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