5c4939411fa4632c7ce51e0a636eb4d6e469f144
[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(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;
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
144           if (!multijob && !feof(fp))
145             multijob = 1;
146
147           if (multijob)
148             printf("test %d:\n", multijob++);
149           if (list)
150             {
151               int selflags = SELECTION_NAME|SELECTION_PROVIDES|SELECTION_CANON|SELECTION_DOTARCH|SELECTION_REL|SELECTION_GLOB|SELECTION_FLAT;
152               if (*list == '/')
153                 selflags |= SELECTION_FILELIST;
154               queue_empty(&job);
155               selection_make(pool, &job, list, selflags);
156               if (!job.elements)
157                 printf("No match\n");
158               else
159                 {
160                   Queue q;
161                   int i;
162                   queue_init(&q);
163                   selection_solvables(pool, &job, &q);
164                   for (i = 0; i < q.count; i++)
165                     printf("  - %s\n", testcase_solvid2str(pool, q.elements[i]));
166                   queue_free(&q);
167                 }
168             }
169           else if (result || writeresult)
170             {
171               char *myresult, *resultdiff;
172               struct reportsolutiondata reportsolutiondata;
173               memset(&reportsolutiondata, 0, sizeof(reportsolutiondata));
174               if (rescallback)
175                 {
176                   solv->solution_callback = reportsolutioncb;
177                   solv->solution_callback_data = &reportsolutiondata;
178                 }
179               solver_solve(solv, &job);
180               solv->solution_callback = 0;
181               solv->solution_callback_data = 0;
182               if (!resultflags)
183                 resultflags = TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS;
184               myresult = testcase_solverresult(solv, resultflags);
185               if (rescallback && reportsolutiondata.result)
186                 {
187                   reportsolutiondata.result = solv_dupjoin(reportsolutiondata.result, myresult, 0);
188                   solv_free(myresult);
189                   myresult = reportsolutiondata.result;
190                 }
191               if (writeresult)
192                 {
193                   if (*myresult)
194                     {
195                       if (writeresult > 1)
196                         {
197                           const char *p;
198                           int i;
199                           
200                           printf("result ");
201                           p = "%s";
202                           for (i = 0; resultflags2str[i].str; i++)
203                             if ((resultflags & resultflags2str[i].flag) != 0)
204                               {
205                                 printf(p, resultflags2str[i].str);
206                                 p = ",%s";
207                               }
208                           printf(" <inline>\n");
209                           p = myresult;
210                           while (*p)
211                             {
212                               const char *p2 = strchr(p, '\n');
213                               p2 = p2 ? p2 + 1 : p + strlen(p);
214                               printf("#>%.*s", (int)(p2 - p), p);
215                               p = p2;
216                             }
217                         }
218                       else
219                         printf("%s", myresult);
220                     }
221                 }
222               else
223                 {
224                   resultdiff = testcase_resultdiff(result, myresult);
225                   if (resultdiff)
226                     {
227                       printf("Results differ:\n%s", resultdiff);
228                       ex = 1;
229                       solv_free(resultdiff);
230                     }
231                 }
232               solv_free(result);
233               solv_free(myresult);
234             }
235           else
236             {
237               int pcnt = solver_solve(solv, &job);
238               if (writetestcase)
239                 testcase_write(solv, writetestcase, resultflags, 0, 0);
240               if (pcnt && solq.count)
241                 {
242                   int i, taken = 0;
243                   for (i = 0; i < solq.count; i += 2)
244                     {
245                       if (solq.elements[i] > 0 && solq.elements[i] <= pcnt)
246                         if (solq.elements[i + 1] > 0 && solq.elements[i + 1] <=  solver_solution_count(solv, solq.elements[i]))
247                           {
248                             printf("problem %d: taking solution %d\n", solq.elements[i], solq.elements[i + 1]);
249                             solver_take_solution(solv, solq.elements[i], solq.elements[i + 1], &job);
250                             taken = 1;
251                           }
252                     }
253                   if (taken)
254                     pcnt = solver_solve(solv, &job);
255                 }
256               if (pcnt)
257                 {
258                   int problem, solution, scnt;
259                   printf("Found %d problems:\n", pcnt);
260                   for (problem = 1; problem <= pcnt; problem++)
261                     {
262                       printf("Problem %d:\n", problem);
263 #if 1
264                       solver_printprobleminfo(solv, problem);
265 #else
266                       {
267                         Queue pq;
268                         int j;
269                         queue_init(&pq);
270                         solver_findallproblemrules(solv, problem, &pq);
271                         for (j = 0; j < pq.count; j++)
272                           solver_printproblemruleinfo(solv, pq.elements[j]);
273                         queue_free(&pq);
274                       }
275 #endif
276                       printf("\n");
277                       scnt = solver_solution_count(solv, problem);
278                       for (solution = 1; solution <= scnt; solution++)
279                         {
280                           printf("Solution %d:\n", solution);
281                           solver_printsolution(solv, problem, solution);
282                           printf("\n");
283                         }
284                     }
285                 }
286               else
287                 {
288                   Transaction *trans = solver_create_transaction(solv);
289                   printf("Transaction summary:\n\n");
290                   transaction_print(trans);
291                   transaction_free(trans);
292                 }
293             }
294           queue_free(&job);
295           solver_free(solv);
296         }
297       pool_free(pool);
298       fclose(fp);
299     }
300   queue_free(&solq);
301   exit(ex);
302 }