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 +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
|