CacheBar 1.0.0

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.
@@ -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: []