bixby-common 0.4.4 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab49bbeea61a049b16a3052cf226339fe4ac645a
4
- data.tar.gz: 80ed512df18cbce6fe9f90e57fab0f1a315de3f1
3
+ metadata.gz: 35c3c23073295651e3c85e8e1c6e874890cd0cf2
4
+ data.tar.gz: 82f4b7036f6ac6b98162dd7c77aed1fec5a66841
5
5
  SHA512:
6
- metadata.gz: 59e70fb49c063504490f264c1a7cd50db08a2b3da32795150faf4d9458b8f8d36a6fa710bf90a029214129218b79ce57beb2dcb35e13bb250afc9d21b72c2593
7
- data.tar.gz: 45766f490d69f003c228f37a88357d1941b3ebbc3c3ce16894fd545702b8f05ddca9e4e03ed5ccdf712b2f6b5530d5ab0e7623788ed912747aa73e0b2da2e3f4
6
+ metadata.gz: 2bbfc1cdbda553922468d37fbc7ad96a3ab709dd1634efcdb972b5e22abda26c8105ff54944be50f1f0c3d40aaaa8547ad5e80d71003dc8ecaeb471b6b2e2387
7
+ data.tar.gz: d7b1596b8a5cac4d7ab3bf1bc6078ec5bb9a9ad2cf5b825bdbb09c2bed3632d7b472b83176e6d5ac9ae545e82bce43ad4c057d241175cf14b28efa9ed98a855a
data/Gemfile CHANGED
@@ -8,6 +8,10 @@ gem "logging"
8
8
  gem "api-auth", :git => "https://github.com/chetan/api_auth.git", :branch => "bixby"
9
9
 
10
10
  group :development do
11
+
12
+ # for some tests
13
+ gem "mixlib-shellout"
14
+
11
15
  gem "yard", "~> 0.8"
12
16
  gem "bundler", "~> 1.1"
13
17
  gem "jeweler", :git => "https://github.com/chetan/jeweler.git", :branch => "bixby"
data/Gemfile.lock CHANGED
@@ -31,12 +31,10 @@ GIT
31
31
 
32
32
  GIT
33
33
  remote: https://github.com/chetan/test_guard.git
34
- revision: 7d069b2d7e46fcbecd7a52966fda7d2d1945e2c9
34
+ revision: b60ce3e2cc47746142f0eba0cff5bcf3b550a88c
35
35
  specs:
36
36
  test_guard (0.2.1)
37
37
  awesome_print
38
- debugger
39
- debugger-pry
40
38
  growl
41
39
  listen
42
40
  simplecov
@@ -54,19 +52,9 @@ GEM
54
52
  builder (3.2.2)
55
53
  coderay (1.0.9)
56
54
  colorize (0.5.8)
57
- columnize (0.3.6)
58
55
  crack (0.4.1)
59
56
  safe_yaml (~> 0.9.0)
60
57
  curb (0.8.4)
61
- debugger (1.6.1)
62
- columnize (>= 0.3.1)
63
- debugger-linecache (~> 1.2.0)
64
- debugger-ruby_core_source (~> 1.2.3)
65
- debugger-linecache (1.2.0)
66
- debugger-pry (0.1.1)
67
- debugger (~> 1)
68
- pry (>= 0.9.9)
69
- debugger-ruby_core_source (1.2.3)
70
58
  eventmachine (1.0.3)
71
59
  eventmachine (1.0.3-java)
72
60
  faraday (0.8.8)
@@ -99,7 +87,7 @@ GEM
99
87
  json (1.8.0-java)
100
88
  jwt (0.1.8)
101
89
  multi_json (>= 1.5)
102
- listen (1.3.0)
90
+ listen (1.3.1)
103
91
  rb-fsevent (>= 0.9.3)
104
92
  rb-inotify (>= 0.9)
105
93
  rb-kqueue (>= 0.2)
@@ -110,9 +98,10 @@ GEM
110
98
  metaclass (0.0.1)
111
99
  method_source (0.8.2)
112
100
  minitest (4.7.5)
101
+ mixlib-shellout (1.2.0)
113
102
  mocha (0.14.0)
114
103
  metaclass (~> 0.0.1)
115
- multi_json (1.7.9)
104
+ multi_json (1.8.0)
116
105
  multi_xml (0.5.5)
117
106
  multipart-post (1.2.0)
118
107
  nokogiri (1.5.10)
@@ -139,7 +128,7 @@ GEM
139
128
  rb-fchange (0.0.6)
140
129
  ffi
141
130
  rb-fsevent (0.9.3)
142
- rb-inotify (0.9.1)
131
+ rb-inotify (0.9.2)
143
132
  ffi (>= 0.5.0)
144
133
  rb-kqueue (0.2.0)
145
134
  ffi (>= 0.5.0)
@@ -184,6 +173,7 @@ DEPENDENCIES
184
173
  json
185
174
  logging
