dbdigest.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. {
  2. This file is part of the Free Pascal test suite.
  3. Copyright (c) 2002 by the Free Pascal development team.
  4. This program inserts the last tests run
  5. into TESTSUITE database.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$mode objfpc}
  13. {$h+}
  14. {$ifndef win32}
  15. {$linklib pthread}
  16. {$endif}
  17. program dbdigest;
  18. uses
  19. types, classes, custapp, sysutils, inifiles, teststr, testu, tresults, dbtests, digestanalyst;
  20. Type
  21. { TDBDigestApplication }
  22. TDBDigestApplication = class(TCustomApplication)
  23. Const
  24. ShortOpts =
  25. 'd'+ { coDatabaseName }
  26. 'h'+ { coHost }
  27. 'u'+ { coUserName }
  28. 'p'+ { coPassword }
  29. 'P'+ { coPort }
  30. 'l'+ { coLogFile }
  31. 'L'+ { coLongLogFile }
  32. 'o'+ { coOS }
  33. 'c'+ { coCPU }
  34. 'a'+ { coCategory }
  35. 'v'+ { coVersion }
  36. 't'+ { coDate }
  37. 's'+ { coSubmitter }
  38. 'm'+ { coMachine }
  39. 'C'+ { coComment }
  40. 'S'+ { coTestSrcDir }
  41. 'r'+ { coRelSrcDir }
  42. 'V'+ { coVerbose }
  43. 'Q' { coSQL }
  44. ;
  45. LongOpts : Array of string = (
  46. 'databasename',
  47. 'host',
  48. 'username',
  49. 'password',
  50. 'port',
  51. 'logfile',
  52. 'longlogfile',
  53. 'os',
  54. 'cpu',
  55. 'category',
  56. 'version',
  57. 'date',
  58. 'submitter',
  59. 'machine',
  60. 'comment',
  61. 'testsrcdir',
  62. 'relsrcdir',
  63. 'verbose',
  64. 'sql',
  65. 'compilerdate',
  66. 'compilerfullversion',
  67. 'svncompilerrevision',
  68. 'svntestsrevision',
  69. 'svnrtlrevision',
  70. 'svnpackagesrevision'
  71. );
  72. // Return true if we can continue
  73. function ProcessCommandLine(var aConfig: TDigestConfig; var aData: TTestRunData): Boolean;
  74. private
  75. class function ExtractDate(aValue: string): TDateTime;
  76. procedure Analyze(const aConfig: TDigestConfig; const aData: TTestRunData);
  77. procedure ProcessConfigfile(const aFileName: String; var aConfig: TDigestConfig; var aData: TTestRunData);
  78. function ProcessOption(const aOption: String; aValue: String; var aConfig: TDigestConfig; var aData: TTestRunData): Boolean;
  79. procedure ReadSystemDBConfig(var aConfig: TDigestConfig);
  80. protected
  81. procedure DoRun; override;
  82. procedure Usage(const aMsg: String);
  83. end;
  84. class Function TDBDigestApplication.ExtractDate(aValue : string) : TDateTime;
  85. var
  86. year,month,day,min,hour : word;
  87. begin
  88. if Length(avalue)=12 then
  89. begin
  90. year:=StrToInt(Copy(avalue,1,4));
  91. month:=StrToInt(Copy(avalue,5,2));
  92. day:=StrToInt(Copy(aValue,7,2));
  93. hour:=StrToInt(Copy(aValue,9,2));
  94. min:=StrToInt(Copy(aValue,11,2));
  95. Result:=EncodeDate(year,month,day)+EncodeTime(hour,min,0,0);
  96. end
  97. else
  98. Verbose(V_Error,'Error in date format, use YYYYMMDDhhmm');
  99. end;
  100. Function TDBDigestApplication.ProcessOption(const aOption : String; aValue: String; var aConfig : TDigestConfig; var aData : TTestRunData) : Boolean;
  101. begin
  102. Result:=True;
  103. Verbose(V_DEBUG,'Processing option: '+aOption);
  104. Case aOption of
  105. 'd','databasename' : aConfig.databasename:=aValue;
  106. 'h','host' : aConfig.host:=aValue;
  107. 'u','username': aConfig.username:=aValue;
  108. 'p','password': aConfig.password:=aValue;
  109. 'P','port': aConfig.port:=StrToIntDef(aValue,0);
  110. 'l','logfile': aData.logfile:=aValue;
  111. 'L','longlogfile': aData.longlogfile:=aValue;
  112. 'o','os': aData.os:=aValue;
  113. 'c','cpu': aData.cpu:=aValue;
  114. 'a','category': aData.category:=aValue;
  115. 'v','version': aData.version:=aValue;
  116. 't','date': aData.date:=ExtractDate(aValue);
  117. 's','submitter': aData.submitter:=aValue;
  118. 'm','machine': aData.machine:=aValue;
  119. 'C','comment': aData.config:=aValue;
  120. 'D','description': aData.description:=aValue;
  121. 'S','testsrcdir': aConfig.testsrcdir:=aValue;
  122. 'r','relsrcdir': aConfig.relsrcdir:=aValue;
  123. 'V','verbose': DoVerbose:=True;
  124. // 'S','sql': aConfig.sql:=aValue;
  125. 'compilerdate': aData.CompilerDate:=aValue;
  126. 'compilerfullversion': aData.CompilerFullVersion:=aValue;
  127. 'svncompilerrevision': aData.CompilerRevision:=aValue;
  128. 'svntestsrevision': aData.TestsRevision:=aValue;
  129. 'svnrtlrevision': aData.RTLRevision:=aValue;
  130. 'svnpackagesrevision' : aData.PackagesRevision:=aValue;
  131. else
  132. Verbose(V_ERROR,'Unknown processing option: '+aOption);
  133. end;
  134. end;
  135. Procedure TDBDigestApplication.ProcessConfigfile(const aFileName : String; var aConfig : TDigestConfig; var aData : TTestRunData);
  136. Var
  137. Cfg : TStrings;
  138. aLine,S,N,V : String;
  139. I : Integer;
  140. begin
  141. // Set the default value for old digests without RelSrcDir to the rtl/compiler
  142. // testsuite
  143. If Not FileExists(aFileName) Then
  144. Exit;
  145. Verbose(V_DEBUG,'Parsing config file: '+aFileName);
  146. Cfg:=TStringList.Create;
  147. try
  148. Cfg.LoadFromFile(aFileName);
  149. For aLine in Cfg do
  150. begin
  151. S:=Trim(aLine);
  152. I:=Pos('#',S);
  153. If I<>0 then
  154. S:=Copy(S,1,I-1);
  155. If (S<>'') then
  156. begin
  157. I:=Pos('=',S);
  158. if (I=0) then
  159. Verbose(V_ERROR,'Unknown processing option: '+S)
  160. else
  161. begin
  162. N:=LowerCase(Copy(S,1,I-1));
  163. V:=Copy(S,I+1,Length(S)-I);
  164. ProcessOption(N,V,aConfig,aData);
  165. end;
  166. end;
  167. end;
  168. finally
  169. Cfg.Free;
  170. end;
  171. end;
  172. { TDBDigestApplication }
  173. Procedure TDBDigestApplication.Usage(const aMsg : String);
  174. begin
  175. if (aMsg<>'') then
  176. Writeln('Error : ',aMsg);
  177. Writeln('Usage: ',ExeName,' [options] [test run data options]');
  178. Writeln('Configuration options:');
  179. Writeln('-H --help show this help');
  180. Writeln('-d --databasename=NAME database name');
  181. Writeln('-f --config=FILENAME config file. If not set, dbdigest.cfg is used.');
  182. Writeln('-h --host=HOST database hostname');
  183. Writeln('-p --password=PWD database user password');
  184. Writeln('-P --port=NNN database connection port');
  185. Writeln('-r --relsrcdir relative source dir');
  186. Writeln('-S --testsrcdir test source dir');
  187. Writeln('-u --username=USER database user name');
  188. Writeln('-V --verbose be more verbose');
  189. Writeln('Test run data:');
  190. Writeln('-l --logfile=FILE set log file to analyse');
  191. Writeln('-L --longlogfile=FILE set long log filename (logs of run tests)');
  192. Writeln('-o --os=OS set OS for testrun');
  193. Writeln('-c --cpu=CPU set CPU');
  194. Writeln('-a --category=CAT set category');
  195. Writeln('-v --version=VER set compiler version');
  196. Writeln('-t --date=DATE date in YYYMMDD(hhmmnn) format');
  197. Writeln('-s --submitter=NAME submitter name');
  198. Writeln('-m --machine=NAME set machine name on which testsuite was run');
  199. Writeln('-C --compile-flags=FLAGS set used compilation flags');
  200. Writeln(' --comment=FLAGS backwards compatible way to set compilation flags (deprecated)');
  201. Writeln('-D --description=DESC set config description (helpful comment)');
  202. Writeln(' --compilerdate=DATE set compiler date');
  203. Writeln(' --compilerfullversion=VERSION set full compiler version');
  204. Writeln(' --svncompilerrevision=REV set revision of used compiler');
  205. Writeln(' --svntestsrevision=REV set revision of testsuite files');
  206. Writeln(' --svnrtlrevision=REV set revision of RTL');
  207. Writeln(' --svnpackagesrevision=REV set revison of packages');
  208. Writeln('');
  209. Writeln('The config file can contain the same options as the command-line in the form.');
  210. Writeln('option=value');
  211. Writeln('where option is the long or short version of the option');
  212. Writeln('comments may be included using the # character.');
  213. ExitCode:=Ord(aMsg<>'');
  214. end;
  215. function TDBDigestApplication.ProcessCommandLine(var aConfig: TDigestConfig; var aData : TTestRunData): Boolean;
  216. Function MakeOpts(s : string) : string;
  217. var
  218. C : char;
  219. begin
  220. Result:='';
  221. For C in s do
  222. begin
  223. Result:=Result+C;
  224. if not (C in ['V','Q']) then
  225. Result:=Result+':';
  226. end;
  227. end;
  228. Function MakeLongOpts(s : array of string) : TStringDynArray;
  229. var
  230. I : Integer;
  231. begin
  232. Result:=['help'];
  233. SetLength(Result,1+Length(S));
  234. For I:=0 to Length(S)-1 do
  235. Result[1+i]:=S[I]+':'
  236. end;
  237. var
  238. Long,ErrMsg,lValue : String;
  239. Short : Char;
  240. I : integer;
  241. lHas : boolean;
  242. begin
  243. ErrMsg:=CheckOptions(MakeOpts(ShortOpts)+'H',MakeLongOpts(LongOpts));
  244. Result:=(ErrMsg='');
  245. if (not Result) or HasOption('H','help') then
  246. begin
  247. Usage(ErrMsg);
  248. Exit(false);
  249. end;
  250. I:=0;
  251. For Long in LongOpts do
  252. begin
  253. Inc(I);
  254. if I<=Length(ShortOpts) then
  255. begin
  256. Short:=ShortOpts[I];
  257. if Short='r' then
  258. Writeln('ag');
  259. lHas:=HasOption(Short,Long);
  260. lValue:=GetOptionValue(Short,Long);
  261. end
  262. else
  263. begin
  264. Short:=#0;
  265. lHas:=HasOption(Long);
  266. lValue:=GetOptionValue(Long);
  267. end;
  268. if lHas then
  269. ProcessOption(long,lValue,aConfig,aData);
  270. end;
  271. Result:=True;
  272. end;
  273. procedure TDBDigestApplication.Analyze(const aConfig : TDigestConfig; const aData : TTestRunData);
  274. var
  275. lSQL : TTestSQL;
  276. lDigest : TDBDigestAnalyzer;
  277. begin
  278. lDigest:=Nil;
  279. With aConfig do
  280. lSQL:=TTestSQL.create(databasename,host,username,password,port);
  281. try
  282. lSQL.ConnectToDatabase;
  283. lDigest:=TDBDigestAnalyzer.Create(lSQL);
  284. lDigest.Analyse(aConfig,aData);
  285. finally
  286. lDigest.Free;
  287. lSQL.Free;
  288. end;
  289. end;
  290. procedure TDBDigestApplication.ReadSystemDBConfig(var aConfig : TDigestConfig);
  291. // Keep filename in sync with algorithm in dbadd
  292. var
  293. lFileName : String;
  294. Ini : TCustomIniFile;
  295. begin
  296. lFileName:='/etc/dbdigest.ini';
  297. if not FileExists(lFileName) then exit;
  298. Ini:=TMemIniFile.Create(lFileName);
  299. With Ini do
  300. try
  301. aConfig.DatabaseName:=ReadString(SSection,KeyName,'testsuite');
  302. aConfig.Host:=ReadString(SSection,KeyHost,'localhost');
  303. aConfig.UserName:=ReadString(SSection,KeyUser,'');
  304. aConfig.Password:=ReadString(SSection,KeyPassword,'');
  305. aConfig.Port:=ReadInteger(SSection,KeyPort,0);
  306. finally
  307. Ini.Free;
  308. end;
  309. end;
  310. procedure TDBDigestApplication.DoRun;
  311. var
  312. lConfigFile : String;
  313. lConfig : TDigestConfig;
  314. lData : TTestRunData;
  315. begin
  316. Terminate;
  317. lConfigFile:=GetOptionValue('f','config');
  318. if lConfigFile='' then
  319. lConfigFile:='dbdigest.cfg';
  320. lData:=Default(TTestRunData);
  321. lConfig:=Default(TDigestConfig);
  322. lConfig.RelSrcDir:='tests/';
  323. ReadSystemDBConfig(lConfig);
  324. ProcessConfigFile(lConfigFile,lConfig,lData);
  325. if ProcessCommandLine(lConfig,lData) then
  326. Analyze(lConfig,lData);
  327. end;
  328. var
  329. Application : TDBDigestApplication;
  330. begin
  331. Application:=TDBDigestApplication.Create(Nil);
  332. Application.Initialize;
  333. Application.Run;
  334. Application.Free;
  335. end.