specter 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.
@@ -0,0 +1,18 @@
1
+ {
2
+ "STATUS": [
3
+ {
4
+ "STATUS": "S",
5
+ "When": 1397042303,
6
+ "Code": 22,
7
+ "Msg": "SGMiner versions",
8
+ "Description": "specter 0.1.0"
9
+ }
10
+ ],
11
+ "VERSION": [
12
+ {
13
+ "SGMiner": "4.1.0",
14
+ "API": "1.32"
15
+ }
16
+ ],
17
+ "id": 1
18
+ }
@@ -0,0 +1,22 @@
1
+ require 'middleware'
2
+
3
+ require 'specter/middleware/base'
4
+ require 'specter/middleware/fixture'
5
+ require 'specter/middleware/missing'
6
+ require 'specter/middleware/proxy'
7
+
8
+ module Specter
9
+ module Middleware
10
+
11
+ def self.new(server)
12
+ ::Middleware::Builder.new do
13
+ use Fixture, server
14
+ use Proxy, server if server.options[:proxy]
15
+
16
+ yield if block_given?
17
+
18
+ use Missing, server
19
+ end
20
+ end
21
+ end # Middleware
22
+ end # Specter
@@ -0,0 +1,14 @@
1
+ module Specter
2
+ module Middleware
3
+ class Base
4
+ extend Forwardable
5
+
6
+ def initialize(app, server)
7
+ @app = app
8
+ @server = server
9
+ end
10
+
11
+ def_delegators :@server, :logger, :options
12
+ end # Base
13
+ end # Middleware
14
+ end # Specter
@@ -0,0 +1,32 @@
1
+ require 'pathname'
2
+
3
+ module Specter
4
+ module Middleware
5
+ class Fixture < Base
6
+
7
+ ROOT = Pathname.new(File.expand_path('../../fixtures', __FILE__))
8
+
9
+ def call(env)
10
+ data = load_fixture(env)
11
+
12
+ if data
13
+ env.merge!(data)
14
+ else
15
+ @app.call(env)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def load_fixture(env)
22
+ fixture = ROOT.join("#{env.command}.json")
23
+ return unless fixture.exist?
24
+ logger.debug "loading fixture for #{env.command.inspect}"
25
+ JSON.load(File.read(fixture))
26
+ rescue JSON::ParserError
27
+ logger.debug "failed to parse fixture for #{env.command.inspect}"
28
+ nil
29
+ end
30
+ end # Fixture
31
+ end # Middleware
32
+ end # Specter
@@ -0,0 +1,25 @@
1
+ module Specter
2
+ module Middleware
3
+ class Missing < Base
4
+
5
+ def call(env)
6
+ @app.call(env)
7
+
8
+ if env.empty?
9
+ env.merge!(
10
+ 'STATUS' => [
11
+ {
12
+ 'STATUS' => 'E',
13
+ 'When' => Time.now.to_i,
14
+ 'Code' => 14,
15
+ 'Msg' => 'Invalid command',
16
+ 'Description' => "specter #{VERSION}"
17
+ }
18
+ ],
19
+ 'id' => 1
20
+ )
21
+ end
22
+ end
23
+ end # Missing
24
+ end # Middleware
25
+ end # Specter
@@ -0,0 +1,25 @@
1
+ require 'expedition'
2
+
3
+ module Specter
4
+ module Middleware
5
+ class Proxy < Base
6
+
7
+ def initialize(app, server)
8
+ super
9
+ @miner = Expedition::Client.new(*options[:proxy])
10
+ end
11
+
12
+ def call(env)
13
+ env.merge!(proxy_command(env))
14
+ @app.call(env)
15
+ end
16
+
17
+ private
18
+
19
+ def proxy_command(env)
20
+ logger.debug "proxying #{env.command}, #{env.args.inspect}"
21
+ @miner.send(env.command, *env.args).raw
22
+ end
23
+ end # Proxy
24
+ end # Middleware
25
+ end # Specter
@@ -0,0 +1,40 @@
1
+ require 'json'
2
+
3
+ module Specter
4
+ class Request
5
+
6
+ def self.parse(raw)
7
+ begin
8
+ message = JSON.parse(raw)
9
+ rescue JSON::ParserError
10
+ raise RequestError, $!
11
+ end
12
+
13
+ command = message['command']
14
+ args = message['parameter'].to_s.split(',')
15
+
16
+ new(command, args)
17
+ end
18
+
19
+ attr_reader :command
20
+
21
+ attr_reader :args
22
+
23
+ def initialize(command, args)
24
+ if command.nil? || command.empty?
25
+ raise RequestError, 'command not supplied'
26
+ end
27
+
28
+ @command = command.to_sym
29
+ @args = args
30
+ end
31
+
32
+ def execute(client)
33
+ client.send(command, *args)
34
+ end
35
+
36
+ def inspect
37
+ "#<#{self.class} command:#{command}, args:#{args.inspect}>"
38
+ end
39
+ end # Request
40
+ end # Specer
@@ -0,0 +1,77 @@
1
+ require 'socket'
2
+ require 'logger'
3
+
4
+ require 'specter/middleware'
5
+ require 'specter/request'
6
+ require 'specter/env'
7
+
8
+ module Specter
9
+ class Server
10
+
11
+ attr_reader :cli
12
+
13
+ attr_reader :options
14
+
15
+ attr_reader :logger
16
+
17
+ attr_reader :socket
18
+
19
+ attr_reader :stack
20
+
21
+ def initialize(cli)
22
+ @cli = cli
23
+ @options = cli.options
24
+
25
+ @logger = Logger.new(STDOUT)
26
+ @socket = TCPServer.new(options[:host], options[:port])
27
+ @stack = Middleware.new(self)
28
+ end
29
+
30
+ def run
31
+ BasicSocket.do_not_reverse_lookup = true
32
+ return @thread = Thread.new { handle_requests }
33
+ end
34
+
35
+ def handle_requests
36
+ loop do
37
+ client = socket.accept
38
+ process_request(client)
39
+ end
40
+ end
41
+
42
+ def process_request(client)
43
+ Timeout.timeout(5) do
44
+ req = Request.parse(client.gets)
45
+ env = Env.new(client, req)
46
+ log_request(env)
47
+ @stack.call(env)
48
+ client.write env.to_str
49
+ end
50
+ rescue Timeout::Error
51
+ log_timeout(client)
52
+ rescue Object => e
53
+ log_error(client, e)
54
+ ensure
55
+ client.close rescue nil
56
+ end
57
+
58
+ def log_timeout(client)
59
+ logger.warn "%s - timeout" % [
60
+ client.remote_address.ip_address
61
+ ]
62
+ end
63
+
64
+ def log_error(client, e)
65
+ logger.error "%s - %s: %s\n%s" % [
66
+ client.remote_address.ip_address, e.class, e.message,
67
+ e.backtrace.join("\n")
68
+ ]
69
+ end
70
+
71
+ def log_request(env)
72
+ logger.info "%s - %s - %s" % [
73
+ env.client.remote_address.ip_address, env.request.command, env.request.args.inspect
74
+ ]
75
+ end
76
+ end # Server
77
+ end # Specter
@@ -0,0 +1,3 @@
1
+ module Specter
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'specter/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'specter'
8
+ spec.version = Specter::VERSION
9
+ spec.authors = ['Gabe Evans']
10
+ spec.email = ['gabe@ga.be']
11
+ spec.summary = %q{Specter stubs a subset of the cgminer client protocol. It allows you to test your programs against a dummy server when writing programs that interact with cgminer and cgminer-compatibile software.}
12
+ spec.description = spec.summary
13
+ spec.homepage = 'https://github.com/gevans/specter'
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 'expedition'
22
+ spec.add_dependency 'middleware'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.5'
25
+ spec.add_development_dependency 'rake'
26
+ spec.add_development_dependency 'rspec'
27
+ spec.add_development_dependency 'pry'
28
+ end
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: specter
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-04-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: expedition
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '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: rake
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: rspec
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: pry
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
+ description: Specter stubs a subset of the cgminer client protocol. It allows you
98
+ to test your programs against a dummy server when writing programs that interact
99
+ with cgminer and cgminer-compatibile software.
100
+ email:
101
+ - gabe@ga.be
102
+ executables:
103
+ - specter
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - ".gitignore"
108
+ - ".rspec"
109
+ - ".travis.yml"
110
+ - CHANGELOG.md
111
+ - Gemfile
112
+ - LICENSE.txt
113
+ - README.md
114
+ - Rakefile
115
+ - bin/specter
116
+ - lib/specter.rb
117
+ - lib/specter/cli.rb
118
+ - lib/specter/env.rb
119
+ - lib/specter/fixtures/coin.json
120
+ - lib/specter/fixtures/config.json
121
+ - lib/specter/fixtures/devdetails.json
122
+ - lib/specter/fixtures/devs.json
123
+ - lib/specter/fixtures/gpu.json
124
+ - lib/specter/fixtures/gpucount.json
125
+ - lib/specter/fixtures/notify.json
126
+ - lib/specter/fixtures/pools.json
127
+ - lib/specter/fixtures/stats.json
128
+ - lib/specter/fixtures/summary.json
129
+ - lib/specter/fixtures/version.json
130
+ - lib/specter/middleware.rb
131
+ - lib/specter/middleware/base.rb
132
+ - lib/specter/middleware/fixture.rb
133
+ - lib/specter/middleware/missing.rb
134
+ - lib/specter/middleware/proxy.rb
135
+ - lib/specter/request.rb
136
+ - lib/specter/server.rb
137
+ - lib/specter/version.rb
138
+ - specter.gemspec
139
+ homepage: https://github.com/gevans/specter
140
+ licenses:
141
+ - MIT
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.2.2
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: Specter stubs a subset of the cgminer client protocol. It allows you to test
163
+ your programs against a dummy server when writing programs that interact with cgminer
164
+ and cgminer-compatibile software.
165
+ test_files: []