Merge branch 'master' into develop

This commit is contained in:
Griatch 2017-11-11 01:02:26 +01:00
commit 34acefc587
11 changed files with 461 additions and 29 deletions

View file

@ -30,7 +30,7 @@ RUN apk update && apk add python py-pip python-dev py-setuptools gcc musl-dev jp
ADD . /usr/src/evennia
# install dependencies
RUN pip install -e /usr/src/evennia --index-url=http://pypi.python.org/simple/ --trusted-host pypi.python.org
RUN pip install -e /usr/src/evennia --trusted-host pypi.python.org
# add the game source when rebuilding a new docker image from inside
# a game dir

160
evennia/accounts/tests.py Normal file
View file

@ -0,0 +1,160 @@
from mock import Mock
from random import randint
from unittest import TestCase
from evennia.accounts.accounts import AccountSessionHandler
from evennia.accounts.accounts import DefaultAccount
from evennia.server.session import Session
from evennia.utils import create
from django.conf import settings
class TestAccountSessionHandler(TestCase):
"Check AccountSessionHandler class"
def setUp(self):
self.account = create.create_account("TestAccount%s" % randint(0, 999999), email="test@test.com", password="testpassword", typeclass=DefaultAccount)
self.handler = AccountSessionHandler(self.account)
def test_get(self):
"Check get method"
self.assertEqual(self.handler.get(), [])
self.assertEqual(self.handler.get(100), [])
import evennia.server.sessionhandler
s1 = Session()
s1.logged_in = True
s1.uid = self.account.uid
evennia.server.sessionhandler.SESSIONS[s1.uid] = s1
s2 = Session()
s2.logged_in = True
s2.uid = self.account.uid + 1
evennia.server.sessionhandler.SESSIONS[s2.uid] = s2
s3 = Session()
s3.logged_in = False
s3.uid = self.account.uid + 2
evennia.server.sessionhandler.SESSIONS[s3.uid] = s3
self.assertEqual(self.handler.get(), [s1])
self.assertEqual(self.handler.get(self.account.uid), [s1])
self.assertEqual(self.handler.get(self.account.uid + 1), [])
def test_all(self):
"Check all method"
self.assertEqual(self.handler.get(), self.handler.all())
def test_count(self):
"Check count method"
self.assertEqual(self.handler.count(), len(self.handler.get()))
class TestDefaultAccount(TestCase):
"Check DefaultAccount class"
def setUp(self):
self.s1 = Session()
self.s1.sessid = 0
def test_puppet_object_no_object(self):
"Check puppet_object method called with no object param"
try:
DefaultAccount().puppet_object(self.s1, None)
self.fail("Expected error: 'Object not found'")
except RuntimeError as re:
self.assertEqual("Object not found", re.message)
def test_puppet_object_no_session(self):
"Check puppet_object method called with no session param"
try:
DefaultAccount().puppet_object(None, Mock())
self.fail("Expected error: 'Session not found'")
except RuntimeError as re:
self.assertEqual("Session not found", re.message)
def test_puppet_object_already_puppeting(self):
"Check puppet_object method called, already puppeting this"
import evennia.server.sessionhandler
account = create.create_account("TestAccount%s" % randint(0, 999999), email="test@test.com", password="testpassword", typeclass=DefaultAccount)
self.s1.uid = account.uid
evennia.server.sessionhandler.SESSIONS[self.s1.uid] = self.s1
self.s1.logged_in = True
self.s1.data_out = Mock(return_value=None)
obj = Mock()
self.s1.puppet = obj
account.puppet_object(self.s1, obj)
self.s1.data_out.assert_called_with(options=None, text="You are already puppeting this object.")
self.assertIsNone(obj.at_post_puppet.call_args)
def test_puppet_object_no_permission(self):
"Check puppet_object method called, no permission"
import evennia.server.sessionhandler
account = create.create_account("TestAccount%s" % randint(0, 999999), email="test@test.com", password="testpassword", typeclass=DefaultAccount)
self.s1.uid = account.uid
evennia.server.sessionhandler.SESSIONS[self.s1.uid] = self.s1
self.s1.puppet = None
self.s1.logged_in = True
self.s1.data_out = Mock(return_value=None)
obj = Mock()
obj.access = Mock(return_value=False)
account.puppet_object(self.s1, obj)
self.assertTrue(self.s1.data_out.call_args[1]['text'].startswith("You don't have permission to puppet"))
self.assertIsNone(obj.at_post_puppet.call_args)
def test_puppet_object_joining_other_session(self):
"Check puppet_object method called, joining other session"
import evennia.server.sessionhandler
account = create.create_account("TestAccount%s" % randint(0, 999999), email="test@test.com", password="testpassword", typeclass=DefaultAccount)
self.s1.uid = account.uid
evennia.server.sessionhandler.SESSIONS[self.s1.uid] = self.s1
self.s1.puppet = None
self.s1.logged_in = True
self.s1.data_out = Mock(return_value=None)
obj = Mock()
obj.access = Mock(return_value=True)
obj.account = account
account.puppet_object(self.s1, obj)
# works because django.conf.settings.MULTISESSION_MODE is not in (1, 3)
self.assertTrue(self.s1.data_out.call_args[1]['text'].endswith("from another of your sessions."))
self.assertTrue(obj.at_post_puppet.call_args[1] == {})
def test_puppet_object_already_puppeted(self):
"Check puppet_object method called, already puppeted"
import evennia.server.sessionhandler
account = create.create_account("TestAccount%s" % randint(0, 999999), email="test@test.com", password="testpassword", typeclass=DefaultAccount)
self.s1.uid = account.uid
evennia.server.sessionhandler.SESSIONS[self.s1.uid] = self.s1
self.s1.puppet = None
self.s1.logged_in = True
self.s1.data_out = Mock(return_value=None)
obj = Mock()
obj.access = Mock(return_value=True)
obj.account = Mock()
obj.at_post_puppet = Mock()
account.puppet_object(self.s1, obj)
self.assertTrue(self.s1.data_out.call_args[1]['text'].endswith("is already puppeted by another Account."))
self.assertIsNone(obj.at_post_puppet.call_args)

