CacheBar 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,216 @@
1
+ require 'helper'
2
+
3
+ class TestCacheBar < Test::Unit::TestCase
4
+ context 'CacheBar' do
5
+
6
+ context 'mocking redis' do
7
+ setup do
8
+ @redis = mock
9
+ HTTParty::HTTPCache.redis = @redis
10
+ end
11
+
12
+ context 'with caching on' do
13
+ context 'with a good response' do
14
+ setup do
15
+ @uri_hash = '007a3a7aa28b11ef362040283e114f55'
16
+ @response = fixture_file('user_timeline.json')
17
+ VCR.insert_cassette('good_response')
18
+ end
19
+
20
+ teardown do
21
+ VCR.eject_cassette
22
+ end
23
+
24
+ should "set key with expiration" do
25
+ @redis.stubs(:exists).returns(false)
26
+ @redis.expects(:set).with("api-cache:twitter:#{@uri_hash}", @response).returns(true)
27
+ @redis.expects(:expire).with("api-cache:twitter:#{@uri_hash}", is_a(Integer)).returns(true)
28
+ @redis.stubs(:hset).returns(true)
29
+ TwitterAPI.user_timeline('viget')
30
+ end
31
+
32
+ should "store a backup" do
33
+ @redis.stubs(:exists).returns(false)
34
+ @redis.stubs(:set).returns(true)
35
+ @redis.stubs(:expire).returns(true)
36
+ @redis.expects(:hset).with('api-cache:twitter', @uri_hash, @response).returns(true)
37
+ TwitterAPI.user_timeline('viget')
38
+ end
39
+
40
+ should 'return expected result to PIM class' do
41
+ @redis.stubs(:exists).returns(false)
42
+ @redis.stubs(:set).returns(true)
43
+ @redis.stubs(:expire).returns(true)
44
+ @redis.stubs(:hset).returns(true)
45
+ tweets = TwitterAPI.user_timeline('viget')
46
+ assert_kind_of Array, tweets.parsed_response
47
+ assert tweets.parsed_response.present?
48
+ end
49
+
50
+ context 'and stored in cache' do
51
+ should 'retrieve response from cache correctly' do
52
+ @redis.stubs(:exists).returns(true)
53
+ @redis.expects(:get).with("api-cache:twitter:#{@uri_hash}").returns(@response)
54
+ tweets = TwitterAPI.user_timeline('viget')
55
+ assert_kind_of Array, tweets.parsed_response
56
+ assert tweets.parsed_response.present?
57
+ end
58
+ end
59
+ end
60
+
61
+ context 'with timeout' do
62
+ setup do
63
+ @uri_hash = '007a3a7aa28b11ef362040283e114f55'
64
+ @response = fixture_file('user_timeline.json')
65
+ HTTParty::Request.any_instance.expects(:timeout).raises(Timeout::Error)
66
+ end
67
+
68
+ should 'retrieve from backup if exists' do
69
+ mock_response_in_backup(@uri_hash)
70
+ response = TwitterAPI.user_timeline('viget')
71
+ assert_kind_of Array, response.parsed_response
72
+ assert response.parsed_response.present?
73
+ end
74
+
75
+ should 'raise NoResponseError error if no response in backup' do
76
+ mock_no_response_in_backup(@uri_hash)
77
+ assert_raise HTTParty::HTTPCache::NoResponseError do
78
+ TwitterAPI.user_timeline('viget')
79
+ end
80
+ end
81
+ end
82
+
83
+ context 'with unparsable response' do
84
+ setup do
85
+ VCR.insert_cassette('unparsable')
86
+ @uri_hash = '9780998e3ec445e5c0e56ca0bf10248c'
87
+ @response = fixture_file('user_timeline.json')
88
+ end
89
+
90
+ should 'retrieve from backup if exists' do
91
+ mock_response_in_backup(@uri_hash)
92
+ response = TwitterAPI.bogus_resource
93
+ assert_kind_of Array, response.parsed_response
94
+ assert response.parsed_response.present?
95
+ end
96
+
97
+ should 'raise NoResponseError error if no response in backup' do
98
+ mock_no_response_in_backup(@uri_hash)
99
+ assert_raise HTTParty::HTTPCache::NoResponseError do
100
+ TwitterAPI.bogus_resource
101
+ end
102
+ end
103
+
104
+ teardown do
105
+ VCR.eject_cassette
106
+ end
107
+ end
108
+
109
+ context 'with bad response' do
110
+ setup do
111
+ VCR.insert_cassette('bad_response')
112
+ @uri_hash = '01cedaf99cbf9f7e585ac4fa034a4fd5'
113
+ @response = fixture_file('user_timeline.json')
114
+ end
115
+
116
+ should 'retrieve from backup if exists' do
117
+ mock_response_in_backup(@uri_hash)
118
+ response = TwitterAPI.bogus_timeline('viget')
119
+ assert_kind_of Array, response.parsed_response
120
+ assert response.parsed_response.present?
121
+ end
122
+
123
+ should 'return bad response' do
124
+ mock_no_response_in_backup(@uri_hash)
125
+ response = TwitterAPI.bogus_timeline('viget')
126
+ assert_equal 401, response.code
127
+ assert !response.response.is_a?(Net::HTTPSuccess)
128
+ end
129
+
130
+ teardown do
131
+ VCR.eject_cassette
132
+ end
133
+ end
134
+
135
+ context 'with bad response exception' do
136
+ setup do
137
+ @uri_hash = '9780998e3ec445e5c0e56ca0bf10248c'
138
+ @response = fixture_file('user_timeline.json')
139
+ end
140
+
141
+ should 'retrieve from backup if exists' do
142
+ mock_response_in_backup(@uri_hash)
143
+ mock_http_exception
144
+ response = TwitterAPI.bogus_resource
145
+ assert_kind_of Array, response.parsed_response
146
+ assert response.parsed_response.present?
147
+ end
148
+
149
+ should 'raise NoResponseError error if no response in backup' do
150
+ mock_no_response_in_backup(@uri_hash)
151
+ mock_http_exception
152
+ assert_raise HTTParty::HTTPCache::NoResponseError do
153
+ TwitterAPI.bogus_resource
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ context 'with caching off' do
160
+ setup do
161
+ turn_off_caching
162
+ @redis.expects(:exists).never
163
+ @uri_hash = '007a3a7aa28b11ef362040283e114f55'
164
+ @response = fixture_file('user_timeline.json')
165
+ VCR.insert_cassette('good_response')
166
+ end
167
+
168
+ should 'just return the response' do
169
+ tweets = TwitterAPI.user_timeline('viget')
170
+ assert_kind_of Array, tweets.parsed_response
171
+ assert tweets.parsed_response.present?
172
+ end
173
+
174
+ teardown do
175
+ VCR.eject_cassette
176
+ turn_on_caching
177
+ end
178
+ end
179
+ end
180
+
181
+ context 'connecting to redis' do
182
+ setup do
183
+ VCR.insert_cassette('good_response')
184
+
185
+ redis = Redis.new(:host => 'localhost', :port => 6379,
186
+ :thread_safe => true, :db => '3')
187
+ @redis = Redis::Namespace.new('httpcache', :redis => redis)
188
+ HTTParty::HTTPCache.redis = @redis
189
+
190
+ @redis.keys("api-cache*").each do |key|
191
+ @redis.del(key)
192
+ end
193
+ end
194
+
195
+ should "store its response in the cache" do
196
+ assert_difference "@redis.keys('api-cache:twitter:*').count", 1 do
197
+ TwitterAPI.user_timeline('viget')
198
+ end
199
+ end
200
+
201
+ should "store a backup of its response" do
202
+ assert_difference "@redis.hkeys('api-cache:twitter').count", 1 do
203
+ TwitterAPI.user_timeline('viget')
204
+ end
205
+ end
206
+
207
+ teardown do
208
+ VCR.eject_cassette
209
+ @redis.keys("api-cache*").each do |key|
210
+ @redis.del(key)
211
+ end
212
+ end
213
+ end
214
+
215
+ end
216
+ end
@@ -0,0 +1,22 @@
1
+ module TwitterAPI
2
+ include HTTParty
3
+ base_uri 'https://api.twitter.com/1'
4
+ format :json
5
+
6
+ caches_api_responses :key_name => "twitter", :expire_in => 3600
7
+
8
+ class << self
9
+ def user_timeline(username)
10
+ get '/statuses/user_timeline.json', :query => {:screen_name => username}
11
+ end
12
+
13
+ def bogus_timeline(username)
14
+ get '/statuses/bogus_timeline.json', :query => {:screen_name => username}
15
+ end
16
+
17
+ def bogus_resource
18
+ get '/user_timeline.json'
19
+ end
20
+ end
21
+
22
+ end
metadata ADDED
@@ -0,0 +1,214 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: CacheBar
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brian Landau
9
+ - David Eisinger
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2011-06-01 00:00:00.000000000 -04:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: redis
18
+ requirement: &2156682440 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *2156682440
27
+ - !ruby/object:Gem::Dependency
28
+ name: redis-namespace
29
+ requirement: &2156681960 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: *2156681960
38
+ - !ruby/object:Gem::Dependency
39
+ name: httparty
40
+ requirement: &2156681480 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.7.7
46
+ type: :runtime
47
+ prerelease: false
48
+ version_requirements: *2156681480
49
+ - !ruby/object:Gem::Dependency
50
+ name: activesupport
51
+ requirement: &2156672020 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: *2156672020
60
+ - !ruby/object:Gem::Dependency
61
+ name: SystemTimer
62
+ requirement: &2156671500 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: *2156671500
71
+ - !ruby/object:Gem::Dependency
72
+ name: shoulda
73
+ requirement: &2156671000 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: *2156671000
82
+ - !ruby/object:Gem::Dependency
83
+ name: bundler
84
+ requirement: &2156670400 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: *2156670400
93
+ - !ruby/object:Gem::Dependency
94
+ name: jeweler
95
+ requirement: &2156669900 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ~>
99
+ - !ruby/object:Gem::Version
100
+ version: '1.6'
101
+ type: :development
102
+ prerelease: false
103
+ version_requirements: *2156669900
104
+ - !ruby/object:Gem::Dependency
105
+ name: rcov
106
+ requirement: &2156669420 !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ type: :development
113
+ prerelease: false
114
+ version_requirements: *2156669420
115
+ - !ruby/object:Gem::Dependency
116
+ name: webmock
117
+ requirement: &2156668920 !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ type: :development
124
+ prerelease: false
125
+ version_requirements: *2156668920
126
+ - !ruby/object:Gem::Dependency
127
+ name: vcr
128
+ requirement: &2156668320 !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: *2156668320
137
+ - !ruby/object:Gem::Dependency
138
+ name: mocha
139
+ requirement: &2156667840 !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ! '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: *2156667840
148
+ - !ruby/object:Gem::Dependency
149
+ name: rake
150
+ requirement: &2156667360 !ruby/object:Gem::Requirement
151
+ none: false
152
+ requirements:
153
+ - - ~>
154
+ - !ruby/object:Gem::Version
155
+ version: 0.8.7
156
+ type: :development
157
+ prerelease: false
158
+ version_requirements: *2156667360
159
+ description: A simple API caching layer built on top of HTTParty and Redis
160
+ email: brian.landau@viget.com
161
+ executables: []
162
+ extensions: []
163
+ extra_rdoc_files:
164
+ - LICENSE.txt
165
+ - README.md
166
+ files:
167
+ - .document
168
+ - CacheBar.gemspec
169
+ - Gemfile
170
+ - HISTORY
171
+ - LICENSE.txt
172
+ - README.md
173
+ - Rakefile
174
+ - VERSION
175
+ - lib/cachebar.rb
176
+ - lib/core_ext/hash/require_keys.rb
177
+ - lib/httparty/httpcache.rb
178
+ - test/fixtures/user_timeline.json
179
+ - test/fixtures/vcr_cassettes/bad_response.yml
180
+ - test/fixtures/vcr_cassettes/good_response.yml
181
+ - test/fixtures/vcr_cassettes/unparsable.yml
182
+ - test/helper.rb
183
+ - test/test_cachebar.rb
184
+ - test/twitter_api.rb
185
+ has_rdoc: true
186
+ homepage: http://github.com/vigetlabs/cachebar
187
+ licenses:
188
+ - MIT
189
+ post_install_message:
190
+ rdoc_options: []
191
+ require_paths:
192
+ - lib
193
+ required_ruby_version: !ruby/object:Gem::Requirement
194
+ none: false
195
+ requirements:
196
+ - - ! '>='
197
+ - !ruby/object:Gem::Version
198
+ version: '0'
199
+ segments:
200
+ - 0
201
+ hash: -3416093338450689739
202
+ required_rubygems_version: !ruby/object:Gem::Requirement
203
+ none: false
204
+ requirements:
205
+ - - ! '>='
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
208
+ requirements: []
209
+ rubyforge_project:
210
+ rubygems_version: 1.6.2
211
+ signing_key:
212
+ specification_version: 3
213
+ summary: A simple API caching layer built on top of HTTParty and Redis
214
+ test_files: []