Merge pull request #43 from rtyler/platform-specific-specs

Clean up RSpecs to run the platform-specific tests in the right runtime
This commit is contained in:
R. Tyler Croy 2014-10-08 11:07:04 -07:00
commit 23e4cb41d9
13 changed files with 163 additions and 146 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@ tmp/
*.jar
.ruby-gemset
.ruby-version
Gemfile.lock

View File

@ -2,6 +2,6 @@ language: ruby
rvm:
- ruby-head
- 2.1
- 2.0
- 1.9.3
- 1.8.7
- jruby

View File

@ -16,8 +16,7 @@ Usage is modelled on the
straightforward.
- Kafka 0.8 is supported.
- Ruby 1.8.7 and Ruby 2.1.1 have been tested, but JRuby and versions
>= 1.8 should work as long as the librdkafka library is installed.
- Ruby 1.9.3, 2.1.1 and JRuby are tested against
- This is an early alpha version of the gem, so expect bumps in the
road.
@ -54,7 +53,3 @@ yet coordinate partition (re)assigment within consumer groups.
messages.each do
|msg| p.push(msg)
end
## Questions?
Stan Campbell can be reached at stan.campbell3 at( @ ) gmail.com

View File

@ -12,7 +12,15 @@ Rake::ExtensionTask.new do |t|
end
RSpec::Core::RakeTask.new(:spec) do |r|
r.rspec_opts = '--tag ~type:integration'
options = ['--tag ~type:integration']
if RUBY_PLATFORM == 'java'
options << '--tag ~platform:mri'
else
options << '--tag ~platform:java'
end
r.rspec_opts = options.join(' ')
end
namespace :spec do
@ -29,5 +37,10 @@ end
task :build => [:compile]
task :clean => [:removetmp]
task :default => [:clean, :build, :spec]
if RUBY_PLATFORM == 'java'
task :default => [:clean, :spec]
else
task :default => [:clean, :build, :spec]
end

View File

@ -3,14 +3,15 @@ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/lib'))
require 'hermann/version'
SPEC = Gem::Specification.new do |s|
Gem::Specification.new do |s|
s.name = "hermann"
s.version = Hermann::VERSION
s.authors = ["Stan Campbell", 'R. Tyler Croy']
s.description = 'Ruby gem wrapper for librdkafka'
s.summary = 'A Kafka consumer/producer gem based on the librdkafka C library.'
s.email = ['stan.campbell3@gmail.com', 'rtyler.croy@lookout.com']
s.authors = ['R. Tyler Croy', "Stan Campbell"]
s.description = 'Ruby gem for talking to Kafka'
s.summary = 'A Kafka consumer/producer gem supporting both MRI and JRuby'
s.email = ['rtyler.croy@lookout.com', 'stan.campbell3@gmail.com']
s.homepage = 'https://github.com/lookout/Hermann'
s.licenses = ['MIT']
@ -22,7 +23,7 @@ SPEC = Gem::Specification.new do |s|
s.rubygems_version = '2.2.2'
s.specification_version = 3 if s.respond_to?(:specification_version)
s.add_dependency 'concurrent-ruby'
s.add_dependency 'concurrent-ruby', '~> 0.7.0'
if RUBY_PLATFORM == "java"
s.add_runtime_dependency 'jar-dependencies', '~>0.1.2'

View File

@ -1,5 +1,10 @@
module Hermann
if RUBY_PLATFORM == "java"
def self.jruby?
return RUBY_PLATFORM == "java"
end
if self.jruby?
require 'java'
require 'hermann_jars'
module JavaUtil

View File

@ -1,5 +1,8 @@
require 'hermann'
require 'hermann_lib'
unless Hermann.jruby?
require 'hermann_lib'
end
module Hermann
class Consumer
@ -9,7 +12,9 @@ module Hermann
@topic = topic
@brokers = brokers
@partition = partition
@internal = Hermann::Lib::Consumer.new(topic, brokers, partition)
unless Hermann.jruby?
@internal = Hermann::Lib::Consumer.new(topic, brokers, partition)
end
end
def consume(&block)

View File

@ -1,4 +1,3 @@
require 'java'
require 'hermann'
require 'concurrent'
@ -65,4 +64,4 @@ module Hermann
end
end
end
end
end

View File

@ -1,15 +1,15 @@
# this is a generated file, to avoid over-writing it just delete this comment
require 'jar_dependencies'
require_jar( 'org.slf4j', 'slf4j-api', '1.7.2' )
require_jar( 'org.scala-lang', 'scala-library', '2.10.1' )
require_jar( 'log4j', 'log4j', '1.2.14' )
require_jar( 'com.yammer.metrics', 'metrics-core', '2.2.0' )
require_jar( 'org.apache.zookeeper', 'zookeeper', '3.3.4' )
require_jar( 'net.sf.jopt-simple', 'jopt-simple', '3.2' )
require_jar( 'org.apache.kafka', 'kafka_2.10', '0.8.1.1' )
require_jar( 'jline', 'jline', '0.9.94' )
require_jar( 'com.101tec', 'zkclient', '0.3' )
require_jar( 'org.mod4j.org.eclipse.xtext', 'log4j', '1.2.15' )
require_jar( 'junit', 'junit', '3.8.1' )
require_jar( 'com.101tec', 'zkclient', '0.3' )
require_jar( 'com.yammer.metrics', 'metrics-core', '2.2.0' )
require_jar( 'jline', 'jline', '0.9.94' )
require_jar( 'net.sf.jopt-simple', 'jopt-simple', '3.2' )
require_jar( 'org.apache.zookeeper', 'zookeeper', '3.3.4' )
require_jar( 'log4j', 'log4j', '1.2.14' )
require_jar( 'org.mod4j.org.eclipse.xtext', 'log4j', '1.2.15' )
require_jar( 'org.slf4j', 'slf4j-api', '1.7.2' )
require_jar( 'org.apache.kafka', 'kafka_2.10', '0.8.1.1' )
require_jar( 'org.scala-lang', 'scala-library', '2.10.1' )
require_jar( 'org.xerial.snappy', 'snappy-java', '1.0.5' )

View File

@ -1,7 +1,9 @@
require 'spec_helper'
require 'hermann/consumer'
describe Hermann::Consumer do
# XXX: Hermann::Consumer isn't really supported anywhere, MRI included right
# now
describe Hermann::Consumer, :platform => :mri do
subject(:consumer) { described_class.new(topic, brokers, partition) }
let(:topic) { 'rspec' }

View File

@ -1,10 +1,13 @@
require 'spec_helper'
require 'hermann_lib'
describe Hermann::Lib::Producer do
describe 'Hermann::Lib::Producer', :platform => :mri do
before :all do
require 'hermann_lib'
end
let(:topic) { 'rspec' }
let(:brokers) { 'localhost:1337' }
subject(:producer) { described_class.new(topic, brokers) }
subject(:producer) { Hermann::Lib::Producer.new(topic, brokers) }
let(:timeout) { 3000 }
it { should respond_to :push_single }

View File

