10 #include "solverdebug.h"
14 static struct resultflags2str {
17 } resultflags2str[] = {
18 { TESTCASE_RESULT_TRANSACTION, "transaction" },
19 { TESTCASE_RESULT_PROBLEMS, "problems" },
20 { TESTCASE_RESULT_ORPHANED, "orphaned" },
21 { TESTCASE_RESULT_RECOMMENDED, "recommended" },
22 { TESTCASE_RESULT_UNNEEDED, "unneeded" },
23 { TESTCASE_RESULT_ALTERNATIVES, "alternatives" },
24 { TESTCASE_RESULT_RULES, "rules" },
25 { TESTCASE_RESULT_GENID, "genid" },
26 { TESTCASE_RESULT_REASON, "reason" },
27 { TESTCASE_RESULT_CLEANDEPS, "cleandeps" },
28 { TESTCASE_RESULT_JOBS, "jobs" },
35 fprintf(ex ? stderr : stdout, "Usage: testsolv <testcase>\n");
39 struct reportsolutiondata {
45 reportsolutioncb(Solver *solv, void *cbdata)
47 struct reportsolutiondata *sd = cbdata;
51 res = testcase_solverresult(solv, TESTCASE_RESULT_TRANSACTION);
56 sprintf(prefix, "callback%d:", sd->count);
57 while ((p2 = strchr(p, '\n')) != 0)
61 sd->result = solv_dupappend(sd->result, prefix, p);
71 free_considered(Pool *pool)
75 map_free(pool->considered);
76 pool->considered = solv_free(pool->considered);
81 showwhy(Solver *solv, const char *showwhypkgstr)
83 Pool *pool = solv->pool;
91 i = testcase_str2solvid(pool, showwhypkgstr);
93 solver_get_decisionlist(solv, i, SOLVER_DECISIONLIST_SOLVABLE | SOLVER_DECISIONLIST_SORTED, &dq);
96 int selflags = SELECTION_NAME | SELECTION_CANON;
97 selection_make(pool, &dq, showwhypkgstr, selflags);
98 selection_solvables(pool, &dq, &iq);
100 printf("No package matches %s\n", showwhypkgstr);
102 solver_get_decisionlist_multiple(solv, &iq, SOLVER_DECISIONLIST_SOLVABLE | SOLVER_DECISIONLIST_SORTED, &dq);
104 for (ii = 0; ii < dq.count; ii += 3)
106 Id v = dq.elements[ii];
107 int reason = dq.elements[ii + 1];
108 int info = dq.elements[ii + 2];
110 printf("%s %s:\n", v < 0 ? "conflicted" : "installed", testcase_solvid2str(pool, v >= 0 ? v : -v));
111 /* special case some reasons where we want to show multiple rule infos or extra info */
112 if (reason == SOLVER_REASON_WEAKDEP || reason == SOLVER_REASON_UNIT_RULE || reason == SOLVER_REASON_RESOLVE)
115 if (reason == SOLVER_REASON_WEAKDEP)
116 solver_allweakdepinfos(solv, v, &iq);
118 solver_allruleinfos(solv, info, &iq);
121 for (i = 0; i < iq.count; i += 4)
124 if (iq.elements[i] == SOLVER_RULE_LEARNT)
126 printf(" a learnt rule:\n");
127 solver_ruleliterals(solv, info, &rq);
128 for (i = 0; i < rq.count; i++)
130 Id p2 = rq.elements[i];
131 printf(" %c %s\n", p2 > 0 ? '+' : '-', testcase_solvid2str(pool, p2 > 0 ? p2 : -p2));
135 bits = solver_calc_decisioninfo_bits(solv, v, iq.elements[i], iq.elements[i + 1], iq.elements[i + 2], iq.elements[i + 3]);
136 printf(" %s\n", solver_decisioninfo2str(solv, bits, iq.elements[i], iq.elements[i + 1], iq.elements[i + 2], iq.elements[i + 3]));
141 printf(" %s\n", solver_decisionreason2str(solv, v, reason, info));
149 doshowproof(Solver *solv, Id id, int flags, Queue *lq)
151 Pool *pool = solv->pool;
157 solver_get_decisionlist(solv, id, flags | SOLVER_DECISIONLIST_SORTED | SOLVER_DECISIONLIST_WITHINFO | SOLVER_DECISIONLIST_MERGEDINFO, &q);
158 for (i = 0; i < q.count; i += 8)
160 Id v = q.elements[i];
161 int reason = q.elements[i + 1], bits = q.elements[i + 3], type = q.elements[i + 4];
162 Id from = q.elements[i + 5], to = q.elements[i + 6], dep = q.elements[i + 7];
164 if (reason != SOLVER_REASON_UNSOLVABLE && type == SOLVER_RULE_PKG_SAME_NAME)
165 continue; /* do not show "obvious" decisions */
167 solver_decisionlist_solvables(solv, &q, i, &qp);
168 if (reason == SOLVER_REASON_UNSOLVABLE)
169 printf("unsolvable: ");
171 printf("%s %s: ", v < 0 ? "conflicted" : "installed", pool_solvidset2str(pool, &qp));
172 i += solver_decisionlist_merged(solv, &q, i) * 8;
175 printf("%s\n", solver_reason2str(solv, reason));
178 if (type == SOLVER_RULE_LEARNT && lq)
180 for (j = 0; j < lq->count; j++)
181 if (lq->elements[j] == q.elements[i + 2])
185 printf("learnt rule #%d\n", j + 1);
189 printf("%s\n", solver_decisioninfo2str(solv, bits, type, from, to, dep));
196 main(int argc, char **argv)
201 Solver *solv, *reusesolv = 0;
203 char *showwhypkgstr = 0;
207 char *writetestcase = 0;
213 const char *list = 0;
214 int list_with_deps = 0;
219 while ((c = getopt(argc, argv, "vmrhL:l:s:T:W:P")) >= 0)
244 showwhypkgstr = optarg;
247 if ((p = strchr(optarg, ':')))
248 queue_push2(&solq, atoi(optarg), atoi(p + 1));
250 queue_push2(&solq, 1, atoi(optarg));
253 writetestcase = optarg;
265 for (; optind < argc; optind++)
267 pool = pool_create();
268 pool_setdebuglevel(pool, debuglevel);
269 /* report all errors */
270 pool_setdebugmask(pool, pool->debugmask | SOLV_ERROR);
272 fp = fopen(argv[optind], "r");
275 perror(argv[optind]);
283 solv = testcase_read(pool, fp, argv[optind], &job, &result, &resultflags);
286 free_considered(pool);
289 exit(resultflags == 77 ? 77 : 1);
297 if (!multijob && !feof(fp))
301 printf("test %d:\n", multijob++);
305 int selflags = SELECTION_NAME|SELECTION_PROVIDES|SELECTION_CANON|SELECTION_DOTARCH|SELECTION_REL|SELECTION_GLOB|SELECTION_FLAT;
307 selflags |= SELECTION_FILELIST;
310 p = testcase_str2solvid(pool, list);
312 queue_push2(&job, SOLVER_SOLVABLE, p);
314 selection_make(pool, &job, list, selflags);
316 printf("No match\n");
322 selection_solvables(pool, &job, &q);
323 for (i = 0; i < q.count; i++)
325 printf(" - %s\n", testcase_solvid2str(pool, q.elements[i]));
331 SOLVABLE_PROVIDES, SOLVABLE_REQUIRES, SOLVABLE_CONFLICTS, SOLVABLE_OBSOLETES,
332 SOLVABLE_RECOMMENDS, SOLVABLE_SUGGESTS, SOLVABLE_SUPPLEMENTS, SOLVABLE_ENHANCES,
333 SOLVABLE_PREREQ_IGNOREINST,
336 vendor = pool_lookup_str(pool, q.elements[i], SOLVABLE_VENDOR);
338 printf(" %s: %s\n", pool_id2str(pool, SOLVABLE_VENDOR), vendor);
339 for (j = 0; deps[j]; j++)
343 pool_lookup_idarray(pool, q.elements[i], deps[j], &dq);
345 printf(" %s:\n", pool_id2str(pool, deps[j]));
346 for (k = 0; k < dq.count; k++)
347 printf(" %s\n", pool_dep2str(pool, dq.elements[k]));
355 else if (showwhypkgstr)
357 solver_solve(solv, &job);
358 showwhy(solv, showwhypkgstr);
362 int pcnt = solver_solve(solv, &job);
365 printf("nothing to proof\n");
366 for (problem = 1; problem <= pcnt; problem++)
371 solver_get_learnt(solv, problem, SOLVER_DECISIONLIST_PROBLEM, &lq);
372 for (i = 0; i < lq.count; i++)
374 printf("Learnt rule #%d:\n", i + 1);
375 doshowproof(solv, lq.elements[i], SOLVER_DECISIONLIST_LEARNTRULE, &lq);
378 printf("Proof #%d:\n", problem);
379 doshowproof(solv, problem, SOLVER_DECISIONLIST_PROBLEM, &lq);
385 else if (result || writeresult)
387 char *myresult, *resultdiff;
388 struct reportsolutiondata reportsolutiondata;
389 memset(&reportsolutiondata, 0, sizeof(reportsolutiondata));
392 solv->solution_callback = reportsolutioncb;
393 solv->solution_callback_data = &reportsolutiondata;
395 solver_solve(solv, &job);
396 solv->solution_callback = 0;
397 solv->solution_callback_data = 0;
398 if ((resultflags & ~TESTCASE_RESULT_REUSE_SOLVER) == 0)
399 resultflags |= TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS;
400 myresult = testcase_solverresult(solv, resultflags);
401 if (rescallback && reportsolutiondata.result)
403 reportsolutiondata.result = solv_dupjoin(reportsolutiondata.result, myresult, 0);
405 myresult = reportsolutiondata.result;
418 for (i = 0; resultflags2str[i].str; i++)
419 if ((resultflags & resultflags2str[i].flag) != 0)
421 printf(p, resultflags2str[i].str);
424 printf(" <inline>\n");
428 const char *p2 = strchr(p, '\n');
429 p2 = p2 ? p2 + 1 : p + strlen(p);
430 printf("#>%.*s", (int)(p2 - p), p);
435 printf("%s", myresult);
440 resultdiff = testcase_resultdiff(result, myresult);
443 printf("Results differ:\n%s", resultdiff);
445 solv_free(resultdiff);
453 int pcnt = solver_solve(solv, &job);
456 if (!testcase_write(solv, writetestcase, resultflags, 0, 0))
458 fprintf(stderr, "Could not write testcase: %s\n", pool_errstr(pool));
462 if (pcnt && solq.count)
465 for (i = 0; i < solq.count; i += 2)
467 if (solq.elements[i] > 0 && solq.elements[i] <= pcnt)
468 if (solq.elements[i + 1] > 0 && solq.elements[i + 1] <= solver_solution_count(solv, solq.elements[i]))
470 printf("problem %d: taking solution %d\n", solq.elements[i], solq.elements[i + 1]);
471 solver_take_solution(solv, solq.elements[i], solq.elements[i + 1], &job);
476 pcnt = solver_solve(solv, &job);
480 int problem, solution, scnt;
481 printf("Found %d problems:\n", pcnt);
482 for (problem = 1; problem <= pcnt; problem++)
484 printf("Problem %d:\n", problem);
486 solver_printprobleminfo(solv, problem);
492 solver_findallproblemrules(solv, problem, &pq);
493 for (j = 0; j < pq.count; j++)
494 solver_printproblemruleinfo(solv, pq.elements[j]);
499 scnt = solver_solution_count(solv, problem);
500 for (solution = 1; solution <= scnt; solution++)
502 printf("Solution %d:\n", solution);
503 solver_printsolution(solv, problem, solution);
510 Transaction *trans = solver_create_transaction(solv);
511 printf("Transaction summary:\n\n");
512 transaction_print(trans);
513 transaction_free(trans);
517 if ((resultflags & TESTCASE_RESULT_REUSE_SOLVER) != 0 && !feof(fp))
523 solver_free(reusesolv);
524 free_considered(pool);