rserve-client 0.1.5 → 0.1.6

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 (46) hide show
  1. data.tar.gz.sig +1 -2
  2. data/.gitignore +1 -0
  3. data/History.txt +15 -2
  4. data/Manifest.txt +8 -0
  5. data/README.txt +41 -19
  6. data/lib/rserve.rb +1 -1
  7. data/lib/rserve/connection.rb +152 -69
  8. data/lib/rserve/engine.rb +9 -9
  9. data/lib/rserve/packet.rb +2 -2
  10. data/lib/rserve/protocol.rb +51 -46
  11. data/lib/rserve/protocol/rexpfactory.rb +659 -366
  12. data/lib/rserve/rexp.rb +175 -156
  13. data/lib/rserve/rexp/double.rb +45 -38
  14. data/lib/rserve/rexp/environment.rb +40 -0
  15. data/lib/rserve/rexp/expressionvector.rb +9 -0
  16. data/lib/rserve/rexp/genericvector.rb +5 -3
  17. data/lib/rserve/rexp/integer.rb +38 -38
  18. data/lib/rserve/rexp/language.rb +2 -2
  19. data/lib/rserve/rexp/list.rb +3 -0
  20. data/lib/rserve/rexp/logical.rb +17 -4
  21. data/lib/rserve/rexp/null.rb +20 -14
  22. data/lib/rserve/rexp/raw.rb +19 -0
  23. data/lib/rserve/rexp/reference.rb +42 -0
  24. data/lib/rserve/rexp/s4.rb +10 -0
  25. data/lib/rserve/rexp/string.rb +5 -3
  26. data/lib/rserve/rexp/symbol.rb +3 -0
  27. data/lib/rserve/rexp/vector.rb +30 -15
  28. data/lib/rserve/rexp/wrapper.rb +58 -0
  29. data/lib/rserve/rfactor.rb +10 -10
  30. data/lib/rserve/rlist.rb +129 -100
  31. data/lib/rserve/talk.rb +61 -61
  32. data/spec/rserve_connection_spec.rb +99 -33
  33. data/spec/rserve_double_spec.rb +28 -15
  34. data/spec/rserve_integer_spec.rb +24 -15
  35. data/spec/rserve_logical_spec.rb +21 -12
  36. data/spec/rserve_protocol_spec.rb +7 -7
  37. data/spec/rserve_rexp_spec.rb +3 -3
  38. data/spec/rserve_rexp_wrapper_spec.rb +36 -0
  39. data/spec/rserve_rexpfactory_spec.rb +86 -20
  40. data/spec/rserve_rfactor_spec.rb +2 -2
  41. data/spec/rserve_rlist_spec.rb +53 -0
  42. data/spec/rserve_spec.rb +8 -5
  43. data/spec/rserve_talk_spec.rb +7 -7
  44. data/spec/spec_helper.rb +1 -0
  45. metadata +13 -3
  46. metadata.gz.sig +0 -0
@@ -12,11 +12,29 @@ describe Rserve::REXP::Double do
12
12
  a=Rserve::REXP::Double.new(payload)
13
13
  a.payload.should==[1.1]
14
14
  end
15
-
16
-
17
-
15
+
16
+
17
+
18
+ end
19
+ describe "NA management" do
20
+ before do
21
+ @payload=[3,5,Rserve::REXP::Double::NA, 10,20]
22
+ @a=Rserve::REXP::Double.new(@payload)
23
+ end
24
+
25
+ it "method na? should return coherent answer" do
26
+ @a.na?(@a.as_integers[0]).should be_false
27
+ @a.na?(@a.as_integers[2]).should be_true
28
+ @a.na?.should==[false,false,true,false,false]
29
+ end
30
+ it "to_a should return correct values with NA" do
31
+ @a.to_a.should==[3,5, nil, 10, 20]
32
+ end
33
+ it "to_ruby should return correct values with NA" do
34
+ @a.to_ruby.should==[3,5, nil, 10, 20]
35
+ end
18
36
  end
19
- describe "common methods" do
37
+ describe "common methods" do
20
38
  before do
21
39
  @n=rand(10)+10
22
40
  @payload=@n.times.map {rand(10).to_f}
