]>
Commit | Line | Data |
---|---|---|
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 | } |