chain-reactor 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 1.9.2
5
+ - jruby-18mode
6
+ - jruby-19mode
7
+ - rbx-18mode
8
+ - rbx-19mode
9
+ - ruby-head
10
+ - jruby-head
11
+ - 1.8.7
12
+ - ree
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,10 @@
1
+ == 0.2.1
2
+
3
+ * bug fixes
4
+ * Refactored tests to work with JRuby, Rubinius and Ruby MRI 1.8.7
5
+ * Removed sys-proctable gem to use system's `ps` instead (tests only)
6
+
7
+ == 0.2.0
8
+
9
+ * important changes
10
+ * First release as a gem
data/Gemfile CHANGED
@@ -1,15 +1,17 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in chain-reactor.gemspec
4
3
  gemspec
5
4
 
6
- gem 'json'
7
- gem 'mocha'
8
- gem 'dante'
9
- gem 'log4r'
5
+ gem 'rake', '~> 0.8.7'
6
+ gem 'main', '~> 5.1.1'
7
+ gem 'json', '~> 1.7.5'
8
+ gem 'dante', '~> 0.1.5'
9
+ gem 'log4r', '~> 1.1.10'
10
+ gem 'rdoc', '~> 3.12'
10
11
 
11
- gem 'xml-simple', :require => false
12
+ gem 'xml-simple', '~> 1.1.2', :require => false
12
13
 
13
14
  group :test do
14
- gem 'sys-proctable'
15
+ gem 'test-unit', '~> 2.5.3'
16
+ gem 'mocha', '~> 0.13.1'
15
17
  end
data/README.rdoc CHANGED
@@ -1,5 +1,8 @@
1
1
  = Chain Reactor
2
2
 
