diff --git a/.autotest b/.autotest deleted file mode 100644 index 4ff5008..0000000 --- a/.autotest +++ /dev/null @@ -1,41 +0,0 @@ -# vim: syntax=ruby - -require 'autotest/restart' -# vim: ft=ruby - -Autotest.add_hook :initialize do |at| - - at.libs = %w[lib spec].join(File::PATH_SEPARATOR) - at.testlib = 'rspec' - - at.add_exception 'coverage.info' - at.add_exception 'coverage' - at.add_exception '.git' - - at.clear_mappings - - # file in /spec -> run it - at.add_mapping(%r|^spec/.*_spec\.rb$|) do |filename, _| - filename - end - - # file in /lib -> run test in /spec - at.add_mapping(%r|^lib/(.*)\.rb$|) do |_, match| - at.files_matching %r|^spec/#{match[1]}_spec.rb| - end - - at.add_mapping(%r|^spec/spec_helper\.rb|) do - at.files_matching( %r|^spec/.*_spec\.rb| ) - end - - # Make the class map for things in lib - class_map = {} - sep = File::SEPARATOR - Dir.glob("lib/**/*.rb").each do |f| - c = f.sub(/lib#{sep}/,'').sub(/\.rb$/,'').split sep - c = c.map { |path| path.split(/_|(\d+)/).map { |seq| seq.capitalize }.join } - class_map[c.join("::")] = f - end - at.extra_class_map = class_map -end - diff --git a/.gemtest b/.gemtest deleted file mode 100644 index 8b13789..0000000 --- a/.gemtest +++ /dev/null @@ -1 +0,0 @@ - diff --git a/.gitignore b/.gitignore index 60f7bb5..c0230a1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,8 @@ doc/ coverage/ coverage.info kestrel/ -*.gemspec -Gemfile* +tags +*.swp +# artifact of testing with redis +*.rdb +Gemfile.lock diff --git a/.rvmrc b/.rvmrc deleted file mode 100644 index d8200b9..0000000 --- a/.rvmrc +++ /dev/null @@ -1 +0,0 @@ -rvm use @qup --create diff --git a/.travis.yml b/.travis.yml index 12f7204..8adcbf1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,9 @@ language: ruby rvm: - - "1.9.2" - - "1.9.3" - "2.0.0" - - "2.1.0" - - jruby-18mode # JRuby in 1.8 mode + - "2.1.5" + - "2.2.0" - jruby-19mode # JRuby in 1.9 mode - rbx -install: rake develop +services: + - redis-server diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7770aab..276d6ec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,7 @@ easiest way to contribute. * **Bug reports** please be as detailed as possible. Include: * full ruby engine and version: `ruby -e 'puts RUBY_DESCRIPTION'` * operating system and version - * version of fixme `ruby -rubygems -e "require 'fixme'; puts Fixme::VERSION"` + * version of qup `ruby -rubygems -e "require 'qup'; puts Qup::VERSION"` * as much detail about the bug as possible so I can replicate it. Feel free to link in a [gist][] * **New Feature** @@ -39,8 +39,8 @@ easiest way to contribute. * [Kevin Barnes](https://github.com/vinbarnes) [GitHub Account]: https://github.com/signup/free "GitHub Signup" -[GitHub Issues]: https://github.com/copiousfreetime/fixme/issues "Fixme Issues" -[new issue]: https://github.com/copiousfreetime/fixme/issues/new "New Fixme Issue" +[GitHub Issues]: https://github.com/copiousfreetime/qup/issues "Qup Issues" +[new issue]: https://github.com/copiousfreetime/qup/issues/new "New Qup Issue" [gist]: https://gist.github.com/ "New Gist" -[repo]: https://github.com/copiousfreetime/fixme "Fixme Repo" +[repo]: https://github.com/copiousfreetime/qup "Qup Repo" [pull request]: https://help.github.com/articles/using-pull-requests "Using Pull Requests" diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..01102ad --- /dev/null +++ b/Gemfile @@ -0,0 +1,2 @@ +source "https://rubygems.org/" +gemspec diff --git a/Rakefile b/Rakefile index 01fcb71..b8f5c14 100644 --- a/Rakefile +++ b/Rakefile @@ -9,16 +9,20 @@ This.homepage = "http://github.com/copiousfreetime/#{ This.name }" This.ruby_gemspec do |spec| # The Runtime Dependencies + # FIXME: when jruby has a 2.0 mode update this to 2.2 In the meantime + # there is no real update to maildir other than a new requirement for ruby 2.0 spec.add_runtime_dependency( 'maildir', '~> 2.1.0' ) # Additional functionality if used - spec.add_development_dependency( 'kjess' , '~> 1.2' ) + # FIXME: remove completely at some point + # spec.add_development_dependency( 'kjess' , '~> 1.2' ) spec.add_development_dependency( 'redis' , '~> 3.0' ) # The Development Dependencies - spec.add_development_dependency( 'rake' , '~> 10.1.0' ) - spec.add_development_dependency( 'rspec' , '~> 2.14.0' ) - spec.add_development_dependency( 'rdoc' , '~> 4.0' ) + spec.add_development_dependency( 'simplecov' , '~> 0.9' ) + spec.add_development_dependency( 'rake' , '~> 10.4') + spec.add_development_dependency( 'rspec' , '~> 3.2' ) + spec.add_development_dependency( 'rdoc' , '~> 4.0' ) end diff --git a/lib/qup/adapter/redis.rb b/lib/qup/adapter/redis.rb index b42dafb..d6702a7 100644 --- a/lib/qup/adapter/redis.rb +++ b/lib/qup/adapter/redis.rb @@ -15,6 +15,8 @@ class Redis < ::Qup::Adapter def initialize( uri, options = {} ) @uri = uri @options = options + @client = ::Redis.new host: @uri.host, port: @uri.port + @client.ping @closed = false end @@ -24,7 +26,7 @@ def initialize( uri, options = {} ) # # Returns a Qup::Queue def queue( name ) - Qup::Adapter::Redis::Queue.new( @uri, name ) + Qup::Adapter::Redis::Queue.new( @client, name ) end # Internal: Create a new Topic from this Adapter @@ -33,13 +35,14 @@ def queue( name ) # # Returns a Qup::Topic def topic( name ) - Qup::Adapter::Redis::Topic.new( @uri, name ) + Qup::Adapter::Redis::Topic.new( @client, name ) end # Internal: Close the Redis adapter # # Return nothing def close + @client.disconnect! @closed = true end @@ -47,7 +50,7 @@ def close # # Returns true or false def closed? - @closed + not @client.connected? end end end diff --git a/lib/qup/adapter/redis/connection.rb b/lib/qup/adapter/redis/destination.rb similarity index 57% rename from lib/qup/adapter/redis/connection.rb rename to lib/qup/adapter/redis/destination.rb index b0d214d..c465812 100644 --- a/lib/qup/adapter/redis/connection.rb +++ b/lib/qup/adapter/redis/destination.rb @@ -2,7 +2,7 @@ class Qup::Adapter::Redis # # Internal: The Common base class for Redis Topic and Queue # - class Connection + class Destination # Public: the name of the Queue or Topic attr_reader :name @@ -13,19 +13,18 @@ class Connection # name - the String name of the Connection # # Returns a new Connection. - def initialize( uri, name ) - @uri = uri - @client = Redis.new :host => @uri.host, :port => @uri.port + def initialize( client, name ) + @client = client @name = name + ping end - # Public: destroy the connection + # Internal: Make sure the Topic or Queue exists # - # Closes the redis client connection. - # - # Returns nothing. - def destroy - @client.client.disconnect + # Returns nothing + def ping + @client.ping + return true end end diff --git a/lib/qup/adapter/redis/queue.rb b/lib/qup/adapter/redis/queue.rb index 7ce3412..7c025ea 100644 --- a/lib/qup/adapter/redis/queue.rb +++ b/lib/qup/adapter/redis/queue.rb @@ -1,21 +1,21 @@ -require 'qup/adapter/redis/connection' +require 'qup/adapter/redis/destination' class Qup::Adapter::Redis # # Internal: The Qup implementation for a Redis Queue # - class Queue < Connection + class Queue < Destination include Qup::QueueAPI # Internal: create a new Queue # - # uri - the connection uri for the Redis Client + # client - the Redis client # name - the String name of the Queue # topic_name - (optional) the String name of a parent topic # # Returns a new Queue. - def initialize( uri, name, topic_name = nil ) - super uri, name + def initialize( client, name, topic_name = nil ) + super( client, name ) @topic_name = topic_name @open_messages = {} end diff --git a/lib/qup/adapter/redis/topic.rb b/lib/qup/adapter/redis/topic.rb index 3fdb061..104f3aa 100644 --- a/lib/qup/adapter/redis/topic.rb +++ b/lib/qup/adapter/redis/topic.rb @@ -1,4 +1,4 @@ -require 'qup/adapter/redis/connection' +require 'qup/adapter/redis/destination' class Qup::Adapter::Redis # @@ -8,7 +8,7 @@ class Qup::Adapter::Redis # rather it guarantees durability of all published messages by using # sub-queues internally to deliver messages to subscribers. # - class Topic < Connection + class Topic < Destination include Qup::TopicAPI # Internal: Creates a Publisher for the Topic @@ -29,7 +29,7 @@ def publisher def subscriber(name) subscriber_name = "#{@name}.#{name}" @client.sadd @name, subscriber_name - queue = ::Qup::Adapter::Redis::Queue.new(@uri, subscriber_name, @name) + queue = ::Qup::Adapter::Redis::Queue.new(@client, subscriber_name, @name) ::Qup::Subscriber.new( self, queue ) end @@ -77,7 +77,7 @@ def subscriber_names def subscribers subs = {} subscriber_names.each do |sname| - subs[sname] = ::Qup::Adapter::Redis::Queue.new(@uri, sname, @name) + subs[sname] = ::Qup::Adapter::Redis::Queue.new(@client, sname, @name) end return subs end diff --git a/qup.gemspec b/qup.gemspec new file mode 100644 index 0000000..ef5e034 --- /dev/null +++ b/qup.gemspec @@ -0,0 +1,52 @@ +# DO NOT EDIT - This file is automatically generated +# Make changes to Manifest.txt and/or Rakefile and regenerate +# -*- encoding: utf-8 -*- +# stub: qup 1.4.2 ruby lib + +Gem::Specification.new do |s| + s.name = "qup" + s.version = "1.4.2" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.require_paths = ["lib"] + s.authors = ["Jeremy Hinegardner"] + s.date = "2015-02-18" + s.description = "Qup is a generalized API for Message Queue and Publish/Subscribe messaging patterns with the ability to plug in an appropriate messaging infrastructure based upon your needs. Qup ships with support for (https://github.com/robey/kestrel), (http://redis.io), and a filesystem infrastructure based on (https://rubygems.org/gems/maildir). Additional Adapters will be developed as needs arise. (https://github.com/copiousfreetime/qup/issues) to have a new Adapter created. Pull requests gladly accepted." + s.email = "jeremy@copiousfreetime.org" + s.extra_rdoc_files = ["ADAPTER_API.md", "CONTRIBUTING.md", "HISTORY.md", "Manifest.txt", "README.md"] + s.files = [".autotest", ".gemtest", "ADAPTER_API.md", "CONTRIBUTING.md", "HISTORY.md", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "lib/qup.rb", "lib/qup/adapter.rb", "lib/qup/adapter/kestrel.rb", "lib/qup/adapter/kestrel/destination.rb", "lib/qup/adapter/kestrel/queue.rb", "lib/qup/adapter/kestrel/topic.rb", "lib/qup/adapter/maildir.rb", "lib/qup/adapter/maildir/queue.rb", "lib/qup/adapter/maildir/topic.rb", "lib/qup/adapter/redis.rb", "lib/qup/adapter/redis/connection.rb", "lib/qup/adapter/redis/queue.rb", "lib/qup/adapter/redis/topic.rb", "lib/qup/backoff_sleeper.rb", "lib/qup/batch_consumer.rb", "lib/qup/consumer.rb", "lib/qup/message.rb", "lib/qup/producer.rb", "lib/qup/publisher.rb", "lib/qup/queue_api.rb", "lib/qup/session.rb", "lib/qup/subscriber.rb", "lib/qup/topic_api.rb", "spec/qup/adapter/kestrel/queue_spec.rb", "spec/qup/adapter/kestrel/topic_spec.rb", "spec/qup/adapter/kestrel_context.rb", "spec/qup/adapter/kestrel_spec.rb", "spec/qup/adapter/maildir/queue_spec.rb", "spec/qup/adapter/maildir/topic_spec.rb", "spec/qup/adapter/maildir_context.rb", "spec/qup/adapter/maildir_spec.rb", "spec/qup/adapter/redis/queue_spec.rb", "spec/qup/adapter/redis/topic_spec.rb", "spec/qup/adapter/redis_context.rb", "spec/qup/adapter/redis_spec.rb", "spec/qup/adapter_spec.rb", "spec/qup/backoff_sleeper_sleeper_spec.rb", "spec/qup/batch_consumer_spec.rb", "spec/qup/consumer_spec.rb", "spec/qup/message_spec.rb", "spec/qup/producer_spec.rb", "spec/qup/queue_api_spec.rb", "spec/qup/session_spec.rb", "spec/qup/shared_adapter_examples.rb", "spec/qup/shared_queue_examples.rb", "spec/qup/shared_topic_examples.rb", "spec/qup/topic_api_spec.rb", "spec/qup_spec.rb", "spec/spec_helper.rb", "tasks/default.rake", "tasks/this.rb"] + s.homepage = "http://github.com/copiousfreetime/qup" + s.licenses = ["ISC"] + s.rdoc_options = ["--main", "README.md", "--markup", "tomdoc"] + s.required_ruby_version = Gem::Requirement.new(">= 1.9.3") + s.rubygems_version = "2.4.6" + s.summary = "Qup is a generalized API for Message Queue and Publish/Subscribe messaging patterns with the ability to plug in an appropriate messaging infrastructure based upon your needs." + s.test_files = ["spec/qup/adapter/kestrel/queue_spec.rb", "spec/qup/adapter/kestrel/topic_spec.rb", "spec/qup/adapter/kestrel_context.rb", "spec/qup/adapter/kestrel_spec.rb", "spec/qup/adapter/maildir/queue_spec.rb", "spec/qup/adapter/maildir/topic_spec.rb", "spec/qup/adapter/maildir_context.rb", "spec/qup/adapter/maildir_spec.rb", "spec/qup/adapter/redis/queue_spec.rb", "spec/qup/adapter/redis/topic_spec.rb", "spec/qup/adapter/redis_context.rb", "spec/qup/adapter/redis_spec.rb", "spec/qup/adapter_spec.rb", "spec/qup/backoff_sleeper_sleeper_spec.rb", "spec/qup/batch_consumer_spec.rb", "spec/qup/consumer_spec.rb", "spec/qup/message_spec.rb", "spec/qup/producer_spec.rb", "spec/qup/queue_api_spec.rb", "spec/qup/session_spec.rb", "spec/qup/shared_adapter_examples.rb", "spec/qup/shared_queue_examples.rb", "spec/qup/shared_topic_examples.rb", "spec/qup/topic_api_spec.rb", "spec/qup_spec.rb", "spec/spec_helper.rb"] + + if s.respond_to? :specification_version then + s.specification_version = 4 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["~> 2.1.0"]) + s.add_development_dependency(%q, ["~> 3.0"]) + s.add_development_dependency(%q, ["~> 0.9"]) + s.add_development_dependency(%q, ["~> 10.4"]) + s.add_development_dependency(%q, ["~> 3.2"]) + s.add_development_dependency(%q, ["~> 4.0"]) + else + s.add_dependency(%q, ["~> 2.1.0"]) + s.add_dependency(%q, ["~> 3.0"]) + s.add_dependency(%q, ["~> 0.9"]) + s.add_dependency(%q, ["~> 10.4"]) + s.add_dependency(%q, ["~> 3.2"]) + s.add_dependency(%q, ["~> 4.0"]) + end + else + s.add_dependency(%q, ["~> 2.1.0"]) + s.add_dependency(%q, ["~> 3.0"]) + s.add_dependency(%q, ["~> 0.9"]) + s.add_dependency(%q, ["~> 10.4"]) + s.add_dependency(%q, ["~> 3.2"]) + s.add_dependency(%q, ["~> 4.0"]) + end +end diff --git a/spec/qup/adapter/redis/queue_spec.rb b/spec/qup/adapter/redis/queue_spec.rb index ce26135..89a820f 100644 --- a/spec/qup/adapter/redis/queue_spec.rb +++ b/spec/qup/adapter/redis/queue_spec.rb @@ -9,7 +9,7 @@ context "when initialized with a parent topic's name" do let(:redis) { Redis.new :host => uri.host, :port => uri.port } - let(:queue) { Qup::Adapter::Redis::Queue.new(uri, "test", "parent") } + let(:queue) { Qup::Adapter::Redis::Queue.new(redis, "test", "parent") } before do redis.del "parent" @@ -23,9 +23,9 @@ describe "#destroy" do it "removes its name from the parent topic's subscriber set" do - redis.smembers("parent").should be == ["test"] + expect( redis.smembers("parent") ).to eq ["test"] queue.destroy - redis.smembers("parent").should be == [] + expect( redis.smembers("parent") ).to eq [] end end diff --git a/spec/qup/adapter/redis/topic_spec.rb b/spec/qup/adapter/redis/topic_spec.rb index 80fbc03..3f9546a 100644 --- a/spec/qup/adapter/redis/topic_spec.rb +++ b/spec/qup/adapter/redis/topic_spec.rb @@ -21,9 +21,9 @@ end it "unregisters itself from the Topic when unsubscribed" do - lambda do + expect { subscriber.unsubscribe - end.should change(topic, :subscriber_count).by(-1) + }.to change(topic, :subscriber_count).by(-1) end end end diff --git a/spec/qup/adapter_spec.rb b/spec/qup/adapter_spec.rb index 332033e..e1b607e 100644 --- a/spec/qup/adapter_spec.rb +++ b/spec/qup/adapter_spec.rb @@ -6,7 +6,7 @@ class Qup::AdapterTest < Qup::Adapter describe 'Adapter Registration' do it 'registers an adapter' do - Qup::Adapters['quptest'].should eq Qup::AdapterTest + expect( Qup::Adapters['quptest'] ).to eq Qup::AdapterTest end end @@ -15,13 +15,17 @@ class Qup::AdapterTest < Qup::Adapter %w[ close closed? ].each do |method| it "##{method} kaboom!" do - lambda { api.send( method ) }.should raise_error( NotImplementedError, "please implement '#{method}'" ) + expect { + api.send( method ) + }.to raise_error( NotImplementedError, "please implement '#{method}'" ) end end %w[ queue topic ].each do |method| it "##{method} kaboom!" do - lambda { api.send( method, 'foo' ) }.should raise_error( NotImplementedError, "please implement '#{method}'" ) + expect { + api.send( method, 'foo' ) + }.to raise_error( NotImplementedError, "please implement '#{method}'" ) end end diff --git a/spec/qup/backoff_sleeper_sleeper_spec.rb b/spec/qup/backoff_sleeper_sleeper_spec.rb index c6c2b8d..cfb8cb8 100644 --- a/spec/qup/backoff_sleeper_sleeper_spec.rb +++ b/spec/qup/backoff_sleeper_sleeper_spec.rb @@ -2,43 +2,43 @@ module Qup describe BackoffSleeper do - before { Kernel.stub(:sleep) } + before { allow(Kernel).to receive_messages(sleep: nil) } describe "#length" do it "it returns the multiplier averaged with the multiplier multiplied by rand" do - Kernel.stub(:rand).with().and_return(0.5) + expect(Kernel).to receive(:rand).with(no_args).and_return(0.5) sleeper = BackoffSleeper.new - sleeper.stub(:multiplier => 1) + allow(sleeper).to receive_messages(multiplier: 1) - sleeper.length.should be == ((1 + (1 * 0.5)) / 2) + expect( sleeper.length ).to eq( (1 + (1 * 0.5) ) / 2) end end describe "#tick" do it "starts count at 0" do - subject.count.should be == 0 + expect( subject.count ).to eq 0 end it "increments count by 1 everytime it's called" do subject.tick - subject.count.should be == 1 + expect( subject.count ).to eq 1 subject.tick - subject.count.should be == 2 + expect( subject.count ).to eq 2 end it "sleeps for #length if length is > 0" do - Kernel.should_receive(:sleep).with(0.123) + expect( Kernel ).to receive(:sleep).with(0.123) - subject.stub(:length => 0.123) + allow( subject ).to receive_messages(length: 0.123) subject.tick end it "doesn't call sleep if the length is 0" do - Kernel.should_not_receive(:sleep).with(0) + expect( Kernel ).to_not receive(:sleep).with(0) - subject.stub(:length => 0) + allow( subject).to receive_messages(length: 0) subject.tick end end @@ -52,7 +52,7 @@ module Qup describe "#multiplier" do it "starts at 0" do - subject.multiplier.should be == 0 + expect( subject.multiplier ).to eq 0 end it "backs off exponentially" do @@ -61,12 +61,12 @@ module Qup subject.multiplier end - multipliers.should be == [0.01, 0.1, 1] + expect( multipliers ).to eq [0.01, 0.1, 1] end it "maxes out at the last value of MULTIPLIERS" do 100.times { subject.tick } - subject.multiplier.should == BackoffSleeper::MULTIPLIERS.last + expect( subject.multiplier ).to eq BackoffSleeper::MULTIPLIERS.last end end end diff --git a/spec/qup/batch_consumer_spec.rb b/spec/qup/batch_consumer_spec.rb index 0bd1e17..03790cd 100644 --- a/spec/qup/batch_consumer_spec.rb +++ b/spec/qup/batch_consumer_spec.rb @@ -23,7 +23,7 @@ def messages :session_options => session_options, :queue_uri => "maildir://#{Dir.mktmpdir}" }) - batch_consumer.session.options.should == session_options + expect( batch_consumer.session.options ).to eq session_options end end @@ -81,7 +81,7 @@ def process(*) }) batch_consumer.run - client.messages.should == ["A", "B"] + expect( client.messages ).to eq ["A", "B"] end it "returns when max_age is met" do @@ -112,7 +112,7 @@ def process(*) }) batch_consumer.run - client.messages.should == ["A"] + expect( client.messages ).to eq ["A"] end @@ -129,9 +129,9 @@ def process(*) :queue_name => queue_name }) - client.should_receive(:setup).once.ordered - client.should_receive(:process).once.ordered - client.should_receive(:teardown).once.ordered + expect( client ).to receive(:setup).once.ordered + expect( client ).to receive(:process).once.ordered + expect( client ).to receive(:teardown).once.ordered batch_consumer.run end diff --git a/spec/qup/consumer_spec.rb b/spec/qup/consumer_spec.rb index a8dab95..d57bc44 100644 --- a/spec/qup/consumer_spec.rb +++ b/spec/qup/consumer_spec.rb @@ -17,31 +17,31 @@ it "consumes an item from the queue" do msg = consumer.consume - msg.data.should eq 'consumption' + expect( msg.data ).to eq 'consumption' queue.acknowledge msg - queue.depth.should eq 0 + expect( queue.depth ).to eq 0 end it "acknowledges messages it has consumed" do msg = consumer.consume - msg.data.should eq 'consumption' - queue.depth.should eq 1 + expect( msg.data ).to eq 'consumption' + expect( queue.depth ).to eq 1 consumer.acknowledge( msg ) - queue.depth.should eq 0 + expect( queue.depth ).to eq 0 end it "consumes auto-acknowledges msgs in a block" do consumer.consume do |msg| - msg.data.should eq 'consumption' + expect( msg.data ).to eq 'consumption' end - queue.depth.should eq 0 + expect( queue.depth ).to eq 0 end it "knows how deep the consumer's queue is" do - consumer.depth.should eq 1 + expect( consumer.depth ).to eq 1 consumer.consume do |msg| - msg.data.should eq 'consumption' + expect( msg.data ).to eq 'consumption' end - queue.depth.should eq 0 + expect( queue.depth ).to eq 0 end end diff --git a/spec/qup/message_spec.rb b/spec/qup/message_spec.rb index d3d393a..092680c 100644 --- a/spec/qup/message_spec.rb +++ b/spec/qup/message_spec.rb @@ -4,10 +4,10 @@ let( :message ) { Qup::Message.new( "my unique key", "some data" ) } it "has a key" do - message.key.should == 'my unique key' + expect( message.key ).to eq 'my unique key' end it 'has data' do - message.data.should == 'some data' + expect( message.data ).to eq 'some data' end end diff --git a/spec/qup/producer_spec.rb b/spec/qup/producer_spec.rb index 0b2d545..e704a1b 100644 --- a/spec/qup/producer_spec.rb +++ b/spec/qup/producer_spec.rb @@ -11,8 +11,8 @@ end it "produces items onto the queue" do - queue.depth.should eq 0 + expect( queue.depth ).to eq 0 producer.produce( 'production' ) - queue.depth.should eq 1 + expect( queue.depth ).to eq 1 end end diff --git a/spec/qup/queue_api_spec.rb b/spec/qup/queue_api_spec.rb index 08778ab..26e5e31 100644 --- a/spec/qup/queue_api_spec.rb +++ b/spec/qup/queue_api_spec.rb @@ -9,13 +9,17 @@ class Qup::QueueAPITest %w[ name depth flush destroy consume ].each do |method| it "##{method} kaboom!" do - lambda { api.send( method ) }.should raise_error( NotImplementedError, "please implement '#{method}'" ) + expect { + api.send( method ) + }.to raise_error( NotImplementedError, "please implement '#{method}'" ) end end %w[ produce acknowledge ].each do |method| it "##{method} kaboom!" do - lambda { api.send( method, nil ) }.should raise_error( NotImplementedError, "please implement '#{method}'" ) + expect { + api.send( method, nil ) + }.to raise_error( NotImplementedError, "please implement '#{method}'" ) end end end diff --git a/spec/qup/session_spec.rb b/spec/qup/session_spec.rb index 4fc4725..dfa87fa 100644 --- a/spec/qup/session_spec.rb +++ b/spec/qup/session_spec.rb @@ -11,52 +11,54 @@ end it "has a uri" do - session.uri.to_s.should == "maildir:#{path}" + expect( session.uri.to_s ).to eq "maildir:#{path}" end it 'can be closed' do - session.closed?.should be_false + expect( session.closed? ).to be_falsey session.close - session.closed?.should be_true + expect( session.closed? ).to be_truthy end describe '#open' do it 'returns a new session' do s = Qup::Session.open( uri ) - s.closed?.should be_false + expect( s.closed? ).to be_falsey end it 'yields a new session' do Qup::Session.open( uri ) do |s| - s.closed?.should be_false + expect( s.closed? ).to be_falsey end end it 'closes a session at the end of the block' do save_s = nil Qup::Session.open( uri ) do |s| - s.closed?.should be_false + expect( s.closed? ).to be_falsey save_s = s end - save_s.closed?.should be_true + expect( save_s.closed? ).to be_truthy end end describe '#queue' do it "can return a Queue" do q = session.queue( 'foo' ) - q.name.should == 'foo' + expect( q.name ).to eq 'foo' end it 'can yield a Queue' do session.queue( 'foo' ) do |q| - q.name.should == 'foo' + expect( q.name ).to eq 'foo' end end it 'raises an error if accessing a closed Session' do session.close - lambda { session.queue( 'boom' ) }.should raise_error( Qup::Session::ClosedError, /Session (.*) is closed/ ) + expect { + session.queue( 'boom' ) + }.to raise_error( Qup::Session::ClosedError, /Session (.*) is closed/ ) end end @@ -64,25 +66,27 @@ describe '#topic' do it "can return a Topic" do t = session.topic('t') - t.name.should == 't' + expect( t.name ).to eq 't' end it 'can yiled a Topic' do session.topic('t') do |t| - t.name.should == 't' + expect( t.name ).to eq 't' end end it 'raises an error if accessing a closed Session' do session.close - lambda { session.topic( 'boom' ) }.should raise_error( Qup::Session::ClosedError, /Session (.*) is closed/ ) + expect { + session.topic( 'boom' ) + }.to raise_error( Qup::Session::ClosedError, /Session (.*) is closed/ ) end end describe '#options' do it "holds the options that are used to initialize the session" do - s = Qup::Session.open( uri, { :the => 'Option' } ) - s.options[:the].should == 'Option' + s = Qup::Session.open( uri, { the: 'Option' } ) + expect( s.options[:the] ).to eq 'Option' end end end diff --git a/spec/qup/shared_adapter_examples.rb b/spec/qup/shared_adapter_examples.rb index b033553..3d7f64d 100644 --- a/spec/qup/shared_adapter_examples.rb +++ b/spec/qup/shared_adapter_examples.rb @@ -6,26 +6,26 @@ # shared_examples Qup::Adapter do it 'is registered as an adapter' do - Qup::Adapters[uri.scheme].should eq adapter.class + expect( Qup::Adapters[uri.scheme] ).to eq adapter.class end it 'can be closed' do - adapter.closed?.should be_false + expect( adapter.closed? ).to be_falsey adapter.close - adapter.closed?.should be_true + expect( adapter.closed? ).to be_truthy end it 'can create a QueueAPI-like object' do q = adapter.queue( 'q' ) - q.should be_kind_of( Qup::QueueAPI ) - q.name.should eq 'q' + expect( q ).to be_kind_of( Qup::QueueAPI ) + expect( q.name ).to eq 'q' q.destroy end it 'can create a QueueAPI-like object' do t = adapter.topic( 't' ) - t.should be_kind_of( Qup::TopicAPI ) - t.name.should eq 't' + expect( t ).to be_kind_of( Qup::TopicAPI ) + expect( t.name ).to eq 't' t.destroy end end diff --git a/spec/qup/shared_queue_examples.rb b/spec/qup/shared_queue_examples.rb index d576a54..282e230 100644 --- a/spec/qup/shared_queue_examples.rb +++ b/spec/qup/shared_queue_examples.rb @@ -17,67 +17,67 @@ shared_examples Qup::QueueAPI do it "has a name" do - queue.name.should eq 'foo' + expect( queue.name ).to eq 'foo' end describe "#produce" do it "produces an item on the queue" do - queue.depth.should eq 0 + expect( queue.depth ).to eq 0 queue.produce( "a new message" ) - queue.depth.should eq 1 + expect( queue.depth ).to eq 1 end it "does not create multiple messages for newlines" do queue.produce( "one\nsingle\nmessage" ) - queue.depth.should eq 1 + expect( queue.depth ).to eq 1 end end it "#flush" do 10.times { |x| queue.produce( "message #{x}" ) } - queue.depth.should eq 10 + expect(queue.depth).to eq 10 queue.flush - queue.depth.should eq 0 + expect(queue.depth).to eq 0 end describe '#consume' do before do queue.produce( "consumeable message" ) - queue.depth.should eq 1 + expect(queue.depth).to eq 1 end it 'normally' do msg = queue.consume - msg.data.should eq "consumeable message" + expect( msg.data ).to eq "consumeable message" end it 'with block it auto acknowledges' do queue.consume do |msg| - msg.data.should eq 'consumeable message' + expect( msg.data ).to eq 'consumeable message' end end it 'returns nil if the queue is empty (it is non-blocking)' do queue.consume - queue.consume.should == nil + expect( queue.consume).to be_nil end end describe "#acknowledge" do it "acks a message" do queue.produce( "acknowledgeable message" ) - queue.depth.should eq 1 + expect( queue.depth ).to eq 1 msg = queue.consume - msg.data.should eq "acknowledgeable message" + expect( msg.data ).to eq "acknowledgeable message" queue.acknowledge( msg ) - queue.depth.should eq 0 + expect( queue.depth ).to eq 0 end it "raises an error if you attempt to to acknowledge an unconsumed message" do msg = queue.produce( 'unconsumed' ) - lambda { queue.acknowledge( msg ) }.should raise_error(Qup::Error) + expect { queue.acknowledge( msg ) }.to raise_error(Qup::Error) end end end diff --git a/spec/qup/shared_topic_examples.rb b/spec/qup/shared_topic_examples.rb index c678489..d5edd7a 100644 --- a/spec/qup/shared_topic_examples.rb +++ b/spec/qup/shared_topic_examples.rb @@ -19,12 +19,12 @@ shared_examples Qup::TopicAPI do it "has a name" do - @topic.name.should == 'topic' + expect( @topic.name ).to eq 'topic' end it "creates publisher" do p = @topic.publisher - p.topic.should eq @topic + expect( p.topic ).to eq @topic end @@ -40,19 +40,19 @@ after do @topic2.destroy - @topic.subscriber_count.should eq 0 + expect( @topic.subscriber_count ).to eq 0 end it "updates the publisher with the number of subscribers" do start_count = @topic.subscriber_count - @topic2.subscriber_count.should eq start_count + expect( @topic2.subscriber_count ).to eq start_count current_count = start_count 3.times do |x| current_count += 1 @topic2.subscriber( "sub2-#{x}" ) - @topic.subscriber_count.should eq current_count - @topic2.subscriber_count.should eq current_count + expect( @topic.subscriber_count ).to eq current_count + expect( @topic2.subscriber_count ).to eq current_count end end @@ -62,7 +62,7 @@ @subs.each do |sub| msg = sub.consume - msg.data.should eq 'hi all' + expect( msg.data ).to eq 'hi all' end end @@ -70,7 +70,7 @@ p = @topic.publisher p.publish( "one\nsingle\nmessage" ) @subs.each do |sub| - sub.depth.should eq 1 + expect( sub.depth ).to eq 1 end end end diff --git a/spec/qup/topic_api_spec.rb b/spec/qup/topic_api_spec.rb index 94d7bbf..0a42015 100644 --- a/spec/qup/topic_api_spec.rb +++ b/spec/qup/topic_api_spec.rb @@ -9,13 +9,17 @@ class Qup::TopicAPITest %w[ name destroy publisher subscriber_count ].each do |method| it "##{method} kaboom!" do - lambda { api.send( method ) }.should raise_error( NotImplementedError, /please implement '#{method}'/ ) + expect { + api.send( method ) + }.to raise_error( NotImplementedError, /please implement '#{method}'/ ) end end %w[ publish subscriber ].each do |method| it "##{method} kaboom!" do - lambda { api.send( method, nil ) }.should raise_error( NotImplementedError, /please implement '#{method}'/ ) + expect { + api.send( method, nil ) + }.to raise_error( NotImplementedError, /please implement '#{method}'/ ) end end end diff --git a/spec/qup_spec.rb b/spec/qup_spec.rb index 9184c56..eb829f3 100644 --- a/spec/qup_spec.rb +++ b/spec/qup_spec.rb @@ -6,28 +6,28 @@ let( :uri ) { "maildir://#{path}" } it "should have a version" do - Qup::VERSION.should =~ ( %r[\A\d+\.\d+\.\d+\Z] ) + expect( Qup::VERSION ).to match( %r[\A\d+\.\d+\.\d+\Z] ) end describe '#open' do it 'returns a new session' do s = Qup.open( uri ) - s.closed?.should be_false + expect( s.closed? ).to be_falsey end it 'yields a new session' do Qup.open( uri ) do |s| - s.closed?.should be_false + expect( s.closed? ).to be_falsey end end it 'closes a session at the end of the block' do save_s = nil Qup.open( uri ) do |s| - s.closed?.should be_false + expect( s.closed? ).to be_falsey save_s = s end - save_s.closed?.should be_true + expect( save_s.closed? ).to be_truthy end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 552a254..40415fa 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,7 +3,6 @@ SimpleCov.start if ENV['COVERAGE'] end -require "rspec/autorun" require 'qup' require 'tmpdir' diff --git a/tasks/default.rake b/tasks/default.rake index 768b98b..ced30d2 100644 --- a/tasks/default.rake +++ b/tasks/default.rake @@ -10,39 +10,24 @@ namespace :develop do # Install all the development and runtime dependencies of this gem using the # gemspec. - task :default do + task :default => 'Gemfile' do require 'rubygems/dependency_installer' installer = ::Gem::DependencyInstaller.new - - This.set_coverage_gem - - puts "Installing gem depedencies needed for development" - This.platform_gemspec.dependencies.each do |dep| - if dep.matching_specs.empty? then - puts "Installing : #{dep}" - installer.install dep - else - puts "Skipping : #{dep} -> already installed #{dep.matching_specs.first.full_name}" - end - end + puts "Installing bundler..." + installer.install 'bundler' + sh 'bundle install' puts "\n\nNow run 'rake test'" end # Create a Gemfile that just references the gemspec file 'Gemfile' => :gemspec do File.open( "Gemfile", "w+" ) do |f| + f.puts "# DO NOT EDIT - This file is automatically generated" + f.puts "# Make changes to Manifest.txt and/or Rakefile and regenerate" f.puts 'source "https://rubygems.org/"' f.puts 'gemspec' end end - - desc "Create a bundler Gemfile" - task :using_bundler => 'Gemfile' do - puts "Now you can 'bundle'" - end - - # Gemfiles are build artifacts - CLOBBER << FileList['Gemfile*'] end desc "Boostrap development" task :develop => "develop:default" @@ -56,12 +41,14 @@ begin t.ruby_opts = %w[ -w ] t.rspec_opts = %w[ --color --format documentation ] end + + task :test_requirements + task :test => :test_requirements task :default => :test rescue LoadError This.task_warning( 'test' ) end - #------------------------------------------------------------------------------ # RDoc - standard rdoc rake task, although we must make sure to use a more # recent version of rdoc since it is the one that has 'tomdoc' markup @@ -85,31 +72,16 @@ end # Coverage - optional code coverage, rcov for 1.8 and simplecov for 1.9, so # for the moment only rcov is listed. #------------------------------------------------------------------------------ -if RUBY_VERSION < "1.9.0" - begin - require 'rcov/rcovtask' - Rcov::RcovTask.new( 'coverage' ) do |t| - t.libs << 'spec' - t.pattern = 'spec/**/*_spec.rb' - t.verbose = true - t.rcov_opts << "-x ^/" # remove all the global files - t.rcov_opts << "--sort coverage" # so we see the worst files at the top - end - rescue LoadError - This.task_warning( 'rcov' ) - end -else - begin - require 'simplecov' - desc 'Run tests with code coverage' - task :coverage do - ENV['COVERAGE'] = 'true' - Rake::Task[:test].execute - end - CLOBBER << FileList["coverage"] - rescue LoadError - This.task_warning( 'simplecov' ) +begin + require 'simplecov' + desc 'Run tests with code coverage' + task :coverage do + ENV['COVERAGE'] = 'true' + Rake::Task[:test].execute end + CLOBBER << 'coverage' if File.directory?( 'coverage' ) +rescue LoadError + This.task_warning( 'simplecov' ) end #------------------------------------------------------------------------------ @@ -174,9 +146,10 @@ namespace :fixme do end def outdated_fixme_files - local_fixme_files.reject do |local| + local_fixme_files.select do |local| upstream = fixme_project_path( local ) - Digest::SHA256.file( local ) == Digest::SHA256.file( upstream ) + upstream.exist? && + ( Digest::SHA256.file( local ) != Digest::SHA256.file( upstream ) ) end end @@ -220,13 +193,12 @@ task :fixme => "fixme:default" desc "Build the #{This.name}.gemspec file" task :gemspec do File.open( This.gemspec_file, "wb+" ) do |f| + f.puts "# DO NOT EDIT - This file is automatically generated" + f.puts "# Make changes to Manifest.txt and/or Rakefile and regenerate" f.write This.platform_gemspec.to_ruby end end -# the gemspec is also a dev artifact and should not be kept around. -CLOBBER << This.gemspec_file.to_s - # .rbc files from ruby 2.0 CLOBBER << FileList["**/*.rbc"] diff --git a/tasks/this.rb b/tasks/this.rb index 46edd2b..6d713b1 100644 --- a/tasks/this.rb +++ b/tasks/this.rb @@ -13,7 +13,7 @@ class ThisProject attr_accessor :email # The homepage of this project - attr_accessor :homepage + attr_accessor :homepage # The regex of files to exclude from the manifest attr_accessor :exclude_from_manifest @@ -25,7 +25,11 @@ class ThisProject # # Yields self def initialize(&block) - @exclude_from_manifest = %r/\.(git|DS_Store)|^(doc|coverage|pkg|tmp|Gemfile(\.lock)?)|^[^\/]+\.gemspec|\.(swp|jar|bundle|so|rvmrc)$|~$/ + @exclude_from_manifest = Regexp.union(/\.(git|DS_Store)/, + /^(doc|coverage|pkg|tmp|Gemfile(\.lock)?)/, + /^[^\/]+\.gemspec/, + /\.(swp|jar|bundle|so|rvmrc|travis.yml)$/, + /~$/) @gemspecs = Hash.new yield self if block_given? end @@ -119,7 +123,7 @@ def extension_conf_files # Internal: Returns the gemspace associated with the current ruby platform def platform_gemspec - gemspecs[platform] + gemspecs.fetch(platform) { This.ruby_gemspec } end def core_gemspec @@ -132,6 +136,7 @@ def core_gemspec spec.summary = summary spec.description = description + spec.license = license spec.files = manifest spec.executables = spec.files.grep(/^bin/) { |f| File.basename(f) } @@ -140,6 +145,8 @@ def core_gemspec spec.extra_rdoc_files += spec.files.grep(/(txt|rdoc|md)$/) spec.rdoc_options = [ "--main" , 'README.md', "--markup", "tomdoc" ] + + spec.required_ruby_version = '>= 1.9.3' end end @@ -166,20 +173,6 @@ def yielding_gemspec( key, core ) return spec end - # Internal: Set the recovery gem development dependency - # - # These are dynamically set since they cannot be hard coded as there is - # no way to ship them correctly in the gemspec - # - # Returns nothing. - def set_coverage_gem - if RUBY_VERSION < "1.9.0" - platform_gemspec.add_development_dependency( 'rcov', '~> 1.0.0' ) - else - platform_gemspec.add_development_dependency( 'simplecov', '~> 0.8.2' ) - end - end - # Internal: Return the platform of ThisProject at the current moment in time. def platform (RUBY_PLATFORM == "java") ? 'java' : Gem::Platform::RUBY @@ -189,17 +182,21 @@ def platform def description_section section_of( 'README.md', 'DESCRIPTION') end - - # Internal: Return the summary text from the README + + # Internal: Return the summary text from the README def summary description_section.first end - # Internal: Return the full description text from the READEM + # Internal: Return the full description text from the README def description description_section.join(" ").tr("\n", ' ').gsub(/[{}]/,'').gsub(/\[[^\]]+\]/,'') # strip rdoc end + def license + "ISC" + end + # Internal: The path to the gemspec file def gemspec_file project_path( "#{ name }.gemspec" )