1
0
mirror of https://github.com/meineerde/rackstash.git synced 2026-02-11 13:05:19 +00:00
rackstash/spec/rackstash/adapter_spec.rb
Holger Just aa37d47b8f Singularize the Adapter and Encoder modules
Since we are using single objects from these namespaces, they are much
more suitable to be named in singular than in plural.
2017-10-20 22:27:50 +02:00

281 lines
9.1 KiB
Ruby

# frozen_string_literal: true
#
# Copyright 2017 Holger Just
#
# This software may be modified and distributed under the terms
# of the MIT license. See the LICENSE.txt file for details.
require 'spec_helper'
require 'rackstash/adapter'
describe Rackstash::Adapter do
around(:each) do |example|
types = described_class.send(:adapter_types)
schemes = described_class.send(:adapter_schemes)
described_class.instance_variable_set(:@adapter_types, nil)
described_class.instance_variable_set(:@adapter_schemes, nil)
example.run
described_class.instance_variable_set(:@adapter_types, types)
described_class.instance_variable_set(:@adapter_schemes, schemes)
end
let(:adapter) {
Class.new(Rackstash::Adapter::Adapter) do
def self.from_uri(*args)
new(*args)
end
end
}
describe '#register' do
it 'can register a class' do
expect {
described_class.register adapter, Class.new
described_class.register adapter, String
described_class.register adapter, Numeric
described_class.register adapter, Integer
}.to change { described_class.send(:adapter_types).size }
.from(0).to(4)
expect(described_class.send(:adapter_schemes).size).to eql 0
end
it 'can register a class name (upper-case String)' do
expect {
described_class.register adapter, '❤'
described_class.register adapter, ''
described_class.register adapter, 'Hello::World'
}.to change { described_class.send(:adapter_types).size }
.from(0).to(3)
# Registering 'Hello::World' a second time overwrites the first one
expect {
described_class.register(adapter, 'Hello::World')
}.not_to change { described_class.send(:adapter_types).size }
expect(described_class.send(:adapter_schemes).size).to eql 0
end
it 'can register a method name (symbol)' do
expect {
described_class.register adapter, :foo
}.to change { described_class.send(:adapter_types).size }
.from(0).to(1)
expect(described_class.send(:adapter_schemes).size).to eql 0
end
it 'can register a proc' do
expect {
described_class.register adapter, ->(o) { o.respond_to?(:write) }
described_class.register adapter, -> {}
}.to change { described_class.send(:adapter_types).size }
.from(0).to(2)
expect(described_class.send(:adapter_schemes).size).to eql 0
end
it 'can register a scheme (lower-case String)' do
expect {
described_class.register adapter, 'customscheme'
}.to change { described_class.send(:adapter_schemes).size }
.from(0).to(1)
expect(described_class.send(:adapter_types).size).to eql 0
end
it 'rejects invalid adapter classes' do
expect { described_class.register nil, :foo }
.to raise_error(TypeError)
expect { described_class.register Class.new, :foo }
.to raise_error(TypeError)
end
it 'rejects invalid matchers' do
matcher = Object.new
matcher.instance_eval do
undef :===
end
expect { described_class.register(adapter, matcher) }
.to raise_error(TypeError)
end
end
describe '#[]' do
context 'with a registered class' do
let(:device_class) { Class.new }
before do
described_class.register adapter, device_class
end
it 'creates an adapter if the class was found' do
device = device_class.new
expect(device_class).to receive(:===).with(device).and_call_original
expect(adapter).to receive(:new).with(device).and_call_original
expect(described_class[device]).to be_an Rackstash::Adapter::Adapter
end
it 'creates an adapter if any parent class was found' do
inherited_device = Class.new(device_class).new
expect(device_class).to receive(:===).with(inherited_device).and_call_original
expect(adapter).to receive(:new).with(inherited_device).and_call_original
expect(described_class[inherited_device]).to be_an Rackstash::Adapter::Adapter
end
it 'raises if no class was found' do
expect(adapter).to_not receive(:new)
expect { described_class['foo'] }.to raise_error(ArgumentError)
end
end
context 'with a registered class name' do
before do
class SpecDevice; end
class InheritedSpecDevice < SpecDevice; end
described_class.register adapter, 'SpecDevice'
end
after do
Object.send :remove_const, :InheritedSpecDevice
Object.send :remove_const, :SpecDevice
end
it 'creates an adapter if the class was found' do
device = SpecDevice.new
expect(adapter).to receive(:new).with(device).and_call_original
expect(described_class[device]).to be_an Rackstash::Adapter::Adapter
end
it 'creates an adapter if any parent class was found' do
inherited_device = InheritedSpecDevice.new
expect(adapter).to receive(:new).with(inherited_device).and_call_original
expect(described_class[inherited_device]).to be_an Rackstash::Adapter::Adapter
end
it 'raises if no class was found' do
expect(adapter).to_not receive(:new)
expect { described_class['foo'] }.to raise_error(ArgumentError)
end
end
context 'with a registered symbol' do
before do
described_class.register adapter, :foo
end
it 'creates an adapter if it responds to the registered method' do
device = Struct.new(:foo).new('foo')
expect(adapter).to receive(:new).with(device).and_call_original
expect(described_class[device]).to be_an Rackstash::Adapter::Adapter
end
it 'raises if it does not respond to the registered method' do
device = Struct.new(:bar).new('bar')
expect(adapter).to_not receive(:new)
expect { described_class[device] }.to raise_error(ArgumentError)
end
end
context 'with a registered proc' do
let(:device) { Object.new }
it 'creates an adapter if the proc returns true' do
checker = proc { true }
described_class.register adapter, checker
expect(checker).to receive(:===).with(device).and_call_original
expect(adapter).to receive(:new).with(device).and_call_original
expect(described_class[device]).to be_an Rackstash::Adapter::Adapter
end
it 'does not create an adapter if the proc returns false' do
checker = proc { false }
described_class.register adapter, checker
expect(checker).to receive(:===).with(device).and_call_original
expect(adapter).to_not receive(:new)
expect { described_class[device] }.to raise_error(ArgumentError)
end
end
context 'with a registered scheme' do
before do
described_class.register adapter, 'dummy'
end
it 'creates an adapter from the scheme' do
raw_uri = 'dummy://example.com'
expect(adapter).to receive(:from_uri).with(URI(raw_uri)).and_call_original
expect(described_class[raw_uri]).to be_an Rackstash::Adapter::Adapter
end
it 'calls adapter.new if adapter.from_uri is not available' do
plain_adapter = Class.new(Rackstash::Adapter::Adapter)
described_class.register plain_adapter, 'dummy'
raw_uri = 'dummy://example.com'
expect(plain_adapter).to receive(:new).with(URI(raw_uri)).and_call_original
expect(described_class[raw_uri]).to be_a plain_adapter
end
it 'creates an adapter from a URI' do
uri = URI('dummy://example.com')
expect(adapter).to receive(:from_uri).with(uri).and_call_original
expect(described_class[uri]).to be_an Rackstash::Adapter::Adapter
end
it 'raises if no scheme was found' do
expect(adapter).to_not receive(:new)
expect(adapter).to_not receive(:from_uri)
expect { described_class['unknown://example.com'] }
.to raise_error(ArgumentError)
expect { described_class[URI('unknown://example.com')] }
.to raise_error(ArgumentError)
end
context 'and a registered class' do
before do
described_class.register adapter, Object
end
it 'falls though on invalid URI' do
invalid_uri = '::'
expect(adapter).to_not receive(:from_uri)
# from the fallback
expect(adapter).to receive(:new).with(invalid_uri).and_call_original
expect(described_class[invalid_uri]).to be_an Rackstash::Adapter::Adapter
end
it 'falls though if no scheme was found' do
unknown_uri = 'unknown://example.com'
expect(adapter).to_not receive(:from_uri)
expect(adapter).to receive(:new).with(unknown_uri).and_call_original
expect(described_class[unknown_uri]).to be_an Rackstash::Adapter::Adapter
end
end
end
context 'with an existing adapter object' do
it 'just returns the object' do
adapter_instance = adapter.new
described_class.register adapter, Object
expect(adapter).to_not receive(:new)
expect(described_class[adapter_instance]).to equal adapter_instance
end
end
end
end