drbqs 0.0.15 → 0.0.16

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 (96) hide show
  1. data/.document +3 -0
  2. data/README.md +137 -128
  3. data/VERSION +1 -1
  4. data/docs/FormatExecute.md +119 -0
  5. data/docs/GettingStarted.md +242 -0
  6. data/drbqs.gemspec +36 -13
  7. data/example/command/server_def.rb +4 -5
  8. data/example/execute/execute.rb +41 -0
  9. data/example/execute/server.rb +14 -0
  10. data/example/execute/task.rb +0 -0
  11. data/example/mandelbrot/README.md +15 -0
  12. data/example/mandelbrot/execute.rb +10 -0
  13. data/example/mandelbrot/mandelbrot.rb +56 -0
  14. data/example/mandelbrot/server.rb +49 -0
  15. data/example/server/server.rb +3 -6
  16. data/example/simple/README.md +18 -0
  17. data/example/simple/execute.rb +11 -0
  18. data/example/simple/server.rb +8 -0
  19. data/example/simple/task.rb +11 -0
  20. data/example/sum/server_def.rb +1 -1
  21. data/example/sum2/execute_def.rb +21 -8
  22. data/example/sum2/server_def.rb +8 -7
  23. data/example/transfer/file.rb +42 -8
  24. data/example/transfer/server_def.rb +43 -9
  25. data/lib/drbqs.rb +1 -1
  26. data/lib/drbqs/command_line/command_execute.rb +3 -3
  27. data/lib/drbqs/command_line/command_line.rb +1 -1
  28. data/lib/drbqs/execute/execute_node.rb +50 -0
  29. data/lib/drbqs/execute/process_define.rb +102 -54
  30. data/lib/drbqs/execute/register.rb +241 -87
  31. data/lib/drbqs/execute/server_define.rb +69 -58
  32. data/lib/drbqs/ext/task.rb +2 -0
  33. data/lib/drbqs/ext/task/command_task.rb +43 -0
  34. data/lib/drbqs/manage/manage.rb +5 -4
  35. data/lib/drbqs/manage/ssh_shell.rb +2 -8
  36. data/lib/drbqs/node/connection.rb +1 -1
  37. data/lib/drbqs/node/node.rb +8 -14
  38. data/lib/drbqs/node/task_client.rb +1 -1
  39. data/lib/drbqs/server/history.rb +5 -1
  40. data/lib/drbqs/server/message.rb +7 -34
  41. data/lib/drbqs/server/queue.rb +14 -2
  42. data/lib/drbqs/server/server.rb +86 -43
  43. data/lib/drbqs/server/server_hook.rb +3 -0
  44. data/lib/drbqs/server/test/node.rb +1 -1
  45. data/lib/drbqs/server/test/prof.rb +50 -0
  46. data/lib/drbqs/server/test/server.rb +2 -2
  47. data/lib/drbqs/server/transfer_setting.rb +23 -11
  48. data/lib/drbqs/setting/base.rb +15 -0
  49. data/lib/drbqs/setting/data_container.rb +1 -1
  50. data/lib/drbqs/setting/execute.rb +3 -3
  51. data/lib/drbqs/setting/node.rb +1 -1
  52. data/lib/drbqs/setting/server.rb +2 -2
  53. data/lib/drbqs/task/registrar.rb +39 -0
  54. data/lib/drbqs/task/task.rb +139 -59
  55. data/lib/drbqs/task/task_generator.rb +93 -116
  56. data/lib/drbqs/utility/misc.rb +15 -10
  57. data/lib/drbqs/utility/temporary.rb +7 -2
  58. data/lib/drbqs/utility/transfer/transfer.rb +81 -0
  59. data/lib/drbqs/utility/transfer/transfer_client.rb +68 -69
  60. data/lib/drbqs/utility/transfer/transfer_client_connect.rb +83 -0
  61. data/lib/drbqs/utility/transfer/transfer_file_list.rb +40 -0
  62. data/spec/execute/def/execute1.rb +4 -4
  63. data/spec/execute/def/execute2.rb +24 -0
  64. data/spec/execute/process_define_spec.rb +43 -6
  65. data/spec/execute/register_spec.rb +403 -9
  66. data/spec/execute/server_define_spec.rb +1 -1
  67. data/spec/ext/task/command_task_spec.rb +16 -0
  68. data/spec/integration_test/01_basic_usage_spec.rb +1 -1
  69. data/spec/integration_test/02_use_generator_spec.rb +2 -2
  70. data/spec/integration_test/04_use_unix_domain_spec.rb +1 -1
  71. data/spec/integration_test/05_server_exit_signal_spec.rb +1 -1
  72. data/spec/integration_test/06_node_exit_after_task_spec.rb +4 -4
  73. data/spec/integration_test/08_shutdown_unused_nodes_spec.rb +2 -2
  74. data/spec/integration_test/09_server_process_data_spec.rb +1 -1
  75. data/spec/integration_test/definition/server01.rb +4 -5
  76. data/spec/integration_test/definition/server02.rb +2 -4
  77. data/spec/node/node_spec.rb +34 -0
  78. data/spec/server/message_spec.rb +1 -1
  79. data/spec/server/queue_spec.rb +34 -7
  80. data/spec/server/server_spec.rb +21 -9
  81. data/spec/server/transfer_setting_spec.rb +59 -24
  82. data/spec/setting/base_spec.rb +11 -0
  83. data/spec/setting/data_container_spec.rb +8 -0
  84. data/spec/spec_helper.rb +1 -7
  85. data/spec/task/registrar_spec.rb +34 -0
  86. data/spec/task/task_generator_spec.rb +15 -15
  87. data/spec/task/task_spec.rb +132 -23
  88. data/spec/utility/misc_spec.rb +2 -2
  89. data/spec/utility/transfer/transfer_client_connect_spec.rb +90 -0
  90. data/spec/utility/transfer/transfer_file_list_spec.rb +27 -0
  91. data/spec/{task/file_transfer_spec.rb → utility/transfer/transfer_spec.rb} +24 -24
  92. metadata +66 -45
  93. data/lib/drbqs/manage/execute_node.rb +0 -50
  94. data/lib/drbqs/server/prof.rb +0 -48
  95. data/lib/drbqs/task/command_task.rb +0 -43
  96. data/lib/drbqs/utility/transfer/file_transfer.rb +0 -73