186
175
  minitest (~> 4.0)
176
+ mixlib-shellout
187
177
  mocha
188
178
  multi_json
189
179
  oj
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.4
1
+ 0.4.5
data/bixby-common.gemspec CHANGED
@@ -2,14 +2,15 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: bixby-common 0.4.5 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "bixby-common"
8
- s.version = "0.4.4"
9
+ s.version = "0.4.5"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
12
  s.authors = ["Chetan Sarva"]
12
- s.date = "2013-09-10"
13
+ s.date = "2013-09-13"
13
14
  s.description = "Bixby Common files/libs"
14
15
  s.email = "chetan@pixelcop.net"
15
16
  s.extra_rdoc_files = [
@@ -48,27 +49,35 @@ Gem::Specification.new do |s|
48
49
  "lib/bixby-common/util/log/logger.rb",
49
50
  "lib/bixby-common/websocket/api_channel.rb",
50
51
  "lib/bixby-common/websocket/async_response.rb",
51
- "lib/bixby-common/websocket/client.rb",
52
52
  "lib/bixby-common/websocket/message.rb",
53
53
  "lib/bixby-common/websocket/request.rb",
54
54
  "lib/bixby-common/websocket/response.rb",
55
+ "test/api/http_channel_test.rb",
56
+ "test/base.rb",
55
57
  "test/bixby_common_test.rb",
56
58
  "test/command_response_test.rb",
57
59
  "test/command_spec_test.rb",
58
60
  "test/helper.rb",
61
+ "test/side_effect.rb",
59
62
  "test/support/repo/vendor/test_bundle/bin/cat",
60
63
  "test/support/repo/vendor/test_bundle/bin/cat.json",
61
64
  "test/support/repo/vendor/test_bundle/bin/echo",
62
65
  "test/support/repo/vendor/test_bundle/digest",
63
66
  "test/support/repo/vendor/test_bundle/manifest.json",
67
+ "test/test_handler.rb",
68
+ "test/util/crypto_util_test.rb",
64
69
  "test/util/http_client_test.rb",
65
70
  "test/util/jsonify_test.rb",
66
- "test/util/log_test.rb"
71
+ "test/util/log_test.rb",
72
+ "test/websocket/api_channel_test.rb",
73
+ "test/websocket/async_response_test.rb",
74
+ "test/websocket/request_test.rb",
75
+ "test/websocket/response_test.rb"
67
76
  ]
68
77
  s.homepage = "http://github.com/chetan/bixby-common"
69
78
  s.licenses = ["MIT"]
70
79
  s.require_paths = ["lib"]
71
- s.rubygems_version = "2.0.3"
80
+ s.rubygems_version = "2.1.0"
72
81
  s.summary = "Bixby Common"
73
82
 
74
83
  if s.respond_to? :specification_version then
@@ -80,6 +89,7 @@ Gem::Specification.new do |s|
80
89
  s.add_runtime_dependency(%q<httpi>, [">= 0"])
81
90
  s.add_runtime_dependency(%q<logging>, [">= 0"])
82
91
  s.add_runtime_dependency(%q<api-auth>, [">= 0"])
92
+ s.add_development_dependency(%q<mixlib-shellout>, [">= 0"])
83
93
  s.add_development_dependency(%q<yard>, ["~> 0.8"])
84
94
  s.add_development_dependency(%q<bundler>, ["~> 1.1"])
85
95
  s.add_development_dependency(%q<jeweler>, [">= 0"])
@@ -106,6 +116,7 @@ Gem::Specification.new do |s|
106
116
  s.add_dependency(%q<httpi>, [">= 0"])
107
117
  s.add_dependency(%q<logging>, [">= 0"])
108
118
  s.add_dependency(%q<api-auth>, [">= 0"])
119
+ s.add_dependency(%q<mixlib-shellout>, [">= 0"])
109
120
  s.add_dependency(%q<yard>, ["~> 0.8"])
110
121
  s.add_dependency(%q<bundler>, ["~> 1.1"])
111
122
  s.add_dependency(%q<jeweler>, [">= 0"])
@@ -133,6 +144,7 @@ Gem::Specification.new do |s|
133
144
  s.add_dependency(%q<httpi>, [">= 0"])
134
145
  s.add_dependency(%q<logging>, [">= 0"])
135
146
  s.add_dependency(%q<api-auth>, [">= 0"])
147
+ s.add_dependency(%q<mixlib-shellout>, [">= 0"])
136
148
  s.add_dependency(%q<yard>, ["~> 0.8"])
137
149
  s.add_dependency(%q<bundler>, ["~> 1.1"])
138
150
  s.add_dependency(%q<jeweler>, [">= 0"])
data/lib/bixby-common.rb CHANGED
@@ -17,7 +17,6 @@ module Bixby
17
17
  module WebSocket
18
18
  autoload :APIChannel, "bixby-common/websocket/api_channel"
19
19
  autoload :AsyncResponse, "bixby-common/websocket/async_response"
