]> git.saurik.com Git - apt.git/blob - test/versiontest.cc
merged from debian-sid
[apt.git] / test / versiontest.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: versiontest.cc,v 1.5 2003/08/18 15:55:19 mdz Exp $
4 /* ######################################################################
5
6 Version Test - Simple program to run through a file and comare versions.
7
8 Each version is compared and the result is checked against an expected
9 result in the file. The format of the file is
10 a b Res
11 Where Res is -1, 1, 0. dpkg -D=1 --compare-versions a "<" b can be
12 used to determine what Res should be. # at the start of the line
13 is a comment and blank lines are skipped
14
15 ##################################################################### */
16 /*}}}*/
17 #include <apt-pkg/macros.h>
18 #include <apt-pkg/error.h>
19 #include <apt-pkg/version.h>
20 #include <apt-pkg/debversion.h>
21 #include <iostream>
22 #include <fstream>
23
24 using namespace std;
25
26 static int verrevcmp(const char *val, const char *ref)
27 {
28 int vc, rc;
29 long vl, rl;
30 const char *vp, *rp;
31
32 if (!val)
33 val = "";
34 if (!ref)
35 ref = "";
36 for (;;)
37 {
38 vp = val;
39 while (*vp && !isdigit(*vp))
40 vp++;
41 rp = ref;
42 while (*rp && !isdigit(*rp))
43 rp++;
44 for (;;)
45 {
46 vc= val == vp ? 0 : *val++;
47 rc= ref == rp ? 0 : *ref++;
48 if (!rc && !vc)
49 break;
50 if (vc && !isalpha(vc))
51 vc += 256; /* assumes ASCII character set */
52 if (rc && !isalpha(rc))
53 rc += 256;
54 if (vc != rc)
55 return vc - rc;
56 }
57 val = vp;
58 ref = rp;
59 vl = 0;
60 if (isdigit(*vp))
61 vl = strtol(val,(char**)&val,10);
62 rl = 0;
63 if (isdigit(*rp))
64 rl = strtol(ref,(char**)&ref,10);
65 if (vl != rl)
66 return vl - rl;
67 if (!*val && !*ref)
68 return 0;
69 if (!*val)
70 return -1;
71 if (!*ref)
72 return +1;
73 }
74 }
75
76 #if 0
77 static int verrevcmp(const char *val, const char *ref)
78 {
79 int vc, rc;
80 long vl, rl;
81 const char *vp, *rp;
82
83 if (!val) val= "";
84 if (!ref) ref= "";
85 for (;;)
86 {
87 vp= val; while (*vp && !isdigit(*vp) && *vp != '~') vp++;
88 rp= ref; while (*rp && !isdigit(*rp) && *rp != '~') rp++;
89 for (;;)
90 {
91 vc= val == vp ? 0 : *val++;
92 rc= ref == rp ? 0 : *ref++;
93 if (!rc && !vc) break;
94 if (vc && !isalpha(vc)) vc += 256; /* assumes ASCII character set */
95 if (rc && !isalpha(rc)) rc += 256;
96 if (vc != rc) return vc - rc;
97 }
98
99 val= vp;
100 ref= rp;
101 if (*vp == '~') val++;
102 if (*rp == '~') ref++;
103 vl=0; if (isdigit(*val)) vl= strtol(val,(char**)&val,10);
104 rl=0; if (isdigit(*ref)) rl= strtol(ref,(char**)&ref,10);
105 if (vl == 0 && rl == 0)
106 {
107 if (*vp == '~' && *rp != '~') return -1;
108 if (*vp != '~' && *rp == '~') return +1;
109 }
110 if (*vp == '~')
111 vl *= -1;
112 if (*rp == '~')
113 rl *= -1;
114 if (vl != rl) return vl - rl;
115 if (!*val && !*ref) return 0;
116 if (!*val)
117 {
118 if (*ref == '~')
119 return +1;
120 else
121 return -1;
122 }
123
124 if (!*ref)
125 {
126 if (*val == '~')
127 return -1;
128 else
129 return +1;
130 }
131 }
132 }
133 #endif
134
135 bool RunTest(const char *File)
136 {
137 ifstream F(File,ios::in);
138 if (!F != 0)
139 return false;
140
141 char Buffer[300];
142 int CurLine = 0;
143
144 while (1)
145 {
146 F.getline(Buffer,sizeof(Buffer));
147 CurLine++;
148 if (F.eof() != 0)
149 return true;
150 if (!F != 0)
151 return _error->Error("Line %u in %s is too long",CurLine,File);
152
153 // Comment
154 if (Buffer[0] == '#' || Buffer[0] == 0)
155 continue;
156
157 // First version
158 char *I;
159 char *Start = Buffer;
160 for (I = Buffer; *I != 0 && *I != ' '; I++);
161 string A(Start, I - Start);
162
163 if (*I == 0)
164 return _error->Error("Invalid line %u",CurLine);
165
166 // Second version
167 I++;
168 Start = I;
169 for (I = Start; *I != 0 && *I != ' '; I++);
170 string B(Start,I - Start);
171
172 if (*I == 0 || I[1] == 0)
173 return _error->Error("Invalid line %u",CurLine);
174
175 // Result
176 I++;
177 int Expected = atoi(I);
178 int Res = debVS.CmpVersion(A.c_str(), B.c_str());
179 int Res2 = verrevcmp(A.c_str(),B.c_str());
180 cout << "'" << A << "' ? '" << B << "' = " << Res << " (= " << Expected << ") " << Res2 << endl;
181
182 if (Res < 0)
183 Res = -1;
184 else if (Res > 0)
185 Res = 1;
186
187 if (Res != Expected)
188 _error->Error("Comparison failed on line %u. '%s' ? '%s' %i != %i",CurLine,A.c_str(),B.c_str(),Res,Expected);
189
190 // Check the reverse as well
191 Expected = -1*Expected;
192 Res = debVS.CmpVersion(B.c_str(), A.c_str());
193 Res2 = verrevcmp(B.c_str(),A.c_str());
194
195 cout << "'" << B << "' ? '" << A << "' = " << Res << " (= " << Expected << ") " << Res2 << endl;
196
197 if (Res < 0)
198 Res = -1;
199 else if (Res > 0)
200 Res = 1;
201
202 if (Res != Expected)
203 _error->Error("Comparison failed on line %u. '%s' ? '%s' %i != %i",CurLine,B.c_str(),A.c_str(),Res,Expected);
204 }
205 }
206
207 int main(int argc, char *argv[])
208 {
209 if (argc <= 1)
210 {
211 cerr << "You must specify a test file" << endl;
212 return 0;
213 }
214
215 RunTest(argv[1]);
216
217 // Print any errors or warnings found
218 if (_error->empty() == false)
219 {
220 string Err;
221 while (_error->empty() == false)
222 {
223
224 bool Type = _error->PopMessage(Err);
225 if (Type == true)
226 cout << "E: " << Err << endl;
227 else
228 cout << "W: " << Err << endl;
229 }
230
231 return 0;
232 }
233 }