data/spec/spec_helper.rb CHANGED
@@ -61,7 +61,7 @@ def drbqs_fork_server(uri_arg, opts = {}, &block)
61
61
  task_args = [task_args]
62
62
  end
63
63
  task_args.each do |arg|
64
- if DRbQS::TaskGenerator === arg
64
+ if DRbQS::Task::Generator === arg
65
65
  server.add_task_generator(arg)
66
66
  else
67
67
  server.queue.add(arg)
@@ -69,12 +69,6 @@ def drbqs_fork_server(uri_arg, opts = {}, &block)
69
69
  end
70
70
  end
71
71
 
72
- unless opts[:continue]
73
- server.add_hook(:finish) do |serv|
74
- serv.exit
75
- end
76
- end
77
-
78
72
  server.set_signal_trap
79
73
  server.start
80
74
  server.wait
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ require 'drbqs/task/task'
4
+
5
+ describe DRbQS::Task::Registrar do
6
+ subject do
7
+ DRbQS::Task::Registrar.new({})
8
+ end
9
+
10
+ it "should raise error for invalid argumuents." do
11
+ lambda do
12
+ subject.add("neither DRbQS::Task nor Array")
13
+ end.should raise_error ArgumentError
14
+ end
15
+
16
+ it "should call Fiber.yield." do
17
+ task = DRbQS::Task.new([1, 2, 3], :size, note: "calculate size of an array")
18
+ Fiber.should_receive(:yield).with(task)
19
+ subject.add(task)
20
+ end
21
+
22
+ it "should call Fiber.yield for each task." do
23
+ task_ary = 5.times.map do |i|
24
+ DRbQS::Task.new(i, :to_s, note: "convert to string")
25
+ end
26
+ Fiber.should_receive(:yield).exactly(task_ary.size).times
27
+ subject.add(task_ary)
28
+ end
29
+
30
+ it "should call Fiber.yield with :wait." do
31
+ Fiber.should_receive(:yield).with(:wait)
32
+ subject.wait
33
+ end
34
+ end
@@ -2,24 +2,24 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  require 'drbqs/task/task'
4
4
 