20
- autoload :Client, "bixby-common/websocket/client"
21
20
  autoload :Message, "bixby-common/websocket/message"
22
21
  autoload :Request, "bixby-common/websocket/request"
23
22
  autoload :Response, "bixby-common/websocket/response"
@@ -36,5 +36,14 @@ class JsonRequest
36
36
  MultiJson.dump(self)
37
37
  end
38
38
 
39
+ # Test if this object is equal to some other object
40
+ #
41
+ # @param [JsonRequest] other
42
+ #
43
+ # @return [Boolean]
44
+ def ==(other)
45
+ operation == other.operation && params == other.params
46
+ end
47
+
39
48
  end # JsonRequest
40
49
  end # Bixby
@@ -2,6 +2,9 @@
2
2
  module Bixby
3
3
  class RpcHandler
4
4
 
5
+ def initialize(*args)
6
+ end
7
+
5
8
  # Handle a request
6
9
  #
7
10
  # @param [JsonRequest] request
@@ -66,13 +66,30 @@ module Bixby
66
66
  return data.read
67
67
  end
68
68
 
69
+ # Generate a new 2048-bit RSA keypair
70
+ #
71
+ # @return [OpenSSL::PKey::RSA]
72
+ def generate_keypair
73
+ OpenSSL::PKey::RSA.generate(2048)
74
+ end
75
+
76
+ # Generate a new access key
77
+ #
78
+ # @return [String]
79
+ # :nocov:
69
80
  def generate_access_key
70
81
  Digest.hexencode(Digest::MD5.new.digest(OpenSSL::Random.random_bytes(512)))
71
82
  end
83
+ # :nocov:
72
84
 
85
+ # Generate a new secret key
86
+ #
87
+ # @return [String]
88
+ # :nocov:
73
89
  def generate_secret_key
74
90
  Digest.hexencode(Digest::SHA2.new(512).digest(OpenSSL::Random.random_bytes(512)))
75
91
  end
92
+ # :nocov:
76
93
 
77
94
 
78
95
  private
@@ -2,8 +2,10 @@
2
2
  module Bixby
3
3
  module Debug
4
4
 
5
+ # :nocov:
6
+
5
7
  # Simple helper for use in to_s methods
6
- def self.pretty_str(str) # :nocov:
8
+ def self.pretty_str(str)
7
9
  if str.nil? then
8
10
  "nil"
9
11
  elsif str.empty? then
@@ -13,7 +15,7 @@ module Bixby
13
15
  else
14
16
  '"' + str + '"'
15
17
  end
16
- end # :nocov:
18
+ end
17
19
 
18
20
  # Pretty print a hash
19
21
  #
@@ -41,5 +43,7 @@ module Bixby
41
43
  str.gsub(/\n/, "\n#{indent}")
42
44
  end
43
45
 
46
+ # :nocov:
47
+
44
48
  end # Debug
45
49
  end # Bixby
@@ -22,9 +22,11 @@ module HttpClient
22
22
  #
23
23
  # @param [String] url
24
24
  # @return [Object] Result of calling JSON.parse() on the response body
25
+ # :nocov:
25
26
  def http_get_json(url)
26
27
  MultiJson.load(http_get(url))
27
28
  end
29
+ # :nocov:
28
30
 
29
31
  # Execute an HTTP POST request to the given URL
30
32
  #
@@ -41,9 +43,11 @@ module HttpClient
41
43
  # @param [String] url
42
44
  # @param [Hash] data Key/Value pairs to POST
43
45
  # @return [Object] Result of calling JSON.parse() on the response body
46
+ # :nocov:
44
47
  def http_post_json(url, data)
45
48
  MultiJson.load(http_post(url, data))
46
49
  end
50
+ # :nocov:
47
51
 
48
52
  # Execute an HTTP post request and save the response body
49
53
  #
@@ -3,6 +3,7 @@
3
3
 
4
4
  module Logging
5
5
  class Logger
6
+ # :nocov:
6
7
 
7
8
  # Override to pass trace flag from parent to child
8
9
  def initialize( name )
@@ -16,6 +17,7 @@ module Logging
16
17
  _setup(name, :parent => parent, :trace => parent.trace)
17
18
  end
18
19
 
20
+ # :nocov:
19
21
  end
20
22
  end
21
23
 
@@ -1,6 +1,8 @@
1
1
 
2
2
  require "bixby-common/websocket/async_response"
3
+
3
4
  require "api-auth"
5
+ require "eventmachine"
4
6
 
5
7
  module Bixby
6
8
  module WebSocket
@@ -32,8 +32,8 @@ module Bixby
32
32
  # @param [Object] obj result of request, usually a JsonResponse
33
33
  def response=(obj)
34
34
  @mutex.synchronize {
35
- @completed = true
36
35
  @response = obj
36
+ @completed = true
37
37
  @cond.signal
38
38
  }
39
39
 
