expedition 0.1.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.
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: