#!/usr/bin/env python #-*- coding: utf-8 -*- # Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. # # Use of this source code is governed by a BSD-style license # that can be found in the LICENSE file in the root of the source # tree. An additional intellectual property rights grant can be found # in the file PATENTS. All contributing project authors may # be found in the AUTHORS file in the root of the source tree. """Test the tgrid parser. Compatible with build bot 0.8.4 P1. """ __author__ = 'phoglund@webrtc.org (Patrik Höglund)' import unittest import tgrid_parser SAMPLE_FILE = """ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Buildbot</title> <link rel="stylesheet" href="default.css" type="text/css" /> <link rel="alternate" type="application/rss+xml" title="RSS" href="rss"> </head> <body class="interface"> <div class="header"> <a href=".">Home</a> - <a href="waterfall">Waterfall</a> <a href="grid">Grid</a> <a href="tgrid">T-Grid</a> <a href="console">Console</a> <a href="builders">Builders</a> <a href="one_line_per_build">Recent Builds</a> <a href="buildslaves">Buildslaves</a> <a href="changes">Changesources</a> - <a href="json/help">JSON API</a> - <a href="about">About</a> </div> <hr/> <div class="content"> <h1>Transposed Grid View</h1> <table class="Grid" border="0" cellspacing="0"> <tr> <td class="title"><a href="http://www.chromium.org">WebRTC</a> </td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/Android">Android</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/AndroidNDK">AndroidNDK</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/Chrome">Chrome</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/ChromeOS">ChromeOS</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/Linux32DBG">Linux32DBG</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/Linux32Release">Linux32Release</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/Linux64DBG">Linux64DBG</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/Linux64DBG-GCC4.6">Linux64DBG-GCC4.6</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/Linux64Release">Linux64Release</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/LinuxClang">LinuxClang</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/LinuxValgrind">LinuxValgrind</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/LinuxVideoTest">LinuxVideoTest</a></td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/MacOS32DBG">MacOS32DBG</a></td> <td valign="middle" style="text-align: center" class="builder building"> <a href="builders/MacOS32Release">MacOS32Release</a><br/>(building)</td> <td valign="middle" style="text-align: center" class="builder idle"> <a href="builders/Win32Debug">Win32Debug</a></td> <td valign="middle" style="text-align: center" class="builder building"> <a href="builders/Win32Release">Win32Release</a><br/>(building)</td> </tr> <tr> <td valign="bottom" class="sourcestamp">2006 </td> <td class="build success"> <a href="builders/Android/builds/482">OK</a> </td> <td class="build success"> <a href="builders/AndroidNDK/builds/70">OK</a> </td> <td class="build success"> <a href="builders/Chrome/builds/243">warnings</a> </td> <td class="build success"> <a href="builders/ChromeOS/builds/933">OK</a> </td> <td class="build success"> <a href="builders/Linux32DBG/builds/936">OK</a> </td> <td class="build success"> <a href="builders/Linux32Release/builds/1050">OK</a> </td> <td class="build success"> <a href="builders/Linux64DBG/builds/1038">OK</a> </td> <td class="build success"> <a href="builders/Linux64DBG-GCC4.6/builds/371">OK</a> </td> <td class="build success"> <a href="builders/Linux64Release/builds/936">OK</a> </td> <td class="build success"> <a href="builders/LinuxClang/builds/610">OK</a> </td> <td class="build success"> <a href="builders/LinuxValgrind/builds/317">OK</a> </td> <td class="build"> </td> <td class="build success"> <a href="builders/MacOS32DBG/builds/1052">OK</a> </td> <td class="build"> </td> <td class="build success"> <a href="builders/Win32Debug/builds/822">OK</a> </td> <td class="build"> </td> </tr> <tr> <td valign="bottom" class="sourcestamp">2007 </td> <td class="build success"> <a href="builders/Android/builds/483">OK</a> </td> <td class="build success"> <a href="builders/AndroidNDK/builds/71">OK</a> </td> <td class="build success"> <a href="builders/Chrome/builds/244">OK</a> </td> <td class="build success"> <a href="builders/ChromeOS/builds/934">OK</a> </td> <td class="build success"> <a href="builders/Linux32DBG/builds/937">OK</a> </td> <td class="build success"> <a href="builders/Linux32Release/builds/1051">OK</a> </td> <td class="build success"> <a href="builders/Linux64DBG/builds/1039">OK</a> </td> <td class="build success"> <a href="builders/Linux64DBG-GCC4.6/builds/372">OK</a> </td> <td class="build success"> <a href="builders/Linux64Release/builds/937">OK</a> </td> <td class="build success"> <a href="builders/LinuxClang/builds/611">OK</a> </td> <td class="build success"> <a href="builders/LinuxValgrind/builds/318">OK</a> </td> <td class="build failure"> <a href="builders/LinuxVideoTest/builds/731">failed<br/>voe_auto_test</a> </td> <td class="build success"> <a href="builders/MacOS32DBG/builds/1053">OK</a> </td> <td class="build success"> <a href="builders/MacOS32Release/builds/309">OK</a> </td> <td class="build success"> <a href="builders/Win32Debug/builds/823">OK</a> </td> <td class="build success"> <a href="builders/Win32Release/builds/809">OK</a> </td> </tr> <tr> <td valign="bottom" class="sourcestamp">2008 </td> <td class="build success"> <a href="builders/Android/builds/484">OK</a> </td> <td class="build success"> <a href="builders/AndroidNDK/builds/72">OK</a> </td> <td class="build success"> <a href="builders/Chrome/builds/245">OK</a> </td> <td class="build success"> <a href="builders/ChromeOS/builds/935">OK</a> </td> <td class="build success"> <a href="builders/Linux32DBG/builds/938">OK</a> </td> <td class="build success"> <a href="builders/Linux32Release/builds/1052">OK</a> </td> <td class="build success"> <a href="builders/Linux64DBG/builds/1040">OK</a> </td> <td class="build success"> <a href="builders/Linux64DBG-GCC4.6/builds/373">OK</a> </td> <td class="build success"> <a href="builders/Linux64Release/builds/938">OK</a> </td> <td class="build success"> <a href="builders/LinuxClang/builds/612">OK</a> </td> <td class="build success"> <a href="builders/LinuxValgrind/builds/319">OK</a> </td> <td class="build success"> <a href="builders/LinuxVideoTest/builds/732">OK</a> </td> <td class="build success"> <a href="builders/MacOS32DBG/builds/1054">OK</a> </td> <td class="build success"> <a href="builders/MacOS32Release/builds/310">OK</a> </td> <td class="build success"> <a href="builders/Win32Debug/builds/824">OK</a> </td> <td class="build success"> <a href="builders/Win32Release/builds/810">OK</a> </td> </tr> <tr> <td valign="bottom" class="sourcestamp">2010 </td> <td class="build success"> <a href="builders/Android/builds/485">OK</a> </td> <td class="build success"> <a href="builders/AndroidNDK/builds/73">OK</a> </td> <td class="build"> </td> <td class="build success"> <a href="builders/ChromeOS/builds/936">OK</a> </td> <td class="build success"> <a href="builders/Linux32DBG/builds/939">OK</a> </td> <td class="build success"> <a href="builders/Linux32Release/builds/1053">OK</a> </td> <td class="build success"> <a href="builders/Linux64DBG/builds/1041">OK</a> </td> <td class="build success"> <a href="builders/Linux64DBG-GCC4.6/builds/374">OK</a> </td> <td class="build success"> <a href="builders/Linux64Release/builds/939">OK</a> </td> <td class="build success"> <a href="builders/LinuxClang/builds/613">OK</a> </td> <td class="build success"> <a href="builders/LinuxValgrind/builds/320">OK</a> </td> <td class="build success"> <a href="builders/LinuxVideoTest/builds/733">OK</a> </td> <td class="build success"> <a href="builders/MacOS32DBG/builds/1055">OK</a> </td> <td class="build success"> <a href="builders/MacOS32Release/builds/311">OK</a> </td> <td class="build success"> <a href="builders/Win32Debug/builds/825">OK</a> </td> <td class="build success"> <a href="builders/Win32Release/builds/811">OK</a> </td> </tr> <tr> <td valign="bottom" class="sourcestamp">2011 </td> <td class="build success"> <a href="builders/Android/builds/486">OK</a> </td> <td class="build success"> <a href="builders/AndroidNDK/builds/74">OK</a> </td> <td class="build"> </td> <td class="build success"> <a href="builders/ChromeOS/builds/937">OK</a> </td> <td class="build success"> <a href="builders/Linux32DBG/builds/940">OK</a> </td> <td class="build success"> <a href="builders/Linux32Release/builds/1054">OK</a> </td> <td class="build success"> <a href="builders/Linux64DBG/builds/1042">OK</a> </td> <td class="build success"> <a href="builders/Linux64DBG-GCC4.6/builds/375">OK</a> </td> <td class="build success"> <a href="builders/Linux64Release/builds/940">OK</a> </td> <td class="build success"> <a href="builders/LinuxClang/builds/614">OK</a> </td> <td class="build success"> <a href="builders/LinuxValgrind/builds/321">OK</a> </td> <td class="build success"> <a href="builders/LinuxVideoTest/builds/734">OK</a> </td> <td class="build success"> <a href="builders/MacOS32DBG/builds/1056">OK</a> </td> <td class="build running"> <a href="builders/MacOS32Release/builds/313">building</a> </td> <td class="build success"> <a href="builders/Win32Debug/builds/826">OK</a> </td> <td class="build running"> <a href="builders/Win32Release/builds/813">building</a> </td> </tr> <tr> <td valign="bottom" class="sourcestamp">latest </td> <td class="build running"> <a href="builders/MacOS32Release/builds/313">building</a> </td> <td class="build success"> <a href="builders/Win32Debug/builds/826">OK</a> </td> </tr> </table> </div><div class="footer" style="clear:both"> <hr/> <a href="http://buildbot.net/">BuildBot</a> (0.8.4p1) working for the <a href="http://www.chromium.org">WebRTC </a> project.<br/> Page built: <b>Thu 12 Apr 2012 03:49:32</b> (CDT) </div> </body> </html> """ MINIMAL_OK = """ <tr> <td valign="bottom" class="sourcestamp">1570 </td> <td class="build success"> <a href="builders/Android/builds/121">OK</a></td> </tr> """ MINIMAL_FAIL = """ <tr> <td valign="bottom" class="sourcestamp">1573 </td> <td class="build failure"> <a href="builders/LinuxVideoTest/builds/731">failed<br/>voe_auto_test</a> </td> </tr> """ MINIMAL_BUILDING = """ <tr> <td valign="bottom" class="sourcestamp">1576 </td> <td class="build running"> <a href="builders/Win32Debug/builds/434">building</a></td> voe_auto_test</td> </tr> """ MINIMAL_WARNED = """ <tr> <td valign="bottom" class="sourcestamp">1576 </td> <td class="build warnings"> <a href="builders/Chrome/builds/109">warnings</a><br /> make chrome</td> </tr> """ MINIMAL_EXCEPTION = """ <tr> <td valign="bottom" class="sourcestamp">1576 </td> <td class="build exception"> <a href="builders/Chrome/builds/109">exception</a><br /> Sync</td> </tr> """ MINIMAL_EXCEPTION_SLAVE_LOST = """ <tr> <td valign="bottom" class="sourcestamp">1576 </td> <td class="build retry"> <a href="builders/LinuxValgrind/builds/324">build<br/>successful<br/>exception<br/>slave<br/>lost</a> </td> </tr> """ class TGridParserTest(unittest.TestCase): def test_parser_throws_exception_on_empty_html(self): self.assertRaises(tgrid_parser.FailedToParseBuildStatus, tgrid_parser.parse_tgrid_page, ''); def test_parser_finds_successful_bot(self): result = tgrid_parser.parse_tgrid_page(MINIMAL_OK) self.assertEqual(1, len(result), 'There is only one bot in the sample.') first_mapping = result.items()[0] self.assertEqual('1570--Android', first_mapping[0]) self.assertEqual('121--OK', first_mapping[1]) def test_parser_finds_failed_bot(self): result = tgrid_parser.parse_tgrid_page(MINIMAL_FAIL) self.assertEqual(1, len(result), 'There is only one bot in the sample.') first_mapping = result.items()[0] self.assertEqual('1573--LinuxVideoTest', first_mapping[0]) self.assertEqual('731--failed', first_mapping[1]) def test_parser_finds_building_bot(self): result = tgrid_parser.parse_tgrid_page(MINIMAL_BUILDING) self.assertEqual(1, len(result), 'There is only one bot in the sample.') first_mapping = result.items()[0] self.assertEqual('1576--Win32Debug', first_mapping[0]) self.assertEqual('434--building', first_mapping[1]) def test_parser_finds_warnings(self): result = tgrid_parser.parse_tgrid_page(MINIMAL_WARNED) self.assertEqual(1, len(result), 'There is only one bot in the sample.') first_mapping = result.items()[0] self.assertEqual('1576--Chrome', first_mapping[0]) self.assertEqual('109--warnings', first_mapping[1]) def test_parser_finds_exception_and_maps_to_failed(self): result = tgrid_parser.parse_tgrid_page(MINIMAL_EXCEPTION) self.assertEqual(1, len(result), 'There is only one bot in the sample.') first_mapping = result.items()[0] self.assertEqual('1576--Chrome', first_mapping[0]) self.assertEqual('109--failed', first_mapping[1]) def test_parser_finds_exception_slave_lost_and_maps_to_failed(self): # This is to work around a bug in build bot 0.8.4p1 where it may say that # the build was successful AND the slave was lost. In this case the build # is not actually successful, so treat it as such. result = tgrid_parser.parse_tgrid_page(MINIMAL_EXCEPTION_SLAVE_LOST) self.assertEqual(1, len(result), 'There is only one bot in the sample.') first_mapping = result.items()[0] self.assertEqual('1576--LinuxValgrind', first_mapping[0]) self.assertEqual('324--failed', first_mapping[1]) def test_parser_finds_all_bots_and_revisions_except_forced_builds(self): result = tgrid_parser.parse_tgrid_page(SAMPLE_FILE) # 5*16 = 80 bots in sample. There's also five empty results because some # bots did not run for some revisions, so 80 - 5 = 75 results. There are # two additional statuses under an explicit 'latest' revision, which should # be ignored since that means the build was forced. self.assertEqual(75, len(result)) # Make some samples self.assertTrue(result.has_key('2006--ChromeOS')) self.assertEquals('933--OK', result['2006--ChromeOS']) self.assertTrue(result.has_key('2006--Chrome')) self.assertEquals('243--warnings', result['2006--Chrome']) self.assertTrue(result.has_key('2006--LinuxClang')) self.assertEquals('610--OK', result['2006--LinuxClang']) # This one happened to not get reported in revision 2006, but it should be # there in the next revision: self.assertFalse(result.has_key('2006--Win32Release')) self.assertTrue(result.has_key('2007--Win32Release')) self.assertEquals('809--OK', result['2007--Win32Release']) self.assertTrue(result.has_key('2007--ChromeOS')) self.assertEquals('934--OK', result['2007--ChromeOS']) self.assertTrue(result.has_key('2007--LinuxVideoTest')) self.assertEquals('731--failed', result['2007--LinuxVideoTest']) self.assertTrue(result.has_key('2011--Win32Release')) self.assertEquals('813--building', result['2011--Win32Release']) if __name__ == '__main__': unittest.main()