daacef2fabb21380d69b43ff82d0b8ddb51b6a86
[WebKit-https.git] / Tools / Scripts / webkitpy / tool / bot / ircbot_unittest.py
1 # Copyright (c) 2010 Google Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
5 # met:
6 #
7 #     * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 #     * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the
12 # distribution.
13 #     * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 import unittest2 as unittest
30 import random
31
32 from webkitpy.common.system.outputcapture import OutputCapture
33 from webkitpy.tool.bot import irc_command
34 from webkitpy.tool.bot.queueengine import TerminateQueue
35 from webkitpy.tool.bot.sheriff import Sheriff
36 from webkitpy.tool.bot.ircbot import IRCBot
37 from webkitpy.tool.bot.ircbot import Eliza
38 from webkitpy.tool.bot.sheriff_unittest import MockSheriffBot
39 from webkitpy.tool.mocktool import MockTool
40
41
42 def run(message):
43     tool = MockTool()
44     tool.ensure_irc_connected(None)
45     bot = IRCBot("sheriffbot", tool, Sheriff(tool, MockSheriffBot()), irc_command.commands)
46     bot._message_queue.post(["mock_nick", message])
47     bot.process_pending_messages()
48
49
50 class IRCBotTest(unittest.TestCase):
51     def test_eliza(self):
52         eliza = Eliza()
53         eliza.execute("tom", "hi", None, None)
54         eliza.execute("tom", "bye", None, None)
55
56     def test_parse_command_and_args(self):
57         tool = MockTool()
58         bot = IRCBot("sheriffbot", tool, Sheriff(tool, MockSheriffBot()), irc_command.commands)
59         self.assertEqual(bot._parse_command_and_args(""), (Eliza, [""]))
60         self.assertEqual(bot._parse_command_and_args("   "), (Eliza, [""]))
61         self.assertEqual(bot._parse_command_and_args(" hi "), (irc_command.Hi, []))
62         self.assertEqual(bot._parse_command_and_args(" hi there "), (irc_command.Hi, ["there"]))
63
64     def test_exception_during_command(self):
65         tool = MockTool()
66         tool.ensure_irc_connected(None)
67         bot = IRCBot("sheriffbot", tool, Sheriff(tool, MockSheriffBot()), irc_command.commands)
68
69         class CommandWithException(object):
70             def execute(self, nick, args, tool, sheriff):
71                 raise Exception("mock_exception")
72
73         bot._parse_command_and_args = lambda request: (CommandWithException, [])
74         expected_logs = 'MOCK: irc.post: Exception executing command: mock_exception\n'
75         OutputCapture().assert_outputs(self, bot.process_message, args=["mock_nick", "ignored message"], expected_logs=expected_logs)
76
77         class CommandWithException(object):
78             def execute(self, nick, args, tool, sheriff):
79                 raise KeyboardInterrupt()
80
81         bot._parse_command_and_args = lambda request: (CommandWithException, [])
82         # KeyboardInterrupt and SystemExit are not subclasses of Exception and thus correctly will not be caught.
83         OutputCapture().assert_outputs(self, bot.process_message, args=["mock_nick", "ignored message"], expected_exception=KeyboardInterrupt)
84
85     def test_hi(self):
86         random.seed(23324)
87         expected_logs = 'MOCK: irc.post: "Only you can prevent forest fires." -- Smokey the Bear\n'
88         OutputCapture().assert_outputs(self, run, args=["hi"], expected_logs=expected_logs)
89
90     def test_help(self):
91         expected_logs = 'MOCK: irc.post: mock_nick: Available commands: create-bug, help, hi, ping, restart, roll-chromium-deps, rollout, whois\nMOCK: irc.post: mock_nick: Type "mock-sheriff-bot: help COMMAND" for help on my individual commands.\n'
92         OutputCapture().assert_outputs(self, run, args=["help"], expected_logs=expected_logs)
93         expected_logs = 'MOCK: irc.post: mock_nick: Usage: hi\nMOCK: irc.post: mock_nick: Retrieves a random quip from Bugzilla.\nMOCK: irc.post: mock_nick: Aliases: hello\n'
94         OutputCapture().assert_outputs(self, run, args=["help hi"], expected_logs=expected_logs)
95         OutputCapture().assert_outputs(self, run, args=["help hello"], expected_logs=expected_logs)
96
97     def test_restart(self):
98         expected_logs = "MOCK: irc.post: Restarting...\n"
99         OutputCapture().assert_outputs(self, run, args=["restart"], expected_logs=expected_logs, expected_exception=TerminateQueue)
100
101     def test_rollout(self):
102         expected_logs = "MOCK: irc.post: mock_nick: Preparing rollout for http://trac.webkit.org/changeset/21654 ...\nMOCK: irc.post: mock_nick, abarth, darin, eseidel: Created rollout: http://example.com/36936\n"
103         OutputCapture().assert_outputs(self, run, args=["rollout 21654 This patch broke the world"], expected_logs=expected_logs)
104
105     def test_revert(self):
106         expected_logs = "MOCK: irc.post: mock_nick: Preparing rollout for http://trac.webkit.org/changeset/21654 ...\nMOCK: irc.post: mock_nick, abarth, darin, eseidel: Created rollout: http://example.com/36936\n"
107         OutputCapture().assert_outputs(self, run, args=["revert 21654 This patch broke the world"], expected_logs=expected_logs)
108
109     def test_multi_rollout(self):
110         expected_logs = "MOCK: irc.post: mock_nick: Preparing rollout for http://trac.webkit.org/changeset/21654, http://trac.webkit.org/changeset/21655, and http://trac.webkit.org/changeset/21656 ...\nMOCK: irc.post: mock_nick, abarth, darin, eseidel: Created rollout: http://example.com/36936\n"
111         OutputCapture().assert_outputs(self, run, args=["rollout 21654 21655 21656 This 21654 patch broke the world"], expected_logs=expected_logs)
112
113     def test_rollout_with_r_in_svn_revision(self):
114         expected_logs = "MOCK: irc.post: mock_nick: Preparing rollout for http://trac.webkit.org/changeset/21654 ...\nMOCK: irc.post: mock_nick, abarth, darin, eseidel: Created rollout: http://example.com/36936\n"
115         OutputCapture().assert_outputs(self, run, args=["rollout r21654 This patch broke the world"], expected_logs=expected_logs)
116
117     def test_multi_rollout_with_r_in_svn_revision(self):
118         expected_logs = "MOCK: irc.post: mock_nick: Preparing rollout for http://trac.webkit.org/changeset/21654, http://trac.webkit.org/changeset/21655, and http://trac.webkit.org/changeset/21656 ...\nMOCK: irc.post: mock_nick, abarth, darin, eseidel: Created rollout: http://example.com/36936\n"
119         OutputCapture().assert_outputs(self, run, args=["rollout r21654 21655 r21656 This r21654 patch broke the world"], expected_logs=expected_logs)
120
121     def test_rollout_bananas(self):
122         expected_logs = "MOCK: irc.post: mock_nick: Usage: rollout SVN_REVISION [SVN_REVISIONS] REASON\n"
123         OutputCapture().assert_outputs(self, run, args=["rollout bananas"], expected_logs=expected_logs)
124
125     def test_rollout_invalidate_revision(self):
126         # When folks pass junk arguments, we should just spit the usage back at them.
127         expected_logs = "MOCK: irc.post: mock_nick: Usage: rollout SVN_REVISION [SVN_REVISIONS] REASON\n"
128         OutputCapture().assert_outputs(self, run,
129                                        args=["rollout --component=Tools 21654"],
130                                        expected_logs=expected_logs)
131
132     def test_rollout_invalidate_reason(self):
133         # FIXME: I'm slightly confused as to why this doesn't return the USAGE message.
134         expected_logs = """MOCK: irc.post: mock_nick: Preparing rollout for http://trac.webkit.org/changeset/21654 ...
135 MOCK: irc.post: mock_nick, abarth, darin, eseidel: Failed to create rollout patch:
136 MOCK: irc.post: The rollout reason may not begin with - (\"-bad (Requested by mock_nick on #webkit).\").
137 """
138         OutputCapture().assert_outputs(self, run,
139                                        args=["rollout 21654 -bad"],
140                                        expected_logs=expected_logs)
141
142     def test_multi_rollout_invalidate_reason(self):
143         expected_logs = """MOCK: irc.post: mock_nick: Preparing rollout for http://trac.webkit.org/changeset/21654, http://trac.webkit.org/changeset/21655, and http://trac.webkit.org/changeset/21656 ...
144 MOCK: irc.post: mock_nick, abarth, darin, eseidel: Failed to create rollout patch:
145 MOCK: irc.post: The rollout reason may not begin with - (\"-bad (Requested by mock_nick on #webkit).\").
146 """
147         OutputCapture().assert_outputs(self, run,
148                                        args=["rollout "
149                                              "21654 21655 r21656 -bad"],
150                                        expected_logs=expected_logs)
151
152     def test_rollout_no_reason(self):
153         expected_logs = "MOCK: irc.post: mock_nick: Usage: rollout SVN_REVISION [SVN_REVISIONS] REASON\n"
154         OutputCapture().assert_outputs(self, run, args=["rollout 21654"], expected_logs=expected_logs)
155
156     def test_multi_rollout_no_reason(self):
157         expected_logs = "MOCK: irc.post: mock_nick: Usage: rollout SVN_REVISION [SVN_REVISIONS] REASON\n"
158         OutputCapture().assert_outputs(self, run, args=["rollout 21654 21655 r21656"], expected_logs=expected_logs)