View file

@ -417,7 +417,7 @@ class CmdCBoot(COMMAND_DEFAULT_CLASS):
string = "You don't control this channel."
self.msg(string)
return
if account not in channel.db_subscriptions.all():
if not channel.subscriptions.has(account):
string = "Account %s is not connected to channel %s." % (account.key, channel.key)
self.msg(string)
return

View file

@ -58,7 +58,7 @@ class ChannelAdmin(admin.ModelAdmin):
save_on_top = True
list_select_related = True
fieldsets = (
(None, {'fields': (('db_key',), 'db_lock_storage', 'db_subscriptions')}),
(None, {'fields': (('db_key',), 'db_lock_storage', 'db_account_subscriptions', 'db_object_subscriptions')}),
)
def subscriptions(self, obj):
@ -69,7 +69,7 @@ class ChannelAdmin(admin.ModelAdmin):
obj (Channel): The channel to get subs from.
"""
return ", ".join([str(sub) for sub in obj.db_subscriptions.all()])
return ", ".join([str(sub) for sub in obj.subscriptions.all()])
def save_model(self, request, obj, form, change):
"""

View file

@ -31,10 +31,12 @@ class BodyFunctions(DefaultScript):
This gets called every self.interval seconds. We make
a random check here so as to only return 33% of the time.
"""
if random.random() < 0.66:
# no message this time
return
self.send_random_message()
def send_random_message(self):
rand = random.random()
# return a random message
if rand < 0.1:

View file

@ -0,0 +1,69 @@
from mock import Mock, patch
from evennia.utils.test_resources import EvenniaTest
from .bodyfunctions import BodyFunctions
@patch("evennia.contrib.tutorial_examples.bodyfunctions.random")
class TestBodyFunctions(EvenniaTest):
script_typeclass = BodyFunctions
def setUp(self):
super(TestBodyFunctions, self).setUp()
self.script.obj = self.char1
def tearDown(self):
super(TestBodyFunctions, self).tearDown()
# if we forget to stop the script, DirtyReactorAggregateError will be raised
self.script.stop()
def test_at_repeat(self, mock_random):
"""test that no message will be sent when below the 66% threshold"""
mock_random.random = Mock(return_value=0.5)
old_func = self.script.send_random_message
self.script.send_random_message = Mock()
self.script.at_repeat()
self.script.send_random_message.assert_not_called()
# test that random message will be sent
mock_random.random = Mock(return_value=0.7)
self.script.at_repeat()
self.script.send_random_message.assert_called()
self.script.send_random_message = old_func
def test_send_random_message(self, mock_random):
"""Test that correct message is sent for each random value"""
old_func = self.char1.msg
self.char1.msg = Mock()
# test each of the values
mock_random.random = Mock(return_value=0.05)
self.script.send_random_message()
self.char1.msg.assert_called_with("You tap your foot, looking around.")
mock_random.random = Mock(return_value=0.15)
self.script.send_random_message()
self.char1.msg.assert_called_with("You have an itch. Hard to reach too.")
mock_random.random = Mock(return_value=0.25)
self.script.send_random_message()
self.char1.msg.assert_called_with("You think you hear someone behind you. ... "
"but when you look there's noone there.")
mock_random.random = Mock(return_value=0.35)
self.script.send_random_message()
self.char1.msg.assert_called_with("You inspect your fingernails. Nothing to report.")
mock_random.random = Mock(return_value=0.45)
self.script.send_random_message()
self.char1.msg.assert_called_with("You cough discreetly into your hand.")
mock_random.random = Mock(return_value=0.55)
self.script.send_random_message()
self.char1.msg.assert_called_with("You scratch your head, looking around.")
mock_random.random = Mock(return_value=0.65)
self.script.send_random_message()
self.char1.msg.assert_called_with("You blink, forgetting what it was you were going to do.")
mock_random.random = Mock(return_value=0.75)
self.script.send_random_message()
self.char1.msg.assert_called_with("You feel lonely all of a sudden.")
mock_random.random = Mock(return_value=0.85)
self.script.send_random_message()
self.char1.msg.assert_called_with("You get a great idea. Of course you won't tell anyone.")
mock_random.random = Mock(return_value=0.95)
self.script.send_random_message()
self.char1.msg.assert_called_with("You suddenly realize how much you love Evennia!")
self.char1.msg = old_func

View file

@ -0,0 +1,93 @@
from django.test import TestCase
from mock import Mock
from .dummyrunner_settings import (c_creates_button, c_creates_obj, c_digs, c_examines, c_help, c_idles, c_login,
c_login_nodig, c_logout, c_looks, c_moves, c_moves_n, c_moves_s, c_socialize)
class TestDummyrunnerSettings(TestCase):
def setUp(self):
self.client = Mock()
self.client.cid = 1
self.client.counter = Mock(return_value=1)
self.client.gid = "20171025161153-1"
self.client.name = "Dummy-%s" % self.client.gid
self.client.password = "password-%s" % self.client.gid
self.client.start_room = "testing_room_start_%s" % self.client.gid
self.client.objs = []
self.client.exits = []
def clear_client_lists(self):
self.client.objs = []
self.client.exits = []
def test_c_login(self):
self.assertEqual(c_login(self.client), ('create %s %s' % (self.client.name, self.client.password),
'connect %s %s' % (self.client.name, self.client.password),
'@dig %s' % self.client.start_room,
'@teleport %s' % self.client.start_room,
"@dig testing_room_1 = exit_1, exit_1"))
def test_c_login_no_dig(self):
self.assertEqual(c_login_nodig(self.client), ('create %s %s' % (self.client.name, self.client.password),
'connect %s %s' % (self.client.name, self.client.password)))
def test_c_logout(self):
self.assertEqual(c_logout(self.client), "@quit")
def perception_method_tests(self, func, verb, alone_suffix=""):
self.assertEqual(func(self.client), "%s%s" % (verb, alone_suffix))
self.client.exits = ["exit1", "exit2"]
self.assertEqual(func(self.client), ["%s exit1" % verb, "%s exit2" % verb])
self.client.objs = ["foo", "bar"]
self.assertEqual(func(self.client), ["%s foo" % verb, "%s bar" % verb])
self.clear_client_lists()
def test_c_looks(self):
self.perception_method_tests(c_looks, "look")
def test_c_examines(self):
self.perception_method_tests(c_examines, "examine", " me")
def test_idles(self):
self.assertEqual(c_idles(self.client), ('idle', 'idle'))
def test_c_help(self):
self.assertEqual(c_help(self.client), ('help', 'help @teleport', 'help look', 'help @tunnel', 'help @dig'))
def test_c_digs(self):
self.assertEqual(c_digs(self.client), ('@dig/tel testing_room_1 = exit_1, exit_1'))
self.assertEqual(self.client.exits, ['exit_1', 'exit_1'])
self.clear_client_lists()
def test_c_creates_obj(self):
objname = "testing_obj_1"
self.assertEqual(c_creates_obj(self.client), ('@create %s' % objname,
'@desc %s = "this is a test object' % objname,
'@set %s/testattr = this is a test attribute value.' % objname,
'@set %s/testattr2 = this is a second test attribute.' % objname))
self.assertEqual(self.client.objs, [objname])
self.clear_client_lists()
def test_c_creates_button(self):
objname = "testing_button_1"
typeclass_name = "contrib.tutorial_examples.red_button.RedButton"
self.assertEqual(c_creates_button(self.client), ('@create %s:%s' % (objname, typeclass_name),
'@desc %s = test red button!' % objname))
self.assertEqual(self.client.objs, [objname])
self.clear_client_lists()
def test_c_socialize(self):
self.assertEqual(c_socialize(self.client), ('ooc Hello!', 'ooc Testing ...', 'ooc Testing ... times 2',
'say Yo!', 'emote stands looking around.'))
def test_c_moves(self):
self.assertEqual(c_moves(self.client), "look")
self.client.exits = ["south", "north"]
self.assertEqual(c_moves(self.client), ["south", "north"])
self.clear_client_lists()
def test_c_move_n(self):
self.assertEqual(c_moves_n(self.client), "north")
def test_c_move_s(self):
self.assertEqual(c_moves_s(self.client), "south")

View file

@ -15,11 +15,6 @@ Guidelines:
used as test methods by the runner. Inside the test methods, special member
methods assert*() are used to test the behaviour.
"""
import os
import sys
import glob
try:
from django.utils.unittest import TestCase
except ImportError:
@ -31,6 +26,8 @@ except ImportError:
from django.test.runner import DiscoverRunner
from .deprecations import check_errors
class EvenniaTestSuiteRunner(DiscoverRunner):
"""
@ -46,3 +43,37 @@ class EvenniaTestSuiteRunner(DiscoverRunner):
import evennia
evennia._init()
return super(EvenniaTestSuiteRunner, self).build_suite(test_labels, extra_tests=extra_tests, **kwargs)
class MockSettings(object):
"""
Class for simulating django.conf.settings. Created with a single value, and then sets the required
WEBSERVER_ENABLED setting to True or False depending if we're testing WEBSERVER_PORTS.
"""
def __init__(self, setting, value=None):
setattr(self, setting, value)
if setting == "WEBSERVER_PORTS":
self.WEBSERVER_ENABLED = True
else:
self.WEBSERVER_ENABLED = False
class TestDeprecations(TestCase):
"""
Class for testing deprecations.check_errors.
"""
deprecated_settings = ("CMDSET_DEFAULT", "CMDSET_OOC", "BASE_COMM_TYPECLASS", "COMM_TYPECLASS_PATHS",
"CHARACTER_DEFAULT_HOME", "OBJECT_TYPECLASS_PATHS", "SCRIPT_TYPECLASS_PATHS",
"ACCOUNT_TYPECLASS_PATHS", "CHANNEL_TYPECLASS_PATHS", "SEARCH_MULTIMATCH_SEPARATOR",
"TIME_SEC_PER_MIN", "TIME_MIN_PER_HOUR", "TIME_HOUR_PER_DAY", "TIME_DAY_PER_WEEK",
"TIME_WEEK_PER_MONTH", "TIME_MONTH_PER_YEAR")
def test_check_errors(self):
"""
All settings in deprecated_settings should raise a DeprecationWarning if they exist. WEBSERVER_PORTS
raises an error if the iterable value passed does not have a tuple as its first element.
"""
for setting in self.deprecated_settings:
self.assertRaises(DeprecationWarning, check_errors, MockSettings(setting))
# test check for WEBSERVER_PORTS having correct value
self.assertRaises(DeprecationWarning, check_errors, MockSettings("WEBSERVER_PORTS", value=["not a tuple"]))

View file

@ -192,12 +192,12 @@ def _batch_create_object(*objparams):
# call all setup hooks on each object
objparam = objparams[iobj]
# setup
obj._createdict = {"permissions": objparam[1],
obj._createdict = {"permissions": make_iter(objparam[1]),
"locks": objparam[2],
"aliases": objparam[3],
"aliases": make_iter(objparam[3]),
"nattributes": objparam[4],
"attributes": objparam[5],
"tags": objparam[6]}
"tags": make_iter(objparam[6])}
# this triggers all hooks
obj.save()
# run eventual extra code

View file

@ -10,17 +10,25 @@ from django.conf import settings
from evennia.utils.utils import get_evennia_version
# Determine the site name and server version
def set_game_name_and_slogan():
"""
Sets global variables GAME_NAME and GAME_SLOGAN which are used by
general_context.
try:
GAME_NAME = settings.SERVERNAME.strip()
except AttributeError:
GAME_NAME = "Evennia"
SERVER_VERSION = get_evennia_version()
try:
GAME_SLOGAN = settings.GAME_SLOGAN.strip()
except AttributeError:
GAME_SLOGAN = SERVER_VERSION
Notes:
This function is used for unit testing the values of the globals.
"""
global GAME_NAME, GAME_SLOGAN, SERVER_VERSION
try:
GAME_NAME = settings.SERVERNAME.strip()
except AttributeError:
GAME_NAME = "Evennia"
SERVER_VERSION = get_evennia_version()
try:
GAME_SLOGAN = settings.GAME_SLOGAN.strip()
except AttributeError:
GAME_SLOGAN = SERVER_VERSION
set_game_name_and_slogan()
# Setup lists of the most relevant apps so
# the adminsite becomes more readable.
@ -32,13 +40,23 @@ CONNECTIONS = ['Irc']
WEBSITE = ['Flatpages', 'News', 'Sites']
def set_webclient_settings():
"""
As with set_game_name_and_slogan above, this sets global variables pertaining
to webclient settings.
Notes:
Used for unit testing.
"""
global WEBCLIENT_ENABLED, WEBSOCKET_CLIENT_ENABLED, WEBSOCKET_PORT, WEBSOCKET_URL
WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED
WEBSOCKET_CLIENT_ENABLED = settings.WEBSOCKET_CLIENT_ENABLED
WEBSOCKET_PORT = settings.WEBSOCKET_CLIENT_PORT
WEBSOCKET_URL = settings.WEBSOCKET_CLIENT_URL
set_webclient_settings()
# The main context processor function
WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED
WEBSOCKET_CLIENT_ENABLED = settings.WEBSOCKET_CLIENT_ENABLED
WEBSOCKET_PORT = settings.WEBSOCKET_CLIENT_PORT
WEBSOCKET_URL = settings.WEBSOCKET_CLIENT_URL
def general_context(request):
"""
Returns common Evennia-related context stuff, which

