enable APT in unpack/configure ordering to handle loops as well
[ntk/apt.git] / test / libapt / compareversion_test.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 /* ######################################################################
4
5 Version Test - Simple program to run through a file and comare versions.
6
7 Each version is compared and the result is checked against an expected
8 result in the file. The format of the file is
9 a b Res
10 Where Res is -1, 1, 0. dpkg -D=1 --compare-versions a "<" b can be
11 used to determine what Res should be. # at the start of the line
12 is a comment and blank lines are skipped
13
14 The runner will also call dpkg --compare-versions to check if APT and
15 dpkg have (still) the same idea.
16
17 ##################################################################### */
18 /*}}}*/
19 #include <apt-pkg/macros.h>
20 #include <apt-pkg/error.h>
21 #include <apt-pkg/version.h>
22 #include <apt-pkg/debversion.h>
23 #include <apt-pkg/fileutl.h>
24 #include <iostream>
25 #include <fstream>
26
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/wait.h>
31
32 using namespace std;
33
34 bool callDPkg(const char *val, const char *ref, const char &op) {
35 pid_t Process = ExecFork();
36 if (Process == 0)
37 {
38 const char * args[6];
39 args[0] = "/usr/bin/dpkg";
40 args[1] = "--compare-versions";
41 args[2] = val;
42 args[3] = (op == 1) ? ">>" : ( (op == 0) ? "=" : "<<");
43 args[4] = ref;
44 args[5] = 0;
45 execv(args[0], (char**) args);
46 exit(1);
47 }
48 int Ret;
49 waitpid(Process, &Ret, 0);
50 return WIFEXITED(Ret) == true && WEXITSTATUS(Ret) == 0;
51 }
52
53 void assertVersion(int const &CurLine, string const &A, string const &B, int const &Expected) {
54 int Res = debVS.CmpVersion(A.c_str(), B.c_str());
55 bool const dpkg = callDPkg(A.c_str(),B.c_str(), Expected);
56 Res = (Res < 0) ? -1 : ( (Res > 0) ? 1 : Res);
57
58 if (Res != Expected)
59 _error->Error("Comparison failed on line %u. '%s' '%s' '%s' %i != %i",CurLine,A.c_str(),((Expected == 1) ? "<<" : ( (Expected == 0) ? "=" : ">>")) ,B.c_str(),Res,Expected);
60 if (dpkg == false)
61 _error->Error("DPkg differ with line: %u. '%s' '%s' '%s' == false",CurLine,A.c_str(),((Expected == 1) ? "<<" : ( (Expected == 0) ? "=" : ">>")),B.c_str());
62 }
63
64 bool RunTest(const char *File)
65 {
66 if (FileExists(File) == false)
67 return _error->Error("Versiontestfile %s doesn't exist!", File);
68
69 ifstream F(File,ios::in);
70 if (!F != 0)
71 return false;
72
73 char Buffer[300];
74 int CurLine = 0;
75
76 while (1)
77 {
78 F.getline(Buffer,sizeof(Buffer));
79 CurLine++;
80 if (F.eof() != 0)
81 return true;
82 if (!F != 0)
83 return _error->Error("Line %u in %s is too long",CurLine,File);
84
85 // Comment
86 if (Buffer[0] == '#' || Buffer[0] == 0)
87 continue;
88
89 // First version
90 char *I;
91 char *Start = Buffer;
92 for (I = Buffer; *I != 0 && *I != ' '; I++);
93 string A(Start, I - Start);
94
95 if (*I == 0)
96 return _error->Error("Invalid line %u",CurLine);
97
98 // Second version
99 I++;
100 Start = I;
101 for (I = Start; *I != 0 && *I != ' '; I++);
102 string B(Start,I - Start);
103
104 if (*I == 0 || I[1] == 0)
105 return _error->Error("Invalid line %u",CurLine);
106
107 // Result
108 I++;
109 int const Expected = atoi(I);
110 assertVersion(CurLine, A, B, Expected);
111 // Check the reverse as well
112 assertVersion(CurLine, B, A, Expected*-1);
113 }
114 }
115
116 int main(int argc, char *argv[])
117 {
118 if (argc != 2)
119 return 1;
120 else
121 RunTest(argv[1]);
122
123 // Print any errors or warnings found
124 _error->DumpErrors();
125 return 0;
126 }