5
- describe DRbQS::TaskGenerator do
5
+ describe DRbQS::Task::Generator do
6
6
  def check_task_ary(tasks, num, cl = DRbQS::Task)
7
7
  tasks.should have(num).items
8
8
  tasks.all? { |t| cl === t }.should be_true
9
9
  end
10
10
 
11
- subject { DRbQS::TaskGenerator.new(:abc => 'ABC', :def => 123, :data => [1, 2, 3]) }
11
+ subject { DRbQS::Task::Generator.new(:abc => 'ABC', :def => 123, :data => [1, 2, 3]) }
12
12
 
13
13
  it "should initialize instance varibles" do
14
- source = subject.instance_variable_get('@source')
15
- source.instance_variable_get('@abc').should == 'ABC'
16
- source.instance_variable_get('@def').should == 123
14
+ registrar = subject.instance_variable_get('@registrar')
15
+ registrar.instance_variable_get('@abc').should == 'ABC'
16
+ registrar.instance_variable_get('@def').should == 123
17
17
  end
18
18
 
19
19
  it "should create new tasks" do
20
- subject.set(:generate => 2) do
20
+ subject.set(:generate => 2) do |reg|
21
21
  @data.each do |i|
22
- create_add_task(i, :to_s)
22
+ reg.create_add(i, :to_s)
23
23
  end
24
24
  end
25
25
  subject.init
@@ -29,22 +29,22 @@ describe DRbQS::TaskGenerator do
29
29
  end
30
30
 
31
31
  it "should should create task sets" do
32
- subject.set(:generate => 2, :collect => 10) do
32
+ subject.set(:generate => 2, :collect => 10) do |reg|
33
33
  100.times do |i|
34
- create_add_task(i, :to_s)
34
+ reg.create_add(i, :to_s)
35
35
  end
36
36
  end
37
37
  subject.init
38
38
  5.times do |i|
39
- check_task_ary(subject.new_tasks, 2, DRbQS::TaskSet)
39
+ check_task_ary(subject.new_tasks, 2, DRbQS::Task::TaskSet)
40
40
  end
41
41
  subject.new_tasks.should be_nil
42
42
  end
43
43
 
44
44
  it "should debug generator" do
45
- subject.set(:generate => 2) do
45
+ subject.set(:generate => 2) do |reg|
46
46
  @data.each do |i|
47
- create_add_task(i, :to_s)
47
+ reg.create_add(i, :to_s)
48
48
  end
49
49
  end
50
50
  subject.init
@@ -54,12 +54,12 @@ describe DRbQS::TaskGenerator do
54
54
  end
55
55
 
56
56
  it "should wait" do
57
- subject.set(:generate => 2) do
57
+ subject.set(:generate => 2) do |reg|
58
58
  @data.each do |i|
59
59
  if i == 2
60
- wait_all_tasks
60
+ reg.wait
61
61
  end
62
- create_add_task(i, :to_s)
62
+ create_add(i, :to_s)
63
63
  end
64
64
  end
65
65
  subject.init
@@ -2,46 +2,126 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  require 'drbqs/task/task'
4
4
 
5
+ class TestTask
6
+ def initialize(result)
7
+ @result = result
8
+ end
9
+
10
+ def calc
11
+ end
12
+
13
+ def test_hook(srv, result)
14
+ @result.should == result
15
+ end
16
+ end
17
+
5
18
  describe DRbQS::Task do
6
- it "should not set hook" do
19
+ it "should not set hook." do
7
20
  task = DRbQS::Task.new([1, 2, 3], :size)
8
21
  task.hook.should be_nil
9
22
  end
10
23
 
11
- it "should set hook" do
24
+ it "should set hook of block." do
12
25
  task = DRbQS::Task.new([1, 2, 3], :size) do |server, ret|
13
26
  p ret
14
27
  end
15
28
  task.hook.should be_an_instance_of Proc
16
29
  end
17
30
 
