1<?php
2/*=========================================================================
3
4  Program:   CDash - Cross-Platform Dashboard System
5  Module:    $Id$
6  Language:  PHP
7  Date:      $Date$
8  Version:   $Revision$
9
10  Copyright (c) 2002 Kitware, Inc.  All rights reserved.
11  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12
13     This software is distributed WITHOUT ANY WARRANTY; without even
14     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15     PURPOSE.  See the above copyright notices for more information.
16
17=========================================================================*/
18require_once 'xml_handlers/abstract_handler.php';
19require_once('models/build.php');
20require_once('models/label.php');
21require_once('models/site.php');
22require_once('models/test.php');
23require_once('models/image.php');
24require_once('models/feed.php');
25
26class TestingHandler extends AbstractHandler
27{
28  private $StartTimeStamp;
29  private $EndTimeStamp;
30  private $UpdateEndTime; // should we update the end time of the build
31
32  private $BuildId;
33  private $Test;
34  private $BuildTest;
35  private $BuildTestDiff;
36  private $TestImage;
37  private $TestMeasurement;
38  private $Label;
39  private $Append;
40
41  // Keep a record of the number of tests passed, failed and notrun
42  // This works only because we have one test file per submission
43  private $NumberTestsFailed;
44  private $NumberTestsNotRun;
45  private $NumberTestsPassed;
46
47  /** Constructor */
48  public function __construct($projectID, $scheduleID)
49    {
50    parent::__construct($projectID, $scheduleID);
51    $this->Build = new Build();
52    $this->Site = new Site();
53    $this->UpdateEndTime = false;
54    $this->NumberTestsFailed=0;
55    $this->NumberTestsNotRun=0;
56    $this->NumberTestsPassed=0;
57    $this->Feed = new Feed();
58    }
59
60  /** Destructor */
61  public function __destruct()
62    {
63    }
64
65  /** Start Element */
66  public function startElement($parser, $name, $attributes)
67    {
68    parent::startElement($parser, $name, $attributes);
69    $parent = $this->getParent(); // should be before endElement
70
71    if($name=='SITE')
72      {
73      $this->Site->Name = $attributes['NAME'];
74      if(empty($this->Site->Name))
75        {
76        $this->Site->Name = "(empty)";
77        }
78      $this->Site->Insert();
79
80      $siteInformation = new SiteInformation();
81      $buildInformation =  new BuildInformation();
82
83      // Fill in the attribute
84      foreach($attributes as $key=>$value)
85        {
86        $siteInformation->SetValue($key,$value);
87        $buildInformation->SetValue($key,$value);
88        }
89
90      $this->Site->SetInformation($siteInformation);
91
92      $this->Build->SiteId = $this->Site->Id;
93      $this->Build->Name = $attributes['BUILDNAME'];
94      if(empty($this->Build->Name))
95        {
96        $this->Build->Name = "(empty)";
97        }
98      $this->Build->SetStamp($attributes['BUILDSTAMP']);
99      $this->Build->Generator = $attributes['GENERATOR'];
100      $this->Build->Information = $buildInformation;
101
102      if (array_key_exists('APPEND', $attributes))
103        {
104        $this->Append = $attributes['APPEND'];
105        }
106      else
107        {
108        $this->Append = false;
109        }
110      }
111    else if($name == "TEST" && count($attributes) > 0)
112      {
113      $this->Test = new Test();
114      $this->Test->ProjectId = $this->projectid;
115      $this->BuildTest = new BuildTest();
116      $this->BuildTest->Status = $attributes['STATUS'];
117
118      if($attributes['STATUS'] == "passed")
119        {
120        $this->NumberTestsPassed++;
121        }
122      else if($attributes['STATUS'] == "failed")
123        {
124        $this->NumberTestsFailed++;
125        }
126      else if($attributes['STATUS'] == "notrun")
127        {
128        $this->NumberTestsNotRun++;
129        }
130      }
131    else if($name == "NAMEDMEASUREMENT")
132      {
133      $this->TestMeasurement = new TestMeasurement();
134
135      if($attributes['TYPE'] == 'file')
136        {
137        $this->TestMeasurement->Name = $attributes['FILENAME'];
138        }
139      else
140        {
141        $this->TestMeasurement->Name = $attributes['NAME'];
142        }
143      $this->TestMeasurement->Type = $attributes['TYPE'];
144      }
145    else if($name == "VALUE" && $parent== "MEASUREMENT" )
146      {
147      if(isset($attributes['COMPRESSION']) && $attributes['COMPRESSION']=="gzip")
148        {
149        $this->Test->CompressedOutput = true;
150        }
151      }
152    else if($name == 'LABEL' && $parent == 'LABELS')
153      {
154      $this->Label = new Label();
155      }
156    else if($name == "TESTLIST" && $parent == 'TESTING')
157      {
158      $start_time = gmdate(FMT_DATETIME, $this->StartTimeStamp);
159      $this->Build->ProjectId = $this->projectid;
160      $buildid = $this->Build->GetIdFromName($this->SubProjectName);
161
162      // If the build doesn't exist we add it
163      if($buildid==0)
164        {
165        $this->Build->ProjectId = $this->projectid;
166        $this->Build->StartTime = $start_time;
167        $this->Build->EndTime = $start_time;
168        $this->Build->SubmitTime = gmdate(FMT_DATETIME);
169        $this->Build->SetSubProject($this->SubProjectName);
170        $this->Build->Append = $this->Append;
171        $this->Build->InsertErrors = false;
172        add_build($this->Build, $this->scheduleid);
173
174        $this->UpdateEndTime = true;
175        $buildid = $this->Build->Id;
176        }
177      else
178        {
179        $this->Build->Id = $buildid;
180        //if the build already exists factor the number of tests that have
181        //already been run into our running total
182        $this->NumberTestsFailed += $this->Build->GetNumberOfFailedTests();
183        $this->NumberTestsNotRun += $this->Build->GetNumberOfNotRunTests();
184        $this->NumberTestsPassed += $this->Build->GetNumberOfPassedTests();
185        }
186
187      $GLOBALS['PHP_ERROR_BUILD_ID'] = $buildid;
188      $this->BuildId = $buildid;
189      }
190    } // end startElement
191
192
193  /** End Element */
194  public function endElement($parser, $name)
195    {
196    $parent = $this->getParent(); // should be before endElement
197    parent::endElement($parser, $name);
198
199    if($name == "TEST" && $parent == 'TESTING')
200      {
201      $this->Test->Insert();
202      if($this->Test->Id>0)
203        {
204        $this->BuildTest->TestId = $this->Test->Id;
205        $this->BuildTest->BuildId = $this->BuildId;
206        $this->BuildTest->Insert();
207
208        $this->Test->InsertLabelAssociations($this->BuildId);
209        }
210      else
211        {
212        add_log("Cannot insert test","Test XML parser",LOG_ERR,
213                $this->projectid,$this->BuildId);
214        }
215      }
216    else if($name == 'LABEL' && $parent == 'LABELS')
217      {
218      if(isset($this->Test))
219        {
220        $this->Test->AddLabel($this->Label);
221        }
222      }
223    else if($name == "NAMEDMEASUREMENT")
224      {
225      if($this->TestMeasurement->Name == 'Execution Time')
226        {
227        $this->BuildTest->Time = $this->TestMeasurement->Value;
228        }
229      else if($this->TestMeasurement->Name == 'Exit Code')
230        {
231        if(strlen($this->Test->Details)>0)
232          {
233          $this->Test->Details .= ' ('.$this->TestMeasurement->Value.')';
234          }
235        else
236          {
237          $this->Test->Details = $this->TestMeasurement->Value;
238          }
239        }
240      else if($this->TestMeasurement->Name == 'Completion Status')
241        {
242        if(strlen($this->Test->Details)>0)
243          {
244          $this->Test->Details =  $this->TestMeasurement->Value.' ('.$this->Test->Details.')';
245          }
246        else
247          {
248          $this->Test->Details = $this->TestMeasurement->Value;
249          }
250        }
251      else if($this->TestMeasurement->Name == 'Command Line')
252        {
253        // don't do anything since it should already be in the FullCommandLine
254        }
255      else // explicit measurement
256        {
257        // If it's an image we add it as an image
258        if(strpos($this->TestMeasurement->Type,'image')!== false)
259          {
260          $image = new Image();
261          $image->Extension = $this->TestMeasurement->Type;
262          $image->Data = $this->TestMeasurement->Value;
263          $image->Name = $this->TestMeasurement->Name;
264          $this->Test->AddImage($image);
265          }
266        else
267          {
268          $this->TestMeasurement->Value = trim($this->TestMeasurement->Value);
269          $this->Test->AddMeasurement($this->TestMeasurement);
270          }
271        }
272      } // end named measurement
273    else if($name == "SITE")
274      {
275      if(strlen($this->EndTimeStamp)>0 && $this->UpdateEndTime)
276        {
277        $end_time = gmdate(FMT_DATETIME, $this->EndTimeStamp); // The EndTimeStamp
278        $this->Build->UpdateEndTime($end_time);
279        }
280
281      // Update the number of tests in the Build table
282      $this->Build->UpdateTestNumbers($this->NumberTestsPassed,
283                                      $this->NumberTestsFailed,
284                                      $this->NumberTestsNotRun);
285      $this->Build->ComputeTestTiming();
286
287      // Insert the build into the feed
288      $this->Feed->InsertTest($this->projectid,$this->Build->Id);
289      }
290    } // end endElement
291
292  /** Text function */
293  public function text($parser, $data)
294    {
295    $parent = $this->getParent();
296    $element = $this->getElement();
297
298    if($parent == 'TESTING' && $element == 'STARTDATETIME')
299      {
300      $this->StartTimeStamp = str_to_time($data, $this->Build->GetStamp());
301      }
302    else if($parent == 'TESTING' && $element == 'STARTTESTTIME')
303      {
304      $this->StartTimeStamp = $data;
305      }
306    else if($parent == 'TESTING' && $element == 'ENDDATETIME')
307      {
308      $this->EndTimeStamp = str_to_time($data, $this->Build->GetStamp());
309      }
310    else if($parent == 'TESTING' && $element == 'ENDTESTTIME')
311      {
312      $this->EndTimeStamp = $data;
313      }
314    else if($parent == 'TESTING' && $element == 'ELAPSEDMINUTES')
315      {
316      $this->Build->SaveTotalTestsTime($data);
317      }
318    else if($parent == "TEST")
319      {
320      switch ($element)
321        {
322        case "NAME":
323          $this->Test->Name .= $data;
324        break;
325        case "PATH":
326          $this->Test->Path .= $data;
327        break;
328        case "FULLNAME":
329          //$this->Test->Command = $data;
330          break;
331        case "FULLCOMMANDLINE":
332          $this->Test->Command .= $data;
333          break;
334        }
335      }
336    else if($parent == "NAMEDMEASUREMENT" && $element == "VALUE")
337      {
338      $this->TestMeasurement->Value .= $data;
339      }
340    else if($parent == "MEASUREMENT" && $element == "VALUE")
341      {
342      $this->Test->Output .= $data;
343      }
344    else if($parent == 'LABELS' && $element == 'LABEL')
345      {
346      $this->Label->SetText($data);
347      }
348    }
349}
350?>
351