tmm1-erlectricity 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/CONTRIBUTORS +2 -0
  2. data/History.txt +1 -0
  3. data/Manifest.txt +45 -0
  4. data/README.txt +51 -0
  5. data/Rakefile +71 -0
  6. data/examples/gruff/gruff.erl +62 -0
  7. data/examples/gruff/gruff_provider.rb +36 -0
  8. data/examples/gruff/gruff_run.erl +17 -0
  9. data/examples/gruff/stat_run.erl +18 -0
  10. data/examples/gruff/stat_writer.erl +40 -0
  11. data/examples/tinderl/tinderl.erl +45 -0
  12. data/examples/tinderl/tinderl.rb +27 -0
  13. data/ext/decoder.c +391 -0
  14. data/ext/extconf.rb +11 -0
  15. data/lib/erlectricity.rb +37 -0
  16. data/lib/erlectricity/condition.rb +51 -0
  17. data/lib/erlectricity/conditions/hash.rb +14 -0
  18. data/lib/erlectricity/conditions/static.rb +13 -0
  19. data/lib/erlectricity/conditions/type.rb +17 -0
  20. data/lib/erlectricity/constants.rb +37 -0
  21. data/lib/erlectricity/decoder.rb +204 -0
  22. data/lib/erlectricity/encoder.rb +127 -0
  23. data/lib/erlectricity/errors/decode_error.rb +3 -0
  24. data/lib/erlectricity/errors/encode_error.rb +3 -0
  25. data/lib/erlectricity/errors/erlectricity_error.rb +3 -0
  26. data/lib/erlectricity/matcher.rb +38 -0
  27. data/lib/erlectricity/port.rb +46 -0
  28. data/lib/erlectricity/receiver.rb +78 -0
  29. data/lib/erlectricity/types/function.rb +3 -0
  30. data/lib/erlectricity/types/list.rb +1 -0
  31. data/lib/erlectricity/types/new_function.rb +3 -0
  32. data/lib/erlectricity/types/new_reference.rb +3 -0
  33. data/lib/erlectricity/types/pid.rb +3 -0
  34. data/lib/erlectricity/types/reference.rb +3 -0
  35. data/lib/erlectricity/version.rb +9 -0
  36. data/setup.rb +1585 -0
  37. data/test/condition_spec.rb +73 -0
  38. data/test/decode_spec.rb +129 -0
  39. data/test/encode_spec.rb +132 -0
  40. data/test/matcher_spec.rb +69 -0
  41. data/test/port_spec.rb +35 -0
  42. data/test/receiver_spec.rb +105 -0
  43. data/test/spec_suite.rb +2 -0
  44. data/test/test_erlectricity.rb +2 -0
  45. data/test/test_helper.rb +42 -0
  46. metadata +102 -0
