erlectricity 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. data/Manifest.txt +41 -0
  2. data/README.txt +3 -0
  3. data/Rakefile +68 -0
  4. data/examples/gruff/gruff.erl +62 -0
  5. data/examples/gruff/gruff_provider.rb +38 -0
  6. data/examples/gruff/gruff_run.erl +17 -0
  7. data/examples/gruff/stat_run.erl +18 -0
  8. data/examples/gruff/stat_writer.erl +40 -0
  9. data/examples/tinderl/tinderl.erl +41 -0
  10. data/examples/tinderl/tinderl.rb +23 -0
  11. data/lib/erlectricity/condition.rb +48 -0
  12. data/lib/erlectricity/conditions/hash.rb +15 -0
  13. data/lib/erlectricity/conditions/static.rb +17 -0
  14. data/lib/erlectricity/conditions/type.rb +19 -0
  15. data/lib/erlectricity/constants.rb +37 -0
  16. data/lib/erlectricity/decoder.rb +202 -0
  17. data/lib/erlectricity/encoder.rb +127 -0
  18. data/lib/erlectricity/errors/decode_error.rb +3 -0
  19. data/lib/erlectricity/errors/encode_error.rb +3 -0
  20. data/lib/erlectricity/errors/erlectricity_error.rb +3 -0
  21. data/lib/erlectricity/match_context.rb +20 -0
  22. data/lib/erlectricity/matcher.rb +60 -0
  23. data/lib/erlectricity/port.rb +46 -0
  24. data/lib/erlectricity/receiver.rb +74 -0
  25. data/lib/erlectricity/types/function.rb +3 -0
  26. data/lib/erlectricity/types/new_function.rb +3 -0
  27. data/lib/erlectricity/types/new_reference.rb +3 -0
  28. data/lib/erlectricity/types/pid.rb +3 -0
  29. data/lib/erlectricity/types/reference.rb +3 -0
  30. data/lib/erlectricity/version.rb +9 -0
  31. data/lib/erlectricity.rb +23 -0
  32. data/setup.rb +1585 -0
  33. data/test/condition_spec.rb +78 -0
  34. data/test/decode_spec.rb +133 -0
  35. data/test/encode_spec.rb +125 -0
  36. data/test/matcher_spec.rb +73 -0
  37. data/test/port_spec.rb +35 -0
  38. data/test/receiver_spec.rb +105 -0
  39. data/test/spec_suite.rb +2 -0
  40. data/test/test_erlectricity.rb +2 -0
  41. data/test/test_helper.rb +36 -0
  42. metadata +87 -0
@@ -0,0 +1,78 @@
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 diffeent 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, even if a name is supplied" do
18
+ s = Erlectricity::StaticCondition.new(:foo, :bound_name)
19
+ s.bindings_for(:foo).should == {}
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 to the name specified with no transormations" do
46
+ s = Erlectricity::TypeCondition.new(Symbol, :bound_name)
47
+ s.bindings_for(:foo).should == {:bound_name => :foo}
48
+ s.bindings_for(:bar).should == {:bound_name => :bar}
49
+ end
50
+
51
+ specify "should not bind anything if no binding name is specified" do
52
+
53
+ s = Erlectricity::TypeCondition.new(Symbol)
54
+ s.bindings_for(:foo).should == {}
55
+ end
56
+ end
57
+
58
+ context "Erlectricity::HashConditions" do
59
+ specify "should satisfy an args of the form [[key, value], [key, value]]" do
60
+ Erlectricity::HashCondition.new.satisfies?([[:foo, 3], [:bar, Object.new]]).should == true
61
+ Erlectricity::HashCondition.new.satisfies?([[:foo, 3]]).should == true
62
+ end
63
+
64
+ specify "should satisfy on empty arrays" do
65
+ Erlectricity::HashCondition.new.satisfies?([]).should == true
66
+ end
67
+
68
+ specify "should nat satisfy other args" do
69
+ Erlectricity::HashCondition.new.satisfies?(:foo).should == false
70
+ Erlectricity::HashCondition.new.satisfies?("foo").should == false
71
+ Erlectricity::HashCondition.new.satisfies?(3.0).should == false
72
+ end
73
+
74
+ specify "should product a binder" do
75
+ s = Erlectricity::HashCondition.new(:bound_name)
76
+ s.bindings_for([[:foo, 3], [:bar, [3,4,5]]]).should == {:bound_name => {:foo => 3, :bar => [3,4,5] }}
77
+ end
78
+ end
@@ -0,0 +1,133 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ context "The byte reader attached to decoder" do
4
+ specify "should not advance the stream when peeking unless there arent enough bytes available" do
5
+ @decoder = Erlectricity::Decoder.new(StringIO.new('abcdefghijklmnopqrstuvwxyz'))
6
+ 100.times{ @decoder.peek_1.should == 'a'[0] }
7
+ 100.times{ @decoder.peek_2.should == 'ab'.unpack("n").first }
8
+ end
9
+ end
10
+
11
+ context "When unpacking from a binary stream" do
12
+ setup do
13
+ @decoder = Erlectricity::Decoder.new(nil)
14
+ end
15
+
16
+ specify "an erlang atom should decode to a ruby symbol" do
17
+ get("haha").should == :haha
18
+ end
19
+
20
+ specify "an erlang number encoded as a small_int (< 255) should decode to a fixnum" do
21
+ get("0").should == 0
22
+ get("255").should == 255
23
+ end
24
+
25
+ specify "an erlang number encoded as a int (signed 27-bit number) should decode to a fixnum" do
26
+ get("256").should == 256
27
+ get("#{(1 << 27) -1}").should == (1 << 27) -1
28
+ get("-1").should == -1
29
+ get("#{-(1 << 27)}").should == -(1 << 27)
30
+ end
31
+
32
+
33
+ specify "an erlang number encoded as a small bignum (1 byte length) should decode to fixnum if it can" do
34
+ get("#{(1 << 27)}").should == (1 << 27)
35
+ get("#{-(1 << 27) - 1}").should == -(1 << 27) - 1
36
+ get("#{(1 << word_length) - 1}").should == (1 << word_length) - 1
37
+ get("#{-(1 << word_length)}").should == -(1 << word_length)
38
+ end
39
+
40
+ specify "an erlang number encoded as a small bignum (1 byte length) should decode to bignum if it can't be a fixnum" do
41
+ get("#{(1 << word_length)}").should == (1 << word_length)
42
+ get("#{-(1 << word_length) - 1}").should == -(1 << word_length) - 1
43
+ get("#{(1 << (255 * 8)) - 1}").should == (1 << (255 * 8)) - 1
44
+ get("#{-((1 << (255 * 8)) - 1)}").should == -((1 << (255 * 8)) - 1)
45
+ end
46
+
47
+
48
+ specify "an erlang number encoded as a big bignum (4 byte length) should decode to bignum" do
49
+ get("#{(1 << (255 * 8)) }").should == (1 << (255 * 8))
50
+ get("#{-(1 << (255 * 8))}").should == -(1 << (255 * 8))
51
+ get("#{(1 << (512 * 8)) }").should == (1 << (512 * 8))
52
+ get("#{-(1 << (512 * 8))}").should == -(1 << (512 * 8))
53
+ end
54
+
55
+ specify "an erlang float should decode to a Float" do
56
+ get("#{1.0}").should == 1.0
57
+ get("#{-1.0}").should == -1.0
58
+ get("#{123.456}").should == 123.456
59
+ get("#{123.456789012345}").should == 123.456789012345
60
+ end
61
+
62
+
63
+ specify "an erlang reference should decode to a Reference object" do
64
+ ref = get("make_ref()")
65
+ ref.should.be.instance_of Erlectricity::NewReference
66
+ ref.node.should.be.instance_of Symbol
67
+ end
68
+
69
+ specify "an erlang pid should decode to a Pid object" do
70
+ pid = get("spawn(fun() -> 3 end)")
71
+ pid.should.be.instance_of Erlectricity::Pid
72
+ pid.node.should.be.instance_of Symbol
73
+ end
74
+
75
+
76
+ specify "an erlang tuple encoded as a small tuple (1-byte length) should decode to an array" do
77
+ ref = get("{3}")
78
+ ref.length.should == 1
79
+ ref.first.should == 3
80
+
81
+ ref = get("{3, a, make_ref()}")
82
+ ref.length.should == 3
83
+ ref[0].should == 3
84
+ ref[1].should == :a
85
+ ref[2].class.should == Erlectricity::NewReference
86
+
87
+ tuple_meat = (['3'] * 255).join(', ')
88
+ ref = get("{#{tuple_meat}}")
89
+ ref.length.should == 255
90
+ ref.each{|r| r.should == 3}
91
+ end
92
+
93
+
94
+ specify "an erlang tuple encoded as a large tuple (4-byte length) should decode to an array" do
95
+ tuple_meat = (['3'] * 256).join(', ')
96
+ ref = get("{#{tuple_meat}}")
97
+ ref.length.should == 256
98
+ ref.each{|r| r.should == 3}
99
+
100
+ tuple_meat = (['3'] * 512).join(', ')
101
+ ref = get("{#{tuple_meat}}")
102
+ ref.length.should == 512
103
+ ref.each{|r| r.should == 3}
104
+ end
105
+
106
+
107
+ specify "an empty erlang list encoded as a nil should decode to an array" do
108
+ get("[]").should == []
109
+ end
110
+
111
+ specify "an erlang list encoded as a string should decode to an array of bytes (less than ideal, but consistent)" do
112
+ get("\"asdasd\"").should == "asdasd".split('').map{|c| c[0]}
113
+ get("\"#{'a' * 65534}\"").should == ['a'[0]] * 65534
114
+ end
115
+
116
+ specify "an erlang list encoded as a list should decode to a array" do
117
+ get("[3,4,256]").should == [3,4,256]
118
+ get("\"#{'a' * 65535 }\"").should == [97] * 65535
119
+ get("[3,4, foo, {3,4,5,bar}, 256]").should == [3,4, :foo, [3,4,5,:bar], 256]
120
+ end
121
+
122
+
123
+ specify "an erlang binary should decode to a string" do
124
+ get("<< 3,4,255 >>").should == "\003\004\377"
125
+ get("<< \"whatup\" >>").should == "whatup"
126
+ end
127
+
128
+ def get(str)
129
+ bin = run_erl("term_to_binary(#{str})")
130
+ @decoder.in = StringIO.new(bin)
131
+ @decoder.read_any
132
+ end
133
+ end
@@ -0,0 +1,125 @@
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 array written with write_list should encode as erlang would a list" do
92
+ get{@encoder.write_list [1,2,300]}.should == get_erl("[1,2,300]")
93
+ get{@encoder.write_list [300] * 255}.should == get_erl("[#{([300] * 255).join(',')}]")
94
+ get{@encoder.write_list [300] * 256}.should == get_erl("[#{([300] * 256).join(',')}]")
95
+ get{@encoder.write_list [300] * 512}.should == get_erl("[#{([300] * 512).join(',')}]")
96
+ end
97
+
98
+ specify "a string should be encoded as a erlang binary would be" do
99
+ get{@encoder.write_binary "hey who"}.should == get_erl("<< \"hey who\" >>")
100
+ get{@encoder.write_binary ""}.should == get_erl("<< \"\" >>")
101
+
102
+ write_any("hey who").should == get_erl_with_magic("<< \"hey who\" >>")
103
+ write_any("").should == get_erl_with_magic("<< \"\" >>")
104
+ end
105
+
106
+ def get
107
+ @encoder.out = StringIO.new('', 'w')
108
+ yield
109
+ @encoder.out.string
110
+ end
111
+
112
+ def write_any(term)
113
+ @encoder.out = StringIO.new('', 'w')
114
+ @encoder.write_any term
115
+ @encoder.out.string
116
+ end
117
+
118
+ def get_erl(str)
119
+ get_erl_with_magic(str)[1..-1] #[1..-1] to chop off the magic number
120
+ end
121
+
122
+ def get_erl_with_magic(str)
123
+ run_erl("term_to_binary(#{str})")
124
+ end
125
+ end
@@ -0,0 +1,73 @@
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
70
+
71
+ context "a matcher" do
72
+
73
+ end
data/test/port_spec.rb ADDED
@@ -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
9
+ match(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
21
+ match(:foo, :foo) do
22
+ :first
23
+ end
24
+
25
+ match(:foo, 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
45
+ match(:bar) { }
46
+ match(any) { 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
56
+ match(:foo) do
57
+ receive do
58
+ match(:bar){ :ok }
59
+ end
60
+ receive_loop
61
+ end
62
+
63
+ match(: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
75
+ match(:foo) do
76
+ receive do
77
+ match(:bar){ :ok }
78
+ end
79
+ receive_loop
80
+ end
81
+
82
+ match(: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
95
+ match(atom(:bindinated)) do
96
+ results << bindinated
97
+ receive_loop
98
+ end
99
+ end
100
+
101
+ @receiver.run.should == nil
102
+ results.should == [:foo, :bar, :baz]
103
+ end
104
+
105
+ end
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ Dir[File.dirname(__FILE__) + '/*_spec.rb'].each{ |f| require f}
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
@@ -0,0 +1,36 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+ require 'rubygems'
3
+ require 'test/unit'
4
+ require 'test/spec'
5
+ require 'erlectricity'
6
+
7
+ class Test::Unit::TestCase
8
+
9
+ def run_erl(code)
10
+ `erl -noshell -eval 'A = #{code.split.join(' ')}, io:put_chars(A).' -s erlang halt`
11
+ end
12
+
13
+ def word_length
14
+ (1.size * 8) - 2
15
+ end
16
+ end
17
+
18
+ class FakePort < Erlectricity::Port
19
+ attr_reader :sent
20
+ attr_reader :terms
21
+
22
+ def initialize(*terms)
23
+ @terms = terms
24
+ @sent = []
25
+ super(StringIO.new(""), StringIO.new(""))
26
+ end
27
+
28
+ def send(term)
29
+ sent << term
30
+ end
31
+
32
+ private
33
+ def read_from_input
34
+ @terms.shift
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: erlectricity
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2007-05-08 00:00:00 -07:00
8
+ summary: A library to interface erlang and ruby through the erlang port system
9
+ require_paths:
10
+ - lib
11
+ email: nullstyle@gmail.com
12
+ homepage: http://erlectricity.rubyforge.org
13
+ rubyforge_project: erlectricity
14
+ description: A library to interface erlang and ruby through the erlang port system
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Scott Fleckenstein
31
+ files:
32
+ - Manifest.txt
33
+ - README.txt
34
+ - Rakefile
35
+ - examples/gruff/gruff.erl
36
+ - examples/gruff/gruff_provider.rb
37
+ - examples/gruff/gruff_run.erl
38
+ - examples/gruff/stat_run.erl
39
+ - examples/gruff/stat_writer.erl
40
+ - examples/tinderl/tinderl.erl
41
+ - examples/tinderl/tinderl.rb
42
+ - lib/erlectricity.rb
43
+ - lib/erlectricity/condition.rb
44
+ - lib/erlectricity/conditions/hash.rb
45
+ - lib/erlectricity/conditions/static.rb
46
+ - lib/erlectricity/conditions/type.rb
47
+ - lib/erlectricity/constants.rb
48
+ - lib/erlectricity/decoder.rb
49
+ - lib/erlectricity/encoder.rb
50
+ - lib/erlectricity/errors/decode_error.rb
51
+ - lib/erlectricity/errors/encode_error.rb
52
+ - lib/erlectricity/errors/erlectricity_error.rb
53
+ - lib/erlectricity/match_context.rb
54
+ - lib/erlectricity/matcher.rb
55
+ - lib/erlectricity/port.rb
56
+ - lib/erlectricity/receiver.rb
57
+ - lib/erlectricity/types/function.rb
58
+ - lib/erlectricity/types/new_function.rb
59
+ - lib/erlectricity/types/new_reference.rb
60
+ - lib/erlectricity/types/pid.rb
61
+ - lib/erlectricity/types/reference.rb
62
+ - lib/erlectricity/version.rb
63
+ - setup.rb
64
+ - test/condition_spec.rb
65
+ - test/decode_spec.rb
66
+ - test/encode_spec.rb
67
+ - test/matcher_spec.rb
68
+ - test/port_spec.rb
69
+ - test/receiver_spec.rb
70
+ - test/spec_suite.rb
71
+ - test/test_erlectricity.rb
72
+ - test/test_helper.rb
73
+ test_files:
74
+ - test/test_erlectricity.rb
75
+ - test/test_helper.rb
76
+ rdoc_options: []
77
+
78
+ extra_rdoc_files: []
79
+
80
+ executables: []
81
+
82
+ extensions: []
83
+
84
+ requirements: []
85
+
86
+ dependencies: []
87
+