sk-hoth 0.0.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/README.rdoc +69 -39
  2. data/THANKS.md +9 -0
  3. data/TODO +2 -0
  4. data/lib/hoth/encoding/json.rb +28 -0
  5. data/lib/hoth/encoding/no_op.rb +19 -0
  6. data/lib/hoth/endpoint.rb +28 -0
  7. data/lib/hoth/exceptions.rb +14 -0
  8. data/lib/hoth/extension/core/exception.rb +15 -0
  9. data/lib/hoth/modules.rb +27 -0
  10. data/lib/hoth/providers/bertrpc_provider.rb +35 -0
  11. data/lib/hoth/providers/rack_provider.rb +45 -0
  12. data/lib/hoth/service.rb +50 -0
  13. data/lib/hoth/service_definition.rb +18 -0
  14. data/lib/hoth/service_module.rb +49 -0
  15. data/lib/hoth/service_registry.rb +34 -0
  16. data/lib/hoth/services.rb +51 -0
  17. data/lib/hoth/transport/base.rb +19 -0
  18. data/lib/hoth/transport/bert.rb +87 -0
  19. data/lib/hoth/transport/http.rb +41 -0
  20. data/lib/hoth/transport/http_hmac.rb +37 -0
  21. data/lib/hoth/transport/workling.rb +23 -0
  22. data/lib/hoth/transport.rb +48 -0
  23. data/lib/hoth/util/logger.rb +46 -0
  24. data/lib/hoth.rb +56 -0
  25. data/spec/spec_helper.rb +7 -26
  26. data/spec/unit/encoding/json_spec.rb +25 -0
  27. data/spec/unit/endpoint_spec.rb +34 -0
  28. data/spec/unit/extension/core/exception_spec.rb +34 -0
  29. data/spec/unit/hoth_spec.rb +30 -0
  30. data/spec/unit/providers/rack_provider_spec.rb +49 -0
  31. data/spec/unit/service_definition_spec.rb +21 -0
  32. data/spec/unit/service_module_spec.rb +59 -0
  33. data/spec/unit/service_spec.rb +77 -0
  34. data/spec/unit/transport/base_spec.rb +43 -0
  35. data/spec/unit/transport/http_hmac_spec.rb +44 -0
  36. data/spec/unit/transport/http_spec.rb +73 -0
  37. data/spec/unit/transport/workling_spec.rb +42 -0
  38. data/spec/unit/transport_spec.rb +29 -0
  39. metadata +86 -23
  40. data/lib/king_soa/rack/middleware.rb +0 -47
  41. data/lib/king_soa/registry.rb +0 -55
  42. data/lib/king_soa/service.rb +0 -88
  43. data/lib/king_soa.rb +0 -56
  44. data/spec/king_soa/rack/middleware_spec.rb +0 -36
  45. data/spec/king_soa/registry_spec.rb +0 -28
  46. data/spec/king_soa/service_spec.rb +0 -46
  47. data/spec/server/app.rb +0 -26
