script/lib/tweetstream/tests/test_tweetstream.py
changeset 14 10e7a0c7c64f
parent 13 79b6e132e3d7
child 527 80e5b9543cac
equal deleted inserted replaced
13:79b6e132e3d7 14:10e7a0c7c64f
     1 import contextlib
     1 import contextlib
     2 import threading
     2 import threading
     3 import time
     3 import time
     4 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
       
     5 
     4 
     6 from tweetstream import TweetStream, FollowStream, TrackStream, LocationStream
     5 from tweetstream import TweetStream, FollowStream, TrackStream, LocationStream
     7 from tweetstream import ConnectionError, AuthenticationError, SampleStream
     6 from tweetstream import ConnectionError, AuthenticationError, SampleStream, FilterStream
     8 
     7 
     9 import pytest
     8 import pytest
    10 from pytest import raises
     9 from pytest import raises
    11 slow = pytest.mark.slow
    10 slow = pytest.mark.slow
    12 
    11 
    13 from servercontext import test_server
    12 from servercontext import test_server
    14 
    13 
    15 single_tweet = r"""{"in_reply_to_status_id":null,"in_reply_to_user_id":null,"favorited":false,"created_at":"Tue Jun 16 10:40:14 +0000 2009","in_reply_to_screen_name":null,"text":"record industry just keeps on amazing me: http:\/\/is.gd\/13lFo - $150k per song you've SHARED, not that somebody has actually DOWNLOADED.","user":{"notifications":null,"profile_background_tile":false,"followers_count":206,"time_zone":"Copenhagen","utc_offset":3600,"friends_count":191,"profile_background_color":"ffffff","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/250715794\/profile_normal.png","description":"Digital product developer, currently at Opera Software. My tweets are my opinions, not those of my employer.","verified_profile":false,"protected":false,"favourites_count":0,"profile_text_color":"3C3940","screen_name":"eiriksnilsen","name":"Eirik Stridsklev N.","following":null,"created_at":"Tue May 06 12:24:12 +0000 2008","profile_background_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_background_images\/10531192\/160x600opera15.gif","profile_link_color":"0099B9","profile_sidebar_fill_color":"95E8EC","url":"http:\/\/www.stridsklev-nilsen.no\/eirik","id":14672543,"statuses_count":506,"profile_sidebar_border_color":"5ED4DC","location":"Oslo, Norway"},"id":2190767504,"truncated":false,"source":"<a href=\"http:\/\/widgets.opera.com\/widget\/7206\">Twitter Opera widget<\/a>"}"""
    14 single_tweet = r"""{"in_reply_to_status_id":null,"in_reply_to_user_id":null,"favorited":false,"created_at":"Tue Jun 16 10:40:14 +0000 2009","in_reply_to_screen_name":null,"text":"record industry just keeps on amazing me: http:\/\/is.gd\/13lFo - $150k per song you've SHARED, not that somebody has actually DOWNLOADED.","user":{"notifications":null,"profile_background_tile":false,"followers_count":206,"time_zone":"Copenhagen","utc_offset":3600,"friends_count":191,"profile_background_color":"ffffff","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/250715794\/profile_normal.png","description":"Digital product developer, currently at Opera Software. My tweets are my opinions, not those of my employer.","verified_profile":false,"protected":false,"favourites_count":0,"profile_text_color":"3C3940","screen_name":"eiriksnilsen","name":"Eirik Stridsklev N.","following":null,"created_at":"Tue May 06 12:24:12 +0000 2008","profile_background_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_background_images\/10531192\/160x600opera15.gif","profile_link_color":"0099B9","profile_sidebar_fill_color":"95E8EC","url":"http:\/\/www.stridsklev-nilsen.no\/eirik","id":14672543,"statuses_count":506,"profile_sidebar_border_color":"5ED4DC","location":"Oslo, Norway"},"id":2190767504,"truncated":false,"source":"<a href=\"http:\/\/widgets.opera.com\/widget\/7206\">Twitter Opera widget<\/a>"}""" + "\r"
    16 
    15 
    17 
    16 
    18 def parameterized(funcarglist):
    17 def parameterized(funcarglist):
    19     def wrapper(function):
    18     def wrapper(function):
    20         function.funcarglist = funcarglist
    19         function.funcarglist = funcarglist
    27 
    26 
    28 
    27 
    29 streamtypes = [
    28 streamtypes = [
    30     dict(cls=TweetStream, args=[], kwargs=dict()),
    29     dict(cls=TweetStream, args=[], kwargs=dict()),
    31     dict(cls=SampleStream, args=[], kwargs=dict()),
    30     dict(cls=SampleStream, args=[], kwargs=dict()),
       
    31     dict(cls=FilterStream, args=[], kwargs=dict(track=("test",))),
    32     dict(cls=FollowStream, args=[[1, 2, 3]], kwargs=dict()),
    32     dict(cls=FollowStream, args=[[1, 2, 3]], kwargs=dict()),
    33     dict(cls=TrackStream, args=["opera"], kwargs=dict()),
    33     dict(cls=TrackStream, args=["opera"], kwargs=dict()),
    34     dict(cls=LocationStream, args=["123,4321"], kwargs=dict())
    34     dict(cls=LocationStream, args=["123,4321"], kwargs=dict())
    35 ]
    35 ]
    36 
    36 
    40     """Test that the proper exception is raised when the user could not be
    40     """Test that the proper exception is raised when the user could not be
    41     authenticated"""
    41     authenticated"""
    42     def auth_denied(request):
    42     def auth_denied(request):
    43         request.send_error(401)
    43         request.send_error(401)
    44 
    44 
    45     with test_server(handler=auth_denied, methods=("post", "get"), port="random") as server:
    45     with raises(AuthenticationError):
    46         stream = cls("user", "passwd", *args, url=server.baseurl)
    46         with test_server(handler=auth_denied, methods=("post", "get"), port="random") as server:
       
    47             stream = cls("user", "passwd", *args, url=server.baseurl)
       
    48             for e in stream: pass
    47 
    49 
    48 
    50 
    49 @parameterized(streamtypes)
    51 @parameterized(streamtypes)
    50 def test_404_url(cls, args, kwargs):
    52 def test_404_url(cls, args, kwargs):
    51     """Test that the proper exception is raised when the stream URL can't be
    53     """Test that the proper exception is raised when the stream URL can't be
    52     found"""
    54     found"""
    53     def not_found(request):
    55     def not_found(request):
    54         request.send_error(404)
    56         request.send_error(404)
    55 
    57 
    56     with test_server(handler=not_found, methods=("post", "get"), port="random") as server:
    58     with raises(ConnectionError):
    57         stream = cls("user", "passwd", *args, url=server.baseurl)
    59         with test_server(handler=not_found, methods=("post", "get"), port="random") as server:
       
    60             stream = cls("user", "passwd", *args, url=server.baseurl)
       
    61             for e in stream: pass
    58 
    62 
    59 
    63 
    60 @parameterized(streamtypes)
    64 @parameterized(streamtypes)
    61 def test_bad_content(cls, args, kwargs):
    65 def test_bad_content(cls, args, kwargs):
    62     """Test error handling if we are given invalid data"""
    66     """Test error handling if we are given invalid data"""
    63     def bad_content(request):
    67     def bad_content(request):
    64         for n in xrange(10):
    68         for n in xrange(10):
    65             # what json we pass doesn't matter. It's not verifying the
    69             # what json we pass doesn't matter. It's not verifying the
    66             # strcuture, only checking that it's parsable
    70             # strcuture, only checking that it's parsable
    67             yield "[1,2,3]"
    71             yield "[1,2,3]\r"
    68         yield "[1,2, I need no stinking close brace"
    72         yield "[1,2, I need no stinking close brace\r"
    69         yield "[1,2,3]"
    73         yield "[1,2,3]\r"
    70 
    74 
    71 
    75 
    72     with raises(ConnectionError):
    76     with raises(ConnectionError):
    73         with test_server(handler=bad_content, methods=("post", "get"), port="random") as server:
    77         with test_server(handler=bad_content, methods=("post", "get"), port="random") as server:
    74             stream = cls("user", "passwd", *args, url=server.baseurl)
    78             stream = cls("user", "passwd", *args, url=server.baseurl)
    82     cnt = 1000
    86     cnt = 1000
    83     def bad_content(request):
    87     def bad_content(request):
    84         for n in xrange(cnt):
    88         for n in xrange(cnt):
    85             # what json we pass doesn't matter. It's not verifying the
    89             # what json we pass doesn't matter. It's not verifying the
    86             # strcuture, only checking that it's parsable
    90             # strcuture, only checking that it's parsable
    87             yield "[1,2,3]"
    91             yield "[1,2,3]\r"
    88 
    92 
    89     with raises(ConnectionError):
    93     with raises(ConnectionError):
    90         with test_server(handler=bad_content, methods=("post", "get"), port="random") as server:
    94         with test_server(handler=bad_content, methods=("post", "get"), port="random") as server:
    91             stream = cls("foo", "bar", *args, url=server.baseurl)
    95             stream = cls("foo", "bar", *args, url=server.baseurl)
    92             for tweet in stream:
    96             for tweet in stream: