circuit 0.2.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.
- data/Gemfile +34 -0
- data/LICENSE +20 -0
- data/README.md +161 -0
- data/Rakefile +27 -0
- data/config.ru +7 -0
- data/description.md +5 -0
- data/docs/COMPATIBILITY.md +14 -0
- data/docs/ROADMAP.md +29 -0
- data/lib/circuit.rb +125 -0
- data/lib/circuit/behavior.rb +99 -0
- data/lib/circuit/compatibility.rb +73 -0
- data/lib/circuit/middleware.rb +6 -0
- data/lib/circuit/middleware/rewriter.rb +43 -0
- data/lib/circuit/rack.rb +14 -0
- data/lib/circuit/rack/behavioral.rb +45 -0
- data/lib/circuit/rack/builder.rb +50 -0
- data/lib/circuit/rack/multi_site.rb +22 -0
- data/lib/circuit/rack/request.rb +81 -0
- data/lib/circuit/railtie.rb +24 -0
- data/lib/circuit/storage.rb +74 -0
- data/lib/circuit/storage/memory_model.rb +70 -0
- data/lib/circuit/storage/nodes.rb +56 -0
- data/lib/circuit/storage/nodes/memory_store.rb +63 -0
- data/lib/circuit/storage/nodes/model.rb +67 -0
- data/lib/circuit/storage/nodes/mongoid_store.rb +56 -0
- data/lib/circuit/storage/sites.rb +38 -0
- data/lib/circuit/storage/sites/memory_store.rb +53 -0
- data/lib/circuit/storage/sites/model.rb +29 -0
- data/lib/circuit/storage/sites/mongoid_store.rb +43 -0
- data/lib/circuit/validators.rb +74 -0
- data/lib/circuit/version.rb +3 -0
- data/spec/internal/app/behaviors/change_path.rb +7 -0
- data/spec/internal/app/controllers/application_controller.rb +5 -0
- data/spec/internal/app/helpers/application_helper.rb +2 -0
- data/spec/internal/config/initializers/circuit.rb +7 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/db/schema.rb +1 -0
- data/spec/lib/circuit/behavior_spec.rb +113 -0
- data/spec/lib/circuit/middleware/rewriter_spec.rb +79 -0
- data/spec/lib/circuit/rack/behavioral_spec.rb +60 -0
- data/spec/lib/circuit/rack/builder_spec.rb +125 -0
- data/spec/lib/circuit/rack/multi_site_spec.rb +34 -0
- data/spec/lib/circuit/rack/request_spec.rb +80 -0
- data/spec/lib/circuit/railtie_spec.rb +34 -0
- data/spec/lib/circuit/storage/nodes_spec.rb +62 -0
- data/spec/lib/circuit/storage/sites_spec.rb +60 -0
- data/spec/lib/circuit/storage_spec.rb +20 -0
- data/spec/lib/circuit/validators_spec.rb +69 -0
- data/spec/lib/circuit_spec.rb +139 -0
- data/spec/spec_helper.rb +79 -0
- data/spec/support/blueprints.rb +24 -0
- data/spec/support/matchers/be_current_time_matcher.rb +14 -0
- data/spec/support/matchers/extended_have_key.rb +31 -0
- data/spec/support/matchers/have_accessor_matcher.rb +13 -0
- data/spec/support/matchers/have_attribute_matcher.rb +22 -0
- data/spec/support/matchers/have_block_matcher.rb +14 -0
- data/spec/support/matchers/have_errors_on_matcher.rb +30 -0
- data/spec/support/matchers/have_module_matcher.rb +13 -0
- data/spec/support/matchers/have_reader_matcher.rb +18 -0
- data/spec/support/matchers/have_writer_matcher.rb +18 -0
- data/spec/support/matchers/set_instance_variable.rb +32 -0
- data/spec/support/spec_helpers/base_behaviors.rb +20 -0
- data/spec/support/spec_helpers/base_models.rb +64 -0
- data/spec/support/spec_helpers/logger_helpers.rb +58 -0
- data/spec/support/spec_helpers/multi_site_helper.rb +48 -0
- data/spec/support/spec_helpers/rack_helpers.rb +8 -0
- data/spec/support/spec_helpers/shared_examples/node_store.rb +87 -0
- data/spec/support/spec_helpers/shared_examples/site_store.rb +76 -0
- data/spec/support/spec_helpers/simple_machinable.rb +29 -0
- data/spec/support/spec_helpers/stores_cleaner.rb +46 -0
- data/vendor/active_support-3.2/core_ext/string/inflections.rb +53 -0
- data/vendor/active_support-3.2/inflector/methods.rb +65 -0
- data/vendor/rack-1.4/builder.rb +167 -0
- data/vendor/rack-1.4/urlmap.rb +96 -0
- metadata +238 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Circuit::Rack::Request do
|
4
|
+
context "Rack::Request should have module" do
|
5
|
+
it { ::Rack::Request.included_modules.should include(::Circuit::Rack::Request) }
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "site" do
|
9
|
+
let(:site) { mock() }
|
10
|
+
|
11
|
+
context "get" do
|
12
|
+
subject { mock_request(Circuit::Rack::Request::ENV_SITE => site).site }
|
13
|
+
it { should == site }
|
14
|
+
end
|
15
|
+
|
16
|
+
context "set" do
|
17
|
+
subject { mock_request.tap { |r| r.site = site } }
|
18
|
+
it { subject.site.should == site }
|
19
|
+
it { subject.env[Circuit::Rack::Request::ENV_SITE].should == site }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "path segments" do
|
24
|
+
context "splits by slashes" do
|
25
|
+
subject { mock_request.path_segments }
|
26
|
+
it { should == [nil]+%w[foo bar baz] }
|
27
|
+
end
|
28
|
+
|
29
|
+
context "path_segments with blanks and double slashes" do
|
30
|
+
subject { mock_request(:path => "/foo//bar/baz///").path_segments }
|
31
|
+
it { should == [nil]+%w[foo bar baz] }
|
32
|
+
end
|
33
|
+
|
34
|
+
context "class method" do
|
35
|
+
it do
|
36
|
+
::Rack::Request.expects(:path_segments).once.with("/foo/bar/baz")
|
37
|
+
mock_request.path_segments
|
38
|
+
end
|
39
|
+
after { ::Rack::Request.unstub(:path_segments) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "route" do
|
44
|
+
let(:route) { mock() }
|
45
|
+
|
46
|
+
context "none" do
|
47
|
+
subject { mock_request.route }
|
48
|
+
it { should be_nil }
|
49
|
+
end
|
50
|
+
|
51
|
+
context "get" do
|
52
|
+
subject { mock_request(Circuit::Rack::Request::ENV_ROUTE => route).route }
|
53
|
+
it { should == route }
|
54
|
+
end
|
55
|
+
|
56
|
+
context "set" do
|
57
|
+
let(:path) { "/foo/bar/baz" }
|
58
|
+
let(:route) { mock(:last => mock(:path => path), :length => 4) }
|
59
|
+
subject { mock_request.tap { |r| r.route = route } }
|
60
|
+
it { subject.route.should == route }
|
61
|
+
it { subject.env["SCRIPT_NAME"].should == "/foo/bar/baz" }
|
62
|
+
it { subject.env["PATH_INFO"].should == "" }
|
63
|
+
it { subject.path.should == "/foo/bar/baz" }
|
64
|
+
it { subject.circuit_originals["SCRIPT_NAME"].should == "" }
|
65
|
+
it { subject.circuit_originals["PATH_INFO"].should == "/foo/bar/baz" }
|
66
|
+
end
|
67
|
+
|
68
|
+
context "set partial path" do
|
69
|
+
let(:path) { "/foo/bar" }
|
70
|
+
let(:route) { mock(:last => mock(:path => path), :length => 3) }
|
71
|
+
subject { mock_request.tap { |r| r.route = route } }
|
72
|
+
it { subject.route.should == route }
|
73
|
+
it { subject.env["SCRIPT_NAME"].should == "/foo/bar" }
|
74
|
+
it { subject.env["PATH_INFO"].should == "/baz" }
|
75
|
+
it { subject.path.should == "/foo/bar/baz" }
|
76
|
+
it { subject.circuit_originals["SCRIPT_NAME"].should == "" }
|
77
|
+
it { subject.circuit_originals["PATH_INFO"].should == "/foo/bar/baz" }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Circuit::Railtie do
|
4
|
+
context "middlewares" do
|
5
|
+
subject { Rails.application.config.middleware }
|
6
|
+
it { subject[0].klass.should == Circuit::Rack::MultiSite }
|
7
|
+
it { subject[1].klass.should == Circuit::Rack::Behavioral }
|
8
|
+
end
|
9
|
+
|
10
|
+
context "default cru_path" do
|
11
|
+
subject { Circuit.cru_path }
|
12
|
+
it { should == Rails.root.join("app", "behaviors") }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "application paths" do
|
16
|
+
subject { Rails.application.config.paths.all_paths }
|
17
|
+
it { should include(["app/behaviors"]) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "eager load paths" do
|
21
|
+
subject { Rails.application.config.paths.eager_load }
|
22
|
+
it { should include(Circuit.cru_path.to_s) }
|
23
|
+
it do
|
24
|
+
Dir.glob(Circuit.cru_path.join("**", "*.rb")).each do |path|
|
25
|
+
subject.should include(path)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "logger" do
|
31
|
+
subject { Circuit.logger }
|
32
|
+
it { should equal(Rails.logger) }
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Circuit::Storage::Nodes do
|
4
|
+
include SpecHelpers::StoresCleaner
|
5
|
+
include SpecHelpers::BaseModels
|
6
|
+
|
7
|
+
describe Circuit::Storage::Nodes::BaseStore do
|
8
|
+
context "unimplemented store" do
|
9
|
+
class Circuit::Storage::Nodes::UnimplementedStore < Circuit::Storage::Nodes::BaseStore
|
10
|
+
end
|
11
|
+
|
12
|
+
subject { Circuit::Storage::Nodes::UnimplementedStore.new }
|
13
|
+
|
14
|
+
it do
|
15
|
+
expect { subject.get("foo", "bar") }.
|
16
|
+
to raise_error(Circuit::Storage::Nodes::UnimplementedError, "Circuit::Storage::Nodes::UnimplementedStore#get not implemented.")
|
17
|
+
end
|
18
|
+
|
19
|
+
it do
|
20
|
+
expect { subject.get!("foo", "bar") }.
|
21
|
+
to raise_error(Circuit::Storage::Nodes::UnimplementedError, "Circuit::Storage::Nodes::UnimplementedStore#get not implemented.")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "empty store" do
|
26
|
+
class Circuit::Storage::Nodes::EmptyStore < Circuit::Storage::Nodes::BaseStore
|
27
|
+
def get(site, path) nil; end
|
28
|
+
end
|
29
|
+
|
30
|
+
subject { Circuit::Storage::Nodes::EmptyStore.new }
|
31
|
+
|
32
|
+
it { subject.get("foo", "bar").should be_nil }
|
33
|
+
|
34
|
+
it do
|
35
|
+
expect { subject.get!("foo", "bar").
|
36
|
+
to raise_error(Circuit::Storage::Nodes::NotFoundError, "Host not found")
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe Circuit::Storage::Nodes::MemoryStore do
|
43
|
+
use_storage :memory_store
|
44
|
+
let!(:store) { :memory_store }
|
45
|
+
include_examples "node store"
|
46
|
+
|
47
|
+
describe Circuit::Storage::Nodes::MemoryStore::Node do
|
48
|
+
subject { child }
|
49
|
+
it { should have_attribute(:slug) }
|
50
|
+
it { should have_attribute(:behavior_klass) }
|
51
|
+
it { should have_attribute(:site) }
|
52
|
+
it { should have_attribute(:parent) }
|
53
|
+
it { should have_attribute(:children) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "Circuit::Storage::Nodes::MongoidStore", :if => $mongo_tests do
|
58
|
+
use_storage :mongoid_store
|
59
|
+
let!(:store) { :mongoid_store }
|
60
|
+
include_examples "node store"
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Circuit::Storage::Sites do
|
4
|
+
include SpecHelpers::StoresCleaner
|
5
|
+
include SpecHelpers::BaseModels
|
6
|
+
|
7
|
+
describe Circuit::Storage::Sites::BaseStore do
|
8
|
+
context "unimplemented store" do
|
9
|
+
class Circuit::Storage::Sites::UnimplementedStore < Circuit::Storage::Sites::BaseStore
|
10
|
+
end
|
11
|
+
|
12
|
+
subject { Circuit::Storage::Sites::UnimplementedStore.new }
|
13
|
+
|
14
|
+
it do
|
15
|
+
expect { subject.get("foo") }.
|
16
|
+
to raise_error(Circuit::Storage::Sites::UnimplementedError, "Circuit::Storage::Sites::UnimplementedStore#get not implemented.")
|
17
|
+
end
|
18
|
+
|
19
|
+
it do
|
20
|
+
expect { subject.get!("foo") }.
|
21
|
+
to raise_error(Circuit::Storage::Sites::UnimplementedError, "Circuit::Storage::Sites::UnimplementedStore#get not implemented.")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "empty store" do
|
26
|
+
class Circuit::Storage::Sites::EmptyStore < Circuit::Storage::Sites::BaseStore
|
27
|
+
def get(host) nil; end
|
28
|
+
end
|
29
|
+
|
30
|
+
subject { Circuit::Storage::Sites::EmptyStore.new }
|
31
|
+
|
32
|
+
it { subject.get("foo").should be_nil }
|
33
|
+
|
34
|
+
it do
|
35
|
+
expect { subject.get!("foo").
|
36
|
+
to raise_error(Circuit::Storage::Sites::NotFoundError, "Host not found")
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe Circuit::Storage::Sites::MemoryStore do
|
43
|
+
use_storage :memory_store
|
44
|
+
let!(:store) { :memory_store }
|
45
|
+
include_examples "site store"
|
46
|
+
|
47
|
+
describe Circuit::Storage::Sites::MemoryStore::Site do
|
48
|
+
subject { site }
|
49
|
+
it { should have_attribute(:host) }
|
50
|
+
it { should have_attribute(:aliases) }
|
51
|
+
it { should have_attribute(:route) }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "Circuit::Storage::Sites::MongoidStore", :if => $mongo_tests do
|
56
|
+
use_storage :mongoid_store
|
57
|
+
let!(:store) { :mongoid_store }
|
58
|
+
include_examples "site store"
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Circuit::Storage do
|
4
|
+
include SpecHelpers::StoresCleaner
|
5
|
+
|
6
|
+
context "undefined site store" do
|
7
|
+
it do
|
8
|
+
expect { Circuit.site_store }.
|
9
|
+
to raise_error(Circuit::Storage::InstanceUndefinedError, "Storage instance is undefined.")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "undefined node store" do
|
14
|
+
it do
|
15
|
+
expect { Circuit.node_store }.
|
16
|
+
to raise_error(Circuit::Storage::InstanceUndefinedError, "Storage instance is undefined.")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'circuit/validators'
|
3
|
+
|
4
|
+
describe Circuit::Validators do
|
5
|
+
describe Circuit::Validators::DomainValidator do
|
6
|
+
subject { DomainValidator.new(:attributes => :domain) }
|
7
|
+
let(:record) { stub(:errors => ActiveModel::Errors.new(nil)) }
|
8
|
+
|
9
|
+
context "with a top level domain" do
|
10
|
+
before { subject.validate_each(record, :domain, "localhost") }
|
11
|
+
it { record.errors.should be_empty }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "with a real domain name" do
|
15
|
+
before { subject.validate_each(record, :domain, "google.com") }
|
16
|
+
it { record.errors.should be_empty }
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with a subdomain" do
|
20
|
+
before { subject.validate_each(record, :domain, "plus.google.com") }
|
21
|
+
it { record.errors.should be_empty }
|
22
|
+
end
|
23
|
+
|
24
|
+
context "with a invalid characters" do
|
25
|
+
before { subject.validate_each(record, :domain, "bad%domain.com") }
|
26
|
+
it { record.errors.to_hash.should == {:domain => ["is not a valid domain."]} }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe Circuit::Validators::DomainArrayValidator do
|
31
|
+
subject { DomainArrayValidator.new(:attributes => :aliases) }
|
32
|
+
let(:record) { stub(:errors => ActiveModel::Errors.new(nil)) }
|
33
|
+
|
34
|
+
context "with a String" do
|
35
|
+
before { subject.validate_each(record, :domain, "localhost") }
|
36
|
+
it { record.errors.should be_empty }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with an empty array" do
|
40
|
+
before { subject.validate_each(record, :domain, []) }
|
41
|
+
it { record.errors.should be_empty }
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with multiple bad domains" do
|
45
|
+
before { subject.validate_each(record, :domain, %w[bad%domain1.com bad%domain2.com]) }
|
46
|
+
it { record.errors.to_hash.should == {:domain => ["has an invalid domain."]} }
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with all good domains" do
|
50
|
+
before { subject.validate_each(record, :domain, %w[google.com plus.google.com www.google.com]) }
|
51
|
+
it { record.errors.should be_empty }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe Circuit::Validators::SlugValidator do
|
56
|
+
subject { SlugValidator.new(:attributes => :slug) }
|
57
|
+
let(:record) { stub(:errors => ActiveModel::Errors.new(nil)) }
|
58
|
+
|
59
|
+
context "with a valid slug" do
|
60
|
+
before { subject.validate_each(record, :slug, "a-path-segment") }
|
61
|
+
it { record.errors.should be_empty }
|
62
|
+
end
|
63
|
+
|
64
|
+
context "with an invalid slug" do
|
65
|
+
before { subject.validate_each(record, :slug, "%") }
|
66
|
+
it { record.errors.to_hash.should == {:slug => ["is not a valid path segment."]} }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
describe Circuit do
|
5
|
+
include SpecHelpers::LoggerHelpers
|
6
|
+
include SpecHelpers::StoresCleaner
|
7
|
+
|
8
|
+
context 'object' do
|
9
|
+
subject { lambda { Circuit } }
|
10
|
+
it { should_not raise_error }
|
11
|
+
end
|
12
|
+
|
13
|
+
context "logger" do
|
14
|
+
context "default" do
|
15
|
+
subject { Circuit.logger }
|
16
|
+
it { should be_instance_of(::Logger) }
|
17
|
+
end
|
18
|
+
|
19
|
+
context "set" do
|
20
|
+
before &:clean_logger!
|
21
|
+
let(:new_logger) { ::Logger.new(StringIO.new) }
|
22
|
+
before { Circuit.logger = new_logger }
|
23
|
+
subject { Circuit.logger }
|
24
|
+
it { should == new_logger }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "change" do
|
28
|
+
let(:new_logger) { ::Logger.new(StringIO.new) }
|
29
|
+
before { Circuit.logger = new_logger }
|
30
|
+
subject { Circuit.logger }
|
31
|
+
it { should == new_logger }
|
32
|
+
it { should_not == default_logger }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "site store" do
|
37
|
+
let(:klass) { $mongo_tests ? Circuit::Storage::Sites::MongoidStore : Circuit::Storage::Sites::MemoryStore }
|
38
|
+
|
39
|
+
context "get" do
|
40
|
+
let(:mock_instance) { mock() }
|
41
|
+
before { Circuit::Storage::Sites.expects(:instance).returns(mock_instance) }
|
42
|
+
after { Circuit::Storage::Sites.unstub(:instance) }
|
43
|
+
it { Circuit.site_store.should == mock_instance}
|
44
|
+
end
|
45
|
+
|
46
|
+
context "not set" do
|
47
|
+
it do
|
48
|
+
expect { Circuit.site_store }.
|
49
|
+
to raise_error(Circuit::Storage::InstanceUndefinedError, "Storage instance is undefined.")
|
50
|
+
end
|
51
|
+
it { expect { Circuit::Site }.to raise_error(NameError) }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "set by class" do
|
55
|
+
before { Circuit.set_site_store klass }
|
56
|
+
it { Circuit.site_store.should be_instance_of klass }
|
57
|
+
it { Circuit::Site.should == klass.const_get(:Site) }
|
58
|
+
end
|
59
|
+
|
60
|
+
context "set by instance" do
|
61
|
+
let(:instance) { klass.new }
|
62
|
+
before { Circuit.set_site_store instance }
|
63
|
+
it { Circuit.site_store.should == instance }
|
64
|
+
it { Circuit::Site.should == klass.const_get(:Site) }
|
65
|
+
end
|
66
|
+
|
67
|
+
context "set by symbol" do
|
68
|
+
before { Circuit.set_site_store($mongo_tests ? :mongoid_store : :memory_store) }
|
69
|
+
it { Circuit.site_store.should be_instance_of(klass) }
|
70
|
+
it { Circuit::Site.should == klass.const_get(:Site) }
|
71
|
+
end
|
72
|
+
|
73
|
+
context "set wrong type" do
|
74
|
+
it do
|
75
|
+
expect { Circuit.set_site_store Object.new }.
|
76
|
+
to raise_error(ArgumentError, "Unexpected type for storage instance: Object")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "set with no Site class" do
|
81
|
+
it do
|
82
|
+
expect { Circuit.set_site_store Object }.
|
83
|
+
to raise_error(ArgumentError, "Cannot determine a Site or Node class for storage type: Object")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "node store" do
|
89
|
+
let(:klass) { $mongo_tests ? Circuit::Storage::Nodes::MongoidStore : Circuit::Storage::Nodes::MemoryStore }
|
90
|
+
|
91
|
+
context "get" do
|
92
|
+
let(:mock_instance) { mock() }
|
93
|
+
before { Circuit::Storage::Nodes.expects(:instance).returns(mock_instance) }
|
94
|
+
after { Circuit::Storage::Nodes.unstub(:instance) }
|
95
|
+
it { Circuit.node_store.should == mock_instance}
|
96
|
+
end
|
97
|
+
|
98
|
+
context "not set" do
|
99
|
+
it do
|
100
|
+
expect { Circuit.node_store }.
|
101
|
+
to raise_error(Circuit::Storage::InstanceUndefinedError, "Storage instance is undefined.")
|
102
|
+
end
|
103
|
+
it { expect { Circuit::Node }.to raise_error(NameError) }
|
104
|
+
end
|
105
|
+
|
106
|
+
context "set by class" do
|
107
|
+
before { Circuit.set_node_store klass }
|
108
|
+
it { Circuit.node_store.should be_instance_of klass }
|
109
|
+
it { Circuit::Node.should == klass.const_get(:Node) }
|
110
|
+
end
|
111
|
+
|
112
|
+
context "set by instance" do
|
113
|
+
let(:instance) { klass.new }
|
114
|
+
before { Circuit.set_node_store instance }
|
115
|
+
it { Circuit.node_store.should == instance }
|
116
|
+
it { Circuit::Node.should == klass.const_get(:Node) }
|
117
|
+
end
|
118
|
+
|
119
|
+
context "set by symbol" do
|
120
|
+
before { Circuit.set_node_store($mongo_tests ? :mongoid_store : :memory_store) }
|
121
|
+
it { Circuit.node_store.should be_instance_of klass }
|
122
|
+
it { Circuit::Node.should == klass.const_get(:Node) }
|
123
|
+
end
|
124
|
+
|
125
|
+
context "set wrong type" do
|
126
|
+
it do
|
127
|
+
expect { Circuit.set_node_store Object.new }.
|
128
|
+
to raise_error(ArgumentError, "Unexpected type for storage instance: Object")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "set with no Node class" do
|
133
|
+
it do
|
134
|
+
expect { Circuit.set_node_store Object }.
|
135
|
+
to raise_error(ArgumentError, "Cannot determine a Site or Node class for storage type: Object")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|