#!perl use warnings; use strict; use Test::More tests => 89; use Test::Bot::BasicBot::Pluggable; use FindBin qw( $Bin ); use lib $Bin; my $bot = Test::Bot::BasicBot::Pluggable->new(); # this one is a complete bugger to build eval "use XML::Feed"; our $HAS_XML_FEED = $@ ? 0 : 1; ok( my $ib = $bot->load("Infobot"), "Loaded infobot module"); ok( my $uur = $ib->get("user_unknown_responses") , "got list of unknown responses") or die; my $no_regex = qr/($uur)/; # ok, the intent here is to test / document the infobot grammar, because # every time I mess with it I get annoying regressions. In general, B::B::P # wasn't built with Test-Driven techniques, and this is hurting me recently, # it's way too hard to write tests retroactively.. ok( $ib->help, "module has help text" ); # by default, the infobot doesn't learn things that it merely overhears ok( ! $bot->tell_indirect("foo is red"), "passive learning off by default" ); ok( ! $bot->tell_indirect("foo?"), "no answer to passive learn" ); like( $bot->tell_direct("foo?"), $no_regex, "no info on foo" ); # ..but it will learn things it's told $bot->tell_directly. like( $bot->tell_direct("foo?"), $no_regex, "no info on foo" ); is( $bot->tell_direct("foo is red"), "Okay.", "active learning works" ); is( $bot->tell_direct("foo?"), "foo is red", "correct answer to active learn" ); like( $bot->tell_direct("quux?"), $no_regex, "no info on quux" ); is( $bot->tell_direct("quux are blue"), "Okay.", "active learning works" ); is( $bot->tell_direct("quux?"), "quux are blue", "correct answer to active learn" ); # you can tell someone about foo is( $bot->tell_direct("tell testbot about foo"),"Told testbot about foo.","tell someone about foo"); ok( !$bot->tell_indirect("foo?"), "passive questioning off by default" ); # you can turn on the ability to ask questions without addressing the bot ok( $ib->set("user_passive_answer", 1), "activate passive ask" ); is( $bot->tell_indirect("foo?"), "foo is red", "passive questioning now on" ); # and the ability to add factoids without addressing the bot ok( $ib->set("user_passive_learn", 1), "activate passive learn" ); is( $bot->tell_direct("bar is green"), "Okay.", "passive learning now works" ); is( $bot->tell_indirect("bar?"), "bar is green", "passive questioning works" ); # you can search factoids, but not in public is( $bot->tell_direct("search for foo"), "privmsg only, please", "not searched in public"); $ib->set("user_allow_searching",0); is( $bot->tell_private("search for foo"), "searching disabled", "searched for 'foo' disabled"); $ib->set("user_allow_searching",1); is( $bot->tell_private("search for foo"), "I know about: 'foo'.", "searched for 'foo'"); is( $bot->tell_private("search for foobar"), "I don't know anything about foobar.", "searched for 'foobar' (which we know nothing about)"); is( $bot->tell_private("search for foo bar"), "I know about: 'foo', 'bar'.", "searched for 'foo' and 'bar'"); $ib->set('user_num_results' => 1); is( $bot->tell_private("search for foo bar"), "I know about: 'foo'.", "searched for 'foo' and 'bar' with user_num_results set to 1"); # you can append strings to factoids is( $bot->tell_direct("foo is also blue"), "Okay.", "can append to faactoids" ); is( $bot->tell_direct("foo?"), "foo is red or blue", "works" ); is( $bot->tell_direct("foo is also pink"), "Okay.", "can append to faactoids" ); is( $bot->tell_direct("foo?"), "foo is red or blue or pink", "works" ); # factoids can be forgotten is( $bot->tell_direct("forget foo"), "I forgot about foo.", "forgotten foo"); like( $bot->tell_direct("foo?"), $no_regex, "no info on foo" ); is( $bot->tell_direct("forget foo"), "I don't know anything about foo." , "can't forget something i don't know" ); # factoids can be replaced my $but_reply = '... but bar is green ...'; # ok, why does this get interpreted as '1' is( $bot->tell_direct("bar is yellow"), $but_reply, "Can't just redefine factoids" ); is( $bot->tell_indirect("bar is yellow"), '', "Can't just redefine factoids" ); is( $bot->tell_indirect("bar?"), "bar is green", "not changed" ); is( $bot->tell_direct("no, bar is yellow"), "Okay.", "Can explicitly redefine factoids" ); is( $bot->tell_indirect("bar?"), "bar is yellow", "changed" ); # factoids can contain RSS { local $TODO = !$HAS_XML_FEED; is( $bot->tell_direct("rsstest is "), "Okay.", "set RSS" ); is( $bot->tell_indirect("rsstest?"), "title", "can read rss"); $bot->tell_direct("rsstest2 is "); like( $bot->tell_indirect("rsstest2?"), qr{rsstest2 is << Error parsing RSS from file:///.*/05infobot.t: Cannot detect feed type >>}, "can't read rss"); } my $old_stopwords = $ib->get("user_stopwords"); # certain things can't be factoid keys. ok( $ib->set("user_stopwords", "and"), "set stopword 'and'" ); ok( !$bot->tell_direct("and is mumu"), "can't set 'and' as factoid"); ok( !$bot->tell_direct("dkjsdlfkdsjfglkdsfjglfkdjgldksfjglkdfjglds is mumu"), "can't set very long factoid"); $ib->set("user_stopwords", $old_stopwords); # literal syntax is( $bot->tell_direct("literal rsstest?"), "rsstest =is= ", "literal of rsstest" ); ok( $bot->tell_direct("bar is also fum"), "bar also fum" ); is( $bot->tell_direct("literal bar?"), "bar =is= yellow =or= fum", "bar" ); # alternate factoids ('|') is( $bot->tell_direct("foo is one"), "Okay.", "foo is one"); is( $bot->tell_direct("foo is also two"), "Okay.", "foo is also two"); is( $bot->tell_direct("foo is also |maybe"), "Okay.", "foo is also maybe"); ok( my $reply = $bot->tell_direct("foo?"), "got one of the foos" ); ok( ( $reply eq 'foo is maybe' or $reply eq 'foo is one or two' ), "it's one of the two"); # blech's torture test, all three in one # notes on dipsy differences: # * 'ok' is 'okay.' in a true infobot # * literal doesn't highlight =or= like it does =is= # * infobots attempt to parse english # * there's a difference between 'is' and 'are' # * doesn't respond to a passive attempt to reset an item is( $bot->tell_direct("forget foo"), "I forgot about foo.", "forgotten foo"); is( $bot->tell_direct("foo is foo"), "Okay.", "simple set" ); is( $bot->tell_direct("foo?"), "foo is foo", "simple get" ); is( $bot->tell_direct("what is foo?"), "foo is foo", "English-language get" ); # fails is( $bot->tell_direct("where is foo?"), "foo is foo", "Another English get" ); is( $bot->tell_direct("who is foo?"), "foo is foo", "Yet another English get" ); is( $bot->tell_direct("hoogas are things"), "Okay.", "simple 'are' set"); # fails is( $bot->tell_direct("what are hoogas?"), "hoogas are things", "English-language 'are' get" ); is( $bot->tell_direct("foo is a silly thing"), "... but foo is foo ...", "warning about overwriting" ); is( $bot->tell_indirect("foo is a silly thing"), "", "shouldn't get a reply" ); is( $bot->tell_direct("foo is also bar"), "Okay.", "simple append"); is( $bot->tell_direct("foo?"), "foo is foo or bar", "appended ok"); is( $bot->tell_direct("foo is also baz or quux"), "Okay.", "complex append"); is( $bot->tell_direct("foo?"), "foo is foo or bar or baz or quux", "also ok"); is( $bot->tell_direct("foo is also | a silly thing"), "Okay.", "alternate appended"); is( $bot->tell_direct("literal foo?"), "foo =is= foo =or= bar =or= baz =or= quux =or= |a silly thing", "entire factoid looks right"); is( $bot->tell_direct("foo is also |this is a very silly thing"), "Okay.", "and a reply"); is( $bot->tell_direct("literal foo?"), "foo =is= foo =or= bar =or= baz =or= quux =or= |a silly thing =or= |this is a very silly thing", "entire entry looks fine to me"); # run through a few times, and see what we get out foreach my $i (0..9) { ok( $reply = $bot->tell_direct("foo?"), "got one of the foos" ); ok( ( $reply eq 'foo is foo or bar or baz or quux' or $reply eq 'foo is a silly thing' or $reply eq 'this is a very silly thing' ), "it's '$reply'" ); }