@@ -0,0 +1,73 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ context "Erlectricity::StaticConditions" do
4
+ specify "should satisfy on the same value" do
5
+ Erlectricity::StaticCondition.new(:foo).satisfies?(:foo).should == true
6
+ Erlectricity::StaticCondition.new([:foo]).satisfies?([:foo]).should == true
7
+ Erlectricity::StaticCondition.new(3).satisfies?(3).should == true
8
+ end
9
+
10
+ specify "should not satisfy on different values" do
11
+ Erlectricity::StaticCondition.new(:foo).satisfies?("foo").should == false
12
+ Erlectricity::StaticCondition.new([:foo]).satisfies?(:foo).should == false
13
+ Erlectricity::StaticCondition.new(Object.new).satisfies?(Object.new).should == false
14
+ Erlectricity::StaticCondition.new(3).satisfies?(3.0).should == false
15
+ end
16
+
17
+ specify "should not produce any bindings" do
18
+ s = Erlectricity::StaticCondition.new(:foo)
19
+ s.binding_for(:foo).should == nil
20
+ end
21
+ end
22
+
23
+ context "Erlectricity::TypeConditions" do
24
+ specify "should be satisfied when the arg has the same class" do
25
+ Erlectricity::TypeCondition.new(Symbol).satisfies?(:foo).should == true
26
+ Erlectricity::TypeCondition.new(Symbol).satisfies?(:bar).should == true
27
+ Erlectricity::TypeCondition.new(String).satisfies?("foo").should == true
28
+ Erlectricity::TypeCondition.new(String).satisfies?("bar").should == true
29
+ Erlectricity::TypeCondition.new(Array).satisfies?([]).should == true
30
+ Erlectricity::TypeCondition.new(Fixnum).satisfies?(3).should == true
31
+ end
32
+
33
+ specify "should be satisfied when the arg is of a descendent class" do
34
+ Erlectricity::TypeCondition.new(Object).satisfies?(:foo).should == true
35
+ Erlectricity::TypeCondition.new(Object).satisfies?("foo").should == true
36
+ Erlectricity::TypeCondition.new(Object).satisfies?(3).should == true
37
+ end
38
+
39
+ specify "should not be satisfied when the arg is of a different class" do
40
+ Erlectricity::TypeCondition.new(String).satisfies?(:foo).should == false
41
+ Erlectricity::TypeCondition.new(Symbol).satisfies?("foo").should == false
42
+ Erlectricity::TypeCondition.new(Fixnum).satisfies?(3.0).should == false
43
+ end
44
+
45
+ specify "should bind the arg with no transormations" do
46
+ s = Erlectricity::TypeCondition.new(Symbol)
47
+ s.binding_for(:foo).should == :foo
48
+ s.binding_for(:bar).should == :bar
49
+ end
50
+
51
+ end
52
+
53
+ context "Erlectricity::HashConditions" do
54
+ specify "should satisfy an args of the form [[key, value], [key, value]]" do
55
+ Erlectricity::HashCondition.new.satisfies?([[:foo, 3], [:bar, Object.new]]).should == true
56
+ Erlectricity::HashCondition.new.satisfies?([[:foo, 3]]).should == true
57
+ end
58
+
59
+ specify "should satisfy on empty arrays" do
60
+ Erlectricity::HashCondition.new.satisfies?([]).should == true
61
+ end
62
+
63
+ specify "should nat satisfy other args" do
64
+ Erlectricity::HashCondition.new.satisfies?(:foo).should == false
65
+ Erlectricity::HashCondition.new.satisfies?("foo").should == false
66
+ Erlectricity::HashCondition.new.satisfies?(3.0).should == false
67
+ end
68
+
69
+ specify "should bind to a Hash" do
70
+ s = Erlectricity::HashCondition.new()
71
+ s.binding_for([[:foo, 3], [:bar, [3,4,5]]]).should == {:foo => 3, :bar => [3,4,5] }
72
+ end
73
+ end
@@ -0,0 +1,129 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ context "When unpacking from a binary stream" do
4
+ setup do
5
+ end
6
+
7
+ specify "an erlang atom should decode to a ruby symbol" do
8
+ get("haha").should == :haha
9
+ end
10
+
11
+ specify "an erlang number encoded as a small_int (< 255) should decode to a fixnum" do
12
+ get("0").should == 0
13
+ get("255").should == 255
14
+ end
15
+
16
+ specify "an erlang number encoded as a int (signed 27-bit number) should decode to a fixnum" do
17
+ get("256").should == 256
18
+ get("#{(1 << 27) -1}").should == (1 << 27) -1
19
+ get("-1").should == -1
20
+ get("#{-(1 << 27)}").should == -(1 << 27)
21
+ end
22
+
23
+
24
+ specify "an erlang number encoded as a small bignum (1 byte length) should decode to fixnum if it can" do
25
+ get("#{(1 << 27)}").should == (1 << 27)
26
+ get("#{-(1 << 27) - 1}").should == -(1 << 27) - 1
27
+ get("#{(1 << word_length) - 1}").should == (1 << word_length) - 1
28
+ get("#{-(1 << word_length)}").should == -(1 << word_length)
29
+ end
30
+
31
+ specify "an erlang number encoded as a small bignum (1 byte length) should decode to bignum if it can't be a fixnum" do
32
+ get("#{(1 << word_length)}").should == (1 << word_length)
33
+ get("#{-(1 << word_length) - 1}").should == -(1 << word_length) - 1
34
+ get("#{(1 << (255 * 8)) - 1}").should == (1 << (255 * 8)) - 1
35
+ get("#{-((1 << (255 * 8)) - 1)}").should == -((1 << (255 * 8)) - 1)
36
+ end
37
+
38
+
39
+ specify "an erlang number encoded as a big bignum (4 byte length) should decode to bignum" do
40
+ get("#{(1 << (255 * 8)) }").should == (1 << (255 * 8))
41
+ get("#{-(1 << (255 * 8))}").should == -(1 << (255 * 8))
42
+ get("#{(1 << (512 * 8)) }").should == (1 << (512 * 8))
43
+ get("#{-(1 << (512 * 8))}").should == -(1 << (512 * 8))
44
+ end
45
+
46
+ specify "an erlang float should decode to a Float" do
47
+ get("#{1.0}").should == 1.0
48
+ get("#{-1.0}").should == -1.0
49
+ get("#{123.456}").should == 123.456
50
+ get("#{123.456789012345}").should == 123.456789012345
51
+ end
52
+
53
+
54
+ specify "an erlang reference should decode to a Reference object" do
55
+ ref = get("make_ref()")
56
+ ref.should.be.instance_of Erlectricity::NewReference
57
+ ref.node.should.be.instance_of Symbol
58
+ end
59
+
60
+ specify "an erlang pid should decode to a Pid object" do
61
+ pid = get("spawn(fun() -> 3 end)")
62
+ pid.should.be.instance_of Erlectricity::Pid
63
+ pid.node.should.be.instance_of Symbol
64
+ end
65
+
66
+
67
+ specify "an erlang tuple encoded as a small tuple (1-byte length) should decode to an array" do
68
+ ref = get("{3}")
69
+ ref.length.should == 1
70
+ ref.first.should == 3
71
+
72
+ ref = get("{3, a, make_ref()}")
73
+ ref.length.should == 3
74
+ ref[0].should == 3
75
+ ref[1].should == :a
76
+ ref[2].class.should == Erlectricity::NewReference
77
+
78
+ tuple_meat = (['3'] * 255).join(', ')
79
+ ref = get("{#{tuple_meat}}")
80
+ ref.length.should == 255
81
+ ref.each{|r| r.should == 3}
82
+ end
83
+
84
+
85
+ specify "an erlang tuple encoded as a large tuple (4-byte length) should decode to an array" do
86
+ tuple_meat = (['3'] * 256).join(', ')
87
+ ref = get("{#{tuple_meat}}")
88
+ ref.length.should == 256
89
+ ref.each{|r| r.should == 3}
90
+
91
+ tuple_meat = (['3'] * 512).join(', ')
92
+ ref = get("{#{tuple_meat}}")
93
+ ref.length.should == 512
94
+ ref.each{|r| r.should == 3}
95
+ end
96
+
97
+
98
+ specify "an empty erlang list encoded as a nil should decode to an array" do
99
+ get("[]").should == []
100
+ end
101
+
102
+ specify "an erlang list encoded as a string should decode to an array of bytes (less than ideal, but consistent)" do
103
+ get("\"asdasd\"").should == "asdasd".split('').map{|c| c[0]}
104
+ get("\"#{'a' * 65534}\"").should == ['a'[0]] * 65534
105
+ end
106
+
107
+ specify "an erlang list encoded as a list should decode to a array" do
108
+ get("[3,4,256]").should == [3,4,256]
109
+ get("\"#{'a' * 65535 }\"").should == [97] * 65535
110
+ get("[3,4, foo, {3,4,5,bar}, 256]").should == [3,4, :foo, [3,4,5,:bar], 256]
111
+ end
112
+
113
+
114
+ specify "an erlang binary should decode to a string" do
115
+ get("<< 3,4,255 >>").should == "\003\004\377"
116
+ get("<< \"whatup\" >>").should == "whatup"
117
+ end
118
+
119
+ specify "a good thing should be awesome" do
120
+ get(%Q-[{options,{struct,[{test,<<"I'm chargin' mah lazer">>}]}},{passage,<<"Why doesn't this work?">>}]-).should ==
121
+ [[:options, [:struct, [[:test, "I'm chargin' mah lazer"]]]], [:passage, "Why doesn't this work?"]]
122
+ end
123
+
124
+ def get(str)
125
+ x = "term_to_binary(#{str.gsub(/"/, '\\\"')})"
126
+ bin = run_erl(x)
127
+ Erlectricity::Decoder.read_any_from(bin)
128
+ end
129
+ end
@@ -0,0 +1,132 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ context "When packing to a binary stream" do
4
+ setup do
5
+ @out = StringIO.new('', 'w')
6
+ @encoder = Erlectricity::Encoder.new(@out)
7
+ end
8
+ specify "A symbol should be encoded to an erlang atom" do
9
+ get{@encoder.write_symbol :haha}.should == get_erl("haha")
10
+ write_any(:haha).should == get_erl_with_magic("haha")
11
+ end
12
+
13
+ specify "A number should be encoded as an erlang number would be" do
14
+
15
+ #SMALL_INTS
16
+ get{@encoder.write_fixnum 0}.should == get_erl("0")
17
+ get{@encoder.write_fixnum 255}.should == get_erl("255")
18
+ write_any(0).should == get_erl_with_magic("0")
19
+ write_any(255).should == get_erl_with_magic("255")
20
+
21
+ #INTS
22
+ get{@encoder.write_fixnum 256}.should == get_erl("256")
23
+ get{@encoder.write_fixnum((1 << 27) - 1)}.should == get_erl("#{(1 << 27) - 1}")
24
+ get{@encoder.write_fixnum(-1)}.should == get_erl("-1")
25
+ get{@encoder.write_fixnum(-(1 << 27))}.should == get_erl("#{-(1 << 27)}")
26
+ write_any(256).should == get_erl_with_magic("256")
27
+ write_any((1 << 27) - 1).should == get_erl_with_magic("#{(1 << 27) - 1}")
28
+ write_any(-1).should == get_erl_with_magic("-1")
29
+ write_any(-(1 << 27)).should == get_erl_with_magic("#{-(1 << 27)}")
30
+
31
+ # #SMALL_BIGNUMS
32
+ # get{@encoder.write_fixnum((1 << word_length))}.should == get_erl("#{(1 << word_length)}")
33
+ # get{@encoder.write_fixnum(-(1 << word_length) - 1)}.should == get_erl("#{-(1 << word_length) - 1}")
34
+ # get{@encoder.write_fixnum((1 << (255 * 8)) - 1)}.should == get_erl("#{(1 << (255 * 8)) - 1}")
35
+ # get{@encoder.write_fixnum(-((1 << (255 * 8)) - 1))}.should == get_erl("#{-((1 << (255 * 8)) - 1)}")
36
+ #
37
+ # write_any((1 << word_length)).should == get_erl_with_magic("#{(1 << word_length)}")
38
+ # write_any(-(1 << word_length) - 1).should == get_erl_with_magic("#{-(1 << word_length) - 1}")
39
+ # write_any((1 << (255 * 8)) - 1).should == get_erl_with_magic("#{(1 << (255 * 8)) - 1}")
40
+ # write_any(-((1 << (255 * 8)) - 1)).should == get_erl_with_magic("#{-((1 << (255 * 8)) - 1)}")
41
+ #
42
+ # #LARG_BIGNUMS
43
+ # get{@encoder.write_fixnum((1 << (255 * 8)))}.should == get_erl("#{(1 << (255 * 8))}")
44
+ # get{@encoder.write_fixnum(-(1 << (255 * 8))}.should == get_erl("#{-(1 << (255 * 8)}")
45
+ # get{@encoder.write_fixnum((1 << (512 * 8))}.should == get_erl("#{(1 << (512 * 8))}")
46
+ # get{@encoder.write_fixnum(-((1 << (512 * 8)) - 1))}.should == get_erl("#{-((1 << (512 * 8)) - 1)}")
47
+ #
48
+ # write_any((1 << (255 * 8))).should == get_erl_with_magic("#{(1 << (255 * 8))}")
49
+ # write_any(-(1 << (255 * 8)).should == get_erl_with_magic("#{-(1 << (255 * 8)}")
50
+ # write_any((1 << (512 * 8))).should == get_erl_with_magic("#{(1 << (512 * 8))}")
51
+ # write_any(-((1 << (512 * 8)) - 1)).should == get_erl_with_magic("#{-((1 << (512 * 8)) - 1)}")
52
+ end
53
+
54
+ # specify "A float (that is within the truncated precision of ruby compared to erlang) should encode as erlang does" do
55
+ # get{@encoder.write_float 1.0}.should == get_erl("1.0")
56
+ # get{@encoder.write_float -1.0}.should == get_erl("-1.0")
57
+ # get{@encoder.write_float 123.456}.should == get_erl("123.456")
58
+ # get{@encoder.write_float 123.456789012345}.should == get_erl("123.456789012345")
59
+ # end
60
+
61
+ specify "An Erlectiricity::NewReference should encode back to its original form" do
62
+ ref_bin = run_erl("term_to_binary(make_ref())")
63
+ ruby_ref = Erlectricity::Decoder.read_any_from(ref_bin)
64
+
65
+ get{@encoder.write_new_reference(ruby_ref)}.should == ref_bin[1..-1]
66
+ write_any(ruby_ref).should == ref_bin
67
+ end
68
+
69
+ specify "An Erlectiricity::Pid should encode back to its original form" do
70
+ pid_bin = run_erl("term_to_binary(spawn(fun() -> 3 end))")
71
+ ruby_pid = Erlectricity::Decoder.read_any_from(pid_bin)
72
+
73
+ get{@encoder.write_pid(ruby_pid)}.should == pid_bin[1..-1]
74
+ write_any(ruby_pid).should == pid_bin
75
+ end
76
+
77
+ specify "An array written with write_tuple should encode as erlang would a tuple" do
78
+ get{@encoder.write_tuple [1,2,3]}.should == get_erl("{1,2,3}")
79
+ get{@encoder.write_tuple [3] * 255}.should == get_erl("{#{([3] * 255).join(',')}}")
80
+ get{@encoder.write_tuple [3] * 256}.should == get_erl("{#{([3] * 256).join(',')}}")
81
+ get{@encoder.write_tuple [3] * 512}.should == get_erl("{#{([3] * 512).join(',')}}")
82
+ end
83
+
84
+ specify "An array should by default be written as a tuple" do
85
+ write_any([1,2,3]).should == get_erl_with_magic("{1,2,3}")
86
+ write_any([3] * 255).should == get_erl_with_magic("{#{([3] * 255).join(',')}}")
87
+ write_any([3] * 256).should == get_erl_with_magic("{#{([3] * 256).join(',')}}")
88
+ write_any([3] * 512).should == get_erl_with_magic("{#{([3] * 512).join(',')}}")
89
+ end
90
+
91
+ specify "An Erlectricity::List should by default be written as a list" do
92
+ write_any(Erl::List.new([1,2,300])).should == get_erl_with_magic("[1,2,300]")
93
+ write_any(Erl::List.new([300] * 255)).should == get_erl_with_magic("[#{([300] * 255).join(',')}]")
94
+ write_any(Erl::List.new([300] * 256)).should == get_erl_with_magic("[#{([300] * 256).join(',')}]")
95
+ write_any(Erl::List.new([300] * 512)).should == get_erl_with_magic("[#{([300] * 512).join(',')}]")
96
+ end
97
+
98
+ specify "An array written with write_list should encode as erlang would a list" do
99
+ get{@encoder.write_list [1,2,300]}.should == get_erl("[1,2,300]")
100
+ get{@encoder.write_list [300] * 255}.should == get_erl("[#{([300] * 255).join(',')}]")
101
+ get{@encoder.write_list [300] * 256}.should == get_erl("[#{([300] * 256).join(',')}]")
102
+ get{@encoder.write_list [300] * 512}.should == get_erl("[#{([300] * 512).join(',')}]")
103
+ end
104
+
105
+ specify "a string should be encoded as a erlang binary would be" do
106
+ get{@encoder.write_binary "hey who"}.should == get_erl("<< \"hey who\" >>")
107
+ get{@encoder.write_binary ""}.should == get_erl("<< \"\" >>")
108
+
109
+ write_any("hey who").should == get_erl_with_magic("<< \"hey who\" >>")
110
+ write_any("").should == get_erl_with_magic("<< \"\" >>")
111
+ end
112
+
113
+ def get
114
+ @encoder.out = StringIO.new('', 'w')
115
+ yield
116
+ @encoder.out.string
117
+ end
118
+
119
+ def write_any(term)
120
+ @encoder.out = StringIO.new('', 'w')
121
+ @encoder.write_any term
122
+ @encoder.out.string
123
+ end
124
+
125
+ def get_erl(str)
126
+ get_erl_with_magic(str)[1..-1] #[1..-1] to chop off the magic number
127
+ end
128
+
129
+ def get_erl_with_magic(str)
130
+ run_erl("term_to_binary(#{str.gsub(/"/, '\\\"')})")
131
+ end
132
+ end
@@ -0,0 +1,69 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ def false_match(matcher, arg)
4
+ matcher.matches?(arg).should == false
5
+ end
6
+
7
+ context "A matcher whose condition is Symbol (the class object)" do
8
+ setup do
9
+ @matcher = Erlectricity::Matcher.new(nil, Erlectricity::TypeCondition.new(Symbol), nil)
10
+ end
11
+
12
+ specify "should match any symbol" do
13
+ @matcher.matches?(:foo).should == true
14
+ @matcher.matches?(:bar).should == true
15
+ @matcher.matches?(:baz).should == true
16
+ end
17
+
18
+ specify "should not match strings" do
19
+ @matcher.matches?("foo").should == false
20
+ @matcher.matches?("bar").should == false
21
+ @matcher.matches?("baz").should == false
22
+ end
23
+
24
+ specify "should not match a arrays" do
25
+ @matcher.matches?([:foo]).should == false
26
+ @matcher.matches?([:foo, :bar]).should == false
27
+ @matcher.matches?([:foo, :bar, :baz]).should == false
28
+ end
29
+ end
30
+
31
+ context "a matcher whose condition is a symbol" do
32
+ setup do
33
+ @matcher = Erlectricity::Matcher.new(nil, Erlectricity::StaticCondition.new(:foo), nil)
34
+ end
35
+
36
+ specify "should match that symbol" do
37
+ @matcher.matches?(:foo).should == true
38
+ end
39
+
40
+ specify "should not match any other symbol" do
41
+ @matcher.matches?(:bar).should == false
42
+ @matcher.matches?(:baz).should == false
43
+ end
44
+ end
45
+
46
+ context "a matcher whose matcher is an array" do
47
+ setup do
48
+ end
49
+
50
+ specify "should match if all of its children match" do
51
+ Erlectricity::Matcher.new(nil, [Erlectricity::StaticCondition.new(:speak), Erlectricity::TypeCondition.new(Object)], nil).matches?([:paste, "haha"]).should == false
52
+
53
+ matcher = Erlectricity::Matcher.new(nil, [Erlectricity::StaticCondition.new(:foo), Erlectricity::StaticCondition.new(:bar)], nil)
54
+ matcher.matches?([:foo, :bar]).should == true
55
+ end
56
+
57
+ specify "should not match any of its children dont match" do
58
+ matcher = Erlectricity::Matcher.new(nil, [Erlectricity::StaticCondition.new(:foo), Erlectricity::StaticCondition.new(:bar)], nil)
59
+ matcher.matches?([:foo]).should == false
60
+ matcher.matches?([:foo, :bar, :baz]).should == false
61
+ matcher.matches?([:fooo, :barr]).should == false
62
+ matcher.matches?([3, :bar]).should == false
63
+ end
64
+
65
+ specify "should not match if arg isn't an array" do
66
+ matcher = Erlectricity::Matcher.new(nil, [Erlectricity::StaticCondition.new(:foo), Erlectricity::StaticCondition.new(:bar)], nil)
67
+ matcher.matches?(:foo).should == false
68
+ end
69
+ end
@@ -0,0 +1,35 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ context "A port" do
4
+ specify "should return terms from the queue if it is not empty" do
5
+ port = FakePort.new()
6
+ port.queue.clear
7
+ port.queue << :foo << :bar
8
+ port.receive.should == :foo
9
+ port.receive.should == :bar
10
+ port.receive.should == nil
11
+ end
12
+
13
+ specify "should read_from_input if the queue gets empty" do
14
+ port = FakePort.new(:bar)
15
+ port.queue.clear
16
+ port.queue << :foo
17
+ port.receive.should == :foo
18
+ port.receive.should == :bar
19
+ port.receive.should == nil
20
+ end
21
+
22
+ specify "should put the terms in skipped at the front of queue when restore_skipped is called" do
23
+ port = FakePort.new(:baz)
24
+ port.queue.clear
25
+ port.queue << :bar
26
+ port.skipped << :foo
27
+ port.restore_skipped
28
+
29
+ port.receive.should == :foo
30
+ port.receive.should == :bar
31
+ port.receive.should == :baz
32
+ port.receive.should == nil
33
+
34
+ end
35
+ end
@@ -0,0 +1,105 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ def simple_receiver_and_port(*terms, &block)
4
+ port = FakePort.new(*terms)
5
+ receiver = if block
6
+ Erlectricity::Receiver.new(port, &block)
7
+ else
8
+ Erlectricity::Receiver.new(port) do |f|
9
+ f.when Erl.any do
10
+ :matched
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+
17
+ context "When a receiver is passed a message that matches two match blocks it" do
18
+ setup do
19
+ @port = FakePort.new([:foo, :foo])
20
+ @receiver = Erlectricity::Receiver.new(@port) do |f|
21
+ f.when(:foo, :foo) do
22
+ :first
23
+ end
24
+
25
+ f.when(:foo, Erl.any) do
26
+ :second
27
+ end
28
+ end
29
+ end
30
+
31
+ specify "should run the first matching receiver's block" do
32
+ @receiver.run.should == :first
33
+ end
34
+ end
35
+
36
+ context "A receiver" do
37
+ specify "should return the result of the match block when finished" do
38
+ simple_receiver_and_port(:foo).run.should == :matched
39
+ simple_receiver_and_port(:bar).run.should == :matched
40
+ simple_receiver_and_port(:bar, :baz).run.should == :matched
41
+ end
42
+
43
+ specify "should process another message if the matched block returns the results of receive_loop" do
44
+ recv = simple_receiver_and_port(:foo, :bar, :baz) do |f|
45
+ f.when(:bar) { }
46
+ f.when(Erl.any) { f.receive_loop }
47
+ end
48
+
49
+ recv.run
50
+ recv.port.terms.should == [:baz]
51
+ end
52
+
53
+ specify "should properly nest" do
54
+ @port = FakePort.new(:foo, :bar, :baz)
55
+ @receiver = Erlectricity::Receiver.new(@port) do |f|
56
+ f.when(:foo) do
57
+ f.receive do |g|
58
+ g.when(:bar){ :ok }
59
+ end
60
+ f.receive_loop
61
+ end
62
+
63
+ f.when(:baz) do
64
+ :done
65
+ end
66
+ end
67
+
68
+ @receiver.run.should == :done
69
+ @port.terms.should == []
70
+ end
71
+
72
+ specify "should queue up skipped results and restore them when a match happens" do
73
+ @port = FakePort.new(:foo, :baz, :bar)
74
+ @receiver = Erlectricity::Receiver.new(@port) do |f|
75
+ f.when(:foo) do
76
+ f.receive do |g|
77
+ g.when(:bar){ :ok }
78
+ end
79
+ f.receive_loop
80
+ end
81
+
82
+ f.when(:baz) do
83
+ :done
84
+ end
85
+ end
86
+
87
+ @receiver.run.should == :done
88
+ @port.terms.should == []
89
+ end
90
+
91
+ specify "should expose bindings to the matched block" do
92
+ @port = FakePort.new(:foo, :bar, :baz)
93
+ results = []
94
+ @receiver = Erlectricity::Receiver.new(@port) do |f|
95
+ f.when(Erl.atom) do |bindinated|
96
+ results << bindinated
97
+ f.receive_loop
98
+ end
99
+ end
100
+
101
+ @receiver.run.should == nil
102
+ results.should == [:foo, :bar, :baz]
103
+ end
104
+
105
+ end