3
+ {<img src="https://travis-ci.org/joonty/chain-reactor.png?branch=master" alt="Build Status" />}[https://travis-ci.org/joonty/chain-reactor]
4
+ {<img src="https://codeclimate.com/badge.png" />}[https://codeclimate.com/github/joonty/chain-reactor]
5
+
3
6
  Chain Reactor is a simple server that waits for incoming connections, then kicks off some code when one is made. Clients are locked down by IP address, so you will only recieve connections from known clients. Also, data can be passed via JSON, XML, or anything you like.
4
7
 
5
8
  The "reactions" are written in ruby code, like this:
@@ -31,7 +34,9 @@ This can be installed through ruby gems:
31
34
 
32
35
  == Usage
33
36
 
34
- A chain file is required to run, as this specifies which clients to accept and what to do. Fortunately, it's easy to create a template:
37
+ Chain reactor comes with two command line tools, <tt>chain-reactor</tt> (the server) and <tt>chain-reactor-client</tt> (I think you can guess).
38
+
39
+ A chain file is required to run the server, as this specifies which clients to accept and what to do. Fortunately, it's easy to create a template:
35
40
 
36
41
  $ chain-reactor template > Chainfile.rb
37
42
 
@@ -45,6 +50,8 @@ The --ontop option stops it from running as a daemon, making it easier to see wh
45
50
 
46
51
  Follow the instructions by adding key/value pair data to send to the server, then watch it react!
47
52
 
53
+ For more information on configuration, take a look at the wiki.
54
+
48
55
  == Contributing
49
56
 
50
57
  1. Fork it
@@ -20,6 +20,11 @@ module ChainReactor
20
20
  #
21
21
  # Uses dante as the daemonizer.
22
22
  def start
23
+ if not @config.on_top? and RUBY_PLATFORM == 'java'
24
+ @log.warn { "fork() is not implemented in JRuby, chain-reactor will run on top instead of daemonizing" }
25
+ @config.on_top = true
26
+ end
27
+
23
28
  # Change output format for logging to file if daemonizing
24
29
  unless @config.on_top?
25
30
  @log.outputters.first.formatter = ChainReactor::PatternFormatter.new(:pattern => "[%l] %d :: %m")
@@ -24,7 +24,7 @@ module ChainReactor
24
24
  attr_accessor :options
25
25
 
26
26
  # Create a new reaction, with the options and code block to run.
27
- def initialize(options = {},block,logger)
27
+ def initialize(options,block,logger)
28
28
  @options = { :parser => :json, :required_keys => [], :keys_to_sym => true }.merge(options)
29
29
  @block = block
30
30
  @log = logger
@@ -1,5 +1,5 @@
1
1
  # The ChainReactor module encapsulates all classes in the gem.
2
2
  module ChainReactor
3
3
  # Current gem version.
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.1"
5
5
  end
data/test/helpers.rb CHANGED
@@ -14,6 +14,12 @@ module ChainReactor
14
14
  end
15
15
  end
16
16
 
17
+ # KeyError doesn't exist in ruby 1.8
18
+ if !defined? ::KeyError
19
+ class ::KeyError < ::IndexError
20
+ end
21
+ end
22
+
17
23
  class Params
18
24
  def initialize(hash_data)
19
25
  @hash = hash_data
@@ -26,7 +32,7 @@ module ChainReactor
26
32
  def fetch(key,&block)
27
33
  begin
28
34
  @hash.fetch(key,&block)
29
- rescue KeyError => e
35
+ rescue ::KeyError,::IndexError => e
30
36
  raise ::Main::Parameter::NoneSuch, key
31
37
  end
32
38
  end
@@ -10,12 +10,18 @@ class TestChainReactorOptions < Test::Unit::TestCase
10
10
  Open3.popen3("#{bin_path} #{arg_string}")
11
11
  end
12
12
 
13
+ # Thread can be nil, if ruby 1.8 is used
14
+ def assert_exit_status(thread,expected_status)
15
+ unless thread.nil?
16
+ assert_equal expected_status, thread.value.exitstatus
17
+ end
18
+ end
19
+
13
20
  def test_help_returns_help_in_stdout
14
21
  out = exec_with('--help')
15
22
  help = out[1].read
16
- status = out[3].value
17
23
 
18
- assert_equal 1, status.exitstatus
24
+ assert_exit_status(out[3],1)
19
25
  assert_match(/NAME\s*chain\-reactor/, help)
20
26
  assert_match(/SYNOPSIS\s*chain\-reactor \(start|stop|template\) chainfile\.rb/, help)
21
27
  end
@@ -23,9 +29,8 @@ class TestChainReactorOptions < Test::Unit::TestCase
23
29
  def test_no_args_returns_help_in_stdout_and_fails
24
30
  out = exec_with('')
25
31
  help = out[1].read
26
- status = out[3].value
27
32
 
28
- assert_equal 1, status.exitstatus
33
+ assert_exit_status(out[3],1)
29
34
  assert_match(/NAME\s*chain\-reactor/, help)
30
35
  assert_match(/SYNOPSIS\s*chain\-reactor \(start|stop|template\) chainfile\.rb/, help)
31
36
  end
@@ -33,9 +38,8 @@ class TestChainReactorOptions < Test::Unit::TestCase
33
38
  def test_invalid_mode_returns_help_and_fails
34
39
  out = exec_with('ssaduhdui')
35
40
  help = out[1].read
36
- status = out[3].value
37
41
 
38
- assert_equal 1, status.exitstatus
42
+ assert_exit_status(out[3],1)
39
43
  assert_match(/NAME\s*chain\-reactor/, help)
40
44
  assert_match(/SYNOPSIS\s*chain\-reactor \(start|stop|template\) chainfile\.rb/, help)
41
45
  end
@@ -43,27 +47,24 @@ class TestChainReactorOptions < Test::Unit::TestCase
43
47
  def test_template_returns_chainfile_in_stdout
44
48
  out = exec_with('template')
45
49
  template = out[1].read
46
- status = out[3].value
47
50
 
48
- assert_equal 0, status.exitstatus
51
+ assert_exit_status(out[3],0)
49
52
  assert_match(/react_to\(/, template)
50
53
  end
51
54
 
52
55
  def test_start_without_chainfile_fails
53
56
  out = exec_with('start')
54
57
  error = out[2].read
55
- status = out[3].value
56
58
 
57
- assert_equal 1, status.exitstatus
59
+ assert_exit_status(out[3],1)
58
60
  assert_match(/chain-reactor: A valid chainfile must be supplied/, error)
59
61
  end
60
62
 
61
63
  def test_stop_without_chainfile_fails
62
64
  out = exec_with('stop')
63
65
  error = out[2].read
64
- status = out[3].value
65
66
 
66
- assert_equal 1, status.exitstatus
67
+ assert_exit_status(out[3],1)
67
68
  assert_match(/chain-reactor: A valid chainfile must be supplied/, error)
68
69
  end
69
70
  end
@@ -1,88 +1,103 @@
1
1
  require 'test/unit'
2
2
  require 'rubygems'
3
3
  require 'open3'
4
- require 'sys/proctable'
5
4
  require 'client'
6
5
 
7
6
  # Test case for the options of the chain reactor executable.
8
7
  class TestChainReactorStart < Test::Unit::TestCase
9
- include Sys
10
8
 
11
- def setup
12
- @test_path = File.dirname(__FILE__)
13
- @bin_path = @test_path + '/../bin/chain-reactor'
14
- @chainfile_path = @test_path + '/chainfile.test'
15
- @pid_path = @test_path + '/chain-reactor.pid'
16
- end
9
+ if RUBY_PLATFORM != 'java'
10
+ def setup
11
+ @test_path = File.dirname(__FILE__)
12
+ @bin_path = @test_path + '/../bin/chain-reactor'
13
+ @chainfile_path = @test_path + '/chainfile.test'
14
+ @pid_path = @test_path + '/chain-reactor.pid'
15
+ end
17
16
 
18
- def teardown
19
- _,_,_,t = stop_chain_reactor
20
- t.value
21
-
22
- $stdout = STDOUT
23
- end
17
+ def teardown
18
+ _,_,_,t = stop_chain_reactor
19
+ if t.nil?
20
+ # Ruby 1.8
21
+ sleep 2
22
+ else
23
+ # Ruby 1.9+
24
+ t.value
25
+ end
26
+
27
+ $stdout = STDOUT
28
+ end
24
29
 
25
- def start_chain_reactor(arg_string)
26
- Open3.popen3("#{@bin_path} start #{@chainfile_path} #{arg_string} --pidfile #{@pid_path}")
27
- end
30
+ def start_chain_reactor(arg_string)
31
+ Open3.popen3("#{@bin_path} start #{@chainfile_path} #{arg_string} --pidfile #{@pid_path}")
32
+ end
28
33
 
29
- def stop_chain_reactor
30
- Open3.popen3("#{@bin_path} stop #{@chainfile_path} --pidfile #{@pid_path}")
31
- end
34
+ def stop_chain_reactor
35
+ Open3.popen3("#{@bin_path} stop #{@chainfile_path} --pidfile #{@pid_path}")
36
+ end
32
37
 
33
- def test_start_daemon
34
- _, stdout, _, thread = start_chain_reactor('')
35
- output = stdout.read
38
+ def test_start_daemon
39
+ if RUBY_VERSION.to_f < 1.9
40
+ # Thread is not available
41
+ return
42
+ end
43
+ _, stdout, _, thread = start_chain_reactor('')
44
+ output = stdout.read
36
45
 
37
- assert_match(/Registered 1 reactions/,output)
38
- assert_match(/Starting daemon, PID file => #{@pid_path}/,output)
39
- assert_match(/Daemon has started successfully/,output)
46
+ assert_match(/Registered 1 reactions/,output)
47
+ assert_match(/Starting daemon, PID file => #{@pid_path}/,output)
48
+ assert_match(/Daemon has started successfully/,output)
40
49
 
41
- # Thread stopped as it's daemonized
42
- assert_equal true, thread.stop?
50
+ # Wait for thread to exit
51
+ thread.value
43
52
 
44
- assert File.file? @pid_path
45
- pid = File.new(@pid_path).read.to_i
46
- prc = ProcTable.ps(pid)
53
+ # Thread stopped as it's daemonized
54
+ assert_equal true, thread.stop?
47
55
 
48
- assert_not_nil prc
49
- assert_match(/chain\-reactor start/,prc.cmdline)
50
- end
56
+ assert File.file? @pid_path
57
+ pid = File.new(@pid_path).read.to_i
51
58
 
52
- def test_start_daemon_and_communicate_with_client
53
- _, stdout, _, _ = start_chain_reactor('')
54
- output = stdout.read
55
- assert_match(/Daemon has started successfully/,output)
59
+ ps_output = `ps p #{pid} --no-heading`
60
+ assert_not_equal "", ps_output
56
61
 
57
- assert_nothing_raised ChainReactor::ClientError do
58
- $stdout = File.new('/dev/null','w')
59
- client = ChainReactor::Client.new('127.0.0.1',20000)
60
- client.send_as_json({:hello => :world})
62
+ assert_match(/chain\-reactor start/,ps_output)
61
63
  end
62
- end
63
64
 
64
- def test_start_daemon_with_port_override_and_communicate_with_client
65
- _, stdout, _, _ = start_chain_reactor('--port 20100')
66
- output = stdout.read
67
- assert_match(/Daemon has started successfully/,output)
65
+ def test_start_daemon_and_communicate_with_client
66
+ _, stdout, stderr, _ = start_chain_reactor('')
67
+ output = stdout.read
68
+ assert_match(/Daemon has started successfully/,output)
68
69
 
69
- assert_nothing_raised ChainReactor::ClientError do
70
- $stdout = File.new('/dev/null','w')
71
- client = ChainReactor::Client.new('127.0.0.1',20100)
72
- client.send({:hello => :world})
70
+ assert_nothing_raised ChainReactor::ClientError do
71
+ $stdout = File.new('/dev/null','w')
72
+ client = ChainReactor::Client.new('127.0.0.1',1987)
73
+ client.send_as_json({:hello => :world})
74
+ end
73
75
  end
74
- end
75
76
 
76
- def test_start_daemon_with_address_override_and_communicate_with_client
77
- _, stdout, _, _ = start_chain_reactor('--address 0.0.0.0')
78
- output = stdout.read
79
- assert_match(/Daemon has started successfully/,output)
77
+ def test_start_daemon_with_port_override_and_communicate_with_client
78
+ _, stdout, _, _ = start_chain_reactor('--port 20100')
79
+ output = stdout.read
80
+ assert_match(/Daemon has started successfully/,output)
80
81
 
81
- assert_nothing_raised ChainReactor::ClientError do
82
- $stdout = File.new('/dev/null','w')
83
- client = ChainReactor::Client.new('0.0.0.0',20000)
84
- client.send({:hello => :world})
82
+ assert_nothing_raised ChainReactor::ClientError do
83
+ $stdout = File.new('/dev/null','w')
84
+ client = ChainReactor::Client.new('127.0.0.1',20100)
85
+ client.send({:hello => :world})
86
+ end
87
+ end
88
+
89
+ def test_start_daemon_with_address_override_and_communicate_with_client
90
+ _, stdout, _, _ = start_chain_reactor('--address 0.0.0.0')
91
+ output = stdout.read
92
+ assert_match(/Daemon has started successfully/,output)
93
+
94
+ assert_nothing_raised ChainReactor::ClientError do
95
+ $stdout = File.new('/dev/null','w')
96
+ client = ChainReactor::Client.new('0.0.0.0',1987)
97
+ client.send({:hello => :world})
98
+ end
85
99
  end
86
100
  end
101
+
87
102
  end
88
103
 
@@ -50,7 +50,7 @@ class TestChainfileParser < Test::Unit::TestCase
50
50
 
51
51
  def test_single_reaction_with_options_is_added_to_reactor
52
52
  chain = <<-chain
53
- react_to('192.168.0.1', parser: :dummy, required_keys: [:hello,:world]) { |data| puts data.inspect }
53
+ react_to('192.168.0.1', :parser => :dummy, :required_keys => [:hello,:world]) { |data| puts data.inspect }
54
54
  chain
55
55
 
56
56
  parser = ChainReactor::ChainfileParser.new(File.new(chain),
data/test/test_reactor.rb CHANGED
@@ -15,21 +15,21 @@ class TestReactor < Test::Unit::TestCase
15
15
 
16
16
  def test_adding_reaction_makes_address_allowable
17
17
  reactor = ChainReactor::Reactor.new get_logger
18
- reactor.add(['127.0.0.1'],{parser: :dummy},Proc.new {})
18
+ reactor.add(['127.0.0.1'],{:parser => :dummy},Proc.new {})
19
19
  assert reactor.address_allowed? '127.0.0.1'
20
20
  end
21
21
 
22
22
  def test_react_raises_error
23
23
  reactor = ChainReactor::Reactor.new get_logger
24
24
  assert_raises RuntimeError, 'Address is not allowed' do
25
- reactor.react('127.0.0.1',{parser: :dummy})
25
+ reactor.react('127.0.0.1',{:parser => :dummy})
26
26
  end
27
27
  end
28
28
 
29
29
  def test_react_calls_block
30
30
  reactor = ChainReactor::Reactor.new get_logger
31
31
  block = Proc.new { |d| 'block has been called' }
32
- reactor.add(['127.0.0.1'],{parser: :dummy},block)
32
+ reactor.add(['127.0.0.1'],{:parser => :dummy},block)
33
33
  reactions = reactor.reactions_for('127.0.0.1')
34
34
  reactor.react('127.0.0.1','This is a string')
35
35
  assert_equal 'block has been called', reactions[0].previous_result
@@ -41,8 +41,8 @@ class TestReactor < Test::Unit::TestCase
41
41
  block1 = Proc.new { |d| 'block1' }
42
42
  block2 = Proc.new { |d| 'block2' }
43
43
 
44
- reactor.add(['127.0.0.1'],{parser: :dummy},block1)
45
- reactor.add(['127.0.0.1'],{parser: :dummy},block2)
44
+ reactor.add(['127.0.0.1'],{:parser => :dummy},block1)
45
+ reactor.add(['127.0.0.1'],{:parser => :dummy},block2)
46
46
 
47
47
  reactor.react('127.0.0.1','This is a string')
48
48
 
@@ -54,7 +54,7 @@ class TestReactor < Test::Unit::TestCase
54
54
  def test_react_catches_exceptions
55
55
  reactor = ChainReactor::Reactor.new get_logger
56
56
  block = Proc.new { |d| raise 'Block has been called' }
57
- reactor.add(['127.0.0.1'],{parser: :dummy},block)
57
+ reactor.add(['127.0.0.1'],{:parser => :dummy},block)
58
58
  reactor.reactions_for('127.0.0.1')
59
59
  assert_nothing_raised do
60
60
  reactor.react('127.0.0.1','This is a string')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chain-reactor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-17 00:00:00.000000000 Z
12
+ date: 2012-12-21 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Trigger events across networks using TCP/IP sockets
15
15
  email:
@@ -21,6 +21,8 @@ extensions: []
21
21
  extra_rdoc_files: []
22
22
  files:
23
23
  - .gitignore
24
+ - .travis.yml
25
+ - CHANGELOG.rdoc
24
26
  - Gemfile
25
27
  - LICENSE.txt
26
28
  - README.rdoc