expedition 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 141d6721450724842c369dc719dc7c730bf9ca33
4
+ data.tar.gz: fe74ec4f70c28284ce8368ba260eccafebd6a307
5
+ SHA512:
6
+ metadata.gz: 5be107f3cf7a0c8a449c3022e5d1fc9f1b862384a92db439e9d6c4125f49451714b4771dda11edd7cee6df4f803b16ee9276c3ea79251a92adfce5ae72aeb269
7
+ data.tar.gz: 3064b19068add7e17547c07b610655446e308a8e1fd9ee94759c1f5e420986f645ce0260e587c81cb5f6d4be2e8517ab779ec32940b505a4044e1082a90dbd6e
data/.coveralls.yml ADDED
@@ -0,0 +1,2 @@
1
+ service_name: travis-ci
2
+ repo_token: FK7rLLtMdgyrVRQP6Ex4SIILDWOvOQmZT
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.pryrc ADDED
@@ -0,0 +1,13 @@
1
+ require 'bundler/setup'
2
+ require 'expedition'
3
+
4
+ def reload!
5
+ old_verbose, $VERBOSE = $VERBOSE, nil
6
+ Dir["#{File.dirname(__FILE__)}/lib/**/*.rb"].sort.each { |f| load f }
7
+ ensure
8
+ $VERBOSE = old_verbose
9
+ end
10
+
11
+ def client(host = 'localhost', port = 4028)
12
+ Expedition.new(host, port)
13
+ end
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.1
4
+ - 2.1.0
5
+ - 2.0.0
data/.yardopts ADDED
@@ -0,0 +1,3 @@
1
+ --title 'Expedition API Docs'
2
+ --charset utf-8
3
+ --markup markdown
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in expedition.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,15 @@
1
+ guard 'bundler' do
2
+ watch('Gemfile')
3
+ watch(%r{\w+\.gemspec})
4
+ end
5
+
6
+ guard 'rspec', cmd: 'bundle exec rspec', all_on_start: true do
7
+ watch(%r{^spec/.+_spec\.rb$})
8
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
9
+ watch('spec/spec_helper.rb') { 'spec' }
10
+ watch(%r{^lib/config/locales}) { 'spec/launchkey/errors' }
11
+ end
12
+
13
+ guard 'yard' do
14
+ watch(%r{lib/.+\.rb})
15
+ end
data/MIT-LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Gabe Evans
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Expedition
2
+
3
+ Expedition is a gem for interacting with cgminer and cgminer-compatible APIs.
4
+ The goal of this project is to offer Rubyists easier integration with the
5
+ [cgminer API](https://github.com/ckolivas/cgminer/blob/master/API-README) “the
6
+ Ruby way.”
7
+
8
+ **tl;dr** This gem lets you interact with cgminer’s API the way a Ruby hipster
9
+ would want to.
10
+
11
+ Now for some fancy badges:
12
+
13
+ [![Gem Version](https://badge.fury.io/rb/expedition.png)](http://badge.fury.io/rb/expedition)
14
+ [![Dependency Status](https://gemnasium.com/gevans/expedition.png)](https://gemnasium.com/gevans/expedition)
15
+ [![Build Status](https://travis-ci.org/gevans/expedition.png?branch=master)](https://travis-ci.org/gevans/expedition)
16
+ [![Code Climate](https://codeclimate.com/github/gevans/expedition.png)](https://codeclimate.com/github/gevans/expedition)
17
+ [![Coverage Status](https://coveralls.io/repos/gevans/expedition/badge.png?branch=master)](https://coveralls.io/r/gevans/expedition?branch=master)
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ ```ruby
24
+ gem 'expedition'
25
+ ```
26
+
27
+ And then execute:
28
+
29
+ $ bundle
30
+
31
+ Or install it yourself as:
32
+
33
+ $ gem install expedition
34
+
35
+ ## Usage
36
+
37
+ TODO: Write usage instructions here
38
+
39
+ ## Contributing
40
+
41
+ 1. Fork it (http://github.com/gevans/expedition/fork)
42
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
43
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
44
+ 4. Push to the branch (`git push origin my-new-feature`)
45
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/expedition ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'expedition'
4
+
5
+ puts JSON.pretty_generate(Expedition.new.send(*ARGV).to_hash)
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'expedition/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'expedition'
8
+ spec.version = Expedition::VERSION
9
+ spec.authors = ['Gabe Evans']
10
+ spec.email = ['gabe@ga.be']
11
+ spec.summary = %q{Expedition is an implementation of the cgminer client protocol. It allows you to write programs that interact with cgminer and cgminer-compatible software.}
12
+ spec.description = spec.summary
13
+ spec.homepage = 'https://github.com/gevans/expedition'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = %w(lib)
20
+
21
+ spec.add_dependency 'multi_json', '~> 1.3'
22
+ spec.add_dependency 'activesupport', '~> 4.0'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.5'
25
+ spec.add_development_dependency 'coveralls'
26
+ spec.add_development_dependency 'guard'
27
+ spec.add_development_dependency 'guard-bundler'
28
+ spec.add_development_dependency 'guard-rspec'
29
+ spec.add_development_dependency 'guard-yard'
30
+ spec.add_development_dependency 'pry'
31
+ spec.add_development_dependency 'rake'
32
+ spec.add_development_dependency 'rb-fsevent'
33
+ spec.add_development_dependency 'rb-inotify'
34
+ spec.add_development_dependency 'rspec'
35
+ spec.add_development_dependency 'terminal-notifier-guard'
36
+ spec.add_development_dependency 'yard'
37
+ end
@@ -0,0 +1,68 @@
1
+ require 'multi_json'
2
+ require 'socket'
3
+
4
+ require 'expedition/response'
5
+
6
+ module Expedition
7
+ class Client
8
+
9
+ ##
10
+ # @return [String]
11
+ # The host this client will execute commands on.
12
+ attr_accessor :host
13
+
14
+ ##
15
+ # @return [Integer]
16
+ # The host port this client will connect to.
17
+ attr_accessor :port
18
+
19
+ ##
20
+ # Initializes a new `Client` for executing commands.
21
+ #
22
+ # @param [String] host
23
+ # The host to connect to.
24
+ #
25
+ # @param [Integer] port
26
+ # The port to connect to.
27
+ def initialize(host = 'localhost', port = 4028)
28
+ @host = host
29
+ @port = port
30
+ end
31
+
32
+ ##
33
+ # Sends the supplied `command` with optionally supplied `parameters` to the
34
+ # service and returns the result, if any.
35
+ #
36
+ # **Note:** Since `Object#send` is overridden, use `Object#__send__` to call
37
+ # an actual method.
38
+ #
39
+ # @param [Symbol, String] command
40
+ # The command to send to the service.
41
+ #
42
+ # @param [Array] parameters
43
+ # Optional parameters to send to the service.
44
+ #
45
+ # @return [Response]
46
+ # The service's response.
47
+ def send(command, *parameters)
48
+ socket = TCPSocket.new(host, port)
49
+ socket.puts command_json(command, *parameters)
50
+
51
+ parse(socket.gets)
52
+ ensure
53
+ socket.close if socket.respond_to?(:close)
54
+ end
55
+
56
+ alias method_missing send
57
+
58
+ private
59
+
60
+ def parse(response)
61
+ Response.parse(MultiJson.load(response.chomp("\x0")))
62
+ end
63
+
64
+ def command_json(command, *parameters)
65
+ MultiJson.dump(command: command, parameter: parameters.join(','))
66
+ end
67
+ end # Client
68
+ end # Expedition
@@ -0,0 +1,56 @@
1
+ require 'expedition/status'
2
+
3
+ module Expedition
4
+ class Response
5
+
6
+ attr_reader :body
7
+
8
+ attr_reader :raw
9
+
10
+ attr_reader :status
11
+
12
+ def self.parse(raw)
13
+ new(normalize(raw), raw)
14
+ end
15
+
16
+ def initialize(normalized, raw)
17
+ @body = normalized
18
+ @raw = raw
19
+ @status = Status.new(normalized[:status])
20
+ end
21
+
22
+ delegate :success?, :informational?, :warning?, :error?, :fatal?,
23
+ :executed_at, to: :status
24
+
25
+ delegate :[], :to_hash, to: :body
26
+
27
+ def respond_to_missing?(method_name, include_private = false)
28
+ body.has_key?(method_name) || super
29
+ end
30
+
31
+ def method_missing(method_name, *arguments, &block)
32
+ if respond_to_missing?(method_name)
33
+ body[method_name]
34
+ else
35
+ super
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def self.normalize(value)
42
+ case value
43
+ when Hash
44
+ Hash[value.collect { |k, v| [normalize_key(k), normalize(v)] }]
45
+ when Array
46
+ value.collect { |v| normalize(v) }
47
+ else
48
+ value
49
+ end
50
+ end
51
+
52
+ def self.normalize_key(key)
53
+ key.gsub(/(\w)%/, '\\1_percent').gsub('%', 'percent').gsub(/\s/, '_').downcase.to_sym
54
+ end
55
+ end # Response
56
+ end # Expedition
@@ -0,0 +1,58 @@
1
+ module Expedition
2
+ class Status
3
+
4
+ SEVERITIES = {
5
+ 'S' => :success,
6
+ 'I' => :info,
7
+ 'W' => :warning,
8
+ 'E' => :error,
9
+ 'F' => :fatal
10
+ }.freeze
11
+
12
+ OK_SEVERITIES = %i(success info warning).freeze
13
+
14
+ attr_reader :severity
15
+
16
+ attr_reader :code
17
+
18
+ attr_reader :message
19
+
20
+ attr_reader :description
21
+
22
+ attr_reader :executed_at
23
+
24
+ def initialize(body)
25
+ status = body.try(:first) || {}
26
+
27
+ @severity = SEVERITIES[status[:status]]
28
+ @code = status[:code]
29
+ @message = status[:msg]
30
+ @description = status[:description]
31
+ @executed_at = Time.at(status[:when]) rescue nil
32
+ end
33
+
34
+ def success?
35
+ severity == :success
36
+ end
37
+
38
+ def info?
39
+ severity == :info
40
+ end
41
+
42
+ def warning?
43
+ severity == :warning
44
+ end
45
+
46
+ def error?
47
+ severity == :error
48
+ end
49
+
50
+ def fatal?
51
+ severity == :fatal
52
+ end
53
+
54
+ def ok?
55
+ OK_SEVERITIES.include?(severity)
56
+ end
57
+ end
58
+ end # Expedition
@@ -0,0 +1,3 @@
1
+ module Expedition
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/expedition.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+
4
+ require 'expedition/client'
5
+ require 'expedition/version'
6
+
7
+ module Expedition
8
+
9
+ ##
10
+ # Initializes a new {Expedition::Client}.
11
+ #
12
+ # @param [String] host
13
+ # The host to connect to.
14
+ #
15
+ # @param [Integer] port
16
+ # The port to connect to.
17
+ #
18
+ # @return [Client]
19
+ # A client for accessing the API of a cgminer-compatible service.
20
+ def self.new(host = 'localhost', port = 4028)
21
+ Client.new(host, port)
22
+ end
23
+
24
+ ##
25
+ # Returns the default client for connection to `localhost` on port `4028`.
26
+ # Used for simple scripts that access the `Expedition` constant directly.
27
+ #
28
+ # @return [Client]
29
+ # The default client.
30
+ def self.client
31
+ @client ||= new
32
+ end
33
+ end # Expedition
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Expedition::Client do
4
+
5
+ describe '#initialize' do
6
+
7
+ subject(:client) do
8
+ described_class.new('example.com', 1234)
9
+ end
10
+
11
+ context 'by default' do
12
+
13
+ subject(:client) do
14
+ described_class.new
15
+ end
16
+
17
+ it 'sets host to "localhost"' do
18
+ expect(client.host).to eq('localhost')
19
+ end
20
+
21
+ it 'sets port to 4028' do
22
+ expect(client.port).to eq(4028)
23
+ end
24
+ end
25
+
26
+ it 'initializes with supplied host and port' do
27
+ expect(client.host).to eq('example.com')
28
+ expect(client.port).to eq(1234)
29
+ end
30
+ end
31
+
32
+ %i(send method_missing).each do |method_name|
33
+
34
+ describe "##{method_name}" do
35
+
36
+ subject(:client) do
37
+ described_class.new
38
+ end
39
+
40
+ let(:socket) do
41
+ double(TCPSocket)
42
+ end
43
+
44
+ before do
45
+ allow(TCPSocket).to receive(:new).with(client.host, client.port).and_return(socket)
46
+ end
47
+
48
+ it 'sends supplied command and parameters to configured host and port' do
49
+ expect(socket).to receive(:puts).with('{"command":"foo","parameter":"bar,baz"}')
50
+ expect(socket).to receive(:gets).and_return(%/{}\x0/)
51
+ client.__send__(method_name, 'foo', 'bar', 'baz')
52
+ end
53
+
54
+ it 'returns Expedition::Response with parsed body' do
55
+ expect(socket).to receive(:puts).with('{"command":"foo","parameter":"bar,baz"}')
56
+ expect(socket).to receive(:gets).and_return(%/{"what a":["body"]}\x0/)
57
+ result = client.__send__(method_name, 'foo', 'bar', 'baz')
58
+ expect(result.body).to eq(
59
+ what_a: ['body']
60
+ )
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,314 @@
1
+ require 'spec_helper'
2
+
3
+ describe Expedition::Response do
4
+
5
+ let(:original_data) do
6
+ {
7
+ 'STATUS' => [
8
+ {
9
+ 'STATUS' => 'S',
10
+ 'When' => 1394855182,
11
+ 'Code' => 17,
12
+ 'Msg' => 'GPU0',
13
+ 'Description' => 'sgminer 4.1.0'
14
+ }
15
+ ],
16
+ 'GPU' => [
17
+ {
18
+ 'GPU' => 0,
19
+ 'Enabled' => 'Y',
20
+ 'Status' => 'Alive',
21
+ 'Temperature' => 72.0,
22
+ 'Fan Speed' => -1,
23
+ 'Fan Percent' => 100,
24
+ 'GPU Clock' => 947,
25
+ 'Memory Clock' => 1500,
26
+ 'GPU Voltage' => 0.0,
27
+ 'GPU Activity' => 100,
28
+ 'Powertune' => 30,
29
+ 'MHS av' => 0.9245,
30
+ 'MHS 5s' => 0.9228,
31
+ 'KHS av' => 924,
32
+ 'KHS 5s' => 923,
33
+ 'Accepted' => 1627,
34
+ 'Rejected' => 7,
35
+ 'Hardware Errors' => 3359,
36
+ 'Utility' => 0.5465,
37
+ 'Intensity' => '20',
38
+ 'Last Share Pool' => 0,
39
+ 'Last Share Time' => 1394735379,
40
+ 'Total MH' => 165125.5542,
41
+ 'Diff1 Work' => 836803,
42
+ 'Difficulty Accepted' => 833024.0,
43
+ 'Difficulty Rejected' => 3584.0,
44
+ 'Last Share Difficulty' => 512.0,
45
+ 'Last Valid Work' => 1394735379,
46
+ 'Device Hardware%' => 0.3998,
47
+ 'Device Rejected%' => 0.4283,
48
+ 'Device Elapsed' => 178612
49
+ }
50
+ ],
51
+ 'id' => 1
52
+ }
53
+ end
54
+
55
+ let(:normalized_data) do
56
+ {
57
+ status: [
58
+ {
59
+ status: 'S',
60
+ when: 1394855182,
61
+ code: 17,
62
+ msg: 'GPU0',
63
+ description: 'sgminer 4.1.0'
64
+ }
65
+ ],
66
+ gpu: [
67
+ {
68
+ gpu: 0,
69
+ enabled: 'Y',
70
+ status: 'Alive',
71
+ temperature: 72.0,
72
+ fan_speed: -1,
73
+ fan_percent: 100,
74
+ gpu_clock: 947,
75
+ memory_clock: 1500,
76
+ gpu_voltage: 0.0,
77
+ gpu_activity: 100,
78
+ powertune: 30,
79
+ mhs_av: 0.9245,
80
+ mhs_5s: 0.9228,
81
+ khs_av: 924,
82
+ khs_5s: 923,
83
+ accepted: 1627,
84
+ rejected: 7,
85
+ hardware_errors: 3359,
86
+ utility: 0.5465,
87
+ intensity: '20',
88
+ last_share_pool: 0,
89
+ last_share_time: 1394735379,
90
+ total_mh: 165125.5542,
91
+ diff1_work: 836803,
92
+ difficulty_accepted: 833024.0,
93
+ difficulty_rejected: 3584.0,
94
+ last_share_difficulty: 512.0,
95
+ last_valid_work: 1394735379,
96
+ device_hardware_percent: 0.3998,
97
+ device_rejected_percent: 0.4283,
98
+ device_elapsed: 178612
99
+ }
100
+ ],
101
+ id: 1
102
+ }
103
+ end
104
+
105
+ let(:response) do
106
+ described_class.parse(original_data)
107
+ end
108
+
109
+ describe '.parse' do
110
+
111
+ subject { response }
112
+
113
+ it 'returns Expedition::Response' do
114
+ expect(response).to be_an(Expedition::Response)
115
+ end
116
+
117
+ it 'initializes with normalized and original data' do
118
+ expect(Expedition::Response).to receive(:new).with(normalized_data, original_data)
119
+ response
120
+ end
121
+
122
+ it 'retains original hash' do
123
+ expect(response.raw).to eq(original_data)
124
+ end
125
+ end
126
+
127
+ describe '#status' do
128
+
129
+ subject(:status) do
130
+ response.status
131
+ end
132
+
133
+ it 'returns Expedition::Status' do
134
+ expect(status).to be_an(Expedition::Status)
135
+ end
136
+
137
+ context 'when success' do
138
+
139
+ before do
140
+ original_data['STATUS'].first['STATUS'] = 'S'
141
+ end
142
+
143
+ it 'is success' do
144
+ expect(status).to be_success
145
+
146
+ expect(status).not_to be_info
147
+ expect(status).not_to be_warning
148
+ expect(status).not_to be_info
149
+ expect(status).not_to be_info
150
+ expect(status).not_to be_info
151
+ end
152
+
153
+ it 'is okay' do
154
+ expect(status).to be_ok
155
+ end
156
+ end
157
+
158
+ context 'when info' do
159
+
160
+ before do
161
+ original_data['STATUS'].first['STATUS'] = 'I'
162
+ end
163
+
164
+ it 'is info' do
165
+ expect(status).to be_info
166
+
167
+ expect(status).not_to be_success
168
+ expect(status).not_to be_warning
169
+ expect(status).not_to be_error
170
+ expect(status).not_to be_fatal
171
+ end
172
+
173
+ it 'is okay' do
174
+ expect(status).to be_ok
175
+ end
176
+ end
177
+
178
+ context 'when warning' do
179
+
180
+ before do
181
+ original_data['STATUS'].first['STATUS'] = 'W'
182
+ end
183
+
184
+ it 'is warning' do
185
+ expect(status).to be_warning
186
+
187
+ expect(status).not_to be_success
188
+ expect(status).not_to be_info
189
+ expect(status).not_to be_error
190
+ expect(status).not_to be_fatal
191
+ end
192
+
193
+ it 'is okay' do
194
+ expect(status).to be_ok
195
+ end
196
+ end
197
+
198
+ context 'when error' do
199
+
200
+ before do
201
+ original_data['STATUS'].first['STATUS'] = 'E'
202
+ end
203
+
204
+ it 'is error' do
205
+ expect(status).to be_error
206
+
207
+ expect(status).not_to be_success
208
+ expect(status).not_to be_info
209
+ expect(status).not_to be_warning
210
+ expect(status).not_to be_fatal
211
+ end
212
+
213
+ it 'is not okay' do
214
+ expect(status).not_to be_ok
215
+ end
216
+ end
217
+
218
+ context 'when fatal' do
219
+
220
+ before do
221
+ original_data['STATUS'].first['STATUS'] = 'F'
222
+ end
223
+
224
+ it 'is fatal' do
225
+ expect(status).to be_fatal
226
+
227
+ expect(status).not_to be_success
228
+ expect(status).not_to be_info
229
+ expect(status).not_to be_warning
230
+ expect(status).not_to be_error
231
+ end
232
+
233
+ it 'is not okay' do
234
+ expect(status).not_to be_ok
235
+ end
236
+ end
237
+ end
238
+
239
+ %i(success? informational? warning? error? fatal? executed_at).each do |method_name|
240
+
241
+ describe "##{method_name}" do
242
+
243
+ it 'delegates to #status' do
244
+ expect(response.status).to receive(method_name)
245
+ response.send(method_name)
246
+ end
247
+ end
248
+ end
249
+
250
+ %i([] to_hash).each do |method_name|
251
+
252
+ describe "##{method_name}" do
253
+
254
+ it 'delegates to #body' do
255
+ expect(response.body).to receive(method_name)
256
+ response.send(method_name)
257
+ end
258
+ end
259
+ end
260
+
261
+ describe '#respond_to_missing?' do
262
+
263
+ let(:response) do
264
+ described_class.new(body, {})
265
+ end
266
+
267
+ context 'when #body has key' do
268
+
269
+ let(:body) do
270
+ {
271
+ foo: 'blah'
272
+ }
273
+ end
274
+
275
+ it 'returns true' do
276
+ expect(response).to respond_to(:foo)
277
+ end
278
+ end
279
+
280
+ context 'when #body does not have key' do
281
+
282
+ let(:body) do
283
+ {}
284
+ end
285
+
286
+ it 'returns false' do
287
+ expect(response).not_to respond_to(:foo)
288
+ end
289
+ end
290
+ end
291
+
292
+ describe '#method_missing' do
293
+
294
+ context 'when key in #body' do
295
+
296
+ before do
297
+ allow(response).to receive(:body).and_return(something: 'stuff')
298
+ end
299
+
300
+ it 'returns value' do
301
+ expect(response.something).to eq('stuff')
302
+ end
303
+ end
304
+
305
+ context 'when not key in #body' do
306
+
307
+ it 'raises NoMethodError' do
308
+ expect {
309
+ response.bananas
310
+ }.to raise_error(NoMethodError)
311
+ end
312
+ end
313
+ end
314
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Expedition do
4
+
5
+ describe '.new' do
6
+
7
+ subject(:client) do
8
+ described_class.new('example.com', 12345)
9
+ end
10
+
11
+ let!(:mock_client) do
12
+ double(Expedition::Client)
13
+ end
14
+
15
+ it 'returns new Expedition::Client with supplied host and port' do
16
+ expect(Expedition::Client).to receive(:new).with('example.com', 12345).and_return(mock_client)
17
+ expect(client).to eq(mock_client)
18
+ end
19
+ end
20
+
21
+ describe '.client' do
22
+
23
+ subject(:client) do
24
+ Expedition.client
25
+ end
26
+
27
+ it 'returns an Expedition::Client' do
28
+ expect(client).to be_an(Expedition::Client)
29
+ end
30
+
31
+ it 'returns the same instance' do
32
+ expect(client.object_id).to eq(described_class.client.object_id)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ]
8
+ SimpleCov.start
9
+
10
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
11
+ require 'expedition'
12
+
13
+ RSpec.configure do |config|
14
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
15
+ config.filter_run focus: true unless ENV['CI']
16
+ config.order = 'random'
17
+ config.run_all_when_everything_filtered = true
18
+ config.treat_symbols_as_metadata_keys_with_true_values = true
19
+ end
20
+
21
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
metadata ADDED
@@ -0,0 +1,284 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: expedition
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gabe Evans
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: multi_json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: coveralls
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: guard-yard
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rake
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rb-fsevent
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rb-inotify
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rspec
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: terminal-notifier-guard
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: yard
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ description: Expedition is an implementation of the cgminer client protocol. It allows
224
+ you to write programs that interact with cgminer and cgminer-compatible software.
225
+ email:
226
+ - gabe@ga.be
227
+ executables:
228
+ - expedition
229
+ extensions: []
230
+ extra_rdoc_files: []
231
+ files:
232
+ - ".coveralls.yml"
233
+ - ".gitignore"
234
+ - ".pryrc"
235
+ - ".rspec"
236
+ - ".travis.yml"
237
+ - ".yardopts"
238
+ - Gemfile
239
+ - Guardfile
240
+ - MIT-LICENSE.txt
241
+ - README.md
242
+ - Rakefile
243
+ - bin/expedition
244
+ - expedition.gemspec
245
+ - lib/expedition.rb
246
+ - lib/expedition/client.rb
247
+ - lib/expedition/response.rb
248
+ - lib/expedition/status.rb
249
+ - lib/expedition/version.rb
250
+ - spec/expedition/client_spec.rb
251
+ - spec/expedition/response_spec.rb
252
+ - spec/expedition_spec.rb
253
+ - spec/spec_helper.rb
254
+ homepage: https://github.com/gevans/expedition
255
+ licenses:
256
+ - MIT
257
+ metadata: {}
258
+ post_install_message:
259
+ rdoc_options: []
260
+ require_paths:
261
+ - lib
262
+ required_ruby_version: !ruby/object:Gem::Requirement
263
+ requirements:
264
+ - - ">="
265
+ - !ruby/object:Gem::Version
266
+ version: '0'
267
+ required_rubygems_version: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - ">="
270
+ - !ruby/object:Gem::Version
271
+ version: '0'
272
+ requirements: []
273
+ rubyforge_project:
274
+ rubygems_version: 2.2.2
275
+ signing_key:
276
+ specification_version: 4
277
+ summary: Expedition is an implementation of the cgminer client protocol. It allows
278
+ you to write programs that interact with cgminer and cgminer-compatible software.
279
+ test_files:
280
+ - spec/expedition/client_spec.rb
281
+ - spec/expedition/response_spec.rb
282
+ - spec/expedition_spec.rb
283
+ - spec/spec_helper.rb
284
+ has_rdoc: