Last active
December 18, 2015 23:59
-
-
Save kschiess/5865739 to your computer and use it in GitHub Desktop.
Taking the transaction behaviour discussion into code. Use 'rspec transactions_spec.rb'
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'rspec' | |
| require 'dm-transactions' | |
| RSpec.configure do |rspec| | |
| rspec.mock_with :flexmock | |
| end | |
| describe 'transaction block behaviour' do | |
| let(:t) { DataMapper::Transaction.new() } | |
| def transaction &block | |
| t.commit &block | |
| end | |
| def be_committed | |
| be_commit | |
| end | |
| def be_rolled_back | |
| be_rollback | |
| end | |
| # Remove comments on this code block for an alternate implementation that | |
| # fixes most of these problems. NOTE The code in this implementation is | |
| # not correct, since it drops a few of the original aspects. They should be | |
| # easy to add back in. | |
| # | |
| # def transaction &block | |
| # t.begin | |
| # begin | |
| # t.within(&block) | |
| # rescue Exception => e | |
| # t.rollback | |
| # raise | |
| # ensure | |
| # t.commit if t.begin? | |
| # end | |
| # end | |
| describe "directly called" do | |
| it "can return" do | |
| # When not inside the context of a method call, returning should not | |
| # work. | |
| expect { | |
| transaction { return :something } | |
| }.to raise_error(LocalJumpError) | |
| end | |
| it "can call next with a value" do | |
| transaction { next :something }.should == :something | |
| t.should be_committed | |
| end | |
| it "can call break with a value" do | |
| loop do | |
| transaction { break } | |
| fail "SHOULD NOT BE REACHED" | |
| end | |
| pending "break is real hard to catch..." do | |
| t.should be_committed | |
| end | |
| end | |
| it "can raise an exception" do | |
| e = Exception.new | |
| expect { | |
| transaction { raise e } | |
| }.to raise_error(e) | |
| t.should be_rolled_back | |
| end | |
| it "can throw a value" do | |
| pending 'Throwing?' do | |
| expect { | |
| transaction { throw :value } | |
| }.to throw_symbol(:value) | |
| t.should be_committed | |
| end | |
| end | |
| end | |
| describe "wrapped in a method call" do | |
| def mc &block | |
| c = Class.new | |
| i = c.new | |
| m = i.define_singleton_method(:foo, &block) | |
| m.call | |
| end | |
| it "can return" do | |
| pending 'Would be nice to have return working.' do | |
| mc { | |
| transaction { return :something } | |
| }.should == :something | |
| t.should be_committed | |
| end | |
| end | |
| it "can call next with a value" do | |
| mc { | |
| transaction { next :something } | |
| }.should == :something | |
| t.should be_committed | |
| end | |
| it "can call break with a value" do | |
| # Break from inside a method call is not something one would attempt. | |
| expect { | |
| mc { | |
| loop do | |
| transaction { break :something } | |
| fail "SHOULD NOT BE REACHED" | |
| end | |
| } | |
| }.to raise_error(RuntimeError) | |
| end | |
| it "can raise an exception" do | |
| e = Exception.new | |
| expect { | |
| mc { | |
| transaction { raise e } | |
| } | |
| }.to raise_error(e) | |
| t.should be_rolled_back | |
| end | |
| it "can throw a value" do | |
| pending 'Throwing as a means to exit many levels of call stack quickly...' do | |
| expect { | |
| mc { | |
| transaction { throw :value } | |
| } | |
| }.to throw_symbol(:value) | |
| t.should be_committed | |
| end | |
| end | |
| end | |
| end |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Running with 1.9.3 - dm-transactions implementation:
transaction block behaviour directly called can return can call next with a value can call break with a value (FAILED - 1) can raise an exception can throw a value (PENDING: Throwing?) wrapped in a method call can return (PENDING: Would be nice to have return working.) can call next with a value can call break with a value can raise an exception can throw a value (PENDING: Throwing as a means to exit many levels of call stack quickly...) Pending: transaction block behaviour directly called can throw a value # Throwing? # ./transactions_spec.rb:71 transaction block behaviour wrapped in a method call can return # Would be nice to have return working. # ./transactions_spec.rb:89 transaction block behaviour wrapped in a method call can throw a value # Throwing as a means to exit many levels of call stack quickly... # ./transactions_spec.rb:126 Failures: 1) transaction block behaviour directly called can call break with a value Failure/Error: fail "SHOULD NOT BE REACHED" RuntimeError: SHOULD NOT BE REACHED # ./transactions_spec.rb:56:in `block (4 levels) in <top (required)>' # ./transactions_spec.rb:54:in `loop' # ./transactions_spec.rb:54:in `block (3 levels) in <top (required)>' Finished in 0.00788 seconds 10 examples, 1 failure, 3 pendingRunning with my transactions implementation:
transaction block behaviour directly called can return can call next with a value can call break with a value (FAILED - 1) can raise an exception can throw a value (FAILED - 2) wrapped in a method call can return (FAILED - 3) can call next with a value can call break with a value can raise an exception can throw a value (FAILED - 4) Failures: 1) transaction block behaviour directly called can call break with a value Failure/Error: fail "SHOULD NOT BE REACHED" RuntimeError: SHOULD NOT BE REACHED # ./transactions_spec.rb:56:in `block (4 levels) in <top (required)>' # ./transactions_spec.rb:54:in `loop' # ./transactions_spec.rb:54:in `block (3 levels) in <top (required)>' 2) transaction block behaviour directly called can throw a value FIXED Expected pending 'Throwing?' to fail. No Error was raised. # ./transactions_spec.rb:72:in `block (3 levels) in <top (required)>' 3) transaction block behaviour wrapped in a method call can return FIXED Expected pending 'Would be nice to have return working.' to fail. No Error was raised. # ./transactions_spec.rb:90:in `block (3 levels) in <top (required)>' 4) transaction block behaviour wrapped in a method call can throw a value FIXED Expected pending 'Throwing as a means to exit many levels of call stack quickly...' to fail. No Error was raised. # ./transactions_spec.rb:127:in `block (3 levels) in <top (required)>' Finished in 0.00741 seconds 10 examples, 4 failures