@@ -9,10 +9,7 @@ module Bixby
9
9
  def initialize(id=nil, type="rpc", headers=nil)
10
10
  @id = id || SecureRandom.uuid
11
11
  @type = type
12
- @hash = { :type => @type, :id => @id }
13
-
14
- headers ||= {}
15
- @headers = @hash[:headers] = headers
12
+ @headers = headers || {}
16
13
  end
17
14
 
18
15
  def self.from_wire(body)
@@ -39,7 +36,12 @@ module Bixby
39
36
  end
40
37
 
41
38
  def to_wire
42
- @body
39
+ hash = { :type => @type,
40
+ :id => @id,
41
+ :headers => @headers,
42
+ :data => @body }
43
+
44
+ MultiJson.dump(hash)
43
45
  end
44
46
 
45
47
  # Convert object to String, useful for debugging
@@ -10,8 +10,7 @@ module Bixby
10
10
  end
11
11
  super(id, type, headers)
12
12
 
13
- @hash[:data] = json_request.to_wire
14
- @body = MultiJson.dump(@hash)
13
+ @body = json_request.to_wire
15
14
  end
16
15
 
17
16
  def json_request
@@ -10,8 +10,7 @@ module Bixby
10
10
  end
11
11
  super(id, "rpc_result", headers)
12
12
 
13
- @hash[:data] = json_response.to_wire
14
- @body = MultiJson.dump(@hash)
13
+ @body = json_response.to_wire
15
14
  end
16
15
 
17
16
  def json_response
@@ -0,0 +1,65 @@
1
+
2
+ require 'helper'
3
+
4
+ module Bixby
5
+ module Test
6
+ module API
7
+ class TestHttpChannel < TestCase
8
+
9
+ def test_exec
10
+ url = "http://google.com/"
11
+
12
+ json_req = JsonRequest.new("exec", {"foo" => "bar"})
13
+ signed_json_req = SignedJsonRequest.new(json_req, "foo", "bar")
14
+
15
+ # setup response stub
16
+ cr = CommandResponse.new(:status => 0, :stdout => "foobar", :stderr => "")
17
+ json_res = JsonResponse.new("success", nil, cr.to_hash)
18
+ res_mock = mock()
19
+ res_mock.expects(:body).once.returns(json_res.to_wire)
20
+ HTTPI.expects(:post).with{ |r| r.kind_of?(HTTPI::Request) && r.url.to_s == url }.returns(res_mock)
21
+
22
+ chan = HttpChannel.new(url)
23
+ res = chan.execute(signed_json_req)
24
+
25
+ # req should have been modified
26
+ assert_includes signed_json_req.headers, "Content-Type"
27
+ assert_equal "application/json", signed_json_req.headers["Content-Type"]
28
+
29
+ assert res
30
+ assert_kind_of JsonResponse, res
31
+ assert res.success?
32
+
33
+ cr = CommandResponse.from_json_response(res)
34
+ assert cr
35
+ assert_equal 0, cr.status
36
+ assert_equal "foobar", cr.stdout
37
+ assert_equal "", cr.stderr
38
+ end
39
+
40
+ def test_exec_download
41
+ url = "http://google.com/"
42
+
43
+ json_req = JsonRequest.new("exec", {"foo" => "bar"})
44
+ signed_json_req = SignedJsonRequest.new(json_req, "foo", "bar")
45
+
46
+ # setup response stub
47
+ HTTPI.expects(:post).with{ |r| r.kind_of?(HTTPI::Request) && r.url.to_s == url }
48
+
49
+ chan = HttpChannel.new(url)
50
+ res = chan.execute_download(signed_json_req) do
51
+ end
52
+
53
+ # req should have been modified
54
+ assert_includes signed_json_req.headers, "Content-Type"
55
+ assert_equal "application/json", signed_json_req.headers["Content-Type"]
56
+
57
+ assert res
58
+ assert_kind_of JsonResponse, res
59
+ assert res.success?
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+ end
data/test/base.rb ADDED
@@ -0,0 +1,16 @@
1
+
2
+ module Bixby
3
+ module Test
4
+ class TestCase < MiniTest::Unit::TestCase
5
+
6
+ def setup
7
+ ENV["BIXBY_HOME"] = File.join(File.expand_path(File.dirname(__FILE__)), "support")
8
+ end
9
+
10
+ def teardown
11
+ EM.stop_event_loop if EM.reactor_running?
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -1,10 +1,11 @@
1
1
 
2
2
  require 'helper'
3
+ require 'mixlib/shellout'
3
4
 
4
5
  module Bixby
5
6
  module Test
6
7
 
7
- class TestCommandResponse < MiniTest::Unit::TestCase
8
+ class TestCommandResponse < TestCase
8
9
 
9
10
  def test_from_json_response
10
11
  res = JsonResponse.new("fail", "unknown")
@@ -30,6 +31,36 @@ class TestCommandResponse < MiniTest::Unit::TestCase
30
31
  assert_nil cr.stderr
