powertrack 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module PowerTrack
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'powertrack/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'powertrack'
8
+ spec.version = PowerTrack::VERSION
9
+ spec.authors = ['Laurent Farcy', 'Eric Wendelin', 'Ryan Weald']
10
+ spec.email = ['laurent.farcy@ecairn.com', 'me@eriwen.com', 'ryan@weald.com']
11
+ spec.summary = %q{Powertrack-rb is a gem used to develop GNIP PowerTrack streaming clients.}
12
+ spec.description = spec.summary
13
+ spec.homepage = 'https://github.com/ecairn/powertrack-rb'
14
+ spec.license = 'MIT license'
15
+ spec.required_ruby_version = '~> 1.9'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.7'
23
+ spec.add_development_dependency 'rake', '~> 10.3'
24
+ spec.add_development_dependency 'minitest', '~> 5.5'
25
+ spec.add_development_dependency 'ruby-prof', '~> 0.15'
26
+
27
+ spec.add_dependency 'multi_json', '~> 1.11'
28
+ spec.add_dependency 'eventmachine', '~> 1.0'
29
+ spec.add_dependency 'em-http-request', '~> 1.1'
30
+ spec.add_dependency 'exponential-backoff', '~> 0.0.2'
31
+ spec.add_dependency 'void_logger', '~> 0.1'
32
+ end
@@ -0,0 +1,41 @@
1
+ gem 'minitest'
2
+ require 'minitest/autorun'
3
+ require 'yaml'
4
+
5
+ class Minitest::Test
6
+
7
+ POWERTRACK_CONFIG_FILEPATH = File.join(File.dirname(__FILE__), "powertrack.yml")
8
+
9
+ # Returns the PowerTrack configuration as defined in test/powertrack.yml.
10
+ def powertrack_config
11
+ unless defined?(@loaded) && @loaded
12
+ begin
13
+ if File.exist?(POWERTRACK_CONFIG_FILEPATH)
14
+ @pwtk_config = (YAML.load_file(POWERTRACK_CONFIG_FILEPATH) || {})
15
+ else
16
+ $stderr.puts "No PowerTrack config file found at '#{POWERTRACK_CONFIG_FILEPATH}'"
17
+ end
18
+ rescue Exception
19
+ $stderr.puts "Exception while loading PowerTrack config file: #{$!.message}"
20
+ ensure
21
+ @pwtk_config ||= {}
22
+ end
23
+
24
+ # symbolize keys
25
+ @pwtk_config = Hash[@pwtk_config.map{ |k, v| [k.to_sym, v] }]
26
+ @loaded = true
27
+ end
28
+
29
+ @pwtk_config
30
+ end
31
+
32
+ # Returns a brand-new stream based on the config found in test/powertrack.yml.
33
+ def new_stream
34
+ PowerTrack::Stream.new(
35
+ powertrack_config[:username],
36
+ powertrack_config[:password],
37
+ powertrack_config[:account_name],
38
+ powertrack_config[:data_source],
39
+ powertrack_config[:stream_label])
40
+ end
41
+ end
@@ -0,0 +1,30 @@
1
+ require 'minitest_helper'
2
+ require 'powertrack'
3
+ require 'multi_json'
4
+
5
+ class TestManageRules < Minitest::Test
6
+
7
+ def test_add_then_delete_a_single_rule
8
+ stream = new_stream
9
+
10
+ rule = PowerTrack::Rule.new('coke')
11
+ assert rule.valid?
12
+
13
+ pre_existing_rules = stream.list_rules
14
+ assert pre_existing_rules.is_a?(Array)
15
+
16
+ assert_nil stream.add_rule(rule)
17
+
18
+ rules_after_addition = stream.list_rules(false)
19
+ assert rules_after_addition.is_a?(Array)
20
+ assert_equal pre_existing_rules.size + 1, rules_after_addition.size
21
+ assert [ rule ], rules_after_addition - pre_existing_rules
22
+
23
+ assert_nil stream.delete_rules(rule)
24
+
25
+ rules_after_removal = stream.list_rules
26
+ assert rules_after_removal.is_a?(Array)
27
+ assert_equal rules_after_addition.size - 1, rules_after_removal.size
28
+ assert_equal [], rules_after_removal - rules_after_addition
29
+ end
30
+ end
data/test/test_rule.rb ADDED
@@ -0,0 +1,163 @@
1
+ require 'minitest_helper'
2
+ require 'powertrack'
3
+ require 'multi_json'
4
+
5
+ class TestRule < Minitest::Test
6
+
7
+ def test_valid_rule
8
+ rule = PowerTrack::Rule.new('coke')
9
+ assert_equal 'coke', rule.value
10
+ assert_nil rule.tag
11
+ assert !rule.long?
12
+ assert rule.valid?
13
+ assert_nil rule.error
14
+
15
+ rule = PowerTrack::Rule.new('pepsi', 'soda', true)
16
+ assert_equal 'pepsi', rule.value
17
+ assert_equal 'soda', rule.tag
18
+ assert rule.long?
19
+ assert rule.valid?
20
+ assert_nil rule.error
21
+ end
22
+
23
+ def test_too_long_tag
24
+ long_tag = 'a' * PowerTrack::Rule::MAX_TAG_LENGTH
25
+ rule = PowerTrack::Rule.new('coke', long_tag, false)
26
+ assert rule.valid?
27
+ assert_nil rule.error
28
+
29
+ long_tag = 'b' * 2 * PowerTrack::Rule::MAX_TAG_LENGTH
30
+ rule = PowerTrack::Rule.new('coke', long_tag, true)
31
+ assert !rule.valid?
32
+ assert_match /too long tag/i, rule.error
33
+ end
34
+
35
+ def test_too_long_value
36
+ long_val = 'a' * PowerTrack::Rule::MAX_STD_RULE_VALUE_LENGTH
37
+ rule = PowerTrack::Rule.new(long_val)
38
+ assert rule.valid?
39
+
40
+ long_val = 'c' * PowerTrack::Rule::MAX_LONG_RULE_VALUE_LENGTH
41
+ rule = long_val.to_pwtk_rule(nil, false)
42
+
43
+ assert !rule.valid?
44
+ assert_match /too long value/i, rule.error
45
+
46
+ assert long_val.to_pwtk_rule.valid?
47
+ assert long_val.to_pwtk_rule(nil, true).valid?
48
+
49
+ very_long_val = 'rrr' * PowerTrack::Rule::MAX_LONG_RULE_VALUE_LENGTH
50
+ rule = very_long_val.to_pwtk_rule
51
+ assert !rule.valid?
52
+ assert_match /too long value/i, rule.error
53
+ end
54
+
55
+ def test_too_many_positive_terms
56
+ phrase = ([ 'coke' ] * PowerTrack::Rule::MAX_POSITIVE_TERMS).join(' ')
57
+ rule = PowerTrack::Rule.new(phrase)
58
+ assert !rule.long?
59
+ assert rule.valid?
60
+ assert_nil rule.error
61
+
62
+ long_rule = PowerTrack::Rule.new(phrase, nil, true)
63
+ assert long_rule.long?
64
+ assert long_rule.valid?
65
+ assert_nil long_rule.error
66
+
67
+ phrase = ([ 'coke' ] * (2 * PowerTrack::Rule::MAX_POSITIVE_TERMS)).join(' ')
68
+ rule = PowerTrack::Rule.new(phrase, nil, false)
69
+ assert !rule.long?
70
+ assert !rule.valid?
71
+ assert_match /too many positive terms/i, rule.error
72
+
73
+ long_rule = PowerTrack::Rule.new(phrase, nil, true)
74
+ assert long_rule.long?
75
+ assert long_rule.valid?
76
+ assert_nil long_rule.error
77
+
78
+ phrase = "from:lkv1csayp OR from:u42vf OR from:y OR from:groj OR from:69iqciuxlxerqq OR from:4 OR from:9832xjrqi1ncrs OR from:7kfss6jxtl0oj OR from:b31m9qf0u3tc OR from:0 OR from:abo59n OR from:3lma3kl OR from:5 OR from:ovw7bgov OR from:ubp OR from:gc9a6b OR from:jo7ootfvy4 OR from:sg7oohj OR from:349ankku OR from:9b72n OR from:qz7offt5019u OR from:gkd OR from:cc31p3 OR from:xws9 OR from:bjzbatm OR from:rwjm78cgre3j5 OR from:f1obak7w3w OR from:nontf OR from:4aeas6kgb7nia OR from:dzqy7"
79
+ long_rule = PowerTrack::Rule.new(phrase)
80
+ assert !long_rule.long?
81
+ assert long_rule.valid?, long_rule.error
82
+ assert_nil long_rule.error
83
+
84
+ long_rule = PowerTrack::Rule.new(phrase + " OR from:michel")
85
+ assert !rule.valid?
86
+ assert_match /too many positive terms/i, rule.error
87
+ end
88
+
89
+ def test_too_many_negative_terms
90
+ phrase = ([ '-pepsi' ] * PowerTrack::Rule::MAX_POSITIVE_TERMS).join(' ')
91
+ rule = PowerTrack::Rule.new(phrase)
92
+ assert !rule.long?
93
+ assert rule.valid?
94
+ assert_nil rule.error
95
+
96
+ long_rule = PowerTrack::Rule.new(phrase, nil, true)
97
+ assert long_rule.long?
98
+ assert long_rule.valid?
99
+ assert_nil long_rule.error
100
+
101
+ phrase = ([ '-pepsi' ] * (2 * PowerTrack::Rule::MAX_POSITIVE_TERMS)).join(' ')
102
+ rule = PowerTrack::Rule.new(phrase)
103
+ assert !rule.long?
104
+ assert !rule.valid?
105
+ assert_match /too many negative terms/i, rule.error
106
+
107
+ long_rule = PowerTrack::Rule.new(phrase, nil, true)
108
+ assert long_rule.long?
109
+ assert long_rule.valid?
110
+ assert_nil long_rule.error
111
+ end
112
+
113
+ def test_contains_negated_or
114
+ phrase = 'coke OR -pepsi'
115
+ rule = PowerTrack::Rule.new(phrase)
116
+ assert !rule.long?
117
+ assert !rule.valid?
118
+ assert_match /contains negated or/i, rule.error
119
+ end
120
+
121
+ def test_to_hash_and_json
122
+ res = { value: 'coke OR pepsi' }
123
+ rule = PowerTrack::Rule.new(res[:value])
124
+ assert_equal res, rule.to_hash
125
+ assert_equal MultiJson.encode(res), rule.to_json
126
+
127
+ res[:tag] = 'soda'
128
+ rule = PowerTrack::Rule.new(res[:value], res[:tag], true)
129
+ assert_equal res, rule.to_hash
130
+ assert_equal MultiJson.encode(res), rule.to_json
131
+ end
132
+
133
+ def test_double_quote_jsonification
134
+ rule = PowerTrack::Rule.new('"social data" @gnip')
135
+ assert_equal '{"value":"\"social data\" @gnip"}', rule.to_json
136
+
137
+ rule = PowerTrack::Rule.new('Toys \"R\" Us')
138
+ # 2 backslashes for 1
139
+ assert_equal '{"value":"Toys \\\\\\"R\\\\\\" Us"}', rule.to_json
140
+ end
141
+
142
+ def test_hash
143
+ short_rule = PowerTrack::Rule.new('coke')
144
+ not_long_rule = PowerTrack::Rule.new('coke', nil, false)
145
+ false_long_rule = PowerTrack::Rule.new('coke', nil, true)
146
+ short_rule_with_tag = PowerTrack::Rule.new('coke', 'soda')
147
+
148
+ assert short_rule == not_long_rule
149
+ assert_equal short_rule, not_long_rule
150
+ assert_equal short_rule.hash, not_long_rule.hash
151
+
152
+ assert short_rule != false_long_rule
153
+ h = { short_rule => 1 }
154
+ h[not_long_rule] = 2
155
+ h[false_long_rule] = 3
156
+ h[short_rule_with_tag] = 4
157
+
158
+ assert_equal 2, h[short_rule]
159
+ assert_equal h[short_rule], h[not_long_rule]
160
+ assert_equal 4, h[short_rule_with_tag]
161
+ assert_nil h[PowerTrack::Rule.new('pepsi', 'soda')]
162
+ end
163
+ end
@@ -0,0 +1,72 @@
1
+ require 'minitest_helper'
2
+ require 'powertrack'
3
+ require 'multi_json'
4
+
5
+ class TestTrackStream < Minitest::Test
6
+
7
+ def test_track_simple_stream
8
+ stream = new_stream
9
+
10
+ # add a logger
11
+ stream.logger = Logger.new(STDERR)
12
+
13
+ rule = PowerTrack::Rule.new('ny OR nyc OR #nyc OR new york')
14
+ assert rule.valid?
15
+
16
+ begin
17
+ assert_nil stream.add_rule(rule)
18
+ rules_after_addition = stream.list_rules
19
+ assert rules_after_addition.is_a?(Array)
20
+ assert rules_after_addition.size > 0
21
+
22
+ heartbeats = 0
23
+ received = 0
24
+ tweeted = 0
25
+ closed = false
26
+
27
+ # ready to track
28
+ on_message = lambda do |message|
29
+ received += 1
30
+ end
31
+ on_heartbeat = lambda do
32
+ heartbeats += 1
33
+ end
34
+ on_activity = lambda do |tweet|
35
+ tweeted += 1
36
+ end
37
+
38
+ close_now = lambda { closed }
39
+
40
+ delay = 60
41
+ Thread.new do
42
+ $stderr.puts "Time-bomb thread running for #{delay} seconds..."
43
+ sleep delay
44
+ $stderr.puts "Time to shut down !"
45
+ closed = true
46
+ end
47
+
48
+ started_at = Time.now
49
+ res = stream.track(on_message: on_message,
50
+ on_heartbeat: on_heartbeat,
51
+ on_activity: on_activity,
52
+ close_now: close_now,
53
+ max_retries: 3,
54
+ fake_disconnections: 20)
55
+
56
+ assert_nil res
57
+ assert closed, 'Stream not closed'
58
+ assert Time.now - started_at >= delay
59
+
60
+ assert heartbeats > 0, 'No heartbeat received'
61
+ puts "#{heartbeats} heartbeats received"
62
+
63
+ assert received > 0, 'No message received so far'
64
+ puts "#{received} messages received"
65
+
66
+ assert tweeted > 0, 'No tweet received so far'
67
+ puts "#{tweeted} tweets received"
68
+ ensure
69
+ assert_nil stream.delete_rules(rule)
70
+ end
71
+ end
72
+ end
metadata ADDED
@@ -0,0 +1,202 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: powertrack
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Laurent Farcy
8
+ - Eric Wendelin
9
+ - Ryan Weald
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2015-08-18 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bundler
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.7'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ version: '1.7'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rake
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: '10.3'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ version: '10.3'
43
+ - !ruby/object:Gem::Dependency
44
+ name: minitest
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ version: '5.5'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: '5.5'
57
+ - !ruby/object:Gem::Dependency
58
+ name: ruby-prof
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ~>
62
+ - !ruby/object:Gem::Version
63
+ version: '0.15'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ version: '0.15'
71
+ - !ruby/object:Gem::Dependency
72
+ name: multi_json
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '1.11'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ~>
83
+ - !ruby/object:Gem::Version
84
+ version: '1.11'
85
+ - !ruby/object:Gem::Dependency
86
+ name: eventmachine
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ~>
90
+ - !ruby/object:Gem::Version
91
+ version: !binary |-
92
+ MS4w
93
+ type: :runtime
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ~>
98
+ - !ruby/object:Gem::Version
99
+ version: !binary |-
100
+ MS4w
101
+ - !ruby/object:Gem::Dependency
102
+ name: em-http-request
103
+ requirement: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ~>
106
+ - !ruby/object:Gem::Version
107
+ version: '1.1'
108
+ type: :runtime
109
+ prerelease: false
110
+ version_requirements: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ~>
113
+ - !ruby/object:Gem::Version
114
+ version: '1.1'
115
+ - !ruby/object:Gem::Dependency
116
+ name: exponential-backoff
117
+ requirement: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ~>
120
+ - !ruby/object:Gem::Version
121
+ version: 0.0.2
122
+ type: :runtime
123
+ prerelease: false
124
+ version_requirements: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ~>
127
+ - !ruby/object:Gem::Version
128
+ version: 0.0.2
129
+ - !ruby/object:Gem::Dependency
130
+ name: void_logger
131
+ requirement: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ~>
134
+ - !ruby/object:Gem::Version
135
+ version: '0.1'
136
+ type: :runtime
137
+ prerelease: false
138
+ version_requirements: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ~>
141
+ - !ruby/object:Gem::Version
142
+ version: '0.1'
143
+ description: Powertrack-rb is a gem used to develop GNIP PowerTrack streaming clients.
144
+ email:
145
+ - laurent.farcy@ecairn.com
146
+ - me@eriwen.com
147
+ - ryan@weald.com
148
+ executables: []
149
+ extensions: []
150
+ extra_rdoc_files: []
151
+ files:
152
+ - .gitignore
153
+ - Gemfile
154
+ - Gemfile.lock
155
+ - LICENSE.md
156
+ - README.md
157
+ - Rakefile
158
+ - TODO.md
159
+ - lib/core_ext/class.rb
160
+ - lib/powertrack.rb
161
+ - lib/powertrack/errors.rb
162
+ - lib/powertrack/rules/rule.rb
163
+ - lib/powertrack/rules/string_extension.rb
164
+ - lib/powertrack/streaming/api.rb
165
+ - lib/powertrack/streaming/data_buffer.rb
166
+ - lib/powertrack/streaming/retrier.rb
167
+ - lib/powertrack/streaming/stream.rb
168
+ - lib/powertrack/version.rb
169
+ - powertrack.gemspec
170
+ - test/minitest_helper.rb
171
+ - test/test_manage_rules.rb
172
+ - test/test_rule.rb
173
+ - test/test_track_stream.rb
174
+ homepage: https://github.com/ecairn/powertrack-rb
175
+ licenses:
176
+ - MIT license
177
+ metadata: {}
178
+ post_install_message:
179
+ rdoc_options: []
180
+ require_paths:
181
+ - lib
182
+ required_ruby_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ~>
185
+ - !ruby/object:Gem::Version
186
+ version: '1.9'
187
+ required_rubygems_version: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ! '>='
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ requirements: []
193
+ rubyforge_project:
194
+ rubygems_version: 2.4.6
195
+ signing_key:
196
+ specification_version: 4
197
+ summary: Powertrack-rb is a gem used to develop GNIP PowerTrack streaming clients.
198
+ test_files:
199
+ - test/minitest_helper.rb
200
+ - test/test_manage_rules.rb
201
+ - test/test_rule.rb
202
+ - test/test_track_stream.rb