em-twitter 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +7 -4
- data/README.md +6 -4
- data/em-twitter.gemspec +1 -1
- data/lib/em-twitter.rb +3 -2
- data/lib/em-twitter/client.rb +16 -1
- data/lib/em-twitter/connection.rb +15 -1
- data/lib/em-twitter/reconnectors/application_failure.rb +3 -3
- data/lib/em-twitter/reconnectors/network_failure.rb +5 -6
- data/lib/em-twitter/request.rb +17 -3
- data/lib/em-twitter/response.rb +14 -2
- data/lib/em-twitter/version.rb +1 -1
- data/spec/em-twitter/client_spec.rb +23 -14
- data/spec/em-twitter/connection_reconnect_spec.rb +4 -4
- data/spec/em-twitter/connection_spec.rb +47 -9
- data/spec/em-twitter/reconnectors/application_failure_spec.rb +1 -1
- data/spec/em-twitter/reconnectors/network_failure_spec.rb +3 -3
- data/spec/em-twitter/request_spec.rb +10 -4
- data/spec/em-twitter/response_spec.rb +26 -0
- data/spec/spec_helper.rb +18 -6
- metadata +23 -24
- data/.simplecov +0 -1
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
# EM-Twitter
|
1
|
+
# EM-Twitter [][travis] [][gemnasium]
|
2
|
+
EM-Twitter is an EventMachine-based ruby client for the [Twitter Streaming API](https://dev.twitter.com/docs/streaming-api).
|
2
3
|
|
3
|
-
|
4
|
+
[travis]: http://travis-ci.org/spagalloco/em-twitter
|
5
|
+
[gemnasium]: https://gemnasium.com/spagalloco/em-twitter
|
4
6
|
|
5
7
|
## Usage
|
6
8
|
|
@@ -104,7 +106,7 @@ end
|
|
104
106
|
|
105
107
|
## Inspiration
|
106
108
|
|
107
|
-
EM-Twitter is heavily inspired by Vladimir Kolesnikov's [twitter-stream](https://github.com/voloko/twitter-stream). I learned an incredible amount from studying his code and much of the reconnection handling in EM-Twitter is derived/borrowed from his code as are . Eloy Durán's [ssalleyware](https://github.com/alloy/ssalleyware) was very helpful in adding SSL Certificate verification as was David Graham's [vines](https://github.com/negativecode/vines).
|
109
|
+
EM-Twitter is heavily inspired by Vladimir Kolesnikov's [twitter-stream](https://github.com/voloko/twitter-stream). I learned an incredible amount from studying his code and much of the reconnection handling in EM-Twitter is derived/borrowed from his code as are numerous other bits. Eloy Durán's [ssalleyware](https://github.com/alloy/ssalleyware) was very helpful in adding SSL Certificate verification as was David Graham's [vines](https://github.com/negativecode/vines).
|
108
110
|
|
109
111
|
Testing with EM can be a challenge, but was made incredibly easy through the use of Hayes Davis' awesome [mockingbird](https://github.com/hayesdavis/mockingbird) gem.
|
110
112
|
|
@@ -114,4 +116,4 @@ Pull requests welcome: fork, make a topic branch, commit (squash when possible)
|
|
114
116
|
|
115
117
|
## Copyright
|
116
118
|
|
117
|
-
Copyright (c) 2012 Steve Agalloco. See [LICENSE](https://github.com/spagalloco/em-twitter/blob/master/LICENSE.md) for
|
119
|
+
Copyright (c) 2012 Steve Agalloco. See [LICENSE](https://github.com/spagalloco/em-twitter/blob/master/LICENSE.md) for details.
|
data/em-twitter.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |gem|
|
|
20
20
|
gem.add_development_dependency 'rspec'
|
21
21
|
gem.add_development_dependency 'simplecov'
|
22
22
|
gem.add_development_dependency 'yard'
|
23
|
-
gem.add_development_dependency 'mockingbird',
|
23
|
+
gem.add_development_dependency 'mockingbird', '>= 0.1.1'
|
24
24
|
gem.add_development_dependency 'guard-rspec'
|
25
25
|
|
26
26
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
|
data/lib/em-twitter.rb
CHANGED
@@ -16,13 +16,14 @@ module EventMachine
|
|
16
16
|
:proxy => nil,
|
17
17
|
:ssl => {},
|
18
18
|
:timeout => 0,
|
19
|
-
:
|
20
|
-
:
|
19
|
+
:oauth => {},
|
20
|
+
:basic => {},
|
21
21
|
:encoding => nil,
|
22
22
|
:auto_reconnect => true
|
23
23
|
}
|
24
24
|
|
25
25
|
class ReconnectLimitError < StandardError; end
|
26
|
+
class ConfigurationError < StandardError; end
|
26
27
|
|
27
28
|
def self.logger
|
28
29
|
@logger ||= Logger.new(STDOUT)
|
data/lib/em-twitter/client.rb
CHANGED
@@ -16,7 +16,8 @@ module EventMachine
|
|
16
16
|
:enhance_your_calm_callback,
|
17
17
|
:reconnect_callback,
|
18
18
|
:max_reconnects_callback,
|
19
|
-
:close_callback
|
19
|
+
:close_callback,
|
20
|
+
:no_data_callback
|
20
21
|
].freeze unless defined?(CALLBACKS)
|
21
22
|
|
22
23
|
attr_accessor :connection, :options, :host, :port
|
@@ -32,6 +33,8 @@ module EventMachine
|
|
32
33
|
def initialize(options = {})
|
33
34
|
@options = DEFAULT_CONNECTION_OPTIONS.merge(options)
|
34
35
|
|
36
|
+
validate_client
|
37
|
+
|
35
38
|
@host = @options[:host]
|
36
39
|
@port = @options[:port]
|
37
40
|
|
@@ -96,6 +99,10 @@ module EventMachine
|
|
96
99
|
@close_callback = block
|
97
100
|
end
|
98
101
|
|
102
|
+
def on_no_data_received(&block)
|
103
|
+
@no_data_callback = block
|
104
|
+
end
|
105
|
+
|
99
106
|
# Delegate to EM::Twitter::Connection
|
100
107
|
def method_missing(method, *args, &block)
|
101
108
|
return super unless @connection.respond_to?(method)
|
@@ -106,6 +113,14 @@ module EventMachine
|
|
106
113
|
@connection.respond_to?(method, include_private) || super(method, include_private)
|
107
114
|
end
|
108
115
|
|
116
|
+
private
|
117
|
+
|
118
|
+
def validate_client
|
119
|
+
if @options[:oauth] && @options[:basic]
|
120
|
+
raise ConfigurationError.new('Client cannot be configured for both OAuth and Basic Auth') if !@options[:oauth].empty? && !@options[:basic].empty?
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
109
124
|
end
|
110
125
|
end
|
111
126
|
end
|
@@ -17,7 +17,9 @@ module EventMachine
|
|
17
17
|
module Twitter
|
18
18
|
class Connection < EM::Connection
|
19
19
|
|
20
|
-
MAX_LINE_LENGTH = 1024*1024
|
20
|
+
MAX_LINE_LENGTH = 1024*1024 unless defined?(MAX_LINE_LENGTH)
|
21
|
+
STALL_TIMEOUT = 90 unless defined?(STALL_TIMEOUT)
|
22
|
+
STALL_TIMER = 10 unless defined?(STALL_TIMER)
|
21
23
|
|
22
24
|
attr_reader :host, :port, :client, :options, :headers
|
23
25
|
attr_accessor :reconnector
|
@@ -50,6 +52,14 @@ module EventMachine
|
|
50
52
|
@headers = {}
|
51
53
|
@reconnector = EM::Twitter::Reconnectors::NetworkFailure.new
|
52
54
|
|
55
|
+
@stall_timer = EM::PeriodicTimer.new(STALL_TIMER) do
|
56
|
+
if gracefully_closed?
|
57
|
+
@stall_timer.cancel
|
58
|
+
elsif stalled?
|
59
|
+
invoke_callback(@client.no_data_callback)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
53
63
|
invoke_callback(@on_inited_callback)
|
54
64
|
set_comm_inactivity_timeout(@options[:timeout]) if @options[:timeout] > 0
|
55
65
|
end
|
@@ -99,6 +109,10 @@ module EventMachine
|
|
99
109
|
@immediate_reconnect
|
100
110
|
end
|
101
111
|
|
112
|
+
def stalled?
|
113
|
+
@last_response.older_than?(STALL_TIMEOUT)
|
114
|
+
end
|
115
|
+
|
102
116
|
def update(options={})
|
103
117
|
@options.merge!(options)
|
104
118
|
immediate_reconnect
|
@@ -23,14 +23,14 @@ module EventMachine
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def increment
|
26
|
-
@reconnect_count += 1
|
27
|
-
@reconnect_timeout *= INCREMENTOR
|
28
|
-
|
29
26
|
if maximum_reconnects?
|
30
27
|
raise EM::Twitter::ReconnectLimitError.new("#{@reconnect_count} Reconnects")
|
31
28
|
end
|
32
29
|
|
33
30
|
yield @reconnect_timeout if block_given?
|
31
|
+
|
32
|
+
@reconnect_count += 1
|
33
|
+
@reconnect_timeout *= INCREMENTOR
|
34
34
|
end
|
35
35
|
|
36
36
|
def reset
|
@@ -5,11 +5,10 @@ module EventMachine
|
|
5
5
|
|
6
6
|
START = 0.25
|
7
7
|
INCREMENTOR = 0.25
|
8
|
-
MAX = 16
|
9
8
|
|
10
9
|
MAX_RECONNECTS = 10
|
11
10
|
DEFAULT_RECONNECT = 0
|
12
|
-
MAX_TIMEOUT =
|
11
|
+
MAX_TIMEOUT = 16
|
13
12
|
|
14
13
|
attr_reader :reconnect_count
|
15
14
|
attr_writer :reconnect_timeout
|
@@ -20,18 +19,18 @@ module EventMachine
|
|
20
19
|
end
|
21
20
|
|
22
21
|
def reconnect_timeout
|
23
|
-
[@reconnect_timeout,
|
22
|
+
[@reconnect_timeout, MAX_TIMEOUT].min
|
24
23
|
end
|
25
24
|
|
26
25
|
def increment
|
27
|
-
@reconnect_count += 1
|
28
|
-
@reconnect_timeout += INCREMENTOR
|
29
|
-
|
30
26
|
if maximum_reconnects?
|
31
27
|
raise EM::Twitter::ReconnectLimitError.new("#{@reconnect_count} Reconnects")
|
32
28
|
end
|
33
29
|
|
34
30
|
yield @reconnect_timeout if block_given?
|
31
|
+
|
32
|
+
@reconnect_count += 1
|
33
|
+
@reconnect_timeout += INCREMENTOR
|
35
34
|
end
|
36
35
|
|
37
36
|
def reset
|
data/lib/em-twitter/request.rb
CHANGED
@@ -31,10 +31,11 @@ module EventMachine
|
|
31
31
|
|
32
32
|
data << "User-Agent: #{@options[:user_agent]}" if @options[:user_agent]
|
33
33
|
if put_or_post?
|
34
|
-
data << "Content-
|
35
|
-
data << "Content-
|
34
|
+
data << "Content-Type: #{@options[:content_type]}"
|
35
|
+
data << "Content-Length: #{content.bytesize}"
|
36
36
|
end
|
37
|
-
data << "Authorization: #{oauth_header}"
|
37
|
+
data << "Authorization: #{oauth_header}" if oauth?
|
38
|
+
data << "Authorization: #{basic_auth_header}" if basic_auth?
|
38
39
|
data << "Proxy-Authorization: Basic #{proxy.header}" if proxy?
|
39
40
|
|
40
41
|
@options[:headers].each do |name, value|
|
@@ -93,10 +94,23 @@ module EventMachine
|
|
93
94
|
end.sort.join("&")
|
94
95
|
end
|
95
96
|
|
97
|
+
def oauth?
|
98
|
+
@options[:oauth] && !@options[:oauth].empty?
|
99
|
+
end
|
100
|
+
|
96
101
|
def oauth_header
|
97
102
|
SimpleOAuth::Header.new(@options[:method], full_uri, params, @options[:oauth])
|
98
103
|
end
|
99
104
|
|
105
|
+
def basic_auth?
|
106
|
+
@options[:basic] && !@options[:basic].empty?
|
107
|
+
end
|
108
|
+
|
109
|
+
def basic_auth_header
|
110
|
+
auth_string = "#{@options[:basic][:username]}:#{@options[:basic][:password]}"
|
111
|
+
'Basic ' + [auth_string].pack('m').delete("\r\n")
|
112
|
+
end
|
113
|
+
|
100
114
|
def proxy_uri
|
101
115
|
"#{uri_base}:#{@options[:port]}#{path}"
|
102
116
|
end
|
data/lib/em-twitter/response.rb
CHANGED
@@ -2,13 +2,15 @@ module EventMachine
|
|
2
2
|
module Twitter
|
3
3
|
class Response
|
4
4
|
|
5
|
-
attr_reader :body
|
5
|
+
attr_reader :body, :timestamp
|
6
6
|
|
7
7
|
def initialize(body = '')
|
8
8
|
@body = body
|
9
9
|
end
|
10
10
|
|
11
11
|
def concat(data)
|
12
|
+
@timestamp = Time.now
|
13
|
+
|
12
14
|
return unless data && data.size > 0
|
13
15
|
|
14
16
|
data.strip!
|
@@ -22,7 +24,13 @@ module EventMachine
|
|
22
24
|
alias :<< :concat
|
23
25
|
|
24
26
|
def complete?
|
25
|
-
json_start?(@body) && json_end?(@body)
|
27
|
+
@body.size > 0 && json_start?(@body) && json_end?(@body)
|
28
|
+
end
|
29
|
+
|
30
|
+
def older_than?(seconds)
|
31
|
+
@timestamp ||= Time.now
|
32
|
+
|
33
|
+
age > seconds
|
26
34
|
end
|
27
35
|
|
28
36
|
def empty?
|
@@ -35,6 +43,10 @@ module EventMachine
|
|
35
43
|
|
36
44
|
private
|
37
45
|
|
46
|
+
def age
|
47
|
+
Time.now - @timestamp
|
48
|
+
end
|
49
|
+
|
38
50
|
def json_start?(data)
|
39
51
|
data[0,1] == '{'
|
40
52
|
end
|
data/lib/em-twitter/version.rb
CHANGED
@@ -2,6 +2,15 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe EM::Twitter::Client do
|
4
4
|
|
5
|
+
describe 'initialization' do
|
6
|
+
it 'raises a ConfigurationError if both oauth and basic are used' do
|
7
|
+
opts = default_options.merge(:basic => { :username => 'Steve', :password => 'Agalloco' })
|
8
|
+
lambda {
|
9
|
+
EM::Twitter::Client.new(opts)
|
10
|
+
}.should raise_error(EM::Twitter::ConfigurationError)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
5
14
|
describe '.connect' do
|
6
15
|
before do
|
7
16
|
conn = stub('EventMachine::Connection')
|
@@ -11,26 +20,26 @@ describe EM::Twitter::Client do
|
|
11
20
|
|
12
21
|
context 'without a proxy' do
|
13
22
|
it 'connects to the configured host/port' do
|
14
|
-
EventMachine.should_receive(:connect)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
23
|
+
EventMachine.should_receive(:connect).with(
|
24
|
+
test_options[:host],
|
25
|
+
test_options[:port],
|
26
|
+
EventMachine::Twitter::Connection,
|
27
|
+
kind_of(EM::Twitter::Client),
|
28
|
+
test_options[:host],
|
29
|
+
test_options[:port])
|
21
30
|
EM::Twitter::Client.connect(default_options)
|
22
31
|
end
|
23
32
|
end
|
24
33
|
|
25
34
|
context 'when using a proxy' do
|
26
35
|
it 'connects to the proxy server' do
|
27
|
-
EventMachine.should_receive(:connect)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
36
|
+
EventMachine.should_receive(:connect).with(
|
37
|
+
"my-proxy",
|
38
|
+
8080,
|
39
|
+
EventMachine::Twitter::Connection,
|
40
|
+
kind_of(EM::Twitter::Client),
|
41
|
+
'my-proxy',
|
42
|
+
8080)
|
34
43
|
EM::Twitter::Client.connect(default_options.merge(proxy_options))
|
35
44
|
end
|
36
45
|
end
|
@@ -97,8 +97,8 @@ describe 'EM::Twitter::Connection reconnections' do
|
|
97
97
|
client.connection.reconnector = Reconnectors::ApplicationFailure.new(:reconnect_count => 320)
|
98
98
|
end
|
99
99
|
|
100
|
-
timeout.should eq(
|
101
|
-
retries.should eq(
|
100
|
+
timeout.should eq(10)
|
101
|
+
retries.should eq(320)
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
@@ -131,8 +131,8 @@ describe 'EM::Twitter::Connection reconnections' do
|
|
131
131
|
client.connection.reconnector = Reconnectors::NetworkFailure.new(:reconnect_count => 320)
|
132
132
|
end
|
133
133
|
|
134
|
-
timeout.should eq(0.
|
135
|
-
retries.should eq(
|
134
|
+
timeout.should eq(0.25)
|
135
|
+
retries.should eq(320)
|
136
136
|
end
|
137
137
|
end
|
138
138
|
end
|
@@ -22,12 +22,15 @@ describe EM::Twitter::Connection do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
describe 'streaming' do
|
25
|
-
describe '#
|
25
|
+
describe '#each with partial responses' do
|
26
26
|
before do
|
27
27
|
Mockingbird.setup(test_options) do
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
on_connection('*') do
|
29
|
+
status '200', 'Success'
|
30
|
+
100.times do
|
31
|
+
send '{"foo":"ba'
|
32
|
+
send 'r"}'
|
33
|
+
end
|
31
34
|
end
|
32
35
|
end
|
33
36
|
end
|
@@ -41,20 +44,26 @@ describe EM::Twitter::Connection do
|
|
41
44
|
client = EM::Twitter::Client.connect(default_options)
|
42
45
|
client.each do |message|
|
43
46
|
count = count + 1
|
44
|
-
EM.stop if count
|
47
|
+
EM.stop if count >= 99
|
45
48
|
end
|
49
|
+
|
50
|
+
EM::Timer.new(60) { EM.stop }
|
46
51
|
end
|
47
52
|
|
48
53
|
count.should == 100
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
52
|
-
describe '#each' do
|
57
|
+
describe '#each with full responses' do
|
53
58
|
before do
|
54
59
|
Mockingbird.setup(test_options) do
|
55
|
-
|
56
|
-
|
60
|
+
on_connection('*') do
|
61
|
+
status '200', 'Success'
|
62
|
+
100.times do
|
63
|
+
send '{"foo":"bar"}'
|
64
|
+
end
|
57
65
|
end
|
66
|
+
|
58
67
|
end
|
59
68
|
end
|
60
69
|
|
@@ -62,16 +71,45 @@ describe EM::Twitter::Connection do
|
|
62
71
|
|
63
72
|
it 'emits each complete response chunk' do
|
64
73
|
count = 0
|
74
|
+
responses = []
|
65
75
|
|
66
76
|
EM.run do
|
67
77
|
client = EM::Twitter::Client.connect(default_options)
|
68
78
|
client.each do |message|
|
69
79
|
count = count + 1
|
70
|
-
|
80
|
+
responses << message
|
81
|
+
EM.stop if count >= 99
|
71
82
|
end
|
83
|
+
|
84
|
+
EM::Timer.new(60) { EM.stop }
|
72
85
|
end
|
73
86
|
|
74
87
|
count.should == 100
|
88
|
+
responses.last.should eq('{"foo":"bar"}')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'stall handling' do
|
93
|
+
before do
|
94
|
+
Mockingbird.setup(test_options) do
|
95
|
+
wait(100)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
after { Mockingbird.teardown }
|
100
|
+
|
101
|
+
it 'invokes a no-data callback when no data is received' do
|
102
|
+
called = false
|
103
|
+
EM.run do
|
104
|
+
client = EM::Twitter::Client.connect(default_options)
|
105
|
+
client.connection.stub(:stalled?).and_return(true)
|
106
|
+
client.on_no_data_received do
|
107
|
+
called = true
|
108
|
+
EM.stop
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
called.should be_true
|
75
113
|
end
|
76
114
|
end
|
77
115
|
end
|
@@ -24,8 +24,8 @@ describe EM::Twitter::Reconnectors::NetworkFailure do
|
|
24
24
|
|
25
25
|
it 'returns the maximum timeout when greater than the max' do
|
26
26
|
reconn = NetworkFailure.new
|
27
|
-
reconn.reconnect_timeout = NetworkFailure::
|
28
|
-
reconn.reconnect_timeout.should eq(NetworkFailure::
|
27
|
+
reconn.reconnect_timeout = NetworkFailure::MAX_TIMEOUT + 2
|
28
|
+
reconn.reconnect_timeout.should eq(NetworkFailure::MAX_TIMEOUT)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -50,7 +50,7 @@ describe EM::Twitter::Reconnectors::NetworkFailure do
|
|
50
50
|
recon_timeout = timeout
|
51
51
|
end
|
52
52
|
|
53
|
-
recon_timeout.should eq(0.
|
53
|
+
recon_timeout.should eq(0.25)
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'raises an ReconnectLimitError after exceeding max reconnects' do
|
@@ -34,10 +34,6 @@ describe EM::Twitter::Request do
|
|
34
34
|
it 'requests the defined path' do
|
35
35
|
@request.to_s.should include('/1/statuses/filter.json')
|
36
36
|
end
|
37
|
-
|
38
|
-
it 'includes an OAuth header' do
|
39
|
-
@request.to_s.should include('Authorization: OAuth')
|
40
|
-
end
|
41
37
|
end
|
42
38
|
|
43
39
|
context 'when using a proxy' do
|
@@ -54,6 +50,16 @@ describe EM::Twitter::Request do
|
|
54
50
|
end
|
55
51
|
end
|
56
52
|
|
53
|
+
context 'Basic Authentication' do
|
54
|
+
before do
|
55
|
+
@request = EM::Twitter::Request.new(basic_auth_options)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'creates an authorization header' do
|
59
|
+
@request.to_s.should include('Authorization: Basic')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
57
63
|
it 'adds a POST body' do
|
58
64
|
@request = EM::Twitter::Request.new(default_options)
|
59
65
|
@request.to_s.should include('track=nfl')
|
@@ -56,6 +56,12 @@ describe EM::Twitter::Response do
|
|
56
56
|
response << '{ "status" : true }'
|
57
57
|
response.body.should eq('{ "status" : true }')
|
58
58
|
end
|
59
|
+
|
60
|
+
it 'updates the timestamp when data is received' do
|
61
|
+
response = EM::Twitter::Response.new
|
62
|
+
response << '{ "status" : true }'
|
63
|
+
response.timestamp.should be_kind_of(Time)
|
64
|
+
end
|
59
65
|
end
|
60
66
|
|
61
67
|
describe '#complete?' do
|
@@ -68,6 +74,26 @@ describe EM::Twitter::Response do
|
|
68
74
|
end
|
69
75
|
end
|
70
76
|
|
77
|
+
describe '#older_than?' do
|
78
|
+
it 'returns false when the last response is younger than the number of seconds' do
|
79
|
+
response = EM::Twitter::Response.new
|
80
|
+
response.older_than?(100).should be_false
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'returns true when the last response is older than the number of seconds' do
|
84
|
+
response = EM::Twitter::Response.new
|
85
|
+
response.concat('fakebody')
|
86
|
+
sleep(2)
|
87
|
+
response.older_than?(1).should be_true
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'generates a timestamp when no initial timestamp exists' do
|
91
|
+
response = EM::Twitter::Response.new
|
92
|
+
response.older_than?(100)
|
93
|
+
response.timestamp.should be_kind_of(Time)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
71
97
|
describe '#empty?' do
|
72
98
|
it 'returns true when an empty body' do
|
73
99
|
EM::Twitter::Response.new.should be_empty
|
data/spec/spec_helper.rb
CHANGED
@@ -1,12 +1,18 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
2
|
+
unless ENV['CI']
|
3
|
+
require 'simplecov'
|
4
|
+
SimpleCov.start do
|
5
|
+
add_group 'EM-Twitter', 'lib/em-twitter'
|
6
|
+
add_group 'Specs', 'spec'
|
7
|
+
end
|
8
|
+
end
|
3
9
|
|
4
10
|
require 'em-twitter'
|
5
11
|
require 'rspec'
|
6
12
|
require 'mockingbird'
|
7
13
|
|
8
14
|
def test_options
|
9
|
-
{ :host => '127.0.0.1', :port => 9551, :quiet =>
|
15
|
+
{ :host => '127.0.0.1', :port => 9551, :quiet => false }
|
10
16
|
end
|
11
17
|
|
12
18
|
def default_options
|
@@ -29,6 +35,12 @@ def proxy_options
|
|
29
35
|
{ :proxy => { :uri => 'http://my-proxy:8080', :user => 'username', :password => 'password'} }
|
30
36
|
end
|
31
37
|
|
38
|
+
def basic_auth_options
|
39
|
+
opts = default_options.dup
|
40
|
+
opts.delete(:oauth)
|
41
|
+
opts.merge(:basic => { :username => 'Steve', :password => 'Agalloco' })
|
42
|
+
end
|
43
|
+
|
32
44
|
def error_callback_invoked(callback, code, desc, msg = nil)
|
33
45
|
describe "##{callback}" do
|
34
46
|
before do
|
@@ -43,14 +55,14 @@ def error_callback_invoked(callback, code, desc, msg = nil)
|
|
43
55
|
called = false
|
44
56
|
response_code = nil
|
45
57
|
|
46
|
-
if msg
|
47
|
-
|
48
|
-
response_code =
|
58
|
+
block = if msg
|
59
|
+
lambda do |resp_code|
|
60
|
+
response_code = resp_code
|
49
61
|
called = true
|
50
62
|
EM.stop
|
51
63
|
end
|
52
64
|
else
|
53
|
-
|
65
|
+
lambda do
|
54
66
|
called = true
|
55
67
|
EM.stop
|
56
68
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-twitter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-23 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
16
|
-
requirement: &
|
16
|
+
requirement: &70315157830960 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 1.0.0.beta.4
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70315157830960
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: http_parser.rb
|
27
|
-
requirement: &
|
27
|
+
requirement: &70315157830160 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0.5'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70315157830160
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: simple_oauth
|
38
|
-
requirement: &
|
38
|
+
requirement: &70315157829460 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0.1'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70315157829460
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rake
|
49
|
-
requirement: &
|
49
|
+
requirement: &70315157828960 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70315157828960
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rdiscount
|
60
|
-
requirement: &
|
60
|
+
requirement: &70315157828420 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70315157828420
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
|
-
requirement: &
|
71
|
+
requirement: &70315157827960 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70315157827960
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: simplecov
|
82
|
-
requirement: &
|
82
|
+
requirement: &70315157827220 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70315157827220
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: yard
|
93
|
-
requirement: &
|
93
|
+
requirement: &70315157826560 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,21 +98,21 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70315157826560
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: mockingbird
|
104
|
-
requirement: &
|
104
|
+
requirement: &70315157825840 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
|
-
- -
|
107
|
+
- - ! '>='
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: 0.1.1
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70315157825840
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: guard-rspec
|
115
|
-
requirement: &
|
115
|
+
requirement: &70315157825120 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ! '>='
|
@@ -120,7 +120,7 @@ dependencies:
|
|
120
120
|
version: '0'
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *70315157825120
|
124
124
|
description: Twitter Streaming API client for EventMachine
|
125
125
|
email: steve.agalloco@gmail.com
|
126
126
|
executables: []
|
@@ -130,7 +130,6 @@ files:
|
|
130
130
|
- .gemtest
|
131
131
|
- .gitignore
|
132
132
|
- .rspec
|
133
|
-
- .simplecov
|
134
133
|
- .travis.yml
|
135
134
|
- .yardopts
|
136
135
|
- Gemfile
|
data/.simplecov
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
SimpleCov.start
|