summaryrefslogtreecommitdiffstats
path: root/extras/failed-tests.py
blob: d2aeb7651c20c87b378aaf45e59a1cce836be288 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/python

import blessings
import HTMLParser
import requests
import sys
import re
from collections import defaultdict
from datetime import date, timedelta, datetime
from dateutil.parser import parse

## This tool goes though the Gluster regression links and checks for failures
#
# Usage: failed-tests.py [<regression links,..> | get-summary \
#        <last number of days> <regression link>]
#
# When no options specified, goes through centos regression
# @build.gluster.org/job/rackspace-regression-2GB-triggered/ and gets the
# summary of last 30 builds
# When other regression links (Eg:/job/rackspace-netbsd7-regression-triggered/)
# are specified it goes through those links and prints the summary of last 30
# builds in those links
# When get-summary is specified, it goes through the link specified and gets the
# summary of the builds that have happened in the last number of days specified.

BASE='https://build.gluster.org'
TERM=blessings.Terminal()
MAX_BUILDS=100
summary=defaultdict(list)

def process_failure (url, cut_off_date):
    text = requests.get(url,verify=False).text
    accum = []
    for t in text.split('\n'):
        if t.find("BUILD_TIMESTAMP=") != -1 and cut_off_date != None:
            build_date = parse (t, fuzzy=True)
            if build_date.date() < cut_off_date:
                return 1
        elif t.find("Result: FAIL") != -1:
            print TERM.red + ('FAILURE on %s' % BASE+url) + TERM.normal
            for t2 in accum:
                print t2.encode('utf-8')
                if t2.find("Wstat") != -1:
                     test_case = re.search('\./tests/.*\.t',t2)
                     if test_case:
                          summary[test_case.group()].append(url)
            accum = []
        elif t.find("Result: PASS") != -1:
            accum = []
        elif t.find("cur_cores=/") != -1:
            summary["core"].append([t.split("/")[1]])
            summary["core"].append(url)
        else:
            accum.append(t)
    return 0

class FailureFinder (HTMLParser.HTMLParser):
    def __init__ (*args):
        apply(HTMLParser.HTMLParser.__init__,args)
        self = args[0]
        self.last_href = None
    def handle_starttag (self, tag, attrs):
        if tag == 'a':
            return self.is_a_tag (attrs)
        if tag == 'img':
            return self.is_img_tag (attrs)
    def is_a_tag (self, attrs):
        attrs_dict = dict(attrs)
        try:
            if attrs_dict['class'] != 'build-status-link':
                return
        except KeyError:
            return
        self.last_href = attrs_dict['href']
    def is_img_tag (self, attrs):
        if self.last_href == None:
            return
        attrs_dict = dict(attrs)
        try:
            if attrs_dict['alt'].find('Failed') == -1:
                return
        except KeyError:
            return
        process_failure(BASE+self.last_href, None)
        self.last_href = None

def main (url):
    parser = FailureFinder()
    text = requests.get(url,verify=False).text
    parser.feed(text)

def print_summary():
    for k,v in summary.iteritems():
        if k == 'core':
            print TERM.red + "Found cores:" + TERM.normal
            for cmp,lnk in zip(v[::2], v[1::2]):
                print "\tComponent: %s" % (cmp)
                print "\tRegression Link: %s" % (lnk)
        else:
            print TERM.red + "%s ; Failed %d times" % (k, len(v)) + TERM.normal
            for lnk in v:
                print "\tRegression Links: %s" % (lnk)

def get_summary (build_id, cut_off_date, reg_link):
    for i in xrange(build_id, build_id-MAX_BUILDS, -1):
        url=BASE+reg_link+str(i)+"/consoleFull"
        ret = process_failure(url, cut_off_date)
        if ret == 1:
            return

if __name__ == '__main__':
    if len(sys.argv) < 2:
        main(BASE+'/job/rackspace-regression-2GB-triggered/')
    elif sys.argv[1].find("get-summary") != -1:
        if len(sys.argv) < 4:
            print "Usage: failed-tests.py get-summary <last_no_of_days> <centos|netbsd|regression_link>"
            sys.exit(0)
        num_days=int(sys.argv[2])
        cut_off_date=date.today() - timedelta(days=num_days)
        reg = sys.argv[3]
        if reg == 'centos':
            reg_link = '/job/rackspace-regression-2GB-triggered/'
        elif reg == 'netbsd':
            reg_link = '/job/rackspace-netbsd7-regression-triggered/'
        else:
            reg_link = reg

        build_id = int(requests.get(BASE+reg_link+"lastBuild/buildNumber", verify=False).text)
        get_summary(build_id, cut_off_date, reg_link)
    else:
        for u in sys.argv[1:]:
            main(BASE+u)
    print_summary()