socket-harness 0.0.1

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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6698d5896ed656d1c8795d508072133ba69cd479
4
+ data.tar.gz: 2acecd223f73a33c45f9a470eccd1bbd9d6d7f70
5
+ SHA512:
6
+ metadata.gz: fa1eb4a12bafe6d65cb47c65c0f58d3c74805f90813a5210a4c7790413fa198b7dd6708a19dc91c7242223c23405a450226bf1efe5e61a668abcf31e5e48cceb
7
+ data.tar.gz: d952429a1048a4bb9d6dcb78ddfbdb1d6618989c4b4aab95bc81ca6e2515cc0ae6b51135616ca0a3b0a5e816422bb1b77021085434e0eba71ed4e7755fb929b3
@@ -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/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in socket_harness.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 wpc
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.
@@ -0,0 +1,39 @@
1
+ # SocketHarness
2
+
3
+ SocketHarness is a test utilities that helps implement Test Harness pattern from the book "Release it!". It seats between application and integration server to simulate odd network/server behaviors.
4
+
5
+ Current Feature:
6
+ * delay: help for simulating slow network or server to test timeout failure mode.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'socket_harness'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install socket_harness
21
+
22
+ ## Usage
23
+
24
+ ```
25
+ Usage: bin/socket_harness [options] remotehost remoteport
26
+ -p, --port PORT local port to bind
27
+ -b, --bind ADDRESS local address to bind
28
+ --block-size NUMBER chunck out large data reads. by default 1024 byte
29
+ -d, --delay NUMBER delay for client response: 12 will deplay 12ms for package sending back to the client.
30
+ ```
31
+
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it ( http://github.com/<my-github-username>/socket_harness/fork )
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ git_path = File.join(File.expand_path('../..', __FILE__), '.git')
4
+
5
+ if File.exists?(git_path)
6
+ lib_path = File.expand_path('../../lib', __FILE__)
7
+ $:.unshift(lib_path)
8
+ end
9
+
10
+ require 'socket_harness'
11
+ SocketHarness.cli
@@ -0,0 +1,42 @@
1
+ require "socket_harness/version"
2
+ require "socket_harness/proxy"
3
+ require 'socket'
4
+ require 'optparse'
5
+
6
+ module SocketHarness
7
+
8
+ def self.cli
9
+ options = {}
10
+ parser = OptionParser.new do |opts|
11
+ opts.banner = "Usage: #{$0} [options] remotehost remoteport"
12
+ opts.version = SocketHarness::VERSION
13
+
14
+ opts.on("-p", "--port PORT", "local port to bind") do |v|
15
+ options[:local_port] = v
16
+ end
17
+
18
+ opts.on("-b", "--bind ADDRESS", "local address to bind") do |v|
19
+ options[:local_host] = v
20
+ end
21
+
22
+ opts.on("--block-size NUMBER", "chunck out large data reads. by default 1024 byte") do |v|
23
+ options[:local_host] = v
24
+ end
25
+
26
+
27
+ opts.on("-d", "--delay NUMBER", "delay for client response: 12 will deplay 12ms for package sending back to the client.") do |v|
28
+ options[:delay] = v
29
+ end
30
+ end
31
+ parser.parse!
32
+ remote_host = ARGV.shift
33
+ remote_port = ARGV.shift
34
+
35
+ if remote_host.to_s.empty? || remote_port.to_s.empty?
36
+ puts parser
37
+ exit 1
38
+ end
39
+
40
+ Proxy.new(remote_host, remote_port, options).run
41
+ end
42
+ end
@@ -0,0 +1,87 @@
1
+ module SocketHarness
2
+ class Proxy
3
+ BLOCK_SIZE = 1024
4
+
5
+ def self.default_options
6
+ {
7
+ :local_port => 13012,
8
+ :block_size => 1024,
9
+ :delay => 0,
10
+ }
11
+ end
12
+
13
+ def initialize(remote_host, remote_port, options={})
14
+ @remote_host = remote_host
15
+ @remote_port = remote_port
16
+ @options = self.class.default_options.merge(options)
17
+ end
18
+
19
+ def run
20
+ puts "*** target #{@remote_host}:#{@remote_port}"
21
+ server = TCPServer.open(@options[:local_host], @options[:local_port].to_i)
22
+
23
+ port = server.addr[1]
24
+ addrs = server.addr[2..-1].uniq
25
+
26
+ puts "*** listening on #{addrs.collect{|a|"#{a}:#{port}"}.join(' ')}"
27
+
28
+ # abort on exceptions, otherwise threads will be silently killed in case
29
+ # of unhandled exceptions
30
+ Thread.abort_on_exception = true
31
+
32
+ # have a thread just to process Ctrl-C events on Windows
33
+ # (although Ctrl-Break always works)
34
+ Thread.new { loop { sleep 1 } }
35
+ loop do
36
+ # whenever server.accept returns a new connection, start
37
+ # a handler thread for that connection
38
+ Thread.start(server.accept) { |local| conn_thread(local) }
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def conn_thread(local)
45
+ port, name = local.peeraddr[1..2]
46
+ puts "*** receiving from #{name}:#{port}"
47
+
48
+ # open connection to remote server
49
+ remote = TCPSocket.new(@remote_host, @remote_port)
50
+
51
+ # start reading from both ends
52
+ loop do
53
+ ready = select([local, remote], nil, nil)
54
+ if ready[0].include? local
55
+ # local -> remote
56
+ data = local.recv(@options[:block_size])
57
+ if data.empty?
58
+ puts "local end closed connection"
59
+ break
60
+ end
61
+ puts "#{name}:#{port} -{}-> #{@remote_host}:#{@remote_port} #{data.size} byte ..."
62
+ remote.write(data)
63
+ end
64
+ if ready[0].include? remote
65
+ # remote -&gt; local
66
+ data = remote.recv(@options[:block_size])
67
+ if data.empty?
68
+ puts "remote end closed connection"
69
+ break
70
+ end
71
+ puts "#{@remote_host}:#{@remote_port} -{#{delay}ms}-> #{name}:#{port} #{data.size} byte ..."
72
+ sleep delay * 1.0 / 1000.0
73
+ local.write(data)
74
+ end
75
+ end
76
+
77
+ local.close
78
+ remote.close
79
+
80
+ puts "*** done with #{name}:#{port}"
81
+ end
82
+
83
+ def delay
84
+ @options[:delay].to_i
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module SocketHarness
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'socket_harness/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "socket-harness"
8
+ spec.version = SocketHarness::VERSION
9
+ spec.authors = ["wpc"]
10
+ spec.email = ["alex.hal9000@gmail.com"]
11
+ spec.summary = %q{Proxy for socket test harness.}
12
+ spec.description = %q{SocketHarness is a test utilities that helps implement Test Harness pattern from the book "Release it!". It seats between application and integration server to simulate odd network/application behaviors, e.g. slow network.}
13
+ spec.homepage = "https://github.com/wpc/socket-harness"
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 = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: socket-harness
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - wpc
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: SocketHarness is a test utilities that helps implement Test Harness pattern
42
+ from the book "Release it!". It seats between application and integration server
43
+ to simulate odd network/application behaviors, e.g. slow network.
44
+ email:
45
+ - alex.hal9000@gmail.com
46
+ executables:
47
+ - socket_harness
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - .gitignore
52
+ - Gemfile
53
+ - LICENSE.txt
54
+ - README.md
55
+ - Rakefile
56
+ - bin/socket_harness
57
+ - lib/socket_harness.rb
58
+ - lib/socket_harness/proxy.rb
59
+ - lib/socket_harness/version.rb
60
+ - socket_harness.gemspec
61
+ homepage: https://github.com/wpc/socket-harness
62
+ licenses:
63
+ - MIT
64
+ metadata: {}
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 2.2.0
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: Proxy for socket test harness.
85
+ test_files: []