taverna-player 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.rdoc CHANGED
@@ -1,5 +1,23 @@
1
1
  = Changes log for Taverna Player
2
2
 
3
+ == Version 0.5.0
4
+
5
+ * [TAV-480] Refactor output port downloading.
6
+ * [TAV-480] Add a method to download input ports.
7
+ * [TAV-475] Add RunPort::value_size= setter.
8
+ * [TAV-475] Add RunPort::value_type= setter.
9
+ * Use the new metadata setters in the worker code.
10
+ * Add some tests for internal list code.
11
+ * [TAV-482] Refactor Zip operations into a concern.
12
+ * Fix typo in RunPort#value_is_text? documentation.
13
+ * Add RunPort#value_is_error? method.
14
+ * [TAV-483] Fix getting error values from deep values.
15
+ * Minor fix in RunPort#deep_value.
16
+ * [TAV-484] RunPort#value returns zipped lists.
17
+ * Add RunPort#filename.
18
+ * Refactor RunsController.
19
+ * [TAV-482] Refactor worker code to use Zip concern.
20
+
3
21
  == Version 0.4.0
4
22
 
5
23
  * [TAV-466] Add port metadata to JSON output.
data/LICENCE.rdoc CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 The University of Manchester, UK.
1
+ Copyright (c) 2013, 2014 The University of Manchester, UK.
2
2
 
3
3
  All rights reserved.
4
4
 
data/README.rdoc CHANGED
@@ -4,7 +4,7 @@ Authors:: Robert Haines
4
4
  Contact:: mailto:support@mygrid.org.uk
5
5
  URL:: http://www.taverna.org.uk