31
32
  end
32
33
 
34
+ def test_to_json_response
35
+ cr = CommandResponse.new(:status => 50, :stdout => "foobar", :stderr => "baz")
36
+ js = cr.to_json_response
37
+
38
+ assert js
39
+ assert_kind_of JsonResponse, js
40
+
41
+ refute js.success?
42
+ assert js.fail?
43
+
44
+ assert_nil js.message
45
+ assert js.data
46
+
47
+ assert_equal 50, js.data[:status]
48
+ assert_equal "foobar", js.data[:stdout]
49
+ assert_equal "baz", js.data[:stderr]
50
+ end
51
+
52
+ def test_from_shellout
53
+ cmd = Mixlib::ShellOut.new("uname")
54
+ cmd.run_command
55
+
56
+ cr = CommandResponse.new(cmd)
57
+ assert cr
58
+
59
+ assert_equal 0, cr.status
60
+ assert cr.stdout =~ /^Darwin|Linux$/
61
+ assert_empty cr.stderr
62
+ end
63
+
33
64
  def test_status
34
65
  cr = CommandResponse.new
35
66
  cr.status = 0
@@ -5,10 +5,10 @@ require 'helper'
5
5
  module Bixby
6
6
  module Test
7
7
 
8
- class TestCommandSpec < MiniTest::Unit::TestCase
8
+ class TestCommandSpec < TestCase
9
9
 
10
10
  def setup
11
- ENV["BIXBY_HOME"] = File.join(File.expand_path(File.dirname(__FILE__)), "support")
11
+ super
12
12
  h = { :repo => "vendor", :bundle => "test_bundle", 'command' => "echo", :foobar => "baz" }
13
13
  @c = CommandSpec.new(h)
14
14
  @expected_digest = "2bb6900420c87d5a7cbd8acc9dd1978593670f4e31bfa9218bb9c7c31d4472dd"
data/test/helper.rb CHANGED
@@ -29,6 +29,10 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
29
29
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
30
30
  require 'bixby-common'
31
31
 
32
+ require "base"
33
+ require "test_handler"
34
+ require "side_effect"
35
+
32
36
  Dir.glob(File.dirname(__FILE__) + "/../lib/**/*.rb").each{ |f| require f }
33
37
 
34
38
  MiniTest::Unit.autorun
@@ -0,0 +1,15 @@
1
+
2
+ module Bixby
3
+ module Test
4
+
5
+ class SideEffect
6
+ def initialize(&block)
7
+ @block = block
8
+ end
9
+ def perform
10
+ @block.call
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+
2
+ module Bixby
3
+ module Test
4
+ class TestHandler < Bixby::RpcHandler
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,34 @@
1
+
2
+ require 'helper'
3
+
4
+ module Bixby
5
+ module Test
6
+
7
+ class TestCryptoUtil < TestCase
8
+
9
+ def test_crypto_cycle
10
+
11
+ key1 = CryptoUtil.generate_keypair
12
+ key2 = CryptoUtil.generate_keypair
13
+
14
+ data = {"foo" => "bar"}
15
+ uuid = "123456"
16
+
17
+ encrypted = CryptoUtil.encrypt(MultiJson.dump(data), uuid, key1, key2)
18
+ assert encrypted
19
+ encrypted_io = StringIO.new(encrypted)
20
+ assert_equal uuid, encrypted_io.readline.strip
21
+
22
+ decrypted = CryptoUtil.decrypt(encrypted_io, key1, key2)
23
+ assert decrypted
24
+ data_out = MultiJson.load(decrypted)
25
+ assert data_out
26
+ assert_kind_of Hash, data_out
27
+ assert_equal "bar", data_out["foo"]
28
+ end
29
+
30
+
31
+ end # TestCryptoUtil
32
+
33
+ end # Test
34
+ end # Bixby
@@ -4,11 +4,12 @@ require 'helper'
4
4
  module Bixby
5
5
  module Test
6
6
 
7
- class TestHttpClient < MiniTest::Unit::TestCase
7
+ class TestHttpClient < TestCase
8
8
 
9
9
  include WebMock::API
10
10
 
11
11
  def teardown
12
+ super
12
13
  WebMock.reset!
13
14
  end
14
15
 
@@ -4,7 +4,7 @@ require 'helper'
4
4
  module Bixby
5
5
  module Test
6
6
 
7
- class TestLog < MiniTest::Unit::TestCase
7
+ class TestLog < TestCase
8
8
 
9
9
  def test_setup_logger
10
10
  ENV["BIXBY_DEBUG"] = "1"
@@ -20,6 +20,29 @@ class TestLog < MiniTest::Unit::TestCase
20
20
  assert_equal 1, Logging::Logger.root.level # info
21
21
  end
22
22
 