18
- it "should have same targets" do
19
- task1 = DRbQS::Task.new([1, 2, 3], :concat, [3, 4, 5])
20
- task2 = DRbQS::Task.new([1, 2, 3], :concat, [3, 4, 5])
21
- task1.same_target?(task2).should be_true
31
+ it "should set hook of symbol." do
32
+ task = DRbQS::Task.new([1, 2, 3], :size, hook: :to_s)
33
+ task.hook.should == :to_s
34
+ end
35
+
36
+ it "should return nil for nonexistent hook." do
37
+ task = DRbQS::Task.new([1, 2, 3], :size)
38
+ task.exec_hook(nil, nil).should be_nil
39
+ end
40
+
41
+ it "should execute hook of block." do
42
+ mock = mock('for task')
43
+ task = DRbQS::Task.new(mock, :calc) do |server, result|
44
+ mock.hook_method(server, result)
45
+ end
46
+ mock.should_receive(:hook_method).with(:server, :result)
47
+ task.exec_hook(:server, :result)
48
+ end
49
+
50
+ it "should execute hook of symbol." do
51
+ mock = mock('for task')
52
+ task = DRbQS::Task.new(mock, :calc, hook: :hook_method)
53
+ mock.should_receive(:hook_method).with(:server, :result)
54
+ task.exec_hook(:server, :result)
55
+ end
56
+
57
+ it "should set note." do
58
+ note_string = "Return size"
59
+ task = DRbQS::Task.new([1, 2, 3], :size, note: note_string)
60
+ task.note.should == note_string
61
+ end
62
+
63
+ it "should not have note." do
64
+ note_string = "Return size"
65
+ task = DRbQS::Task.new([1, 2, 3], :size)
66
+ task.note.should be_nil
67
+ end
68
+
69
+ it "should have empty argument array." do
70
+ task = DRbQS::Task.new([1, 2, 3], :size)
71
+ task.args.should == []
72
+ end
73
+
74
+ it "should set arguments." do
75
+ ary = [3, 4, 5]
76
+ task = DRbQS::Task.new([1, 2, 3], :concat, args: ary)
77
+ task.args.should == ary
78
+ end
79
+
80
+ it "should marshalize." do
81
+ task = DRbQS::Task.new(TestTask.new(100), :calc, hook: :test_hook)
82
+ lambda do
83
+ Marshal.dump(task)
84
+ end.should_not raise_error
85
+ end
86
+
87
+ it "should not marshalize." do
88
+ task = DRbQS::Task.new(TestTask.new(100), :calc) do |srv, res|
89
+ p res
90
+ end
91
+ lambda do
92
+ Marshal.dump(task)
93
+ end.should raise_error
22
94
  end
23
95
  end
24
96
 
25
- describe DRbQS::CommandExecute do
26
- it "should execute command" do
27
- cmd_exec = DRbQS::CommandExecute.new('ls > /dev/null')
28
- cmd_exec.exec.should == 0
97
+ describe DRbQS::Task::TaskSet::ContainerTask do
98
+ it "should dump and load" do
99
+ obj = [[1], [1, 2], [1, 2, 3]]
100
+ tasks = obj.map do |ary|
101
+ DRbQS::Task.new(ary, :size)
102
+ end
103
+ container = DRbQS::Task::TaskSet::ContainerTask.new(tasks)
104
+ dump = Marshal.dump(container)
105
+ Marshal.load(dump).should == container
29
106
  end
30
107
 
31
- it "should enqueue files" do
32
- DRbQS::FileTransfer.should_receive(:enqueue).exactly(2)
33
- cmd_exec = DRbQS::CommandExecute.new('ls > /dev/null', :transfer => ['hello', 'world'])
34
- cmd_exec.exec
108
+ it "should execute each task" do
109
+ obj = [[1, 3, 4], [2], [1, 2, 3]]
110
+ tasks = obj.map do |ary|
111
+ DRbQS::Task.new(ary, :size)
112
+ end
113
+ container = DRbQS::Task::TaskSet::ContainerTask.new(tasks)
114
+ container.exec.should == [3, 1, 3]
35
115
  end
36
116
  end
37
117
 
38
- describe DRbQS::TaskContainer do
118
+ describe DRbQS::Task::TaskSet::ContainerWithoutHook do
39
119
  it "should dump and load" do
40
120
  obj = [[1], [1, 2], [1, 2, 3]]
41
121
  tasks = obj.map do |ary|