@@ -37,19 +55,14 @@ describe Rserve::REXP::Double do
37
55
  it "method as_strings should return strings" do
38
56
  @a.as_strings.should==@payload.map(&:to_s)
39
57
  end
40
- it "method na? should return coherent answer" do
41
- payload=[3,5,Rserve::REXP::Double::NA, 10,20]
42
- a=Rserve::REXP::Double.new(payload)
43
- a.na?(a.as_integers[0]).should be_false
44
- a.na?(a.as_integers[2]).should be_true
45
- a.na?.should==[false,false,true,false,false]
46
- end
58
+
59
+
47
60
  it "method to_debug_string and to_s returns a coherent response" do
48
61
  @a.to_debug_string.size.should>0
49
62
  @a.to_s.size.should>0
50
-
51
- end
63
+
52
64
  end
53
-
54
-
65
+ end
66
+
67
+
55
68
  end
@@ -12,11 +12,26 @@ describe Rserve::REXP::Integer do
12
12
  a=Rserve::REXP::Integer.new(payload)
13
13
  a.payload.should==[1]
14
14
  end
15
-
16
-
17
-
15
+
16
+
17
+
18
+ end
19
+ describe "NA management" do
20
+ before do
21
+ @payload=[3,5,Rserve::REXP::Integer::NA, 10,20]
22
+ @a=Rserve::REXP::Integer.new(@payload)
23
+
24
+ end
25
+ it "method is_NA should return coherent answer" do
26
+ @a.na?(@a.as_integers[0]).should be_false
27
+ @a.na?(@a.as_integers[2]).should be_true
28
+ @a.na?.should==[false,false,true,false,false]
29
+ end
30
+ it "to_a should return correct values with NA" do
31
+ @a.to_a.should==[3,5, nil, 10, 20]
32
+ end
18
33
  end
19
- describe "common methods" do
34
+ describe "common methods" do
20
35
  before do
21
36
  @n=rand(10)+10
22
37
  @payload=@n.times.map {rand(10)}
@@ -37,19 +52,13 @@ describe Rserve::REXP::Integer do
37
52
  it "method as_string should return string" do
38
53
  @a.as_strings.should==@payload.map(&:to_s)
39
54
  end
40
- it "method is_NA should return coherent answer" do
41
- payload=[3,5,Rserve::REXP::Integer::NA, 10,20]
42
- a=Rserve::REXP::Integer.new(payload)
43
- a.na?(a.as_integers[0]).should be_false
44
- a.na?(a.as_integers[2]).should be_true
45
- a.na?.should==[false,false,true,false,false]
46
- end
55
+
47
56
  it "method to_debug_string and to_s returns a coherent response" do
48
57
  @a.to_debug_string.size.should>0
49
58
  @a.to_s.size.should>0
50
-
51
- end
59
+
52
60
  end
53
-
54
-
61
+ end
62
+
63
+
55
64
  end
@@ -13,7 +13,22 @@ describe Rserve::REXP::Integer do
13
13
  a.payload.should==[ Rserve::REXP::Logical::TRUE ]
14
14
  end
15
15
  end
16
- describe "common methods" do
16
+ describe "NA management" do
17
+ before do
18
+ @payload=[1,Rserve::REXP::Logical::NA, 0]
19
+ @a=Rserve::REXP::Logical.new(@payload)
20
+
21
+ end
22
+ it "method is_NA should return coherent answer" do
23
+ @a.na?.should==[false,true,false]
24
+ @a.na?(@a.as_bytes[0]).should be_false
25
+ @a.na?(@a.as_bytes[1]).should be_true
26
+ end
27
+ it "method to_a should return correct answer" do
28
+ @a.to_a.should==[true,nil,false]
29
+ end
30
+ end
31
+ describe "common methods" do
17
32
  before do
18
33
  @n=rand(100)
19
34
  @payload=@n.times.map {rand(2)}
@@ -43,19 +58,13 @@ describe Rserve::REXP::Integer do
43
58
  @a.false?.should==@payload.map {|v| v==Rserve::REXP::Logical::FALSE ? true :false}
44
59
  end
45
60
 