View file

@ -0,0 +1,59 @@
from mock import Mock, patch
from django.test import TestCase
from . import general_context
class TestGeneralContext(TestCase):
maxDiff = None
@patch('evennia.web.utils.general_context.GAME_NAME', "test_name")
@patch('evennia.web.utils.general_context.GAME_SLOGAN', "test_game_slogan")
@patch('evennia.web.utils.general_context.WEBSOCKET_CLIENT_ENABLED', "websocket_client_enabled_testvalue")
@patch('evennia.web.utils.general_context.WEBCLIENT_ENABLED', "webclient_enabled_testvalue")
@patch('evennia.web.utils.general_context.WEBSOCKET_PORT', "websocket_client_port_testvalue")
@patch('evennia.web.utils.general_context.WEBSOCKET_URL', "websocket_client_url_testvalue")
def test_general_context(self):
request = Mock()
self.assertEqual(general_context.general_context(request), {
'game_name': "test_name",
'game_slogan': "test_game_slogan",
'evennia_userapps': ['Accounts'],
'evennia_entityapps': ['Objects', 'Scripts', 'Comms', 'Help'],
'evennia_setupapps': ['Permissions', 'Config'],
'evennia_connectapps': ['Irc'],
'evennia_websiteapps': ['Flatpages', 'News', 'Sites'],
"webclient_enabled": "webclient_enabled_testvalue",
"websocket_enabled": "websocket_client_enabled_testvalue",
"websocket_port": "websocket_client_port_testvalue",
"websocket_url": "websocket_client_url_testvalue"
})
# spec being an empty list will initially raise AttributeError in set_game_name_and_slogan to test defaults
@patch('evennia.web.utils.general_context.settings', spec=[])
@patch('evennia.web.utils.general_context.get_evennia_version')
def test_set_game_name_and_slogan(self, mock_get_version, mock_settings):
mock_get_version.return_value = "version 1"
# test default/fallback values
general_context.set_game_name_and_slogan()
self.assertEqual(general_context.GAME_NAME, "Evennia")
self.assertEqual(general_context.GAME_SLOGAN, "version 1")
# test values when the settings are defined
mock_settings.SERVERNAME = "test_name"
mock_settings.GAME_SLOGAN = "test_game_slogan"
general_context.set_game_name_and_slogan()
self.assertEqual(general_context.GAME_NAME, "test_name")
self.assertEqual(general_context.GAME_SLOGAN, "test_game_slogan")
@patch('evennia.web.utils.general_context.settings')
def test_set_webclient_settings(self, mock_settings):
mock_settings.WEBCLIENT_ENABLED = "webclient"
mock_settings.WEBSOCKET_CLIENT_URL = "websocket_url"
mock_settings.WEBSOCKET_CLIENT_ENABLED = "websocket_client"
mock_settings.WEBSOCKET_CLIENT_PORT = "websocket_port"
general_context.set_webclient_settings()
self.assertEqual(general_context.WEBCLIENT_ENABLED, "webclient")
self.assertEqual(general_context.WEBSOCKET_URL, "websocket_url")
self.assertEqual(general_context.WEBSOCKET_CLIENT_ENABLED, "websocket_client")
self.assertEqual(general_context.WEBSOCKET_PORT, "websocket_port")