@@ -0,0 +1,41 @@
1
+ require 'net/http'
2
+
3
+ module Hoth
4
+ module Transport
5
+ class Http < Base
6
+ def call_remote_with(*params)
7
+ begin
8
+ handle_response post_payload(params)
9
+ rescue Exception => e
10
+ raise TransportError.wrap(e)
11
+ end
12
+ end
13
+
14
+ def handle_response(response)
15
+ case response
16
+ when Net::HTTPSuccess
17
+ Hoth::Logger.debug "response.body: #{response.body}"
18
+ encoder.decode(response.body)["result"]
19
+ when Net::HTTPServerError
20
+ begin
21
+ Hoth::Logger.debug "response.body: #{response.body}"
22
+ raise encoder.decode(response.body)["error"]
23
+ rescue JSON::ParserError => jpe
24
+ raise TransportError.wrap(jpe)
25
+ end
26
+ when Net::HTTPRedirection, Net::HTTPClientError, Net::HTTPInformation, Net::HTTPUnknownResponse
27
+ raise NotImplementedError, "code: #{response.code}, message: #{response.body}"
28
+ end
29
+ end
30
+
31
+ def post_payload(payload)
32
+ uri = URI.parse(self.endpoint.to_url)
33
+ return Net::HTTP.post_form(uri,
34
+ 'name' => self.name.to_s,
35
+ 'params' => encoder.encode(payload)
36
+ )
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,37 @@
1
+ require 'king_hmac'
2
+ require 'net/http'
3
+ module Hoth
4
+ module Transport
5
+ class HttpHmac < Http
6
+ attr_accessor :hmac_access_id, :hmac_secret
7
+ # just for testing request
8
+ attr_accessor :req
9
+ # Manually construct the HTTP request because it needs to be signed with
10
+ # hmac before.
11
+ # This function is more or less a copy of HTTP.post_form
12
+ # == Prerequisites
13
+ # you must set both instance variables: hmac_access_id, hmac_secret before
14
+ # the call can be made
15
+ # === Returns
16
+ # <Object>:. Net::HTTPResponse
17
+ def post_payload(payload)
18
+ raise TransportError, 'no hmac credentials set for hmac transport' unless hmac_access_id && hmac_secret
19
+ uri = URI.parse(self.endpoint.to_url)
20
+ # construct request object
21
+ self.req = Net::HTTP::Post.new(uri.path)
22
+ # add its form data
23
+ self.req.form_data = {'name' => self.name.to_s,
24
+ 'params' => encoder.encode(payload) }
25
+ # ensure a date header is set, needed for hmac
26
+ self.req['Date'] = Time.now.httpdate if self.req['Date'].nil?
27
+ # sign request object => set Authorisation header
28
+ KingHmac::Auth.sign!(self.req, hmac_access_id, hmac_secret)
29
+ # go for it
30
+ return Net::HTTP.new(uri.host, uri.port).start {|http|
31
+ http.request(self.req)
32
+ }
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,23 @@
1
+ begin
2
+ require 'simple_publisher'
3
+ rescue LoadError
4
+ STDERR.puts "You need the simple_publisher gem if you want to use Workling/Starling transport."
5
+ end
6
+
7
+ module Hoth
8
+ module Transport
9
+
10
+ class Workling < Base
11
+
12
+ def call_remote_with(*args)
13
+ topic = SimplePublisher::Topic.new(:name => "#{self.module.name.to_s.underscore}_subscribers__#{name.to_s.underscore}")
14
+ connection = SimplePublisher::StarlingConnection.new(:host => endpoint.host, :port => endpoint.port)
15
+
16
+ publisher = SimplePublisher::Publisher.new(:topic => topic, :connection => connection)
17
+ publisher.publish(encoder.encode(args))
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,48 @@
1
+ require 'hoth/transport/base'
2
+ require 'hoth/transport/http'
3
+ require 'hoth/transport/http_hmac'
4
+ require 'hoth/transport/bert'
5
+ require 'hoth/transport/workling'
6
+
7
+ require 'hoth/encoding/json'
8
+ require 'hoth/encoding/no_op'
9
+
10
+ module Hoth
11
+ module Transport
12
+
13
+ POSSIBLE_TRANSPORTS = {
14
+ :json_via_http => {
15
+ :transport_class => Transport::Http,
16
+ :encoder => Encoding::Json
17
+ },
18
+ :http => :json_via_http,
19
+ :json_via_http_hmac => {
20
+ :transport_class => Transport::HttpHmac,
21
+ :encoder => Encoding::Json
22
+ },
23
+ :http_hmac => :json_via_http_hmac,
24
+ :workling => {
25
+ :transport_class => Transport::Workling
26
+ }
27
+ }
28
+
29
+ class <<self
30
+ def create(transport_name, service)
31
+ new_transport_with_encoding(transport_name, service)
32
+ end
33
+
34
+ def new_transport_with_encoding(transport_name, service)
35
+ if POSSIBLE_TRANSPORTS[transport_name.to_sym]
36
+ if POSSIBLE_TRANSPORTS[transport_name.to_sym].kind_of?(Hash)
37
+ POSSIBLE_TRANSPORTS[transport_name.to_sym][:transport_class].new(service, :encoder => POSSIBLE_TRANSPORTS[transport_name.to_sym][:encoder])
38
+ else
39
+ new_transport_with_encoding(POSSIBLE_TRANSPORTS[transport_name.to_sym], service)
40
+ end
41
+ else
42
+ raise TransportException.new("specified transport '#{transport_name}' does not exist, use one of these: #{POSSIBLE_TRANSPORTS.keys.join(", ")}")
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,46 @@
1
+ module Hoth
2
+ class Logger
3
+ class <<self
4
+
5
+ def log_provider=(log_provider)
6
+ @log_provider = log_provider
7
+ end
8
+
9
+ def init_logging!
10
+ Hoth::Logger.log_provider = if Object.const_defined?("Rails")
11
+ Rails.logger
12
+ else
13
+ require 'logger'
14
+ ::Logger.new("/tmp/hoth.log")
15
+ end
16
+ end
17
+
18
+ def debug(msg)
19
+ log_provider.debug msg
20
+ end
21
+
22
+ def info(msg)
23
+ log_provider.info msg
24
+ end
25
+
26
+ def warn(msg)
27
+ log_provider.warn msg
28
+ end
29
+
30
+ def error(msg)
31
+ log_provider.error msg
32
+ end
33
+
34
+ def fatal(msg)
35
+ log_provider.fatal msg
36
+ end
37
+
38
+ private
39
+
40
+ def log_provider
41
+ @log_provider || init_logging!
42
+ end
43
+ end
44
+
45
+ end
46
+ end
data/lib/hoth.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'singleton'
2
+
3
+ require 'active_support/inflector'
4
+
5
+ # must be loaded after alls transports and all encodings
6
+ require 'hoth/transport'
7
+
8
+ require 'hoth/service_definition'
9
+ require 'hoth/service_module'
10
+ require 'hoth/endpoint'
11
+ require 'hoth/service'
12
+ require 'hoth/modules'
13
+ require 'hoth/service_registry'
14
+ require 'hoth/services'
15
+
16
+ require 'hoth/util/logger'
17
+
18
+ require 'hoth/extension/core/exception'
19
+ require 'hoth/exceptions'
20
+
21
+ module Hoth
22
+
23
+ class <<self
24
+ def init!
25
+ load_service_definition
26
+ load_module_definition
27
+ Logger.init_logging!
28
+ end
29
+
30
+ def config_path
31
+ @config_path || "config/"
32
+ end
33
+
34
+ def config_path=(config_path)
35
+ @config_path = config_path
36
+ end
37
+
38
+ def load_service_definition
39
+ require File.join(config_path, "service_definition")
40
+ end
41
+
42
+ def load_module_definition
43
+ require File.join(config_path, "module_definition")
44
+ end
45
+
46
+ def env
47
+ @env || ENV["HOTH_ENV"] || (Object.const_defined?("Rails") ? Rails.env.to_sym : :development)
48
+ end
49
+
50
+ def env=(env)
51
+ @env = env.to_sym
52
+ end
53
+
54
+ end
55
+
56
+ end
data/spec/spec_helper.rb CHANGED
@@ -2,36 +2,17 @@ require 'rubygems'
2
2
 