46
- it "method is_NA should return coherent answer" do
47
- payload=[1,Rserve::REXP::Logical::NA, 0]
48
- a=Rserve::REXP::Logical.new(payload)
49
- a.na?.should==[false,true,false]
50
- a.na?(a.as_bytes[0]).should be_false
51
- a.na?(a.as_bytes[1]).should be_true
52
- end
61
+
53
62
  it "method to_debug_string and to_s returns a coherent response" do
54
63
  @a.to_debug_string.size.should>0
55
64
  @a.to_s.size.should>0
56
-
57
- end
65
+
58
66
  end
59
-
60
-
67
+ end
68
+
69
+
61
70
  end
@@ -24,15 +24,15 @@ describe Rserve::Protocol do
24
24
  end
25
25
  it "set_hdr method should set correctly the header for len>0xFFFFFF" do
26
26
  bytes=[0]*8
27
- cmd=Rserve::Protocol::CMD_login
27
+ cmd=Rserve::Protocol::CMD_login
28
28
  len=0x12345678
29
29
  offset=0
30
30
  expected=[cmd|Rserve::Protocol::DT_LARGE,0x78,0x56,0x34,0x12,0,0,0]
31
31
  @t.set_hdr(cmd,len,bytes,offset)
32
32
  bytes.should==expected
33
- end
33
+ end
34
34
  it "new_hdr method should return a correct header for different lengths" do
35
- cmd=Rserve::Protocol::CMD_login
35
+ cmd=Rserve::Protocol::CMD_login
36
36
  len=0x123456
37
37
  expected=[cmd,0x56,0x34,0x12]
38
38
  @t.new_hdr(cmd,len).should==expected
@@ -44,15 +44,15 @@ describe Rserve::Protocol do
44
44
  buffer=[0xFF,0x78,0x56,0x34,0x12]
45
45
  expected=0x12345678
46
46
  @t.get_int(buffer,1).should==expected
47
-
47
+
48
48
  # Version with errors
49
-
49
+
50
50
  buffer=[0xFF,0xFF78,0xFF56,0xFF34,0xFF12]
51
51
  expected=0x12345678
52
52
  @t.get_int(buffer,1).should==expected
53
53
  end
54
54
  it "get_len method should return correct length from a header" do
55
- cmd=Rserve::Protocol::CMD_login
55
+ cmd=Rserve::Protocol::CMD_login
56
56
  len=0x12345678
57
57
  header=@t.new_hdr(cmd,len)
58
58
  @t.get_len(header,0).should==len
@@ -71,5 +71,5 @@ describe Rserve::Protocol do
71
71
  expected=[0x45,0xDF,0xBC,0x9A,0x78,0x56,0x34,0x12]
72
72
  buffer.slice(1,8).should==expected
73
73
  end
74
-
74
+
75
75
  end
@@ -43,10 +43,10 @@ describe Rserve::REXP do
43
43
  it "method has_attribute? should return false for non existing value" do
44
44
  @l.has_attribute?('at2').should be_false
45
45
  end
46
- it "method get_attrivute should return correct value for attribute" do
46
+ it "method get_attribute should return correct value for attribute" do
47
47
  @l.get_attribute('names').as_strings.should==['at']
48
48
  end
49
-
49
+
50
50
  end
51
-
51
+
52
52
  end
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__)+"/spec_helper.rb"
2
+
3
+ describe Rserve::REXP::Wrapper do
4
+ it "should wrap single value" do
5
+ Rserve::REXP::Wrapper.wrap(1).should==Rserve::REXP::Integer.new(1)
6
+ Rserve::REXP::Wrapper.wrap(1.0).should==Rserve::REXP::Double.new(1.0)
7
+ Rserve::REXP::Wrapper.wrap(true).should==Rserve::REXP::Logical.new(1)
8
+ Rserve::REXP::Wrapper.wrap("a").should==Rserve::REXP::String.new("a")
9
+ end
10
+ it "should wrap arrays of a single type" do
11
+ Rserve::REXP::Wrapper.wrap([1,2]).should==Rserve::REXP::Integer.new([1,2])
12
+ Rserve::REXP::Wrapper.wrap([1.0,2]).should==Rserve::REXP::Double.new([1.0,2.0])
13
+ Rserve::REXP::Wrapper.wrap([true,false]).should==Rserve::REXP::Logical.new([1,0])
14
+ Rserve::REXP::Wrapper.wrap(["a","b"]).should==Rserve::REXP::String.new(["a","b"])
15
+ end
16
+ it "should wrap on a list mixed values" do
17
+ r=Rserve::Connection.new
18
+ Rserve::REXP::Wrapper.wrap([1,2.0,false,"a"]).should==
19
+ Rserve::REXP::GenericVector.new(
20
+ Rserve::Rlist.new([
21
+ Rserve::REXP::Integer.new(1),
22
+ Rserve::REXP::Double.new(2.0),
23
+ Rserve::REXP::Logical.new(0),
24
+ Rserve::REXP::String.new("a"),
25
+
26
+ ])
27
+ )
28
+ end
29
+ it "should wrap arrays with nil values using NA values of specific type" do
30
+ Rserve::REXP::Wrapper.wrap([1,nil]).should==Rserve::REXP::Integer.new([1,Rserve::REXP::Integer::NA])
31
+ Rserve::REXP::Wrapper.wrap([1.0,nil]).should==Rserve::REXP::Double.new([1.0,Rserve::REXP::Double::NA])
32
+ Rserve::REXP::Wrapper.wrap([true,nil]).should==Rserve::REXP::Logical.new([1,Rserve::REXP::Logical::NA])
33
+ Rserve::REXP::Wrapper.wrap(["a",nil]).should==Rserve::REXP::String.new(["a", Rserve::REXP::String::NA])
34
+ end
35
+
36
+ end
@@ -6,11 +6,20 @@ describe Rserve::Protocol::REXPFactory do
6
6
  before do
7
7
  @r=Rserve::Connection.new
8
8
  end
9
+ it "should process null" do
10
+ la=@r.eval("NULL")
11
+ la.should be_instance_of(Rserve::REXP::Null)
12
+ end
9
13
  it "should process single logical" do
10
14
  la=@r.eval("TRUE")
11
15
  la.should be_instance_of(Rserve::REXP::Logical)
12
16
  la.true?.should==[true]
13
17
  end
18
+ it "should process array" do
19
+ @r.void_eval("a<-c(1,2,3,4,5,6,7,8); attr(a,'dim')<-c(2,2,2)")
20
+ la=@r.eval("a")
21
+ la.dim.should==[2,2,2]
22
+ end
14
23
  it "should process logical vector" do
15
24
  la=@r.eval("c(TRUE,FALSE,TRUE)")
16
25
  la.should be_instance_of(Rserve::REXP::Logical)
@@ -19,7 +28,7 @@ describe Rserve::Protocol::REXPFactory do
19
28
  it "should process logical vectors with NA" do
20
29
  la=@r.eval("c(TRUE,NA)")
21
30
  la.should be_instance_of(Rserve::REXP::Logical)
22
- la.na?.should==[false,true]
31
+ la.na?.should==[false,true]
23
32
  end
24
33
  it "should process single double" do
25
34
  la=@r.eval("1.5")
@@ -30,7 +39,7 @@ describe Rserve::Protocol::REXPFactory do
30
39
  a=100.times.map{|i| rand()}
31
40
  la=@r.eval("c("+a.map(&:to_s).join(",")+")")
32
41
  la.should be_instance_of(Rserve::REXP::Double)
33
-
42
+ la.dim.should be_nil
34
43
  la.as_doubles.map(&:to_f).each_with_index {|v,i|
35
44
  v.should be_close(a[i],1e-10)
36
45
  }
@@ -39,7 +48,7 @@ describe Rserve::Protocol::REXPFactory do
39
48
  la=@r.eval("c(1,NA)")
40
49
  la.should be_instance_of(Rserve::REXP::Double)
41
50
  la.na?.should==[false,true]
42
-
51
+
43
52
  end
44
53
  it "should process string vector" do
45
54
  la=@r.eval("c('abc','def','ghi')")
@@ -52,27 +61,84 @@ describe Rserve::Protocol::REXPFactory do
52
61
  la.na?.should==[false,false,true]
53
62
 
54
63
  end
