add '-m' option to test the solution callback
[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   { 0, 0 }
22 };
23
24 static void
25 usage(ex)
26 {
27   fprintf(ex ? stderr : stdout, "Usage: testsolv <testcase>\n");
28   exit(ex);
29 }
30
31 struct reportsolutiondata {
32   int count;
33   char *result;
34 };
35
36 static int
37 reportsolutioncb(Solver *solv, void *cbdata)
38 {
39   struct reportsolutiondata *sd = cbdata;
40   char *res;
41
42   sd->count++;
43   res = testcase_solverresult(solv, TESTCASE_RESULT_TRANSACTION);
44   if (*res)
45     {
46       char prefix[64];
47       char *p2, *p = res;
48       sprintf(prefix, "callback%d:", sd->count);
49       while ((p2 = strchr(p, '\n')) != 0)
50         {
51           char c = p2[1];
52           p2[1] = 0;
53           sd->result = solv_dupappend(sd->result, prefix, p);
54           p2[1] = c;
55           p = p2 + 1;
56         }
57     }
58   solv_free(res);
59   return 0;
60 }
61
62 int
63 main(int argc, char **argv)
64 {
65   Pool *pool;
66   Queue job;
67   Queue solq;
68   Solver *solv;
69   char *result = 0;
70   int resultflags = 0;
71   int debuglevel = 0;
72   int writeresult = 0;
73   int multijob = 0;
74   int rescallback = 0;
75   int c;
76   int ex = 0;
77   const char *list = 0;
78   FILE *fp;
79   const char *p;
80
81   queue_init(&solq);
82   while ((c = getopt(argc, argv, "vmrhl:s:")) >= 0)
83     {
84       switch (c)
85       {
86         case 'v':
87           debuglevel++;
88           break;
89         case 'r':
90           writeresult++;
91           break;
92         case 'm':
93           rescallback = 1;
94           break;
95         case 'h':
96           usage(0);
97           break;
98         case 'l':
99           list = optarg;
100           break;
101         case 's':
102           if ((p = strchr(optarg, ':')))
103             queue_push2(&solq, atoi(optarg), atoi(p + 1));
104           else
105             queue_push2(&solq, 1, atoi(optarg));
106           break;
107         default:
108           usage(1);
109           break;
110       }
111     }
112   if (optind == argc)
113     usage(1);
114   for (; optind < argc; optind++)
115     {
116       pool = pool_create();
117       pool_setdebuglevel(pool, debuglevel);
118
119       fp = fopen(argv[optind], "r");
120       if (!fp)
121         {
122           perror(argv[optind]);
123           exit(0);
124         }
125       while (!feof(fp))
126         {
127           queue_init(&job);
128           result = 0;
129           resultflags = 0;
130           solv = testcase_read(pool, fp, argv[optind], &job, &result, &resultflags);
131           if (!solv)
132             {
133               pool_free(pool);
134               exit(1);
135             }
136
137           if (!multijob && !feof(fp))
138             multijob = 1;
139
140           if (multijob)
141             printf("test %d:\n", multijob++);
142           if (list)
143             {
144               queue_empty(&job);
145               selection_make(pool, &job, list, SELECTION_NAME|SELECTION_PROVIDES|SELECTION_FILELIST|SELECTION_CANON|SELECTION_DOTARCH|SELECTION_REL|SELECTION_GLOB|SELECTION_FLAT);
146               if (!job.elements)
147                 printf("No match\n");
148               else
149                 {
150                   Queue q;
151                   int i;
152                   queue_init(&q);
153                   selection_solvables(pool, &job, &q);
154                   for (i = 0; i < q.count; i++)
155                     printf("  - %s\n", testcase_solvid2str(pool, q.elements[i]));
156                   queue_free(&q);
157                 }
158             }
159           else if (result || writeresult)
160             {
161               char *myresult, *resultdiff;
162               struct reportsolutiondata reportsolutiondata;
163               memset(&reportsolutiondata, 0, sizeof(reportsolutiondata));
164               if (rescallback)
165                 {
166                   solv->solution_callback = reportsolutioncb;
167                   solv->solution_callback_data = &reportsolutiondata;
168                 }
169               solver_solve(solv, &job);
170               solv->solution_callback = 0;
171               solv->solution_callback_data = 0;
172               if (!resultflags)
173                 resultflags = TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS;
174               myresult = testcase_solverresult(solv, resultflags);
175               if (rescallback && reportsolutiondata.result)
176                 {
177                   reportsolutiondata.result = solv_dupjoin(reportsolutiondata.result, myresult, 0);
178                   solv_free(myresult);
179                   myresult = reportsolutiondata.result;
180                 }
181               if (writeresult)
182                 {
183                   if (*myresult)
184                     {
185                       if (writeresult > 1)
186                         {
187                           const char *p;
188                           int i;
189                           
190                           printf("result ");
191                           p = "%s";
192                           for (i = 0; resultflags2str[i].str; i++)
193                             if ((resultflags & resultflags2str[i].flag) != 0)
194                               {
195                                 printf(p, resultflags2str[i].str);
196                                 p = ",%s";
197                               }
198                           printf(" <inline>\n");
199                           p = myresult;
200                           while (*p)
201                             {
202                               const char *p2 = strchr(p, '\n');
203                               p2 = p2 ? p2 + 1 : p + strlen(p);
204                               printf("#>%.*s", (int)(p2 - p), p);
205                               p = p2;
206                             }
207                         }
208                       else
209                         printf("%s", myresult);
210                     }
211                 }
212               else
213                 {
214                   resultdiff = testcase_resultdiff(result, myresult);
215                   if (resultdiff)
216                     {
217                       printf("Results differ:\n%s", resultdiff);
218                       ex = 1;
219                       solv_free(resultdiff);
220                     }
221                 }
222               solv_free(result);
223               solv_free(myresult);
224             }
225           else
226             {
227               int pcnt = solver_solve(solv, &job);
228               if (pcnt && solq.count)
229                 {
230                   int i, taken = 0;
231                   for (i = 0; i < solq.count; i += 2)
232                     {
233                       if (solq.elements[i] > 0 && solq.elements[i] <= pcnt)
234                         if (solq.elements[i + 1] > 0 && solq.elements[i + 1] <=  solver_solution_count(solv, solq.elements[i]))
235                           {
236                             printf("problem %d: taking solution %d\n", solq.elements[i], solq.elements[i + 1]);
237                             solver_take_solution(solv, solq.elements[i], solq.elements[i + 1], &job);
238                             taken = 1;
239                           }
240                     }
241                   if (taken)
242                     pcnt = solver_solve(solv, &job);
243                 }
244               if (pcnt)
245                 {
246                   int problem, solution, scnt;
247                   printf("Found %d problems:\n", pcnt);
248                   for (problem = 1; problem <= pcnt; problem++)
249                     {
250                       printf("Problem %d:\n", problem);
251 #if 1
252                       solver_printprobleminfo(solv, problem);
253 #else
254                       {
255                         Queue pq;
256                         int j;
257                         queue_init(&pq);
258                         solver_findallproblemrules(solv, problem, &pq);
259                         for (j = 0; j < pq.count; j++)
260                           solver_printproblemruleinfo(solv, pq.elements[j]);
261                         queue_free(&pq);
262                       }
263 #endif
264                       printf("\n");
265                       scnt = solver_solution_count(solv, problem);
266                       for (solution = 1; solution <= scnt; solution++)
267                         {
268                           printf("Solution %d:\n", solution);
269                           solver_printsolution(solv, problem, solution);
270                           printf("\n");
271                         }
272                     }
273                 }
274               else
275                 {
276                   Transaction *trans = solver_create_transaction(solv);
277                   printf("Transaction summary:\n\n");
278                   transaction_print(trans);
279                   transaction_free(trans);
280                 }
281             }
282           queue_free(&job);
283           solver_free(solv);
284         }
285       pool_free(pool);
286       fclose(fp);
287     }
288   queue_free(&solq);
289   exit(ex);
290 }