summaryrefslogtreecommitdiff
path: root/qpid/cpp/src/tests/cluster_test_logs.py
blob: 03338228246c324f2218db7c1666f05131c2b28c (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
#!/usr/bin/env python

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

# Functions for comparing broker log files, used by cluster_tests.py.

import os, os.path, re, glob
from itertools import izip

def split_log(log):
    """Split a broker log at checkpoints where a member joins.
    Return the set of checkpoints discovered."""
    checkpoint_re = re.compile("Member joined, frameSeq=([0-9]+), queue snapshot:")
    outfile = None
    checkpoints = []
    for l in open(log):
        match = checkpoint_re.search(l)
        if match:
            checkpoint = match.groups()[0]
            checkpoints.append(checkpoint)
            if outfile: outfile.close()
            outfile = open("%s.%s"%(log, checkpoint), 'w')

        if outfile: outfile.write(l)
    if outfile: outfile.close()
    return checkpoints

def filter_log(log):
    """Filter the contents of a log file to remove data that is expected
    to differ between brokers in a cluster. Filtered log contents between
    the same checkpoints should match across the cluster."""
    out = open("%s.filter"%(log), 'w')
    for l in open(log):
        # Lines to skip entirely
        skip = "|".join([
            'local connection',         # Only on local broker
            'UPDATER|UPDATEE',          # Ignore update process
            'stall for update|unstall, ignore update|cancelled offer .* unstall',
            'caught up',
            'active for links|Passivating links|Activating links',
            'info Connection.* connected to', # UpdateClient connection
            'warning Broker closed connection: 200, OK',
            'task late',
            'task overran',
            'warning CLOSING .* unsent data',
            'Inter-broker link '
            ])
        if re.compile(skip).search(l): continue

        # Regex to match a UUID
        uuid='\w\w\w\w\w\w\w\w-\w\w\w\w-\w\w\w\w-\w\w\w\w-\w\w\w\w\w\w\w\w\w\w\w\w'

        # Regular expression substitutions to remove expected differences
        for pattern,subst in [
            (r'\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d ', ''), # Remove timestamp
            (r'cluster\([0-9.: ]*', 'cluster('), # Remove cluster node id
            (r' local\)| shadow\)', ')'), # Remove local/shadow indication
            (r'CATCHUP', 'READY'), # Treat catchup as equivalent to ready.
            (r'OFFER', 'READY'), # Treat offer as equivalent to ready.
            # System UUID expected to be different
            (r'(org.apache.qpid.broker:system[:(])%s(\)?)'%(uuid), r'\1UUID\2'),

            # FIXME aconway 2010-12-20: substitutions to mask known problems
            # See https://issues.apache.org/jira/browse/QPID-2982
            (r' len=\d+', ' len=NN'),   # buffer lengths
            (r' map={.*_object_name:([^,}]*)[,}].*', r' \1'), # V2 map - just keep name
            (r'\d+-\d+-\d+--\d+', 'X-X-X--X'), # V1 Object IDs
            ]: l = re.sub(pattern,subst,l)
        out.write(l)
    out.close()

def verify_logs(logs):
    """Compare log files from cluster brokers, verify that they correspond correctly."""
    # FIXME aconway 2011-01-19: disable when called from unit tests
    # Causing sporadic failures, see https://issues.apache.org/jira/browse/QPID-3007
    if __name__ != "__main__": return
    
    for l in glob.glob("*.log"): filter_log(l)
    checkpoints = set()
    for l in glob.glob("*.filter"): checkpoints = checkpoints.union(set(split_log(l)))
    errors=[]
    for c in checkpoints:
        fragments = glob.glob("*.filter.%s"%(c))
        fragments.sort(reverse=True, key=os.path.getsize)
        while len(fragments) >= 2:
            a = fragments.pop(0)
            b = fragments[0]
            for ab in izip(open(a), open(b)):
                if ab[0] != ab[1]:
                    errors.append("\n    %s %s"%(a, b))
                    break
    if errors:
        raise Exception("Files differ in %s"%(os.getcwd())+"".join(errors))

# Can be run as a script.
if __name__ == "__main__":
    verify_logs(glob.glob("*.log"))