3
3
  $LOAD_PATH.unshift(File.dirname(__FILE__))
4
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
- require 'king_soa'
5
+ require 'hoth'
6
6
  require 'spec'
7
7
  require 'spec/autorun'
8
8
  # for mocking web requests
9
9
  require 'webmock/rspec'
10
- require 'rack/test'
11
10
  include WebMock
12
11
 
12
+ Hoth.env = "test"
13
13
 
14
-
15
- def local_service
16
- # Rack::Builder.app do
17
- # use KingSoa::Rack::Middleware
18
- # run super
19
- # end
20
-
21
- # Rack::Builder.new do
22
- # use KingSoa::Rack::Middleware
23
- # app = proc do |env|
24
- # [ 200, {'Content-Type' => 'text/plain'}, "b" ]
25
- # end
26
- # run app
27
- # end.to_app
28
- # def app
29
- # Rack::Builder.new {
30
- # # URLs starting with /account (logged in users) go to Rails
31
- # map "/soa" do
32
- # run KingSoa::Rack::Middleware.new
33
- # end
34
- # }.to_app
35
- # end
36
- # app.run
37
- end
14
+ Spec::Matchers.define :string_matching do |regex|
15
+ match do |string|
16
+ string =~ regex
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../', 'spec_helper'))
2
+
3
+ module Hoth
4
+ module Encoding
5
+
6
+ describe Json do
7
+
8
+ it "should decode a JSON string" do
9
+ decoded_json = Json.decode '{"test":23}'
10
+ decoded_json.should ==({"test" => 23})
11
+ end
12
+
13
+ it "should encode a JSON string" do
14
+ encoded_json = Json.encode({"test" => 23})
15
+ '{"test":23}'.should == encoded_json
16
+ end
17
+
18
+ it "should know its ContentType" do
19
+ Json.content_type.should == "application/json"
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ module Hoth
4
+
5
+ describe Endpoint do
6
+
7
+ it "should have a port" do
8
+ endpoint = Endpoint.new { port 3000 }
9
+ endpoint.port.should == 3000
10
+ end
11
+
12
+ it "should have a host name" do
13
+ endpoint = Endpoint.new { host "example.com" }
14
+ endpoint.host.should == "example.com"
15
+ end
16
+
17
+ it "should have a transport name" do
18
+ endpoint = Endpoint.new { transport :json_via_http }
19
+ endpoint.transport.should == :json_via_http
20
+ end
21
+
22
+ it "should should cast itself to URL string" do
23
+ endpoint = Endpoint.new { port 3000; host "example.com" }
24
+ endpoint.to_url.should == "http://example.com:3000/execute"
25
+ end
26
+
27
+ it "should should know the deployment module this endpoint is associated to" do
28
+ endpoint = Endpoint.new { module_name "TestModule" }
29
+ endpoint.module_name.should == "TestModule"
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../../', 'spec_helper'))
2
+
3
+ describe Exception do
4
+
5
+ it "should be able to create json with empty backtrace" do
6
+ e = Exception.new "message"
7
+ e.to_json.should == "{\"json_class\":\"Exception\",\"message\":\"message\",\"backtrace\":null}"
8
+ end
9
+
10
+ it "should be able to create json with backtrace" do
11
+ e = Exception.new "message"
12
+ e.set_backtrace ["back", "trace"]
13
+ e.to_json.should == "{\"json_class\":\"Exception\",\"message\":\"message\",\"backtrace\":[\"back\",\"trace\"]}"
14
+ end
15
+
16
+ it "should be able to deserialize exception from json" do
17
+ e = Exception.new "message"
18
+ e.set_backtrace ["back", "trace"]
19
+ deserialized = JSON(e.to_json)
20
+ deserialized.message.should == "message"
21
+ deserialized.backtrace.should == ["back", "trace"]
22
+ end
23
+
24
+ it "should be able to serialize and deserialize descendants of the Exception class" do
25
+ class ExceptionSpec < Exception; end
26
+ e = ExceptionSpec.new "message"
27
+ e.set_backtrace ["back", "trace"]
28
+ deserialized = JSON(e.to_json)
29
+ deserialized.message.should == "message"
30
+ deserialized.backtrace.should == ["back", "trace"]
31
+ deserialized.should be_a ExceptionSpec
32
+ end
33
+
34
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hoth do
4
+
5
+ before(:each) do
6
+ @old_hoth_env = Hoth.env
7
+ Hoth.instance_variable_set "@env", nil
8
+ end
9
+
10
+ after(:each) do
11
+ Hoth.env = @old_hoth_env
12
+ end
13
+
14
+ it "should set the environment explicitly" do
15
+ Hoth.env = :test
16
+ Hoth.env.should == :test
17
+ end
18
+
19
+ it "should default to :development if no environment is set" do
20
+ Hoth.env.should equal(:development)
21
+ end
22
+
23
+ it "should return the Rails env if Rails is available" do
24
+ module Rails; end
25
+ Rails.should_receive(:env).and_return(:production)
26
+ Hoth.env.should equal(:production)
27
+ Object.send :remove_const, :Rails
28
+ end
29
+
30
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../', 'spec_helper'))
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../../', 'lib', 'hoth', 'providers', 'rack_provider'))
4
+
5
+ require 'rack/mock'
6
+
7
+ module Hoth
8
+ module Providers
9
+
10
+ describe RackProvider do
11
+
12
+ it "should get transport and encoder based on called service" do
13
+ app = stub("ApplicationStub").as_null_object
14
+ middleware = Hoth::Providers::RackProvider.new(app)
15
+
16
+ encoder = mock("EncoderMock")
17
+ encoder.should_receive(:decode).with("some_parameter").and_return(decoded_params = "some_parameter_decoded")
18
+ encoder.should_receive(:content_type).and_return("application/json")
19
+
20
+ transport = mock("TransportMock")
21
+ transport.should_receive(:encoder).exactly(3).times.and_return(encoder)
22
+
23
+ service = mock("ServiceMock")
24
+ service.should_receive(:transport).exactly(3).times.and_return(transport)
25
+ ServiceRegistry.should_receive(:locate_service).with("service_name").and_return(service)
26
+
27
+ Hoth::Services.should_receive(:send).with("service_name", *decoded_params).and_return(service_result = "result")
28
+ encoder.should_receive(:encode).with({"result" => service_result}).and_return("result_encoded")
29
+
30
+ mock_request = Rack::MockRequest.new(middleware)
31
+ mock_request.post("http://localhost/execute?name=service_name&params=some_parameter")
32
+ end
33
+
34
+ it "should be able to handle exceptions" do
35
+ app = stub("ApplicationStub").as_null_object
36
+ middleware = Hoth::Providers::RackProvider.new app
37
+ env = {"PATH_INFO" => "/execute/some_method", "other_params" => nil}
38
+ Rack::Request.should_receive(:new).and_raise(RuntimeError)
39
+
40
+ rack_response = middleware.call env
41
+ rack_response.first.should == 500 #status code
42
+ rack_response.last.should be_a_kind_of(Array)
43
+ rack_response.last.first.should == "An error occuered! (RuntimeError)"
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ module Hoth
4
+ describe ServiceDefinition do
5
+
6
+ it "should create a Service and add it to the registry instance" do
7
+ service_name = :my_service
8
+
9
+ definition = ServiceDefinition.new
10
+ definition.service service_name do |some_params|
11
+ returns :nothing
12
+ end
13
+
14
+ service = ServiceRegistry.locate_service(service_name)
15
+ service.should_not be(nil)
16
+ service.params_arity.should be(1)
17
+ service.return_nothing?.should be(true)
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,59 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ module Hoth
4
+
5
+ describe ServiceModule do
6
+
7
+ it "should have a name" do
8
+ service_module = ServiceModule.new :name => :my_service_module
9
+ service_module.name.should equal(:my_service_module)
10
+ end
11
+
12
+ it "should have an environment" do
13
+ service_module = ServiceModule.new(:name => "service_module_name")
14
+ block = Proc.new {}
15
+ service_module.env :test, &block
16
+ service_module[:test].should be_a(ServiceModule::Environment)
17
+ end
18
+
19
+ it "should have multiple environments" do
20
+ service_module = ServiceModule.new(:name => "service_module_name")
21
+ block = Proc.new {}
22
+ service_module.env :test, :development, &block
23
+ service_module[:test].should be_a(ServiceModule::Environment)
24
+ service_module[:development].should be_a(ServiceModule::Environment)
25
+ end
26
+
27
+ it "should be able to add services" do
28
+ service_module = ServiceModule.new(:name => "service_module_name")
29
+ block = Proc.new {}
30
+
31
+ service_module.env :test, &block
32
+
33
+ ServiceRegistry.should_receive(:locate_service).with(:service_name).and_return(service = mock("ServiceMock"))
34
+ service.should_receive(:module=).with(service_module)
35
+ service.should_receive(:via_endpoint).with(:special_endpoint)
36
+
37
+ service_module.add_service("service_name", :via => :special_endpoint)
38
+ end
39
+
40
+ describe ServiceModule::Environment do
41
+
42
+ it "should have an endpoint" do
43
+ endpoint_mock = mock("Endpoint", :null_object => true)
44
+
45
+ endpoint_block = Proc.new do
46
+ endpoint :development do
47
+ host 'localhost'
48
+ end
49
+ end
50
+
51
+ env = ServiceModule::Environment.new(&endpoint_block)
52
+ env[:development].should_not be(nil)
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,77 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ class TestServiceImpl
4
+ def self.execute(param1, param2)
5
+ end
6
+ end
7
+
8
+ module Hoth
9
+
10
+ describe Service do
11
+
12
+ it "should define parameters and return values" do
13
+ service_block = Proc.new { |param_1, param_2, param_3| returns :some_data }
14
+
15
+ service = Service.new("TestService", &service_block)
16
+
17
+ service.params_arity.should be(3)
18
+ service.return_nothing?.should be(false)
19
+ end
20
+
21
+ it "should know its service-impl class" do
22
+ service = Service.new("TestService") {}
23
+ service.impl_class
24
+ end
25
+
26
+ it "should know that its service-impl class is not available" do
27
+ service = Service.new("TestServiceWithoutImplClass") {}
28
+ service.impl_class.should be(false)
29
+ end
30
+
31
+ it "should know if it is local or not based on Impl-Class availability" do
32
+ service = Service.new("TestServiceWithoutImplClass") {}
33
+ service.is_local?.should be(false)
34
+
35
+ service = Service.new("test_service") {}
36
+ service.is_local?.should be(true)
37
+ end
38
+
39
+ it "should execute the service stub locally if its impl-class was found" do
40
+ service = Service.new("test_service") { |p1, p2| returns :nothing }
41
+
42
+ service.should_receive(:is_local?).and_return(true)
43
+ service.impl_class.should_receive(:execute).with(:arg1, :arg2)
44
+
45
+ service.execute(:arg1, :arg2).should be(nil)
46
+ end
47
+
48
+ it "should execute the service stub locally if its impl-class was found and return a value" do
49
+ service = Service.new("test_service") { |p1, p2| returns :value }
50
+
51
+ service.should_receive(:is_local?).and_return(true)
52
+ service.impl_class.should_receive(:execute).with(:arg1, :arg2).and_return(result = mock("ResultMock"))
53
+
54
+ service.execute(:arg1, :arg2).should be(result)
55
+ end
56
+
57
+ it "should call the remote service if impl-class does not exist" do
58
+ service = Service.new("test_service_without_impl") { |p1, p2| returns :nothing }
59
+
60
+ service.should_receive(:is_local?).and_return(false)
61
+ service.should_receive(:transport).and_return(transport = mock("TransportMock"))
62
+ transport.should_receive(:call_remote_with).with(:arg1, :arg2)
63
+
64
+ service.execute(:arg1, :arg2)
65
+ end
66
+
67
+ it "should create transport instance based on endpoint" do
68
+ service = Service.new("test_service") { |p1, p2| returns :nothing }
69
+ service.should_receive(:endpoint).and_return(endpoint = mock("EndpointMock"))
70
+ endpoint.should_receive(:transport).and_return(:http)
71
+ Hoth::Transport.should_receive(:create).with(:http, service)
72
+ service.transport
73
+ end
74
+
75
+ end
76
+
77
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../', 'spec_helper'))
2
+
3
+ module Hoth
4
+ module Transport
5
+
6
+ describe "Base" do
7
+
8
+ it "should initialize with service-delegate" do
9
+ service = mock("ServiceMock")
10
+ transport = Base.new(service)
11
+ end
12
+
13
+ it "should use an NoOp encoder if no encoder class was given at all" do
14
+ service = mock("ServiceMock")
15
+ transport = Base.new(service)
16
+ transport.encoder.should == Encoding::NoOp
17
+ end
18
+
19
+ it "should delegate calls to service-delegate" do
20
+ service = mock("ServiceMock")
21
+ service.should_receive(:name)
22
+ service.should_receive(:module)
23
+ service.should_receive(:endpoint)
24
+ service.should_receive(:params)
25
+ service.should_receive(:return_nothing?)
26
+ transport = Base.new(service)
27
+
28
+ [:name, :module, :endpoint, :params, :return_nothing?].each do |method|
29
+ transport.send(method)
30
+ end
31
+ end
32
+
33
+ it "should have an encoder" do
34
+ service = mock("ServiceMock")
35
+ encoder = mock("EncoderMock")
36
+ transport = Base.new(service, :encoder => encoder)
37
+ transport.encoder.should be(encoder)
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+ end