versiontest.cc 5.3 KB

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