tests.py
338 lines
| 12.1 KiB
| text/x-python
|
PythonLexer
/ boards / tests.py
neko259
|
r71 | # coding=utf-8 | ||
neko259
|
r545 | import time | ||
import logging | ||||
neko259
|
r801 | import simplejson | ||
neko259
|
r596 | from django.core.paginator import Paginator | ||
neko259
|
r545 | |||
neko259
|
r345 | from django.test import TestCase | ||
Ilyas
|
r13 | from django.test.client import Client | ||
neko259
|
r545 | from django.core.urlresolvers import reverse, NoReverseMatch | ||
neko259
|
r730 | from boards.abstracts.settingsmanager import get_settings_manager | ||
Ilyas
|
r13 | |||
neko259
|
r793 | from boards.models import Post, Tag, Thread, KeyPair | ||
neko259
|
r545 | from boards import urls | ||
neko259
|
r716 | from boards import settings | ||
neko259
|
r801 | from boards.views.api import api_get_threaddiff | ||
from boards.utils import datetime_to_epoch | ||||
neko259
|
r716 | import neboard | ||
neko259
|
r0 | |||
neko259
|
r740 | TEST_TAG = 'test_tag' | ||
neko259
|
r203 | PAGE_404 = 'boards/404.html' | ||
neko259
|
r71 | TEST_TEXT = 'test text' | ||
NEW_THREAD_PAGE = '/' | ||||
neko259
|
r79 | THREAD_PAGE_ONE = '/thread/1/' | ||
THREAD_PAGE = '/thread/' | ||||
TAG_PAGE = '/tag/' | ||||
neko259
|
r71 | HTTP_CODE_REDIRECT = 302 | ||
neko259
|
r79 | HTTP_CODE_OK = 200 | ||
HTTP_CODE_NOT_FOUND = 404 | ||||
neko259
|
r71 | |||
neko259
|
r545 | logger = logging.getLogger(__name__) | ||
neko259
|
r8 | |||
neko259
|
r381 | class PostTests(TestCase): | ||
neko259
|
r203 | |||
neko259
|
r16 | def _create_post(self): | ||
neko259
|
r740 | tag = Tag.objects.create(name=TEST_TAG) | ||
return Post.objects.create_post(title='title', text='text', | ||||
tags=[tag]) | ||||
neko259
|
r0 | |||
def test_post_add(self): | ||||
neko259
|
r381 | """Test adding post""" | ||
neko259
|
r16 | post = self._create_post() | ||
neko259
|
r22 | |||
neko259
|
r740 | self.assertIsNotNone(post, 'No post was created.') | ||
self.assertEqual(TEST_TAG, post.get_thread().tags.all()[0].name, | ||||
'No tags were added to the post.') | ||||
neko259
|
r0 | |||
def test_delete_post(self): | ||||
neko259
|
r381 | """Test post deletion""" | ||
neko259
|
r16 | post = self._create_post() | ||
neko259
|
r8 | post_id = post.id | ||
neko259
|
r22 | |||
neko259
|
r1 | Post.objects.delete_post(post) | ||
neko259
|
r0 | |||
neko259
|
r396 | self.assertFalse(Post.objects.filter(id=post_id).exists()) | ||
neko259
|
r0 | |||
neko259
|
r381 | def test_delete_thread(self): | ||
"""Test thread deletion""" | ||||
neko259
|
r398 | opening_post = self._create_post() | ||
neko259
|
r628 | thread = opening_post.get_thread() | ||
neko259
|
r381 | reply = Post.objects.create_post("", "", thread=thread) | ||
neko259
|
r718 | thread.delete() | ||
neko259
|
r381 | |||
neko259
|
r396 | self.assertFalse(Post.objects.filter(id=reply.id).exists()) | ||
neko259
|
r381 | |||
neko259
|
r380 | def test_post_to_thread(self): | ||
neko259
|
r381 | """Test adding post to a thread""" | ||
neko259
|
r380 | op = self._create_post() | ||
neko259
|
r628 | post = Post.objects.create_post("", "", thread=op.get_thread()) | ||
neko259
|
r380 | |||
self.assertIsNotNone(post, 'Reply to thread wasn\'t created') | ||||
neko259
|
r628 | self.assertEqual(op.get_thread().last_edit_time, post.pub_time, | ||
neko259
|
r380 | 'Post\'s create time doesn\'t match thread last edit' | ||
' time') | ||||
neko259
|
r0 | def test_delete_posts_by_ip(self): | ||
neko259
|
r381 | """Test deleting posts with the given ip""" | ||
neko259
|
r16 | post = self._create_post() | ||
neko259
|
r8 | post_id = post.id | ||
neko259
|
r0 | |||
neko259
|
r1 | Post.objects.delete_posts_by_ip('0.0.0.0') | ||
neko259
|
r0 | |||
neko259
|
r396 | self.assertFalse(Post.objects.filter(id=post_id).exists()) | ||
Ilyas
|
r13 | |||
neko259
|
r17 | def test_get_thread(self): | ||
neko259
|
r381 | """Test getting all posts of a thread""" | ||
neko259
|
r17 | opening_post = self._create_post() | ||
for i in range(0, 2): | ||||
neko259
|
r398 | Post.objects.create_post('title', 'text', | ||
neko259
|
r628 | thread=opening_post.get_thread()) | ||
neko259
|
r17 | |||
neko259
|
r628 | thread = opening_post.get_thread() | ||
neko259
|
r17 | |||
neko259
|
r398 | self.assertEqual(3, thread.replies.count()) | ||
neko259
|
r24 | |||
def test_create_post_with_tag(self): | ||||
neko259
|
r381 | """Test adding tag to post""" | ||
neko259
|
r24 | tag = Tag.objects.create(name='test_tag') | ||
post = Post.objects.create_post(title='title', text='text', tags=[tag]) | ||||
neko259
|
r398 | |||
neko259
|
r628 | thread = post.get_thread() | ||
neko259
|
r398 | self.assertIsNotNone(post, 'Post not created') | ||
self.assertTrue(tag in thread.tags.all(), 'Tag not added to thread') | ||||
self.assertTrue(thread in tag.threads.all(), 'Thread not added to tag') | ||||
neko259
|
r28 | |||
def test_thread_max_count(self): | ||||
neko259
|
r381 | """Test deletion of old posts when the max thread count is reached""" | ||
neko259
|
r28 | for i in range(settings.MAX_THREAD_COUNT + 1): | ||
self._create_post() | ||||
self.assertEqual(settings.MAX_THREAD_COUNT, | ||||
neko259
|
r596 | len(Thread.objects.filter(archived=False))) | ||
neko259
|
r46 | |||
def test_pages(self): | ||||
"""Test that the thread list is properly split into pages""" | ||||
for i in range(settings.MAX_THREAD_COUNT): | ||||
self._create_post() | ||||
neko259
|
r596 | all_threads = Thread.objects.filter(archived=False) | ||
neko259
|
r46 | |||
neko259
|
r596 | paginator = Paginator(Thread.objects.filter(archived=False), | ||
settings.THREADS_PER_PAGE) | ||||
posts_in_second_page = paginator.page(2).object_list | ||||
neko259
|
r46 | first_post = posts_in_second_page[0] | ||
self.assertEqual(all_threads[settings.THREADS_PER_PAGE].id, | ||||
neko259
|
r71 | first_post.id) | ||
neko259
|
r381 | |||
class PagesTest(TestCase): | ||||
def test_404(self): | ||||
"""Test receiving error 404 when opening a non-existent page""" | ||||
tag_name = u'test_tag' | ||||
tag = Tag.objects.create(name=tag_name) | ||||
client = Client() | ||||
Post.objects.create_post('title', TEST_TEXT, tags=[tag]) | ||||
existing_post_id = Post.objects.all()[0].id | ||||
response_existing = client.get(THREAD_PAGE + str(existing_post_id) + | ||||
'/') | ||||
self.assertEqual(HTTP_CODE_OK, response_existing.status_code, | ||||
u'Cannot open existing thread') | ||||
response_not_existing = client.get(THREAD_PAGE + str( | ||||
existing_post_id + 1) + '/') | ||||
neko259
|
r689 | self.assertEqual(PAGE_404, response_not_existing.templates[0].name, | ||
neko259
|
r381 | u'Not existing thread is opened') | ||
response_existing = client.get(TAG_PAGE + tag_name + '/') | ||||
self.assertEqual(HTTP_CODE_OK, | ||||
response_existing.status_code, | ||||
u'Cannot open existing tag') | ||||
response_not_existing = client.get(TAG_PAGE + u'not_tag' + '/') | ||||
self.assertEqual(PAGE_404, | ||||
response_not_existing.templates[0].name, | ||||
u'Not existing tag is opened') | ||||
reply_id = Post.objects.create_post('', TEST_TEXT, | ||||
neko259
|
r398 | thread=Post.objects.all()[0] | ||
neko259
|
r689 | .get_thread()) | ||
neko259
|
r381 | response_not_existing = client.get(THREAD_PAGE + str( | ||
reply_id) + '/') | ||||
self.assertEqual(PAGE_404, | ||||
response_not_existing.templates[0].name, | ||||
u'Reply is opened as a thread') | ||||
class FormTest(TestCase): | ||||
neko259
|
r71 | def test_post_validation(self): | ||
client = Client() | ||||
valid_tags = u'tag1 tag_2 тег_3' | ||||
invalid_tags = u'$%_356 ---' | ||||
response = client.post(NEW_THREAD_PAGE, {'title': 'test title', | ||||
'text': TEST_TEXT, | ||||
'tags': valid_tags}) | ||||
self.assertEqual(response.status_code, HTTP_CODE_REDIRECT, | ||||
msg='Posting new message failed: got code ' + | ||||
str(response.status_code)) | ||||
self.assertEqual(1, Post.objects.count(), | ||||
msg='No posts were created') | ||||
neko259
|
r76 | client.post(NEW_THREAD_PAGE, {'text': TEST_TEXT, | ||
'tags': invalid_tags}) | ||||
neko259
|
r71 | self.assertEqual(1, Post.objects.count(), msg='The validation passed ' | ||
neko259
|
r77 | 'where it should fail') | ||
neko259
|
r181 | # Change posting delay so we don't have to wait for 30 seconds or more | ||
neko259
|
r716 | old_posting_delay = neboard.settings.POSTING_DELAY | ||
neko259
|
r806 | # Wait for the posting delay or we won't be able to post | ||
neboard.settings.POSTING_DELAY = 1 | ||||
neko259
|
r716 | time.sleep(neboard.settings.POSTING_DELAY + 1) | ||
neko259
|
r79 | response = client.post(THREAD_PAGE_ONE, {'text': TEST_TEXT, | ||
neko259
|
r89 | 'tags': valid_tags}) | ||
neko259
|
r79 | self.assertEqual(HTTP_CODE_REDIRECT, response.status_code, | ||
msg=u'Posting new message failed: got code ' + | ||||
neko259
|
r77 | str(response.status_code)) | ||
neko259
|
r181 | # Restore posting delay | ||
neko259
|
r806 | neboard.settings.POSTING_DELAY = old_posting_delay | ||
neko259
|
r77 | |||
self.assertEqual(2, Post.objects.count(), | ||||
neko259
|
r79 | msg=u'No posts were created') | ||
neko259
|
r415 | |||
class ViewTest(TestCase): | ||||
neko259
|
r545 | |||
def test_all_views(self): | ||||
neko259
|
r730 | """ | ||
neko259
|
r545 | Try opening all views defined in ulrs.py that don't need additional | ||
parameters | ||||
neko259
|
r730 | """ | ||
neko259
|
r545 | |||
neko259
|
r415 | client = Client() | ||
neko259
|
r545 | for url in urls.urlpatterns: | ||
try: | ||||
view_name = url.name | ||||
logger.debug('Testing view %s' % view_name) | ||||
neko259
|
r415 | |||
neko259
|
r545 | try: | ||
response = client.get(reverse(view_name)) | ||||
self.assertEqual(HTTP_CODE_OK, response.status_code, | ||||
neko259
|
r730 | '%s view not opened' % view_name) | ||
neko259
|
r545 | except NoReverseMatch: | ||
# This view just needs additional arguments | ||||
pass | ||||
neko259
|
r765 | except Exception as e: | ||
neko259
|
r545 | self.fail('Got exception %s at %s view' % (e, view_name)) | ||
except AttributeError: | ||||
# This is normal, some views do not have names | ||||
pass | ||||
neko259
|
r730 | |||
class AbstractTest(TestCase): | ||||
def test_settings_manager(self): | ||||
request = MockRequest() | ||||
settings_manager = get_settings_manager(request) | ||||
settings_manager.set_setting('test_setting', 'test_value') | ||||
self.assertEqual('test_value', settings_manager.get_setting( | ||||
'test_setting'), u'Setting update failed.') | ||||
class MockRequest: | ||||
def __init__(self): | ||||
neko259
|
r740 | self.session = dict() | ||
neko259
|
r801 | self.GET = dict() | ||
self.POST = dict() | ||||
neko259
|
r793 | class KeyTest(TestCase): | ||
def test_create_key(self): | ||||
key = KeyPair.objects.generate_key('ecdsa') | ||||
self.assertIsNotNone(key, 'The key was not created.') | ||||
def test_validation(self): | ||||
key = KeyPair.objects.generate_key(key_type='ecdsa') | ||||
message = 'msg' | ||||
signature = key.sign(message) | ||||
valid = KeyPair.objects.verify(key.public_key, message, signature, | ||||
neko259
|
r806 | key_type='ecdsa') | ||
neko259
|
r793 | |||
self.assertTrue(valid, 'Message verification failed.') | ||||
neko259
|
r796 | |||
def test_primary_constraint(self): | ||||
KeyPair.objects.generate_key(key_type='ecdsa', primary=True) | ||||
try: | ||||
KeyPair.objects.generate_key(key_type='ecdsa', primary=True) | ||||
neko259
|
r806 | self.fail('Exception should be thrown indicating there can be only' | ||
' one primary key.') | ||||
neko259
|
r796 | except Exception: | ||
pass | ||||
neko259
|
r805 | |||
neko259
|
r801 | class ApiTest(TestCase): | ||
def test_thread_diff(self): | ||||
tag = Tag.objects.create(name=TEST_TAG) | ||||
opening_post = Post.objects.create_post(title='title', text='text', | ||||
neko259
|
r805 | tags=[tag]) | ||
neko259
|
r801 | |||
last_edit_time = datetime_to_epoch(opening_post.last_edit_time) | ||||
# Check the exact timestamp post was added | ||||
empty_response = api_get_threaddiff(MockRequest(), | ||||
neko259
|
r805 | str(opening_post.thread_new.id), | ||
str(last_edit_time)) | ||||
neko259
|
r801 | diff = simplejson.loads(empty_response.content) | ||
self.assertEqual(0, len(diff['added']), | ||||
neko259
|
r805 | 'There must be no added posts in the diff.') | ||
neko259
|
r801 | self.assertEqual(0, len(diff['updated']), | ||
neko259
|
r805 | 'There must be no updated posts in the diff.') | ||
neko259
|
r801 | |||
reply = Post.objects.create_post(title='', | ||||
neko259
|
r805 | text='[post]%d[/post]\ntext' % opening_post.id, | ||
thread=opening_post.thread_new) | ||||
neko259
|
r801 | |||
# Check the timestamp before post was added | ||||
response = api_get_threaddiff(MockRequest(), | ||||
neko259
|
r805 | str(opening_post.thread_new.id), | ||
str(last_edit_time)) | ||||
neko259
|
r801 | diff = simplejson.loads(response.content) | ||
self.assertEqual(1, len(diff['added']), | ||||
neko259
|
r805 | 'There must be 1 added posts in the diff.') | ||
neko259
|
r801 | self.assertEqual(1, len(diff['updated']), | ||
neko259
|
r805 | 'There must be 1 updated posts in the diff.') | ||
neko259
|
r801 | |||
empty_response = api_get_threaddiff(MockRequest(), | ||||
neko259
|
r805 | str(opening_post.thread_new.id), | ||
neko259
|
r806 | str(datetime_to_epoch( | ||
reply.last_edit_time))) | ||||
neko259
|
r801 | diff = simplejson.loads(empty_response.content) | ||
self.assertEqual(0, len(diff['added']), | ||||
neko259
|
r805 | 'There must be no added posts in the diff.') | ||
neko259
|
r801 | self.assertEqual(0, len(diff['updated']), | ||
neko259
|
r805 | 'There must be no updated posts in the diff.') | ||
neko259
|
r801 | |||