23
+ def test_filtering_layout
24
+
25
+ filter = Bixby::Log::FilteringLayout.new
26
+
27
+ f = "foo"
28
+ assert_equal "foo", filter.format_obj(f)
29
+ assert filter.format_obj(nil) =~ /NilClass/
30
+ assert filter.format_obj(3) =~ /Fixnum.*3/
31
+
32
+ begin
33
+ raise "foo"
34
+ rescue => ex
35
+ assert filter.format_obj(ex) =~ /turn/
36
+
37
+ # filter out all turn lines
38
+ filter.set_filter do |ex|
39
+ ex.backtrace.reject{ |s| s =~ /turn/ }
40
+ end
41
+ refute filter.format_obj(ex) =~ /turn/
42
+
43
+ end
44
+ end
45
+
23
46
  end # TestLog
24
47
 
25
48
  end # Test
@@ -0,0 +1,100 @@
1
+
2
+ require 'helper'
3
+
4
+ module Bixby
5
+
6
+
7
+ module WebSocket
8
+ class APIChannel
9
+ def responses
10
+ @responses
11
+ end
12
+ end
13
+ end
14
+
15
+
16
+ module Test
17
+ module WebSocket
18
+ class TestAPIChannel < TestCase
19
+
20
+ attr_reader :api_chan, :ws
21
+
22
+ def setup
23
+ @em_thread = Thread.new { EM.run{} }
24
+ @ws = mock()
25
+ @api_chan = Bixby::WebSocket::APIChannel.new(ws, TestHandler)
26
+ end
27
+
28
+ def test_open
29
+ refute api_chan.connected?
30
+ api_chan.open(nil)
31
+ assert api_chan.connected?
32
+ end
33
+
34
+
35
+ def test_exec
36
+ # test executing a request on the channel
37
+ json_req = JsonRequest.new("exec", {:foo => "bar"})
38
+ ws.expects(:send).once().add_side_effect(SideEffect.new{ api_chan.responses.values.first.response = "hi" })
39
+ assert_equal "hi", api_chan.execute(json_req)
40
+ end
41
+
42
+ def test_message_request
43
+ # test receiving a request on the channel
44
+ json_req = JsonRequest.new("exec", {"foo" => "bar"})
45
+ signed_json_req = SignedJsonRequest.new(json_req, "foo", "bar")
46
+ req = Bixby::WebSocket::Request.new(signed_json_req)
47
+
48
+ cr = CommandResponse.new(:status => 0, :stdout => "foobar", :stderr => "")
49
+ json_res = JsonResponse.new("success", nil, cr.to_hash)
50
+
51
+ event = mock()
52
+ event.expects(:data).once.returns(req.to_wire)
53
+ TestHandler.any_instance.expects(:handle).with{ |r| r == json_req }.returns(json_res)
54
+ ws.expects(:send).once.with { |str|
55
+ res = Bixby::WebSocket::Message.from_wire(str)
56
+ !res.nil? && res.json_response.to_wire == json_res.to_wire
57
+ }
58
+ api_chan.message(event)
59
+ end
60
+
61
+ def test_message_response
62
+ # test receiving a response on the channel
63
+ cr = CommandResponse.new(:status => 0, :stdout => "foobar", :stderr => "")
64
+ json_res = JsonResponse.new("success", nil, cr.to_hash)
65
+ res = Bixby::WebSocket::Response.new(json_res, "1234")
66
+
67
+ event = mock()
68
+ event.expects(:data).once.returns(res.to_wire)
69
+ api_chan.responses["1234"] = Bixby::WebSocket::AsyncResponse.new("1234")
70
+ api_chan.message(event)
71
+ ret = api_chan.fetch_response("1234")
72
+ assert ret
73
+ assert_kind_of JsonResponse, ret
74
+ assert_equal json_res.to_wire, ret.to_wire
75
+ end
76
+
77
+ def test_message_connect
78
+ # test receiving a connect request on the channel
79
+ json_req = JsonRequest.new("", {})
80
+ signed_json_req = SignedJsonRequest.new(json_req, "foo", "bar")
81
+ req = Bixby::WebSocket::Request.new(signed_json_req, nil, "connect")
82
+
83
+ event = mock()
84
+ event.expects(:data).once.returns(req.to_wire)
85
+ TestHandler.any_instance.expects(:connect).with(json_req, api_chan)
86
+ api_chan.message(event)
87
+ end
88
+
89
+ def test_close
90
+ # close
91
+ api_chan.open(nil)
92
+ TestHandler.any_instance.expects(:disconnect).with(api_chan).once()
93
+ api_chan.close(nil)
94
+
95
+ end
96
+
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,43 @@
1
+
2
+ require 'helper'
3
+
4
+ module Bixby
5
+ module Test
6
+ module WebSocket
7
+ class TestAsyncResponse < TestCase
8
+
9
+ def test_block
10
+
11
+ sync_response = nil
12
+ cb_response = nil
13
+
14
+ res = Bixby::WebSocket::AsyncResponse.new("1234") do |r|
15
+ cb_response = r
16
+ end
17
+
18
+ assert res
19
+ assert_equal "1234", res.id
20
+ refute res.completed?
21
+
22
+ # start a thread waiting on the response to be writ ten
23
+ t = Thread.new {
24
+ sync_response = res.response
25
+ }
26
+ assert t.alive?
27
+
28
+ # small sleep here, otherwise execution will continue too quickly, before the thread starts
29
+ assert_nil t.join(0.001)
30
+
31
+ # now write it, thread should complete & callback will fire
32
+ res.response = "hi"
33
+
34
+ t.join
35
+ refute t.alive?
36
+ assert_equal "hi", cb_response
37
+ assert_equal "hi", sync_response
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,65 @@
1
+
2
+ require 'helper'
3
+
4
+ module Bixby
5
+ module Test
6
+ module WebSocket
7
+ class TestRequest < TestCase
8
+
9
+ def test_init
10
+ json_req = JsonRequest.new("exec", {:foo => "bar"})
11
+ req = Bixby::WebSocket::Request.new(json_req)
12
+
13
+ assert req
14
+ assert req.headers
15
+ assert_empty req.headers
16
+
17
+ h = MultiJson.load(req.to_wire)
18
+ test_common_props(h)
19
+ assert_empty h["headers"]
20
+ end
21
+
22
+ def test_signed
23
+ json_req = JsonRequest.new("exec", {:foo => "bar"})
24
+ signed_json_req = SignedJsonRequest.new(json_req, "foo", "bar")
25
+ req = Bixby::WebSocket::Request.new(signed_json_req)
26
+
27
+ assert req
28
+ h = MultiJson.load(req.to_wire)
29
+ test_common_props(h)
30
+ refute_empty h["headers"]
31
+
32
+ assert_includes h["headers"], "Content-MD5"
33
+ assert_includes h["headers"], "Date"
34
+ assert_includes h["headers"], "Authorization"
35
+ assert h["headers"]["Authorization"] =~ /^APIAuth foo:/
36
+ end
37
+
38
+ def test_json_req
39
+ json_req = JsonRequest.new("exec", {"foo" => "bar"})
40
+ req = Bixby::WebSocket::Request.new(json_req)
41
+
42
+ assert req.json_request
43
+ assert_equal json_req, req.json_request
44
+ assert_equal json_req, Bixby::WebSocket::Message.from_wire(req.to_wire).json_request
45
+ end
46
+
47
+
48
+ private
49
+
50
+ def test_common_props(h)
51
+ assert h
52
+ assert_equal "rpc", h["type"]
53
+ assert h["id"]
54
+
55
+ d = MultiJson.load(h["data"])
56
+ assert_equal "exec", d["operation"]
57
+ refute_empty d["params"]
58
+ assert_equal "bar", d["params"]["foo"]
59
+ h
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,45 @@
1
+
2
+ require 'helper'
3
+
4
+ module Bixby
5
+ module Test
6
+ module WebSocket
7
+ class TestResponse < TestCase
8
+
9
+ def test_init
10
+ cr = CommandResponse.new(:status => 0, :stdout => "foobar", :stderr => "")
11
+ json_res = JsonResponse.new("success", nil, cr.to_hash)
12
+ res = Bixby::WebSocket::Response.new(json_res, "1234")
13
+
14
+ assert res
15
+ assert res.headers
16
+ assert_empty res.headers
17
+
18
+ h = MultiJson.load(res.to_wire)
19
+ assert h
20
+ assert_equal "rpc_result", h["type"]
21
+ assert_equal "1234", h["id"]
22
+
23
+ d = MultiJson.load(h["data"])
24
+ assert_equal "success", d["status"]
25
+ refute d["message"]
26
+ refute d["code"]
27
+ assert_equal 0, d["data"]["status"]
28
+ assert_equal "foobar", d["data"]["stdout"]
29
+ assert_equal "", d["data"]["stderr"]
30
+ end
31
+
32
+ def test_json_res
33
+ cr = CommandResponse.new("status" => 0, "stdout" => "foobar", "stderr" => "")
34
+ json_res = JsonResponse.new("success", nil, cr.to_hash)
35
+ res = Bixby::WebSocket::Response.new(json_res, "1234")
36
+
37
+ assert res.json_response
38
+ assert_equal json_res.to_wire, res.json_response.to_wire
39
+ assert_equal json_res.to_wire, Bixby::WebSocket::Message.from_wire(res.to_wire).json_response.to_wire
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bixby-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chetan Sarva
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-10 00:00:00.000000000 Z
11
+ date: 2013-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faye-websocket
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mixlib-shellout
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'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: yard
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -399,22 +413,30 @@ files:
399
413
  - lib/bixby-common/util/log/logger.rb
