circuit 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|