42
122
  DRbQS::Task.new(ary, :size)
43
123
  end
44
- container = DRbQS::TaskContainer.new(tasks)
124
+ container = DRbQS::Task::TaskSet::ContainerWithoutHook.new(tasks)
45
125
  dump = Marshal.dump(container)
46
126
  Marshal.load(dump).should == container
47
127
  end
@@ -51,15 +131,33 @@ describe DRbQS::TaskContainer do
51
131
  tasks = obj.map do |ary|
52
132
  DRbQS::Task.new(ary, :size)
53
133
  end
54
- container = DRbQS::TaskContainer.new(tasks)
134
+ container = DRbQS::Task::TaskSet::ContainerWithoutHook.new(tasks)
55
135
  container.exec.should == [3, 1, 3]
56
136
  end
57
137
  end
58
138
 
59
- describe DRbQS::TaskSet do
60
- it "should execute hooks" do
61
- server = double('server')
62
- methods_for_hook = double('hook')
139
+ describe DRbQS::Task::TaskSet do
140
+ it "should use DRbQS::Task::TaskSet::ContainerTask." do
141
+ tasks = [DRbQS::Task.new([1, 2], :to_s), DRbQS::Task.new([1, 2], :size, hook: :to_s)]
142
+ task_set = DRbQS::Task::TaskSet.new(tasks)
143
+ task_set.obj.should be_an_instance_of DRbQS::Task::TaskSet::ContainerTask
144
+ end
145
+
146
+ it "should use DRbQS::Task::TaskSet::ContainerWithoutHook." do
147
+ tasks = []
148
+ tasks << DRbQS::Task.new([1, 2], :to_s) do |srv, result|
149
+ p result
150
+ end
151
+ tasks << DRbQS::Task.new([1, 2], :size) do |srv, result|
152
+ p result
153
+ end
154
+ task_set = DRbQS::Task::TaskSet.new(tasks)
155
+ task_set.obj.should be_an_instance_of DRbQS::Task::TaskSet::ContainerWithoutHook
156
+ end
157
+
158
+ it "should execute hooks of blocks." do
159
+ server = mock('server')
160
+ methods_for_hook = mock('hook')
63
161
  methods_for_hook.should_receive(:m0).exactly(1)
64
162
  methods_for_hook.should_receive(:m1).exactly(1)
65
163
  methods_for_hook.should_receive(:m2).exactly(1)
@@ -68,7 +166,18 @@ describe DRbQS::TaskSet do
68
166
  tasks << DRbQS::Task.new(obj[0], :size, &methods_for_hook.method(:m0))
69
167
  tasks << DRbQS::Task.new(obj[1], :size, &methods_for_hook.method(:m1))
70
168
  tasks << DRbQS::Task.new(obj[2], :size, &methods_for_hook.method(:m2))
71
- task_set = DRbQS::TaskSet.new(tasks)
72
- task_set.hook.call(server, [1, 2, 3])
169
+ task_set = DRbQS::Task::TaskSet.new(tasks)
170
+ task_set.exec_hook(server, [1, 2, 3])
171
+ end
172
+
173
+ it "should execute hooks of symbols." do
174
+ server = mock('server')
175
+ obj = [TestTask.new(100), TestTask.new(200), TestTask.new(300)]
176
+ tasks = []
177
+ tasks << DRbQS::Task.new(obj[0], :some_method, hook: :test_hook)
178
+ tasks << DRbQS::Task.new(obj[1], :some_method, hook: :test_hook)
179
+ tasks << DRbQS::Task.new(obj[2], :some_method, hook: :test_hook)
180
+ task_set = DRbQS::Task::TaskSet.new(tasks)
181
+ task_set.exec_hook(server, [100, 200, 300])
73
182
  end
74
183
  end
@@ -2,9 +2,9 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  require 'drbqs/utility/temporary'
4
4
 
5
- describe DRbQS::LoggerDummy do
5
+ describe DRbQS::Misc::LoggerDummy do
6
6
  subject do
7
- DRbQS::LoggerDummy.new
7
+ DRbQS::Misc::LoggerDummy.new
8
8
  end
9
9
 
10
10
  it "should respond to info." do
