Join with aliencode
[ntk/apt.git] / test / versiontest.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: versiontest.cc,v 1.2 2001/02/20 07:03:18 jgg 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 #define APT_COMPATIBILITY 1
18 #include <system.h>
19 #include <apt-pkg/error.h>
20 #include <apt-pkg/version.h>
21 #include <iostream.h>
22 #include <fstream.h>
23
24 static int verrevcmp(const char *val, const char *ref)
25 {
26 int vc, rc;
27 long vl, rl;
28 const char *vp, *rp;
29
30 if (!val)
31 val = "";
32 if (!ref)
33 ref = "";
34 for (;;)
35 {
36 vp = val;
37 while (*vp && !isdigit(*vp))
38 vp++;
39 rp = ref;
40 while (*rp && !isdigit(*rp))
41 rp++;
42 for (;;)
43 {
44 vc= val == vp ? 0 : *val++;
45 rc= ref == rp ? 0 : *ref++;
46 if (!rc && !vc)
47 break;
48 if (vc && !isalpha(vc))
49 vc += 256; /* assumes ASCII character set */
50 if (rc && !isalpha(rc))
51 rc += 256;
52 if (vc != rc)
53 return vc - rc;
54 }
55 val = vp;
56 ref = rp;
57 vl = 0;
58 if (isdigit(*vp))
59 vl = strtol(val,(char**)&val,10);
60 rl = 0;
61 if (isdigit(*rp))
62 rl = strtol(ref,(char**)&ref,10);
63 if (vl != rl)
64 return vl - rl;
65 if (!*val && !*ref)
66 return 0;
67 if (!*val)
68 return -1;
69 if (!*ref)
70 return +1;
71 }
72 }
73
74 #if 0
75 static int verrevcmp(const char *val, const char *ref)
76 {
77 int vc, rc;
78 long vl, rl;
79 const char *vp, *rp;
80
81 if (!val) val= "";
82 if (!ref) ref= "";
83 for (;;)
84 {
85 vp= val; while (*vp && !isdigit(*vp) && *vp != '~') vp++;
86 rp= ref; while (*rp && !isdigit(*rp) && *rp != '~') rp++;
87 for (;;)
88 {
89 vc= val == vp ? 0 : *val++;
90 rc= ref == rp ? 0 : *ref++;
91 if (!rc && !vc) break;
92 if (vc && !isalpha(vc)) vc += 256; /* assumes ASCII character set */
93 if (rc && !isalpha(rc)) rc += 256;
94 if (vc != rc) return vc - rc;
95 }
96
97 val= vp;
98 ref= rp;
99 if (*vp == '~') val++;
100 if (*rp == '~') ref++;
101 vl=0; if (isdigit(*val)) vl= strtol(val,(char**)&val,10);
102 rl=0; if (isdigit(*ref)) rl= strtol(ref,(char**)&ref,10);
103 if (vl == 0 && rl == 0)
104 {
105 if (*vp == '~' && *rp != '~') return -1;
106 if (*vp != '~' && *rp == '~') return +1;
107 }
108 if (*vp == '~')
109 vl *= -1;
110 if (*rp == '~')
111 rl *= -1;
112 if (vl != rl) return vl - rl;
113 if (!*val && !*ref) return 0;
114 if (!*val)
115 {
116 if (*ref == '~')
117 return +1;
118 else
119 return -1;
120 }
121
122 if (!*ref)
123 {
124 if (*val == '~')
125 return -1;
126 else
127 return +1;
128 }
129 }
130 }
131 #endif
132
133 bool RunTest(const char *File)
134 {
135 ifstream F(File,ios::in | ios::nocreate);
136 if (!F != 0)
137 return false;
138
139 char Buffer[300];
140 int CurLine = 0;
141
142 while (1)
143 {
144 F.getline(Buffer,sizeof(Buffer));
145 CurLine++;
146 if (F.eof() != 0)
147 return true;
148 if (!F != 0)
149 return _error->Error("Line %u in %s is too long",CurLine,File);
150
151 // Comment
152 if (Buffer[0] == '#' || Buffer[0] == 0)
153 continue;
154
155 // First version
156 char *I;
157 char *Start = Buffer;
158 for (I = Buffer; *I != 0 && *I != ' '; I++);
159 string A(Start, I - Start);
160
161 if (*I == 0)
162 return _error->Error("Invalid line %u",CurLine);
163
164 // Second version
165 I++;
166 Start = I;
167 for (I = Start; *I != 0 && *I != ' '; I++);
168 string B(Start,I - Start);
169
170 if (*I == 0 || I[1] == 0)
171 return _error->Error("Invalid line %u",CurLine);
172
173 // Result
174 I++;
175 int Expected = atoi(I);
176 int Res = pkgVersionCompare(A.c_str(),B.c_str());
177 int Res2 = verrevcmp(A.c_str(),B.c_str());
178 cout << "'" << A << "' ? '" << B << "' = " << Res << " (= " << Expected << ") " << Res2 << endl;
179 if (Res != Expected)
180 _error->Error("Comparison failed on line %u. '%s' ? '%s' %i != %i",CurLine,A.c_str(),B.c_str(),Res,Expected);
181
182 // Check the reverse as well
183 Expected = -1*Expected;
184 Res = pkgVersionCompare(B.c_str(),A.c_str());
185 Res2 = verrevcmp(B.c_str(),A.c_str());
186 cout << "'" << B << "' ? '" << A << "' = " << Res << " (= " << Expected << ") " << Res2 << endl;
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 }
191
192 int main(int argc, char *argv[])
193 {
194 if (argc <= 1)
195 {
196 cerr << "You must specify a test file" << endl;
197 return 0;
198 }
199
200 RunTest(argv[1]);
201
202 // Print any errors or warnings found
203 if (_error->empty() == false)
204 {
205 string Err;
206 while (_error->empty() == false)
207 {
208
209 bool Type = _error->PopMessage(Err);
210 if (Type == true)
211 cout << "E: " << Err << endl;
212 else
213 cout << "W: " << Err << endl;
214 }
215
216 return 0;
217 }
218 }