400
414
  - lib/bixby-common/websocket/api_channel.rb
401
415
  - lib/bixby-common/websocket/async_response.rb
402
- - lib/bixby-common/websocket/client.rb
403
416
  - lib/bixby-common/websocket/message.rb
404
417
  - lib/bixby-common/websocket/request.rb
405
418
  - lib/bixby-common/websocket/response.rb
419
+ - test/api/http_channel_test.rb
420
+ - test/base.rb
406
421
  - test/bixby_common_test.rb
407
422
  - test/command_response_test.rb
408
423
  - test/command_spec_test.rb
409
424
  - test/helper.rb
425
+ - test/side_effect.rb
410
426
  - test/support/repo/vendor/test_bundle/bin/cat
411
427
  - test/support/repo/vendor/test_bundle/bin/cat.json
412
428
  - test/support/repo/vendor/test_bundle/bin/echo
413
429
  - test/support/repo/vendor/test_bundle/digest
414
430
  - test/support/repo/vendor/test_bundle/manifest.json
431
+ - test/test_handler.rb
432
+ - test/util/crypto_util_test.rb
415
433
  - test/util/http_client_test.rb
416
434
  - test/util/jsonify_test.rb
417
435
  - test/util/log_test.rb
436
+ - test/websocket/api_channel_test.rb
437
+ - test/websocket/async_response_test.rb
438
+ - test/websocket/request_test.rb
439
+ - test/websocket/response_test.rb
418
440
  homepage: http://github.com/chetan/bixby-common
