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