rserve-client 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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