55
- it "should process factor" do
56
- la=@r.eval <<-EOF
57
- state <- c("tas", "sa", "qld", "nsw", "nsw", "nt", "wa", "wa",
58
- "qld", "vic", "nsw", "vic", "qld", "qld", "sa", "tas",
59
- "sa", "nt", "wa", "vic", "qld", "nsw", "nsw", "wa",
60
- "sa", "act", "nsw", "vic", "vic", "act");
61
- statef <- factor(state)
62
- EOF
63
- la.should be_factor
64
- la.as_factor.levels.sort.should==%w{act nsw nt qld sa tas vic wa}.sort
65
-
66
- la.as_factor.contains?("tas").should be_true
67
- la.as_factor.contains?("nn").should be_false
64
+ describe "factor processing" do
65
+ it "should process factor without NA" do
66
+ la=@r.eval <<-EOF
67
+ state <- c("tas", "sa", "qld", "nsw", "nsw", "nt", "wa", "wa",
68
+ "qld", "vic", "nsw", "vic", "qld", "qld", "sa", "tas",
69
+ "sa", "nt", "wa", "vic", "qld", "nsw", "nsw", "wa",
70
+ "sa", "act", "nsw", "vic", "vic", "act");
71
+ statef <- factor(state)
72
+ EOF
73
+ la.should be_factor
74
+ la.as_factor.levels.sort.should==%w{act nsw nt qld sa tas vic wa}.sort
68
75
 
76
+ la.as_factor.contains?("tas").should be_true
77
+ la.as_factor.contains?("nn").should be_false
78
+ @r.void_eval("rm(state, statef)")
79
+ end
80
+ it "should process factors with NA" do
81
+ @r.void_eval "other<-c('a','a','b','b',NA)"
82
+ la=@r.eval("factor(other)")
83
+ la.as_strings.should==['a','a','b','b',nil]
84
+ la.as_factor.levels.sort.should==['a','b']
85
+ end
69
86
  end
70
- it "should process list" do
71
- require 'pp'
72
- la=@r.eval("list(name='Fred',age=30,10,20,kids=c(1,2,3))")
87
+ it "should process basic list" do
88
+ la=@r.eval("list(first.name='Fred')")
73
89
  la.should be_list
74
90
  la.should be_recursive
75
- la.as_list.names.should==['name','age','','','kids']
91
+ la.should==Rserve::REXP::GenericVector.new(
92
+ Rserve::Rlist.new([Rserve::REXP::String.new('Fred')], ["first.name"]),
93
+ Rserve::REXP::List.new(
94
+ Rserve::Rlist.new([Rserve::REXP::String.new('first.name')],['names'])
95
+ )
96
+ )
97
+ la.as_list.names.should==['first.name']
98
+ end
99
+
100
+ it "should process list with booleans and NA" do
101
+ la=@r.eval("list(TRUE)")
102
+ la.should be_true
103
+ la=@r.eval("list(2,NA)")
104
+ la.should be_true
105
+ end
106
+ it "should retrieve correct lenght for string" do
107
+ Rserve::Protocol::REXPFactory.new(Rserve::REXP::String.new("a")).get_binary_length.should==8
108
+ Rserve::Protocol::REXPFactory.new(Rserve::REXP::String.new(["a","b"])).get_binary_length.should==8
109
+ Rserve::Protocol::REXPFactory.new(Rserve::REXP::String.new(["aaaa"])).get_binary_length.should==12
110
+
111
+ end
112
+ it "should retrieve correct representation for string" do
113
+ buf=[nil]*8
114
+ off=0
115
+ Rserve::Protocol::REXPFactory.new(Rserve::REXP::String.new("a")).get_binary_representation(buf,off)
116
+ buf[4,4].should==[97,0,1,1]
117
+ buf.size.should==8
118
+ buf=[nil]*8
119
+ Rserve::Protocol::REXPFactory.new(Rserve::REXP::String.new(["a","b"])).get_binary_representation(buf,off)
120
+ buf[4,8].should==[97,0,98,0]
121
+ buf.size.should==8
122
+
123
+ buf=[nil]*12
124
+ Rserve::Protocol::REXPFactory.new(Rserve::REXP::String.new("aaaa")).get_binary_representation(buf,off)
125
+ buf[4,8].should==[97,97,97,97,0,1,1,1]
126
+ buf.size.should==12
127
+ end
128
+ it "should retrieve correct binary representation for Symbol" do
129
+ rexp=Rserve::REXP::Symbol.new('names')
130
+ buf=Array.new(Rserve::Protocol::REXPFactory.new(rexp).get_binary_length)
131
+ Rserve::Protocol::REXPFactory.new(rexp).get_binary_representation(buf,0)
132
+ buf.should_not include(nil)
133
+ end
134
+
135
+ it "should retrieve correct binary representation for List" do
136
+
137
+ rexp=Rserve::REXP::List.new(Rserve::Rlist.new([Rserve::REXP::String.new("a")], ["names"]));
138
+ buf=Array.new(Rserve::Protocol::REXPFactory.new(rexp).get_binary_length)
139
+
140
+ Rserve::Protocol::REXPFactory.new(rexp).get_binary_representation(buf,0)
141
+ buf.should_not include(nil)
76
142
  end
77
143
 
78
144
  end
@@ -16,7 +16,7 @@ describe Rserve::RFactor do
16
16
  @factor[1].should=='a'
17
17
  @factor[3].should=='b'
18
18
  @factor[5].should=='c'
19
-
19
+
20
20
  }
21
21
  end
22
22
  it "methods contains? should work with integers and strings" do
@@ -41,5 +41,5 @@ describe Rserve::RFactor do
41
41
  it "method as_strings should return correct values" do
42
42
  @factor.as_strings==%w{a a b b c c d}
43
43
  end
44
-
44
+
45
45
  end
@@ -0,0 +1,53 @@
1
+ require File.dirname(__FILE__)+"/spec_helper.rb"
2
+
3
+ describe Rserve::Rlist do
4
+ before do
5
+ @r=Rserve::Connection.new
6
+ @l=@r.eval("list(name='Fred',age=30,10,20,kids=c(1,2,3))").as_list
7
+ end
8
+ it "method names return correct names" do
9
+ @l.names.should==['name','age',"","","kids"]
10
+ end
11
+ it "method == should return true for rlist with equal data and names" do
12
+ a=Rserve::Rlist.new([1,2,3],%w{a b c})
13
+ b=Rserve::Rlist.new([1,2,3],%w{a b c})
14
+ (a==b).should be_true
15
+ a=Rserve::Rlist.new([1,2,3],%w{a b c})
16
+ b=Rserve::Rlist.new([1,2,3])
17
+ (a==b).should be_false
18
+ a=Rserve::Rlist.new([1,2,3],%w{a b c})
19
+ b=Rserve::Rlist.new([4,5,6],%w{c d e})
20
+ (a==b).should be_false
21
+
22
+ end
23
+ it "method [] return correct values for strings" do
24
+ @l['name'].to_ruby.should=='Fred'
25
+ @l['age'].to_ruby.should==30
26
+ @l['kids'].to_ruby.should==[1,2,3]
27
+ end
28
+ it "method [] return correct values for integers (0-based)" do
29
+ @l[2].to_ruby.should==10
30
+ @l[3].to_ruby.should==20
31
+ end
32
+ it "method to_a return an array with best ruby representation of data" do
33
+ @l.to_a.should==['Fred',30,10,20,[1,2,3]]
34
+ end
35
+ it "method to_ruby returns a hash when all names are set" do
36
+ list=@r.eval("list(name='Fred', age=30)")
37
+ list.to_ruby.should=={'name'=>'Fred','age'=>30}
38
+ end
39
+ it "method to_ruby returns a hash with numbers (1-based) replacing empty names" do
40
+ list=@r.eval("list(name='Fred', age=30,'aaaa')")
41
+ list.to_ruby.should=={'name'=>'Fred','age'=>30,3=>'aaaa'}
42
+ end
43
+ it "method to_ruby returns an array when no names are set" do
44
+ list=@r.eval("list(10,20,30)")
45
+ list.to_ruby.should==[10,20,30]
46
+ end
47
+ it "should allow recursive list" do
48
+ list=@r.eval("list(l1=list(l11=1,l22=2),l2=list(3,4))").as_list
49
+ list['l1'].to_ruby.should=={'l11'=>1,'l22'=>2}
50
+ list['l2'].to_ruby.should==[3,4]
51
+
52
+ end
53
+ end