6
6
  Licence:: BSD (See LICENCE or http://www.opensource.org/licenses/bsd-license.php)
7
- Copyright:: (c) 2013 The University of Manchester, UK
7
+ Copyright:: (c) 2013, 2014 The University of Manchester, UK
8
8
 
9
9
  {<img src="https://badge.fury.io/rb/taverna-player.png" alt="Gem Version" />}[http://badge.fury.io/rb/taverna-player]
10
10
  {<img src="https://codeclimate.com/github/myGrid/taverna-player.png" />}[https://codeclimate.com/github/myGrid/taverna-player]
@@ -1,5 +1,5 @@
1
1
  #------------------------------------------------------------------------------
2
- # Copyright (c) 2013 The University of Manchester, UK.
2
+ # Copyright (c) 2013, 2014 The University of Manchester, UK.
3
3
  #
4
4
  # BSD Licenced. See LICENCE.rdoc for details.
5
5
  #
@@ -28,6 +28,15 @@ module TavernaPlayer
28
28
  # Convert this port's name to a more presentable form. In practice this
29
29
  # means converting underscores (_) to spaces, while preserving case.
30
30
 
31
+ ##
32
+ # :method: filename
33
+ # :call-seq:
34
+ # filename -> string
35
+ #
36
+ # Return a suitable filename to be used when saving data from a port. This
37
+ # is generated by concatenating the port's name onto the end of the name
38
+ # of its parent run.
39
+
31
40
  ##
32
41
  # :method: value_preview
33
42
  # :call-seq:
@@ -39,13 +48,22 @@ module TavernaPlayer
39
48
  ##
40
49
  # :method: value_size
41
50
  # :call-seq:
42
- # value_size -> string
43
- # value_size(indices) -> string
51
+ # value_size -> integer
52
+ # value_size(indices) -> integer
44
53
  #
45
54
  # Get the size (in bytes) of the value held in this port. Pass in a list
46
55
  # of indices if it is a list port. Returns nil if there is no port
47
56
  # metadata.
48
57
 
58
+ ##
59
+ # :method: value_size=
60
+ # :call-seq:
61
+ # value_size=
62
+ #
63
+ # Set the size (in bytes) of the value held in this port. Pass in a list
64
+ # of sizes if it is a list port. This method does nothing if the depth of
65
+ # the input list does not match that of the port itself.
66
+
49
67
  ##
50
68
  # :method: value_type
51
69
  # :call-seq:
@@ -57,16 +75,34 @@ module TavernaPlayer
57
75
  # metadata so if you create a port and put any other type of data in then
58
76
  # you should adjust the metadata to match.
59
77
 
78
+ ##
79
+ # :method: value_type=
80
+ # :call-seq:
81
+ # value_type=
82
+ #
83
+ # Set the MIME type of the value held in this port. Pass in a list of
84
+ # types if it is a list port. This method does nothing if the depth of
85
+ # the input list does not match that of the port itself.
86
+
60
87
  ##
61
88
  # :method: value_is_text?
62
89
  # :call-seq:
63
- # value_is_text? -> string
64
- # value_is_text?(indices) -> string
90
+ # value_is_text? -> boolean
91
+ # value_is_text?(indices) -> boolean
65
92
  #
66
93
  # Is the type of the value held in this port some sort of text? This
67
94
  # returns true if the media type section of the MIME type is "text". Pass
68
95
  # in a list of indices if it is a list port.
69
96
 
97
+ ##
98
+ # :method: value_is_error?
99
+ # :call-seq:
100
+ # value_is_error? -> boolean
101
+ # value_is_error?(indices) -> boolean
102
+ #
103
+ # Is the type of the value held in this port an error? Pass in a list of
104
+ # indices if it is a list port.
105
+
70
106
  ##
71
107
  # :method: value
72
108
  # :call-seq:
@@ -119,9 +155,12 @@ module TavernaPlayer
119
155
  # :type => ["text/plain", "image/png"]
120
156
  # }
121
157
  #
122
- # <b>Note:</b> By default Taverna Player only uses this field on outputs.
158
+ # <b>Note 1:</b> By default Taverna Player only uses this field on outputs.
123
159
  # It is provided as a field for inputs too as a convenience for
124
160
  # implementors and for possible future use.
161
+ #
162
+ # <b>Note 2:</b> It is preferable to use the #value_size= and #value_type=
163
+ # methods to set this information most of the time.
125
164
 
126
165
  end
127
166
 
data/config/routes.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #------------------------------------------------------------------------------
2
- # Copyright (c) 2013 The University of Manchester, UK.
2
+ # Copyright (c) 2013, 2014 The University of Manchester, UK.
3
3
  #
4
4
  # BSD Licenced. See LICENCE.rdoc for details.
5
5
  #
@@ -20,6 +20,7 @@ TavernaPlayer::Engine.routes.draw do
20
20
  scope "download" do
21
21
  get "log", :action => "download_log"
22
22
  get "results", :action => "download_results"
23
+ get "input/:port", :action => "download_input"
23
24
  get "output/:port", :action => "download_output"
24
25
  end
25
26
 
@@ -1,5 +1,5 @@
1
1
  #------------------------------------------------------------------------------
2
- # Copyright (c) 2013 The University of Manchester, UK.
2
+ # Copyright (c) 2013, 2014 The University of Manchester, UK.
3
3
  #
4
4
  # BSD Licenced. See LICENCE.rdoc for details.
5
5
  #
@@ -26,6 +26,7 @@ module TavernaPlayer
26
26
  before_filter :find_runs, :only => [ :index ]
27
27
  before_filter :find_run, :except => [ :index, :new, :create ]
28
28
  before_filter :find_workflow, :only => [ :new ]
29
+ before_filter :find_port, :only => [ :download_input, :download_output, :input, :output ]
29
30
  before_filter :setup_new_run, :only => :new
30
31
  before_filter :set_run_user, :only => :create
31
32
  before_filter :filter_update_parameters, :only => :update
@@ -49,6 +50,10 @@ module TavernaPlayer
49
50
  @workflow = TavernaPlayer.workflow_proxy.class_name.find(params[:workflow_id])
50
51
  end
51
52
 
53
+ def find_port
54
+ @port = RunPort.find_by_run_id_and_name(@run.id, params[:port])
55
+ end
56
+
52
57
  def setup_new_run
53
58
  @run = Run.new(:workflow_id => @workflow.id)
54
59
  @run.embedded = true if params[:embedded] == "true"
@@ -72,11 +77,14 @@ module TavernaPlayer
72
77
  @interaction = Interaction.find_by_run_id_and_serial(@run.id, params[:serial])
73
78
  end
74
79
 
75
- # Read the data from the results zip file.
76
- def read_from_zip(file)
77
- Zip::ZipFile.open(@run.results.path) do |zip|
78
- zip.read(file)
79
- end
80
+ # Download an input or output port as an "attachment" (i.e. not
81
+ # "inline").
82
+ def download_port
83
+ # If there is no such port then return a 404.
84
+ raise ActionController::RoutingError.new('Not Found') if @port.nil?
85
+
86
+ type = @port.depth == 0 ? @port.value_type : "application/zip"
87
+ send_data @port.value, :type => type, :filename => @port.filename
80
88
  end
81
89
 
82
90
  # Choose a layout for the page depending on action and embedded status.
@@ -183,34 +191,23 @@ module TavernaPlayer
183
191
  :filename => "#{@run.name}-all-results.zip"
184
192
  end
185
193
 
194
+ # GET /runs/1/download/input/:port
195
+ def download_input
196
+ download_port
197
+ end
198
+
186
199
  # GET /runs/1/download/output/:port
187
200
  def download_output
188
- output = RunPort::Output.find_by_run_id_and_name(@run.id, params[:port])
189
-
190
- # If there is no such output port then return a 404.
191
- raise ActionController::RoutingError.new('Not Found') if output.nil?
192
-
193
- if output.file.blank?
194
- send_data output.value, :type => "text/plain",
195
- :filename => "#{@run.name}-#{output.name}.txt"
196
- else
197
- send_file output.file.path, :type => output.file.content_type,
198
- :filename => "#{@run.name}-#{output.file_file_name}"
199
- end
201
+ download_port
200
202
  end
201
203
 
202
204
  # GET /runs/1/input/*
203
205
  def input
204
- input = RunPort::Input.find_by_run_id_and_name(@run.id, params[:port])
205
-
206
206
  # If there is no such input port then return a 404.
207
- raise ActionController::RoutingError.new('Not Found') if input.nil?
207
+ raise ActionController::RoutingError.new('Not Found') if @port.nil?
208
208
 
209
- if input.file.blank?
210
- send_data input.value, :disposition => "inline"
211
- else
212
- send_file input.file.path, :disposition => "inline"
213
- end
209
+ send_data @port.value, :type => @port.value_type,
210
+ :disposition => "inline"
214
211
  end
215
212
 
216
213
  # GET /runs/1/output/*
@@ -222,38 +219,15 @@ module TavernaPlayer
222
219
  path = params[:path].split("/").map { |p| p.to_i }
223
220
  end
224
221
 
225
- output = RunPort::Output.find_by_run_id_and_name(@run.id, params[:port])
226
-
227
222
  # If there is no such output port or the path is the wrong depth then
228
223
  # return a 404.
229
- if output.nil? || path.length != output.depth
224
+ if @port.nil? || path.length != @port.depth
230
225
  raise ActionController::RoutingError.new('Not Found')
231
226
  end
232
227
 
233
- # A singleton should just return the value (if it's small enough) or the
234
- # file if it's bigger. If it's a value in the database then it'll always
235
- # be a text value, although not necessarily "plain".
236
- if output.depth == 0 && !output.value.blank?
237
- send_data output.value, :disposition => "inline",
238
- :type => output.metadata[:type]
239
- else
240
- # We need to rebuild the path indices into a string here (and can't
241
- # re-use the params[:path] variable directly) because files are
242
- # indexed from one in the zip we get back from Server, not zero.
243
- path_s = path.map { |p| p += 1 }.join("/")
244
- file = path_s.blank? ? "#{output.name}" : "#{output.name}/#{path_s}"
245
- type = recurse_into_lists(output.metadata[:type], path)
246
-
247
- # If it's an error, then we need to further hack the file path and
248
- # content type.
249
- if type == "application/x-error"
250
- file += ".error"
251
- type = "text/plain"
252
- end
253
-
254
- send_data read_from_zip(file), :type => type,
255
- :disposition => "inline"
256
- end
228
+ # Just need to mangle the MIME type when sending error messages.
229
+ type = @port.value_is_error?(path) ? "text/plain" : @port.value_type(path)
230
+ send_data @port.value(path), :type => type, :disposition => "inline"
257
231
  end
258
232
 
259
233
  # GET /runs/1/interaction/:int_id
@@ -1,5 +1,5 @@
1
1
  #------------------------------------------------------------------------------
2
- # Copyright (c) 2013 The University of Manchester, UK.
2
+ # Copyright (c) 2013, 2014 The University of Manchester, UK.
3
3
  #
4
4
  # BSD Licenced. See LICENCE.rdoc for details.
5
5
  #
@@ -18,6 +18,7 @@ module TavernaPlayer
18
18
  extend ActiveSupport::Concern
19
19
 
20
20
  include TavernaPlayer::Concerns::Utils
21
+ include TavernaPlayer::Concerns::Zip
21
22
 
22
23
  included do
23
24
 
@@ -80,14 +81,13 @@ module TavernaPlayer
80
81
  end
81
82
 
82
83
  def deep_value(index)
83
- path = index.map { |j| j += 1 }.join("/")
84
+ # Need to mangle the path here in two ways:
85
+ # * Files are indexed from 1 (not zero) in the output zip files.
86
+ # * Errors are saved to a file with a '.error' suffix.
87
+ path = index.map { |i| i + 1 }.join("/")
88
+ path += ".error" if value_is_error?(index)
84
89
 
85
- data = String.new
86
- Zip::ZipFile.open(file.path) do |zip|
87
- data = zip.read("#{path}")
88
- end
89
-
90
- data
90
+ read_file_from_zip(file.path, path)
91
91
  end
92
92
 
93
93
  def value_metadata(field, *indices)
@@ -96,38 +96,66 @@ module TavernaPlayer
96
96
  recurse_into_lists(metadata[field], index)
97
97
  end
98
98
 
99
+ def set_value_metadata(field, value)
100
+ return unless depth == list_depth(value)
101
+
102
+ md = metadata
103
+ md = Hash.new if md.nil?
104
+ md[field] = value
105
+ update_attribute(:metadata, md)
106
+ end
107
+
99
108
  end # included
100
109
 
101
110
  def display_name
102
111
  name.gsub('_', ' ')
103
112
  end
104
113
 
114
+ def filename
115
+ port_file = depth == 0 ? name : "#{name}.zip"
116
+ "#{run.name}-#{port_file}"
117
+ end
118
+
105
119
  def value_type(*indices)
106
120
  value_metadata(:type, *indices) || "text/plain"
107
121
  end
108
122
 
123
+ def value_type=(type)
124
+ set_value_metadata(:type, type)
125
+ end
126
+
109
127
  def value_is_text?(*indices)
110
128
  type = value_type(*indices)
111
129
  type.starts_with?("text")
112
130
  end
113
131
 
132
+ def value_is_error?(*indices)
133
+ value_type(*indices) == "application/x-error"
134
+ end
135
+
114
136
  def value_size(*indices)
115
137
  value_metadata(:size, *indices)
116
138
  end
117
139
 
140
+ def value_size=(size)
141
+ set_value_metadata(:size, size)
142
+ end
143
+
118
144
  def value_preview
119
145
  self[:value]
120
146
  end
121
147
 
122
148
  def value(*indices)
149
+ file_path = file.path
123
150
  if depth == 0
124
- if file.path.blank?
151
+ if file_path.blank?
125
152
  self[:value]
126
153
  else
127
- value_is_text? ? File.read(file.path) : File.binread(file.path)
154
+ value_is_text? ? File.read(file_path) : File.binread(file_path)
128
155
  end
129
156
  else
130
- deep_value([*indices].flatten)
157
+ index = [*indices].flatten
158
+ index.empty? ? File.binread(file_path) : deep_value(index)
131
159
  end
132
160
  end
133
161
 
@@ -1,5 +1,5 @@
1
1
  #------------------------------------------------------------------------------
2
- # Copyright (c) 2013 The University of Manchester, UK.
2
+ # Copyright (c) 2013, 2014 The University of Manchester, UK.
3
3
  #
4
4
  # BSD Licenced. See LICENCE.rdoc for details.
5
5
  #
@@ -25,6 +25,13 @@ module TavernaPlayer
25
25
  recurse_into_lists(list[i], indexes)
26
26
  end
27
27
 
28
+ # Sometimes we need to test an array's depth to check that it matches a
29
+ # port's depth. An empty list has depth 1, because it is a list.
30
+ def list_depth(list, depth = 0)
31
+ return depth if !list.is_a?(Array)
32
+ list.empty? ? depth + 1 : list.map { |l| list_depth(l, depth + 1) }.max
33
+ end
34
+
28
35
  end
29
36
  end
30
37
  end
@@ -0,0 +1,27 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2014 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Taverna Player was developed in the BioVeL project, funded by the European
7
+ # Commission 7th Framework Programme (FP7), through grant agreement
8
+ # number 283359.
9
+ #
10
+ # Author: Robert Haines
11
+ #------------------------------------------------------------------------------
12
+
13
+ module TavernaPlayer
14
+ module Concerns
15
+ module Zip
16
+
17
+ extend ActiveSupport::Concern
18
+
19
+ def read_file_from_zip(zip, file)
20
+ ::Zip::ZipFile.open(zip) do |z|
21
+ z.read(file)
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -11,5 +11,5 @@
11
11
  #------------------------------------------------------------------------------
12
12
 
13
13
  module TavernaPlayer
14
- VERSION = "0.4.0"
14
+ VERSION = "0.5.0"
15
15
  end
@@ -1,5 +1,5 @@
1
1
  #------------------------------------------------------------------------------
2
- # Copyright (c) 2013 The University of Manchester, UK.
2
+ # Copyright (c) 2013, 2014 The University of Manchester, UK.
3
3
  #
4
4
  # BSD Licenced. See LICENCE.rdoc for details.
5
5
  #
@@ -13,6 +13,7 @@
13
13
  module TavernaPlayer
14
14
  class Worker
15
15
  include TavernaPlayer::Concerns::Callback
16
+ include TavernaPlayer::Concerns::Zip
16
17
 
17
18
  # How to get the interaction presentation frame out of the interaction page.
18
19
  INTERACTION_REGEX = /document\.getElementById\(\'presentationFrame\'\)\.src = \"(.+)\";/
@@ -249,13 +250,11 @@ module TavernaPlayer
249
250
  tmp_file_name = File.join(tmp_dir, port.name)
250
251
 
251
252
  if port.depth == 0
252
- Zip::ZipFile.open(@run.results.path) do |zip|
253
- if port.type =~ /text/
254
- output.value = zip.read(port.name)
255
- else
256
- port_name = port.error? ? "#{port.name}.error" : port.name
257
- output.file = singleton_output(port_name, tmp_file_name, zip)
258
- end
253
+ if port.type =~ /text/
254
+ output.value = read_file_from_zip(@run.results.path, port.name)
255
+ else
256
+ port_name = port.error? ? "#{port.name}.error" : port.name
257
+ output.file = singleton_output(port_name, tmp_file_name)
259
258
  end
260
259
  else
261
260
  # TODO: Need to rework this so it's not just re-downloading the
@@ -264,10 +263,9 @@ module TavernaPlayer
264
263
  output.file = File.new("#{tmp_file_name}.zip")
265
264
  end
266
265
 
267
- output.metadata = {
268
- :size => port.size,
269
- :type => port.type
270
- }
266
+ # Set the output port size and type metadata.
267
+ output.value_type = port.type
268
+ output.value_size = port.size
271
269
 
272
270
  outputs << output
273
271
  end
@@ -276,9 +274,9 @@ module TavernaPlayer
276
274
  outputs
277
275
  end
278
276
 
279
- def singleton_output(name, tmp_file, zip)
277
+ def singleton_output(name, tmp_file)
280
278
  File.open(tmp_file, "wb") do |file|
281
- file.write zip.read(name)
279
+ file.write read_file_from_zip(@run.results.path, name)
282
280
  end
283
281
 
284
282
  File.new(tmp_file)
@@ -1,5 +1,5 @@
1
1
  #------------------------------------------------------------------------------
2
- # Copyright (c) 2013 The University of Manchester, UK.
2
+ # Copyright (c) 2013, 2014 The University of Manchester, UK.
3
3
  #
4
4
  # BSD Licenced. See LICENCE.rdoc for details.
5
5
  #
@@ -1,5 +1,5 @@
1
1
  #------------------------------------------------------------------------------
2
- # Copyright (c) 2013 The University of Manchester, UK.
2
+ # Copyright (c) 2013, 2014 The University of Manchester, UK.
3
3
  #
4
4
  # BSD Licenced. See LICENCE.rdoc for details.
5
5
  #
@@ -60,3 +60,10 @@ six:
60
60
  run_id: 2
61
61
  depth: 2
62
62
  metadata: "---\n:size:\n- - 15\n - 20\n- - 17\n - 22\n- - 19\n - 24\n:type:\n- - text/plain\n - text/plain\n- - text/plain\n - text/plain\n- - text/plain\n - text/plain\n"
63
+
64
+ seven:
65
+ name: OUT_Error
66
+ port_type: TavernaPlayer::RunPort::Output
67
+ run_id: 2
68
+ depth: 0
69
+ metadata: "---\n:size: 718\n:type: application/x-error"
@@ -1,5 +1,5 @@
1
1
  #------------------------------------------------------------------------------
2
- # Copyright (c) 2013 The University of Manchester, UK.
2
+ # Copyright (c) 2013, 2014 The University of Manchester, UK.
3
3
  #
4
4
  # BSD Licenced. See LICENCE.rdoc for details.
5
5
  #
@@ -94,6 +94,12 @@ module TavernaPlayer
94
94
  :id => "1" }, {}, {}, "Did not route correctly"
95
95
  end
96
96
 
97
+ test "should route to input port download" do
98
+ assert_routing "/runs/3/download/input/IN_Value",
99
+ { :controller => "taverna_player/runs", :action => "download_input",
100
+ :id => "3", :port => "IN_Value" }, {}, {}, "Did not route correctly"
101
+ end
102
+
97
103
  test "should route to output port download" do
98
104
  assert_routing "/runs/1/download/output/Message",
99
105
  { :controller => "taverna_player/runs", :action => "download_output",
@@ -317,5 +323,61 @@ module TavernaPlayer
317
323
  assert_equal "New name", assigns(:run).name, "Run name not updated"
318
324
  assert_response :success, "Response was not success"
319
325
  end
326
+
327
+ test "should get run input" do
328
+ get :input, :id => @run3, :port => "IN_Value"
329
+ assert_response :success, "Response was not success"
330
+ assert_not_nil assigns(:run), "Did not assign a valid run instance"
331
+ assert_not_nil assigns(:port), "Did not assign a valid port instance"
332
+ assert_not_nil response.headers["Content-Disposition"],
333
+ "Content-Disposition header not set in response"
334
+ assert_equal response.headers["Content-Disposition"], "inline",
335
+ "Content-Disposition should be set to 'inline'"
336
+ assert_not_nil response.headers["Content-Type"],
337
+ "Content-Type header not set in response"
338
+ end
339
+
340
+ test "should download run input" do
341
+ get :download_input, :id => @run3, :port => "IN_Value"
342
+ assert_response :success, "Response was not success"
343
+ assert_not_nil assigns(:run), "Did not assign a valid run instance"
344
+ assert_not_nil assigns(:port), "Did not assign a valid port instance"
345
+ assert_not_nil response.headers["Content-Disposition"],
346
+ "Content-Disposition header not set in response"
347
+ assert response.headers["Content-Disposition"].include?("attachment"),
348
+ "Content-Disposition should be set to 'attachment'"
349
+ assert response.headers["Content-Disposition"].include?("filename="),
350
+ "Content-Disposition should provide a filename"
351
+ assert_not_nil response.headers["Content-Type"],
352
+ "Content-Type header not set in response"
353
+ end
354
+
355
+ test "should get run output" do
356
+ get :output, :id => @run1, :port => "Message"
357
+ assert_response :success, "Response was not success"
358
+ assert_not_nil assigns(:run), "Did not assign a valid run instance"
359
+ assert_not_nil assigns(:port), "Did not assign a valid port instance"
360
+ assert_not_nil response.headers["Content-Disposition"],
361
+ "Content-Disposition header not set in response"
362
+ assert_equal response.headers["Content-Disposition"], "inline",
363
+ "Content-Disposition should be set to 'inline'"
364
+ assert_not_nil response.headers["Content-Type"],
365
+ "Content-Type header not set in response"
366
+ end
367
+
368
+ test "should download run output" do
369
+ get :download_output, :id => @run1, :port => "Message"
370
+ assert_response :success, "Response was not success"
371
+ assert_not_nil assigns(:run), "Did not assign a valid run instance"
372
+ assert_not_nil assigns(:port), "Did not assign a valid port instance"
373
+ assert_not_nil response.headers["Content-Disposition"],
374
+ "Content-Disposition header not set in response"
375
+ assert response.headers["Content-Disposition"].include?("attachment"),
376
+ "Content-Disposition should be set to 'attachment'"
377
+ assert response.headers["Content-Disposition"].include?("filename="),
378
+ "Content-Disposition should provide a filename"
379
+ assert_not_nil response.headers["Content-Type"],
380
+ "Content-Type header not set in response"
381
+ end
320
382
  end
321
383
  end
@@ -1,5 +1,5 @@
1
1
  #------------------------------------------------------------------------------
2
- # Copyright (c) 2013 The University of Manchester, UK.
2
+ # Copyright (c) 2013, 2014 The University of Manchester, UK.
3
3
  #
4
4
  # BSD Licenced. See LICENCE.rdoc for details.
5
5
  #
@@ -20,6 +20,7 @@ module TavernaPlayer
20
20
  @port3 = taverna_player_run_ports(:three)
21
21
  @port5 = taverna_player_run_ports(:five)
22
22
  @port6 = taverna_player_run_ports(:six)
23
+ @port7 = taverna_player_run_ports(:seven)
23
24
  end
24
25
 
25
26
  test "run port inheritance types" do
@@ -326,6 +327,34 @@ module TavernaPlayer
326
327
  assert_nil port.value_size, "Unspecified size should return nil"
327
328
  end
328
329
 
330
+ test "set singleton value types" do
331
+ port = RunPort::Input.create(:depth => 0, :name => "test_port")
332
+
333
+ port.value_type = "text/html"
334
+ port.save
335
+ assert_equal "text/html", port.value_type,
336
+ "Value type was not set correctly"
337
+
338
+ port.value_type = ["text/plain", "text/plain"]
339
+ port.save
340
+ assert_equal "text/html", port.value_type,
341
+ "Value type was changed incorrectly"
342
+ end
343
+
344
+ test "set deep value types" do
345
+ port = RunPort::Input.create(:depth => 1, :name => "test_port")
346
+
347
+ port.value_type = ["text/plain", "text/plain"]
348
+ port.save
349
+ assert_equal ["text/plain", "text/plain"], port.value_type,
350
+ "Value type was not set correctly"
351
+
352
+ port.value_type = "text/html"
353
+ port.save
354
+ assert_equal ["text/plain", "text/plain"], port.value_type,
355
+ "Value type was changed incorrectly"
356
+ end
357
+
329
358
  test "detecting text values" do
330
359
  assert @port1.value_is_text?, "Value not detected as text"
331
360
  assert @port2.value_is_text?(0), "Value not detected as text"
@@ -335,6 +364,14 @@ module TavernaPlayer
335
364
  refute @port2.value_is_text?(2), "Value detected as text"
336
365
  end
337
366
 
367
+ test "detecting error values" do
368
+ refute @port1.value_is_error?, "Value detected as an error"
369
+ refute @port2.value_is_error?(0), "Value detected as an error"
370
+ assert @port2.value_is_error?(2), "Value not detected as an error"
371
+ refute @port6.value_is_error?(0, 1), "Value detected as an error"
372
+ assert @port7.value_is_error?, "Value not detected as an error"
373
+ end
374
+
338
375
  test "get value sizes" do
339
376
  assert_equal 13, @port1.value_size, "Value size not 13"
340
377
  assert_equal 974, @port2.value_size(2), "Value size not 974"
@@ -343,6 +380,32 @@ module TavernaPlayer
343
380
  assert_equal 24, @port6.value_size([2, 1]), "Value size not 24"
344
381
  end
345
382
 
383
+ test "set singleton value sizes" do
384
+ port = RunPort::Input.create(:depth => 0, :name => "test_port")
385
+ assert_nil port.value_size, "Unspecified size should return nil"
386
+
387
+ port.value_size = 12
388
+ port.save
389
+ assert_equal 12, port.value_size, "Value size was not set correctly"
390
+
391
+ port.value_size = [1, 2]
392
+ port.save
393
+ assert_equal 12, port.value_size, "Value size was changed incorrectly"
394
+ end
395
+
396
+ test "set deep value sizes" do
397
+ port = RunPort::Input.create(:depth => 1, :name => "test_port")
398
+ assert_nil port.value_size, "Unspecified size should return nil"
399
+
400
+ port.value_size = [1, 2]
401
+ port.save
402
+ assert_equal [1, 2], port.value_size, "Value size was not set correctly"
403
+
404
+ port.value_size = 12
405
+ port.save
406
+ assert_equal [1, 2], port.value_size, "Value size was changed incorrectly"
407
+ end
408
+
346
409
  test "value methods should not alter input parameters" do
347
410
  index = [1, 1]
348
411
  index_saved = index.dup
@@ -356,5 +419,28 @@ module TavernaPlayer
356
419
  @port6.value_size(index)
357
420
  assert_equal index_saved, index, "Parameter index was altered"
358
421
  end
422
+
423
+ test "port filenames" do
424
+ assert_equal "Test run 1-Message", @port1.filename,
425
+ "Incorrect filename generated"
426
+ refute @port1.filename.ends_with?(".zip"), "Filename has 'zip' suffix"
427
+ assert_equal "Test run 2-OUT.zip", @port2.filename,
428
+ "Incorrect filename generated"
429
+ assert @port2.filename.ends_with?(".zip"),
430
+ "Filename missing 'zip' suffix"
431
+ assert_equal "Test run 3-IN_Value", @port3.filename,
432
+ "Incorrect filename generated"
433
+ refute @port3.filename.ends_with?(".zip"), "Filename has 'zip' suffix"
434
+ assert_equal "Test run 4-Long_N_unnecessary_Name_OUT", @port5.filename,
435
+ "Incorrect filename generated"
436
+ refute @port5.filename.ends_with?(".zip"), "Filename has 'zip' suffix"
437
+ assert_equal "Test run 2-Output.zip", @port6.filename,
438
+ "Incorrect filename generated"
439
+ assert @port6.filename.ends_with?(".zip"),
440
+ "Filename missing 'zip' suffix"
441
+ assert_equal "Test run 2-OUT_Error", @port7.filename,
442
+ "Incorrect filename generated"
443
+ refute @port7.filename.ends_with?(".zip"), "Filename has 'zip' suffix"
444
+ end
359
445
  end
360
446
  end
@@ -0,0 +1,46 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2014 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Taverna Player was developed in the BioVeL project, funded by the European
7
+ # Commission 7th Framework Programme (FP7), through grant agreement
8
+ # number 283359.
9
+ #
10
+ # Author: Robert Haines
11
+ #------------------------------------------------------------------------------
12
+
13
+ require 'test_helper'
14
+
15
+ class UtilsTest < ActiveSupport::TestCase
16
+
17
+ include TavernaPlayer::Concerns::Utils
18
+
19
+ test "recurse into list" do
20
+ test_list1 = [0, 1, 2, 3, 4]
21
+ test_list2 = [[0, 1], [2, 3], [4, 5]]
22
+
23
+ assert_equal 0, recurse_into_lists(0, [0, 0]),
24
+ "A non-list should just be returned unchanged."
25
+ assert_equal test_list1, recurse_into_lists(test_list1, []),
26
+ "With no indices the original list should be returned unchanged."
27
+ assert_equal 0, recurse_into_lists(test_list1, [0]), "Should return 0."
28
+ assert_equal 4, recurse_into_lists(test_list1, [4]), "Should return 4."
29
+ assert_equal 0, recurse_into_lists(test_list2, [0, 0]), "Should return 0."
30
+ assert_equal [0, 1], recurse_into_lists(test_list2, [0]),
31
+ "Should return [0, 1]."
32
+ assert_equal 5, recurse_into_lists(test_list2, [2, 1]), "Should return 5."
33
+ end
34
+
35
+ test "list depth" do
36
+ assert_equal 0, list_depth(1), "Non-list should have depth 0."
37
+ assert_equal 1, list_depth([]), "Empty list should have depth 1."
38
+ assert_equal 1, list_depth([0]), "Should have depth 1."
39
+ assert_equal 1, list_depth([0, 1, 2, 3]), "Should have depth 1."
40
+ assert_equal 2, list_depth([[]]), "Should have depth 2."
41
+ assert_equal 2, list_depth([0, []]), "Should have depth 2."
42
+ assert_equal 2, list_depth([[0], [1], [2]]), "Should have depth 2."
43
+ assert_equal 2, list_depth([0, [1], [2]]), "Should have depth 2."
44
+ assert_equal 10, list_depth([[[[[[[[[[]]]]]]]]]]), "Should have depth 10."
45
+ end
46
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taverna-player
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-12-12 00:00:00.000000000 Z
12
+ date: 2014-01-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -337,6 +337,7 @@ files:
337
337
  - lib/taverna_player/concerns/models/run.rb
338
338
  - lib/taverna_player/concerns/models/run_port.rb
339
339
  - lib/taverna_player/concerns/utils.rb
340
+ - lib/taverna_player/concerns/zip.rb
340
341
  - lib/taverna_player/engine.rb
341
342
  - lib/taverna_player/model_proxy.rb
342
343
  - lib/taverna_player/port_renderer.rb
@@ -436,6 +437,7 @@ files:
436
437
  - test/unit/taverna_player/run_port_test.rb
437
438
  - test/unit/taverna_player/run_test.rb
438
439
  - test/unit/taverna_player/service_credential_test.rb
440
+ - test/unit/utils_test.rb
439
441
  - test/workflows/hello.t2flow
440
442
  - test/workflows/list_with_errors.t2flow
441
443
  - test/workflows/pass_through.t2flow
@@ -454,7 +456,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
454
456
  version: '0'
455
457
  segments:
456
458
  - 0
457
- hash: -1589530692801981432
459
+ hash: -672196183231170536
458
460
  required_rubygems_version: !ruby/object:Gem::Requirement
459
461
  none: false
460
462
  requirements:
@@ -463,7 +465,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
463
465
  version: '0'
464
466
  segments:
465
467
  - 0
466
- hash: -1589530692801981432
468
+ hash: -672196183231170536
467
469
  requirements: []
468
470
  rubyforge_project:
469
471
  rubygems_version: 1.8.21
@@ -561,6 +563,7 @@ test_files:
561
563
  - test/unit/taverna_player/run_port_test.rb
562
564
  - test/unit/taverna_player/run_test.rb
563
565
  - test/unit/taverna_player/service_credential_test.rb
566
+ - test/unit/utils_test.rb
564
567
  - test/workflows/hello.t2flow
565
568
  - test/workflows/list_with_errors.t2flow
566
569
  - test/workflows/pass_through.t2flow