419
441
  licenses:
420
442
  - MIT
@@ -435,7 +457,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
435
457
  version: '0'
436
458
  requirements: []
437
459
  rubyforge_project:
438
- rubygems_version: 2.0.3
460
+ rubygems_version: 2.1.0
439
461
  signing_key:
440
462
  specification_version: 4
441
463
  summary: Bixby Common
@@ -1,125 +0,0 @@
1
-
2
- require 'faye/websocket'
3
- require 'eventmachine'
4
-
5
- module Bixby
6
- module WebSocket
7
-
8
- # WebSocket Client
9
- class Client
10
-
11
- include Bixby::Log
12
-
13
- attr_reader :ws, :api
14
-
15
- def initialize(url, handler)
16
- @url = url
17
- @handler = handler
18
- @tries = 0
19
- @exiting = false
20
- end
21
-
22
- # Start the Client thread
23
- #
24
- # NOTE: This call never returns!
25
- def start
26
-
27
- @exiting = false
28
-
29
- Kernel.trap("EXIT") do
30
- @exiting = true
31
- end
32
-
33
- logger.debug "connecting to #{@url}"
34
- EM.run {
35
- connect()
36
- }
37
- end
38
-
39
- def stop
40
- @exiting = true
41
- EM.stop_event_loop
42
- end
43
-
44
-
45
- private
46
-
47
- # Connect to the WebSocket endpoint given by @url. Will attempt to keep
48
- # the connection open forever, reconnecting as needed.
49
- def connect
50
-
51
- @ws = Faye::WebSocket::Client.new(@url, nil, :ping => 60)
52
- @api = Bixby::WebSocket::APIChannel.new(@ws, @handler)
53
-
54
- ws.on :open do |e|
55
- begin
56
- logger.info "connected to manager at #{@url}"
57
- api.open(e)
58
- @tries = 0
59
-
60
- # send a connection request
61
- id = SecureRandom.uuid
62
- json_req = JsonRequest.new("", "")
63
- signed_req = SignedJsonRequest.new(json_req, Bixby.agent.access_key, Bixby.agent.secret_key)
64
- connect_req = Request.new(signed_req, id, "connect")
65
- EM.next_tick {
66
- ws.send(connect_req.to_wire)
67
- }
68
-
69
- rescue Exception => ex
70
- logger.error ex
71
- end
72
- end
73
-
74
- ws.on :message do |e|
75
- begin
76
- api.message(e)
77
- rescue Exception => ex
78
- logger.error ex
79
- end
80
- end
81
-
82
- ws.on :close do |e|
83
- begin
84
- if api.connected? then
85
- logger.info "lost connection to manager"
86
- else
87
- logger.debug "failed to connect"
88
- end
89
- api.close(e)
90
- backoff()
91
- connect()
92
- rescue Exception => ex
93
- logger.error ex
94
- end
95
- end
96
- end
97
-
98
- # Delay reconnection by a slowly increasing interval
99
- def backoff
100
-
101
- if @exiting or not EM.reactor_running? then
102
- # shutting down, don't try to reconnect
103
- return
104
- end
105
-
106
- @tries += 1
107
- if @tries == 1 then
108
- logger.debug "retrying immediately"
109
- elsif @tries == 2 then
110
- logger.debug "retrying every 1 sec"
111
- sleep 1
112
- elsif @tries <= 30 then
113
- sleep 1
114
- elsif @tries == 31 then
115
- logger.debug "retrying every 5 sec"
116
- sleep 5
117
- else
118
- sleep 5
119
- end
120
- end
121
-
122
- end
123
-
124
- end
125
- end