swh:1:snp:634d2b8906a7a2f6511ccb358da84e19b290d2c9
Raw File
Tip revision: fb569b4ff4b8f6fac68584c57ee0f31e3d3c5089 authored by James Vega on 17 September 2004, 17:29:16 UTC
0.80.0pre2
Tip revision: fb569b4
test_MoobotFactoids.py
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

###
# Copyright (c) 2003, Daniel DiPaolo
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright notice,
#     this list of conditions, and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions, and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#   * Neither the name of the author of this software nor the name of
#     contributors to this software may be used to endorse or promote products
#     derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###

from testsupport import *

import supybot.ircutils as ircutils

try:
    import sqlite
except ImportError:
    sqlite = None

if sqlite is not None:
    MoobotFactoids = Owner.loadPluginModule('MoobotFactoids')
    MF = MoobotFactoids
    class OptionListTestCase(SupyTestCase):
        maxIterations = 267
        def _testOptions(self, s, L):
            max = self.maxIterations
            original = L[:]
            while max and L:
                max -= 1
                option = MF.pickOptions(s)
                self.failUnless(option in original,
                                'Option %s not in %s' % (option, original))
                if option in L:
                    L.remove(option)
            self.failIf(L, 'Some options never seen: %s' % L)

        def testPickOptions(self):
            self._testOptions('(a|b)', ['a', 'b'])
            self._testOptions('a', ['a'])
            self._testOptions('(a|b (c|d))', ['a', 'b c', 'b d'])
            self._testOptions('(a|(b|)c)', ['a', 'bc', 'c'])
            self._testOptions('(a(b|)|(c|)d)', ['a', 'ab', 'cd', 'd'])
            self._testOptions('(a|)', ['a', ''])
            self._testOptions('(|a)', ['a', ''])
            self._testOptions('((a)|(b))', ['(a)', '(b)'])

    class FactoidsTestCase(ChannelPluginTestCase, PluginDocumentation):
        plugins = ('MoobotFactoids', 'User', 'Utilities')
        config = {'reply.whenNotCommand': False}
        def setUp(self):
            ChannelPluginTestCase.setUp(self)
            # Create a valid user to use
            self.prefix = 'mf!bar@baz'
            self.irc.feedMsg(ircmsgs.privmsg(self.nick, 'register tester moo',
                                             prefix=self.prefix))
            m = self.irc.takeMsg() # Response to register.

        def testAddFactoid(self):
            self.assertNotError('moo is foo')
            # Check stripping punctuation
            self.assertError('moo!?    is foo') # 'moo' already exists
            self.assertNotError('foo!?    is foo')
            self.assertResponse('foo', 'foo is foo')
            self.assertNotError('bar is <reply>moo is moo')
            self.assertResponse('bar', 'moo is moo')
            # Check substitution
            self.assertNotError('who is <reply>$who')
            self.assertResponse('who', ircutils.nickFromHostmask(self.prefix))
            # Check that actions ("\x01ACTION...") don't match
            m = ircmsgs.action(self.channel, 'is doing something')
            self.irc.feedMsg(m)
            self.assertNoResponse(' ', 1)

        def testLiteral(self):
            self.assertError('literal moo') # no factoids yet
            self.assertNotError('moo is <reply>foo')
            self.assertResponse('literal moo', '<reply>foo')
            self.assertNotError('moo2 is moo!')
            self.assertResponse('literal moo2', 'moo!')
            self.assertNotError('moo3 is <action>foo')
            self.assertResponse('literal moo3', '<action>foo')

        def testGetFactoid(self):
            self.assertNotError('moo is <reply>foo')
            self.assertResponse('moo', 'foo')
            self.assertNotError('moo2 is moo!')
            self.assertResponse('moo2', 'moo2 is moo!')
            self.assertNotError('moo3 is <action>foo')
            self.assertAction('moo3', 'foo')
            # Test and make sure it's parsing
            self.assertNotError('moo4 is <reply>(1|2|3)')
            self.assertRegexp('moo4', '^(1|2|3)$')
            # Check case-insensitivity
            self.assertResponse('MOO', 'foo')
            self.assertResponse('mOo', 'foo')
            self.assertResponse('MoO', 'foo')
            # Check the "_is_" ability
            self.assertNotError('delete moo')
            self.assertNotError('moo _is_ <reply>foo')
            self.assertResponse('moo', 'foo')
            self.assertNotError('foo is bar _is_ baz')
            self.assertResponse('foo is bar', 'foo is bar is baz')

        def testFactinfo(self):
            self.assertNotError('moo is <reply>foo')
            self.assertRegexp('factinfo moo', '^moo: Created by tester on.*$')
            self.assertNotError('moo')
            self.assertRegexp('factinfo moo', self.prefix + '.*1 time')
            self.assertNotError('moo')
            self.assertRegexp('factinfo moo', self.prefix + '.*2 times')
            self.assertNotError('moo =~ s/foo/bar/')
            self.assertRegexp('factinfo moo',
                              '^moo: Created by tester on'
                              '.*?\. Last modified by tester on .*?\. '
                              'Last requested by %s on .*?, '
                              'requested 2 times.$' % self.prefix)
            self.assertNotError('lock moo')
            self.assertRegexp('factinfo moo',
                              '^moo: Created by tester on'
                              '.*?\. Last modified by tester on .*?\. '
                              'Last requested by %s on .*?, '
                              'requested 2 times. '
                              'Locked by tester on .*\.$' % self.prefix)
            self.assertNotError('unlock moo')
            self.assertRegexp('factinfo moo',
                              '^moo: Created by tester on'
                              '.*?\. Last modified by tester on .*?\. '
                              'Last requested by %s on .*?, '
                              'requested 2 times.$' % self.prefix)
            # Make sure I solved this bug
            # Check and make sure all the other stuff is reset
            self.assertNotError('foo is bar')
            self.assertNotError('foo =~ s/bar/blah/')
            self.assertNotError('foo')
            self.assertNotError('no foo is baz')
            self.assertRegexp('factinfo foo',
                              '^foo: Created by tester on'
                              '(?!(request|modif)).*?\.$')

        def testLockUnlock(self):
            # disable world.testing since we want new users to not
            # magically be endowed with the admin capability
            try:
                world.testing = False
                self.assertNotError('moo is <reply>moo')
                self.assertNotError('lock moo')
                self.assertRegexp('factinfo moo',
                                  '^moo: Created by tester on'
                                  '.*?\. Locked by tester on .*?\.')
                # switch user
                original = self.prefix
                self.prefix = 'moo!moo@moo'
                self.assertNotError('register nottester moo', private=True)
                self.assertError('unlock moo')
                self.assertRegexp('factinfo moo',
                                  '^moo: Created by tester on'
                                  '.*?\. Locked by tester on .*?\.')
                # switch back
                self.prefix = original
                self.assertNotError('identify tester moo', private=True)
                self.assertNotError('unlock moo')
                self.assertRegexp('factinfo moo',
                                  '^moo: Created by tester on.*?\.')
            finally:
                world.testing = True

        def testChangeFactoid(self):
            self.assertNotError('moo is <reply>moo')
            self.assertNotError('moo =~ s/moo/moos/')
            self.assertResponse('moo', 'moos')
            self.assertNotError('moo =~ s/reply/action/')
            self.assertAction('moo', 'moos')
            self.assertNotError('moo =~ s/moos/(moos|woofs)/')
            self.assertActionRegexp('moo', '^(moos|woofs)$')
            self.assertError('moo =~ s/moo/')

        def testMost(self):
            userPrefix1 = 'moo!bar@baz'; userNick1 = 'moo'
            userPrefix2 = 'boo!bar@baz'; userNick2 = 'boo'
            self.assertNotError('register %s bar' % userNick1,
                                frm=userPrefix1, private=True)
            self.assertNotError('register %s bar' % userNick2,
                                frm=userPrefix2, private=True)
            # Check an empty database
            self.assertError('most popular')
            self.assertError('most authored')
            self.assertError('most recent')
            # Check singularity response
            self.prefix = userPrefix1
            self.assertNotError('moogle is <reply>moo')
            self.assertError('most popular')
            self.assertResponse('most authored',
                                'Most prolific author: moo (1)')
            self.assertRegexp('most recent', "1 latest factoid:.*moogle")
            self.assertResponse('moogle', 'moo')
            self.assertRegexp('most popular',
                                "Top 1 requested factoid:.*moogle.*(1)")
            # Check plural response
            self.prefix = userPrefix2
            self.assertNotError('mogle is <reply>mo')
            self.assertRegexp('most authored',
                                'Most prolific authors:.*moo.*(1).*boo.*(1)')
            self.assertRegexp('most recent',
                                "2 latest factoids:.*mogle.*moogle.*")
            self.assertResponse('moogle', 'moo')
            self.assertRegexp('most popular',
                                "Top 1 requested factoid:.*moogle.*(2)")
            self.assertResponse('mogle', 'mo')
            self.assertRegexp('most popular',
                                "Top 2 requested factoids:.*"
                                "moogle.*(2).*mogle.*(1)")
            # Check most author ordering
            self.assertNotError('moo is <reply>oom')
            self.assertRegexp('most authored',
                                'Most prolific authors:.*boo.*(2).*moo.*(1)')

        def testListkeys(self):
            self.assertResponse('listkeys %', 'No keys matching "%" found.')
            self.assertNotError('moo is <reply>moo')
            # With this set, if only one key matches, it should respond with
            # the factoid
            MFconf = conf.supybot.plugins.MoobotFactoids  # looooong!
            MFconf.showFactoidIfOnlyOneMatch.setValue(True)
            self.assertResponse('listkeys moo', 'moo')
            self.assertResponse('listkeys foo', 'No keys matching "foo" '
                                'found.')
            # Throw in a bunch more
            for i in range(10):
                self.assertNotError('moo%s is <reply>moo' % i)
            self.assertRegexp('listkeys moo',
                              '^Key search for "moo" '
                              '\(11 found\): ("moo\d*", )+and "moo9"$')
            self.assertNotError('foo is bar')
            self.assertRegexp('listkeys %',
                              '^Key search for "\%" '
                              '\(12 found\): "foo", ("moo\d*", )+and '
                              '"moo9"$')
            # Check quoting
            self.assertNotError('foo\' is bar')
            self.assertResponse('listkeys foo',
                                'Key search for "foo" '
                                '(2 found): "foo" and "foo\'"')
            # Check unicode stuff
            self.assertResponse('listkeys Б', 'No keys matching "Б" found.')
            self.assertNotError('АБВГДЕЖ is foo')
            self.assertNotError('АБВГДЕЖЗИ is foo')
            self.assertResponse('listkeys Б',
                                'Key search for "Б" '
                                '(2 found): "АБВГДЕЖ" and "АБВГДЕЖЗИ"')

        def testListvalues(self):
            self.assertNotError('moo is moo')
            self.assertResponse('listvalues moo',
                                'Value search for "moo" (1 found): "moo"')

        def testListauth(self):
            self.assertNotError('moo is <reply>moo')
            self.assertRegexp('listauth tester', 'tester.*\(1 found\):.*moo')
            self.assertError('listauth moo')

        def testDelete(self):
            self.assertNotError('moo is <reply>moo')
            self.assertNotError('lock moo')
            self.assertError('delete moo')
            self.assertNotError('unlock moo')
            self.assertNotError('delete moo')

        def testAugmentFactoid(self):
            self.assertNotError('moo is foo')
            self.assertNotError('moo is also bar')
            self.assertResponse('moo', 'moo is foo, or bar')
            self.assertNotError('moo is bar _is_ foo')
            self.assertNotError('moo is bar is also foo')
            self.assertResponse('moo is bar', 'moo is bar is foo, or foo')

        def testReplaceFactoid(self):
            self.assertNotError('moo is foo')
            self.assertNotError('no moo is bar')
            self.assertResponse('moo', 'moo is bar')
            self.assertNotError('no, moo is baz')
            self.assertResponse('moo', 'moo is baz')
            self.assertNotError('lock moo')
            self.assertError('no moo is qux')
            self.assertNotError('foo is bar _is_ foo')
            self.assertNotError('no foo is bar _is_ baz')
            self.assertResponse('foo is bar', 'foo is bar is baz')

        def testRegexpNotCalledIfAlreadyHandled(self):
            self.assertResponse('echo foo is bar', 'foo is bar')
            self.assertNoResponse(' ', 3)

        def testNoResponseToCtcp(self):
            self.assertNotError('foo is bar')
            self.assertResponse('foo', 'foo is bar')
            self.irc.feedMsg(ircmsgs.privmsg(self.irc.nick, '\x01VERSION\x01'))
            m = self.irc.takeMsg()
            self.failIf(m)

        def testAddFactoidNotCalledWithBadNestingSyntax(self):
            self.assertError('re s/Error:.*/jbm is a tard/ ]')
            self.assertNoResponse(' ', 3)

        def testConfigShowFactoidIfOnlyOneMatch(self):
            # man these are long
            MFconf = conf.supybot.plugins.MoobotFactoids
            self.assertNotError('foo is bar')
            # Default to saying the factoid value
            self.assertResponse('listkeys foo', 'foo is bar')
            # Check the False setting
            MFconf.showFactoidIfOnlyOneMatch.setValue(False)
            self.assertResponse('listkeys foo', 'Key search for "foo" '
                                                '(1 found): "foo"')

        def testRandomFactoid(self):
            self.assertNotError('foo is <reply>bar')
            self.assertNotError('bar is <reply>baz')
            self.assertRegexp('randomfactoid', r'bar|baz')


# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
back to top