@ -7,155 +7,148 @@ describe Hermann::Producer do
let(:topic) { 'rspec' }
let(:brokers) { 'localhost:1337' }
context "java" do
if RUBY_PLATFORM == "java"
describe '#create_result' do
subject { producer.create_result }
context "java", :platform => :java do
describe '#create_result' do
subject { producer.create_result }
it { should be_instance_of Hermann::Result }
it { should be_instance_of Hermann::Result }
it 'should add the result to the producers children' do
expect(producer.children).to be_empty
expect(subject).to be_instance_of Hermann::Result
expect(producer.children).to_not be_empty
end
it 'should add the result to the producers children' do
expect(producer.children).to be_empty
expect(subject).to be_instance_of Hermann::Result
expect(producer.children).to_not be_empty
end
end
end
context "not java" do
if RUBY_PLATFORM != "java"
describe '#push' do
subject(:result) { producer.push(value) }
context "not java", :platform => :mri do
describe '#push' do
subject(:result) { producer.push(value) }
context 'error conditions' do
shared_examples 'an error condition' do
it 'should raise an exception' do
expect { producer.push('rspec') }.to raise_error(RuntimeError)
end
end
context 'with a bad broker configuration' do
let(:brokers) { '' }
it_behaves_like 'an error condition'
end
context 'with a non-existing broker' do
let(:brokers) { 'localhost:13337' }
let(:timeout) { 2 }
let(:value) { 'rspec' }
it 'should reject' do
future = result
expect(future).not_to be_nil
producer.tick_reactor(timeout)
expect(future).to be_rejected
end
end
context 'with a bad topic' do
let(:topic) { '' }
it_behaves_like 'an error condition'
context 'error conditions' do
shared_examples 'an error condition' do
it 'should raise an exception' do
expect { producer.push('rspec') }.to raise_error(RuntimeError)
end
end
context 'with a single value' do
let(:value) { 'hello' }
context 'with a bad broker configuration' do
let(:brokers) { '' }
it_behaves_like 'an error condition'
end
it 'should invoke #push_single' do
expect(producer.internal).to receive(:push_single)
expect(result).to be_instance_of Hermann::Result
context 'with a non-existing broker' do
let(:brokers) { 'localhost:13337' }
let(:timeout) { 2 }
let(:value) { 'rspec' }
it 'should reject' do
future = result
expect(future).not_to be_nil
producer.tick_reactor(timeout)
expect(future).to be_rejected
end
end
context 'with an array value' do
let(:value) { ['hello', 'world'] }
it 'should invoke #push_single for each element' do
value.each do |v|
expect(producer.internal).to receive(:push_single).with(v, anything)
end
expect(result).to be_instance_of Array
result.each do |elem|
expect(elem).to be_instance_of Hermann::Result
end
end
context 'with a bad topic' do
let(:topic) { '' }
it_behaves_like 'an error condition'
end
end
describe '#create_result' do
subject { producer.create_result }
context 'with a single value' do
let(:value) { 'hello' }
it { should be_instance_of Hermann::Result }
it 'should add the result to the producers children' do
expect(producer.children).to be_empty
expect(subject).to be_instance_of Hermann::Result
expect(producer.children).to_not be_empty
it 'should invoke #push_single' do
expect(producer.internal).to receive(:push_single)
expect(result).to be_instance_of Hermann::Result
end
end
context 'with an array value' do
let(:value) { ['hello', 'world'] }
describe '#connected?' do
subject { producer.connected? }
context 'by default' do
before :each do
expect(producer.internal).to receive(:connected?).and_call_original
it 'should invoke #push_single for each element' do
value.each do |v|
expect(producer.internal).to receive(:push_single).with(v, anything)
end
it { should be false }
expect(result).to be_instance_of Array
result.each do |elem|
expect(elem).to be_instance_of Hermann::Result
end
end
end
end
describe '#connect' do
let(:timeout) { 0 }
subject(:connect!) { producer.connect(timeout) }
describe '#create_result' do
subject { producer.create_result }
it 'should delegate connection to the underlying Producer' do
expect(producer.internal).to receive(:connect).and_call_original
connect!
end
it { should be_instance_of Hermann::Result }
it 'should add the result to the producers children' do
expect(producer.children).to be_empty
expect(subject).to be_instance_of Hermann::Result
expect(producer.children).to_not be_empty
end
end
describe '#tick_reactor' do
let(:timeout) { 0 }
let(:internal) { double('Hermann::Lib::Producer mock') }
subject(:tick) { producer.tick_reactor(timeout) }
describe '#connected?' do
subject { producer.connected? }
context 'by default' do
before :each do
3.times do
child = Hermann::Result.new(producer)
allow(child).to receive(:reap?) { reap }
producer.children << child
end
producer.instance_variable_set(:@internal, internal)
expect(internal).to receive(:tick)
expect(producer.internal).to receive(:connected?).and_call_original
end
context 'with no reapable children' do
let(:reap) { false }
it { should be false }
end
end
it 'should not reap the children' do
count = producer.children.size
expect(tick).to eql(0)
expect(producer.children.size).to eql(count)
end
describe '#connect' do
let(:timeout) { 0 }
subject(:connect!) { producer.connect(timeout) }
it 'should delegate connection to the underlying Producer' do
expect(producer.internal).to receive(:connect).and_call_original
connect!
end
end
describe '#tick_reactor' do
let(:timeout) { 0 }
let(:internal) { double('Hermann::Lib::Producer mock') }
subject(:tick) { producer.tick_reactor(timeout) }
before :each do
3.times do
child = Hermann::Result.new(producer)
allow(child).to receive(:reap?) { reap }
producer.children << child
end
context 'with reapable children' do
let(:reap) { true }
producer.instance_variable_set(:@internal, internal)
expect(internal).to receive(:tick)
end
it 'should not reap the children' do
count = producer.children.size
expect(tick).to eql(count)
expect(producer.children.size).to_not eql(count)
end
context 'with no reapable children' do
let(:reap) { false }
it 'should not reap the children' do
count = producer.children.size
expect(tick).to eql(0)
expect(producer.children.size).to eql(count)
end
end
context 'with reapable children' do
let(:reap) { true }
it 'should not reap the children' do
count = producer.children.size
expect(tick).to eql(count)
expect(producer.children.size).to_not eql(count)
end
end
end
end
end

View File

@ -1,7 +1,7 @@
require 'spec_helper'
require 'hermann/provider/java_producer'
describe Hermann::Provider::JavaProducer do
describe Hermann::Provider::JavaProducer, :platform => :java do
subject(:producer) { described_class.new(topic, brokers) }
let(:topic) { 'rspec' }