taverna-player 0.4.0 → 0.5.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.
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