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 +18 -0
- data/LICENCE.rdoc +1 -1
- data/README.rdoc +1 -1
- data/app/models/taverna_player/run_port.rb +45 -6
- data/config/routes.rb +2 -1
- data/lib/taverna_player/concerns/controllers/runs_controller.rb +27 -53
- data/lib/taverna_player/concerns/models/run_port.rb +39 -11
- data/lib/taverna_player/concerns/utils.rb +8 -1
- data/lib/taverna_player/concerns/zip.rb +27 -0
- data/lib/taverna_player/version.rb +1 -1
- data/lib/taverna_player/worker.rb +12 -14
- data/taverna_player.gemspec +1 -1
- data/test/fixtures/taverna_player/run_ports.yml +8 -1
- data/test/functional/taverna_player/runs_controller_test.rb +63 -1
- data/test/unit/taverna_player/run_port_test.rb +87 -1
- data/test/unit/utils_test.rb +46 -0
- metadata +7 -4
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
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 ->
|
43
|
-
# value_size(indices) ->
|
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? ->
|
64
|
-
# value_is_text?(indices) ->
|
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
|
-
#
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
-
|
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
|
207
|
+
raise ActionController::RoutingError.new('Not Found') if @port.nil?
|
208
208
|
|
209
|
-
|
210
|
-
|
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
|
224
|
+
if @port.nil? || path.length != @port.depth
|
230
225
|
raise ActionController::RoutingError.new('Not Found')
|
231
226
|
end
|
232
227
|
|
233
|
-
#
|
234
|
-
|
235
|
-
|
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
|
-
|
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
|
-
|
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
|
151
|
+
if file_path.blank?
|
125
152
|
self[:value]
|
126
153
|
else
|
127
|
-
value_is_text? ? File.read(
|
154
|
+
value_is_text? ? File.read(file_path) : File.binread(file_path)
|
128
155
|
end
|
129
156
|
else
|
130
|
-
|
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
|
@@ -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
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
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
|
268
|
-
|
269
|
-
|
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
|
277
|
+
def singleton_output(name, tmp_file)
|
280
278
|
File.open(tmp_file, "wb") do |file|
|
281
|
-
file.write
|
279
|
+
file.write read_file_from_zip(@run.results.path, name)
|
282
280
|
end
|
283
281
|
|
284
282
|
File.new(tmp_file)
|
data/taverna_player.gemspec
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
|
#
|
@@ -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
|
+
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:
|
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: -
|
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: -
|
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
|