@@ -0,0 +1,90 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ require 'drbqs/utility/temporary'
4
+ require 'drbqs/utility/transfer/transfer'
5
+ require 'drbqs/utility/transfer/transfer_client'
6
+
7
+ def create_sample_transfer_files(n = nil)
8
+ tmp_dir = DRbQS::Temporary.directory
9
+ files = []
10
+ (n || 3).times do |i|
11
+ path = File.join(tmp_dir, "test%d.txt" % i)
12
+ files << path
13
+ open(path, 'w') do |f|
14
+ f.puts (i * i).to_s
15
+ end
16
+ end
17
+ [tmp_dir, files]
18
+ end
19
+
20
+ describe DRbQS::Transfer::Client::Local do
21
+ before(:all) do
22
+ @dir = DRbQS::Temporary.directory
23
+ @client = DRbQS::Transfer::Client::Local.new(@dir)
24
+ end
25
+
26
+ it "should move files." do
27
+ tmp_dir, files = create_sample_transfer_files
28
+ @client.transfer(files)
29
+ files.all? do |path|
30
+ !File.exist?(path)
31
+ end.should be_true
32
+ files.all? do |path|
33
+ File.exist?(File.join(@dir, File.basename(path)))
34
+ end.should be_true
35
+ end
36
+
37
+ it "should copy files." do
38
+ tmp_dir, files = create_sample_transfer_files
39
+ @client.download(files)
40
+ files.all? do |path|
41
+ File.exist?(path)
42
+ end.should be_true
43
+ files.all? do |path|
44
+ File.exist?(File.join(@dir, File.basename(path)))
45
+ end.should be_true
46
+ end
47
+
48
+ after(:all) do
49
+ DRbQS::Temporary.delete_all
50
+ end
51
+ end
52
+
53
+ describe DRbQS::Transfer::Client::SFTP do
54
+ module Net::SFTP
55
+ def self.set_mock(m)
56
+ @mock = m
57
+ end
58
+
59
+ def self.start(user, host, &block)
60
+ yield(@mock)
61
+ end
62
+ end
63
+
64
+ before(:all) do
65
+ @dir = DRbQS::Temporary.directory
66
+ @client = DRbQS::Transfer::Client::SFTP.new('user_name', 'example.com', @dir)
67
+ end
68
+
69
+ it "should transfer files." do
70
+ tmp_dir, files = create_sample_transfer_files(1)
71
+ source_path = files[0]
72
+ sftp = mock('sftp')
73
+ sftp.should_receive(:upload).with(source_path, File.join(@dir, File.basename(source_path)))
74
+ FileUtils.should_receive(:rm_r).with(source_path)
75
+ Net::SFTP.set_mock(sftp)
76
+ @client.transfer(files)
77
+ end
78
+
79
+ it "should download files. (incomplete)" do
80
+ tmp_dir, files = create_sample_transfer_files(1)
81
+ sftp = mock('sftp')
82
+ sftp.should_receive(:download)
83
+ Net::SFTP.set_mock(sftp)
84
+ @client.download(files)
85
+ end
86
+
87
+ after(:all) do
88
+ DRbQS::Temporary.delete_all
89
+ end
90
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ require 'drbqs/utility/transfer/transfer'
4
+ require 'drbqs/utility/transfer/transfer_client'
5
+ require 'drbqs/utility/transfer/transfer_file_list'
6
+
7
+ describe DRbQS::Transfer::FileList do
8
+ before(:all) do
9
+ @files = Dir.glob("#{File.dirname(__FILE__)}/*.rb")
10
+ end
11
+
12
+ it "should download files." do
13
+ client = mock('transfer client')
14
+ DRbQS::Transfer::Client.stub(:get).and_return(client)
15
+ client.should_receive(:download).with(@files, nil)
16
+ file_list = DRbQS::Transfer::FileList.new(*@files)
17
+ file_list.path
18
+ end
19
+
20
+ it "should download files with readonly." do
21
+ client = mock('transfer client')
22
+ DRbQS::Transfer::Client.stub(:get).and_return(client)
23
+ client.should_receive(:download).with(@files, true)
24
+ file_list = DRbQS::Transfer::FileList.new(*@files, :readonly => true)
25
+ file_list.path
26
+ end
27
+ end