arrow 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +1590 -0
- data/LICENSE +28 -0
- data/README +75 -0
- data/Rakefile +366 -0
- data/Rakefile.local +63 -0
- data/data/arrow/applets/TEMPLATE.rb.tpl +53 -0
- data/data/arrow/applets/args.rb +50 -0
- data/data/arrow/applets/config.rb +55 -0
- data/data/arrow/applets/error.rb +63 -0
- data/data/arrow/applets/files.rb +46 -0
- data/data/arrow/applets/inspect.rb +46 -0
- data/data/arrow/applets/nosuchapplet.rb +31 -0
- data/data/arrow/applets/status.rb +92 -0
- data/data/arrow/applets/test.rb +133 -0
- data/data/arrow/applets/tutorial/counter.rb +96 -0
- data/data/arrow/applets/tutorial/dingus.rb +67 -0
- data/data/arrow/applets/tutorial/hello.rb +34 -0
- data/data/arrow/applets/tutorial/hello2.rb +73 -0
- data/data/arrow/applets/tutorial/imgtext.rb +90 -0
- data/data/arrow/applets/tutorial/imgtext2.rb +286 -0
- data/data/arrow/applets/tutorial/index.rb +36 -0
- data/data/arrow/applets/tutorial/logo.rb +98 -0
- data/data/arrow/applets/tutorial/memcache.rb +61 -0
- data/data/arrow/applets/tutorial/missing.rb +37 -0
- data/data/arrow/applets/tutorial/protected.rb +100 -0
- data/data/arrow/applets/tutorial/redirector.rb +52 -0
- data/data/arrow/applets/tutorial/rndimages.rb +159 -0
- data/data/arrow/applets/tutorial/sharenotes.rb +83 -0
- data/data/arrow/applets/tutorial/subclassed-hello.rb +32 -0
- data/data/arrow/applets/tutorial/superhello.rb +72 -0
- data/data/arrow/applets/tutorial/timeclock.rb +78 -0
- data/data/arrow/applets/view-applet.rb +123 -0
- data/data/arrow/applets/view-template.rb +85 -0
- data/data/arrow/applets/wiki.rb +274 -0
- data/data/arrow/templates/TEMPLATE.tmpl.tpl +36 -0
- data/data/arrow/templates/applet-status.tmpl +153 -0
- data/data/arrow/templates/args-display.tmpl +120 -0
- data/data/arrow/templates/config/display-table.tmpl +36 -0
- data/data/arrow/templates/config/display.tmpl +36 -0
- data/data/arrow/templates/counter-deleted.tmpl +33 -0
- data/data/arrow/templates/counter.tmpl +59 -0
- data/data/arrow/templates/dingus.tmpl +55 -0
- data/data/arrow/templates/enumtable.tmpl +8 -0
- data/data/arrow/templates/error-display.tmpl +92 -0
- data/data/arrow/templates/filemap.tmpl +89 -0
- data/data/arrow/templates/hello-world-src.tmpl +34 -0
- data/data/arrow/templates/hello-world.tmpl +60 -0
- data/data/arrow/templates/imgtext/fontlist.tmpl +46 -0
- data/data/arrow/templates/imgtext/form.tmpl +70 -0
- data/data/arrow/templates/imgtext/reload-error.tmpl +40 -0
- data/data/arrow/templates/imgtext/reload.tmpl +55 -0
- data/data/arrow/templates/inspect/display.tmpl +80 -0
- data/data/arrow/templates/loginform.tmpl +64 -0
- data/data/arrow/templates/logout.tmpl +32 -0
- data/data/arrow/templates/memcache/display.tmpl +41 -0
- data/data/arrow/templates/navbar.incl +27 -0
- data/data/arrow/templates/nosuchapplet.tmpl +32 -0
- data/data/arrow/templates/printsource.tmpl +35 -0
- data/data/arrow/templates/protected.tmpl +36 -0
- data/data/arrow/templates/rndimages.tmpl +38 -0
- data/data/arrow/templates/service-response.tmpl +13 -0
- data/data/arrow/templates/sharenotes/display.tmpl +38 -0
- data/data/arrow/templates/status.tmpl +120 -0
- data/data/arrow/templates/templateviewer.tmpl +43 -0
- data/data/arrow/templates/test/harness.tmpl +57 -0
- data/data/arrow/templates/test/list.tmpl +48 -0
- data/data/arrow/templates/test/problem.tmpl +42 -0
- data/data/arrow/templates/tutorial/index.tmpl +37 -0
- data/data/arrow/templates/tutorial/missingapplet.tmpl +29 -0
- data/data/arrow/templates/view-applet-nosuch.tmpl +32 -0
- data/data/arrow/templates/view-applet.tmpl +40 -0
- data/data/arrow/templates/view-template.tmpl +83 -0
- data/data/arrow/templates/wiki/formerror.tmpl +47 -0
- data/data/arrow/templates/wiki/markup_help.incl +6 -0
- data/data/arrow/templates/wiki/new.tmpl +56 -0
- data/data/arrow/templates/wiki/new_system.tmpl +122 -0
- data/data/arrow/templates/wiki/sectionlist.tmpl +43 -0
- data/data/arrow/templates/wiki/show.tmpl +34 -0
- data/docs/manual/layouts/default.page +43 -0
- data/docs/manual/lib/api-filter.rb +81 -0
- data/docs/manual/lib/editorial-filter.rb +64 -0
- data/docs/manual/lib/examples-filter.rb +244 -0
- data/docs/manual/lib/links-filter.rb +117 -0
- data/lib/apache/fakerequest.rb +448 -0
- data/lib/apache/logger.rb +33 -0
- data/lib/arrow.rb +51 -0
- data/lib/arrow/acceptparam.rb +207 -0
- data/lib/arrow/applet.rb +725 -0
- data/lib/arrow/appletmixins.rb +218 -0
- data/lib/arrow/appletregistry.rb +590 -0
- data/lib/arrow/applettestcase.rb +503 -0
- data/lib/arrow/broker.rb +255 -0
- data/lib/arrow/cache.rb +176 -0
- data/lib/arrow/config-loaders/yaml.rb +75 -0
- data/lib/arrow/config.rb +615 -0
- data/lib/arrow/constants.rb +24 -0
- data/lib/arrow/cookie.rb +359 -0
- data/lib/arrow/cookieset.rb +108 -0
- data/lib/arrow/dispatcher.rb +368 -0
- data/lib/arrow/dispatcherloader.rb +50 -0
- data/lib/arrow/exceptions.rb +61 -0
- data/lib/arrow/fallbackhandler.rb +48 -0
- data/lib/arrow/formvalidator.rb +631 -0
- data/lib/arrow/htmltokenizer.rb +343 -0
- data/lib/arrow/logger.rb +488 -0
- data/lib/arrow/logger/apacheoutputter.rb +69 -0
- data/lib/arrow/logger/arrayoutputter.rb +63 -0
- data/lib/arrow/logger/coloroutputter.rb +111 -0
- data/lib/arrow/logger/fileoutputter.rb +96 -0
- data/lib/arrow/logger/htmloutputter.rb +54 -0
- data/lib/arrow/logger/outputter.rb +123 -0
- data/lib/arrow/mixins.rb +425 -0
- data/lib/arrow/monkeypatches.rb +94 -0
- data/lib/arrow/object.rb +117 -0
- data/lib/arrow/path.rb +196 -0
- data/lib/arrow/service.rb +447 -0
- data/lib/arrow/session.rb +289 -0
- data/lib/arrow/session/dbstore.rb +100 -0
- data/lib/arrow/session/filelock.rb +160 -0
- data/lib/arrow/session/filestore.rb +132 -0
- data/lib/arrow/session/id.rb +98 -0
- data/lib/arrow/session/lock.rb +253 -0
- data/lib/arrow/session/md5id.rb +42 -0
- data/lib/arrow/session/nulllock.rb +42 -0
- data/lib/arrow/session/posixlock.rb +166 -0
- data/lib/arrow/session/sha1id.rb +54 -0
- data/lib/arrow/session/store.rb +366 -0
- data/lib/arrow/session/usertrackid.rb +52 -0
- data/lib/arrow/spechelpers.rb +73 -0
- data/lib/arrow/template.rb +713 -0
- data/lib/arrow/template/attr.rb +31 -0
- data/lib/arrow/template/call.rb +31 -0
- data/lib/arrow/template/comment.rb +33 -0
- data/lib/arrow/template/container.rb +118 -0
- data/lib/arrow/template/else.rb +41 -0
- data/lib/arrow/template/elsif.rb +44 -0
- data/lib/arrow/template/escape.rb +53 -0
- data/lib/arrow/template/export.rb +87 -0
- data/lib/arrow/template/for.rb +145 -0
- data/lib/arrow/template/if.rb +78 -0
- data/lib/arrow/template/import.rb +119 -0
- data/lib/arrow/template/include.rb +206 -0
- data/lib/arrow/template/iterator.rb +208 -0
- data/lib/arrow/template/nodes.rb +734 -0
- data/lib/arrow/template/parser.rb +571 -0
- data/lib/arrow/template/prettyprint.rb +53 -0
- data/lib/arrow/template/render.rb +191 -0
- data/lib/arrow/template/selectlist.rb +94 -0
- data/lib/arrow/template/set.rb +87 -0
- data/lib/arrow/template/timedelta.rb +81 -0
- data/lib/arrow/template/unless.rb +78 -0
- data/lib/arrow/template/urlencode.rb +51 -0
- data/lib/arrow/template/yield.rb +139 -0
- data/lib/arrow/templatefactory.rb +125 -0
- data/lib/arrow/testcase.rb +567 -0
- data/lib/arrow/transaction.rb +608 -0
- data/rake/191_compat.rb +26 -0
- data/rake/dependencies.rb +76 -0
- data/rake/documentation.rb +114 -0
- data/rake/helpers.rb +502 -0
- data/rake/hg.rb +282 -0
- data/rake/manual.rb +787 -0
- data/rake/packaging.rb +129 -0
- data/rake/publishing.rb +278 -0
- data/rake/style.rb +62 -0
- data/rake/svn.rb +668 -0
- data/rake/testing.rb +187 -0
- data/rake/verifytask.rb +64 -0
- data/spec/arrow/acceptparam_spec.rb +157 -0
- data/spec/arrow/applet_spec.rb +575 -0
- data/spec/arrow/appletmixins_spec.rb +409 -0
- data/spec/arrow/appletregistry_spec.rb +294 -0
- data/spec/arrow/broker_spec.rb +153 -0
- data/spec/arrow/config_spec.rb +224 -0
- data/spec/arrow/cookieset_spec.rb +164 -0
- data/spec/arrow/dispatcher_spec.rb +137 -0
- data/spec/arrow/dispatcherloader_spec.rb +65 -0
- data/spec/arrow/formvalidator_spec.rb +781 -0
- data/spec/arrow/logger_spec.rb +346 -0
- data/spec/arrow/mixins_spec.rb +120 -0
- data/spec/arrow/service_spec.rb +645 -0
- data/spec/arrow/session_spec.rb +121 -0
- data/spec/arrow/template/iterator_spec.rb +222 -0
- data/spec/arrow/templatefactory_spec.rb +185 -0
- data/spec/arrow/transaction_spec.rb +319 -0
- data/spec/arrow_spec.rb +37 -0
- data/spec/lib/appletmatchers.rb +281 -0
- data/spec/lib/constants.rb +77 -0
- data/spec/lib/helpers.rb +41 -0
- data/spec/lib/matchers.rb +44 -0
- data/tests/cookie.tests.rb +310 -0
- data/tests/path.tests.rb +157 -0
- data/tests/session.tests.rb +111 -0
- data/tests/session_id.tests.rb +82 -0
- data/tests/session_lock.tests.rb +191 -0
- data/tests/session_store.tests.rb +53 -0
- data/tests/template.tests.rb +1360 -0
- metadata +339 -0
data/rake/testing.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
#
|
2
|
+
# Rake tasklib for testing tasks
|
3
|
+
|
4
|
+
#
|
5
|
+
# Authors:
|
6
|
+
# * Michael Granger <ged@FaerieMUD.org>
|
7
|
+
#
|
8
|
+
|
9
|
+
unless defined?( COVERAGE_MINIMUM )
|
10
|
+
if ENV['COVVERAGE_MINIMUM']
|
11
|
+
COVERAGE_MINIMUM = Float( ENV['COVERAGE_MINIMUM'] )
|
12
|
+
else
|
13
|
+
COVERAGE_MINIMUM = 85.0
|
14
|
+
end
|
15
|
+
end
|
16
|
+
SPEC_FILES = [] unless defined?( SPEC_FILES )
|
17
|
+
TEST_FILES = [] unless defined?( TEST_FILES )
|
18
|
+
|
19
|
+
COMMON_SPEC_OPTS = ['-Du'] unless defined?( COMMON_SPEC_OPTS )
|
20
|
+
|
21
|
+
COVERAGE_TARGETDIR = BASEDIR + 'coverage' unless defined?( COVERAGE_TARGETDIR )
|
22
|
+
RCOV_EXCLUDES = 'spec,tests,/Library/Ruby,/var/lib,/usr/local/lib' unless
|
23
|
+
defined?( RCOV_EXCLUDES )
|
24
|
+
|
25
|
+
|
26
|
+
desc "Run all defined tests"
|
27
|
+
task :test do
|
28
|
+
unless SPEC_FILES.empty?
|
29
|
+
log "Running specs"
|
30
|
+
Rake::Task['spec:quiet'].invoke
|
31
|
+
end
|
32
|
+
|
33
|
+
unless TEST_FILES.empty?
|
34
|
+
log "Running unit tests"
|
35
|
+
Rake::Task[:unittests].invoke
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
### RSpec specifications
|
41
|
+
begin
|
42
|
+
gem 'rspec', '>= 1.1.3'
|
43
|
+
|
44
|
+
require 'spec'
|
45
|
+
require 'spec/rake/spectask'
|
46
|
+
|
47
|
+
### Task: spec
|
48
|
+
desc "Run specs"
|
49
|
+
task :spec => 'spec:doc'
|
50
|
+
|
51
|
+
namespace :spec do
|
52
|
+
desc "Run rspec every time there's a change to one of the files"
|
53
|
+
task :autotest do
|
54
|
+
require 'autotest/rspec'
|
55
|
+
|
56
|
+
autotester = Autotest::Rspec.new
|
57
|
+
autotester.run
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "Generate regular color 'doc' spec output"
|
61
|
+
Spec::Rake::SpecTask.new( :doc ) do |task|
|
62
|
+
task.spec_files = SPEC_FILES
|
63
|
+
task.spec_opts = COMMON_SPEC_OPTS + ['-f', 's', '-c']
|
64
|
+
end
|
65
|
+
|
66
|
+
desc "Generate spec output with profiling"
|
67
|
+
Spec::Rake::SpecTask.new( :profile ) do |task|
|
68
|
+
task.spec_files = SPEC_FILES
|
69
|
+
task.spec_opts = COMMON_SPEC_OPTS + ['-f', 'o']
|
70
|
+
end
|
71
|
+
|
72
|
+
desc "Generate quiet non-colored plain-text output"
|
73
|
+
Spec::Rake::SpecTask.new( :quiet ) do |task|
|
74
|
+
task.spec_files = SPEC_FILES
|
75
|
+
task.spec_opts = COMMON_SPEC_OPTS + ['-f', 'p']
|
76
|
+
end
|
77
|
+
|
78
|
+
desc "Generate HTML output"
|
79
|
+
Spec::Rake::SpecTask.new( :html ) do |task|
|
80
|
+
task.spec_files = SPEC_FILES
|
81
|
+
task.spec_opts = COMMON_SPEC_OPTS + ['-f', 'h']
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
rescue LoadError => err
|
86
|
+
task :no_rspec do
|
87
|
+
$stderr.puts "Specification tasks not defined: %s" % [ err.message ]
|
88
|
+
end
|
89
|
+
|
90
|
+
task :spec => :no_rspec
|
91
|
+
namespace :spec do
|
92
|
+
task :autotest => :no_rspec
|
93
|
+
task :doc => :no_rspec
|
94
|
+
task :profile => :no_rspec
|
95
|
+
task :quiet => :no_rspec
|
96
|
+
task :html => :no_rspec
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
### Test::Unit tests
|
102
|
+
begin
|
103
|
+
require 'rake/testtask'
|
104
|
+
|
105
|
+
Rake::TestTask.new( :unittests ) do |task|
|
106
|
+
task.libs += [LIBDIR]
|
107
|
+
task.test_files = TEST_FILES
|
108
|
+
task.verbose = true
|
109
|
+
end
|
110
|
+
|
111
|
+
rescue LoadError => err
|
112
|
+
task :no_test do
|
113
|
+
$stderr.puts "Test tasks not defined: %s" % [ err.message ]
|
114
|
+
end
|
115
|
+
|
116
|
+
task :unittests => :no_rspec
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
### RCov (via RSpec) tasks
|
121
|
+
begin
|
122
|
+
gem 'rcov'
|
123
|
+
gem 'rspec', '>= 1.1.3'
|
124
|
+
|
125
|
+
require 'spec'
|
126
|
+
require 'rcov'
|
127
|
+
|
128
|
+
### Task: coverage (via RCov)
|
129
|
+
desc "Build test coverage reports"
|
130
|
+
unless SPEC_FILES.empty?
|
131
|
+
Spec::Rake::SpecTask.new( :coverage ) do |task|
|
132
|
+
task.spec_files = SPEC_FILES
|
133
|
+
task.libs += [LIBDIR]
|
134
|
+
task.spec_opts = ['-f', 'p', '-b']
|
135
|
+
task.rcov_opts = RCOV_OPTS
|
136
|
+
task.rcov = true
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
### Task: rcov
|
142
|
+
task :rcov => :coverage
|
143
|
+
|
144
|
+
### Other coverage tasks
|
145
|
+
namespace :coverage do
|
146
|
+
desc "Generate a detailed text coverage report"
|
147
|
+
Spec::Rake::SpecTask.new( :text ) do |task|
|
148
|
+
task.spec_files = SPEC_FILES
|
149
|
+
task.rcov_opts = RCOV_OPTS + ['--text-report']
|
150
|
+
task.rcov = true
|
151
|
+
end
|
152
|
+
|
153
|
+
desc "Show differences in coverage from last run"
|
154
|
+
Spec::Rake::SpecTask.new( :diff ) do |task|
|
155
|
+
task.spec_files = SPEC_FILES
|
156
|
+
task.spec_opts = ['-f', 'p', '-b']
|
157
|
+
task.rcov_opts = RCOV_OPTS - ['--save'] + ['--text-coverage-diff']
|
158
|
+
task.rcov = true
|
159
|
+
end
|
160
|
+
|
161
|
+
desc "Run RCov in 'spec-only' mode to check coverage from specs"
|
162
|
+
Spec::Rake::SpecTask.new( :speconly ) do |task|
|
163
|
+
task.spec_files = SPEC_FILES
|
164
|
+
task.rcov_opts = ['--exclude', RCOV_EXCLUDES, '--text-report', '--save']
|
165
|
+
task.rcov = true
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
CLOBBER.include( COVERAGE_TARGETDIR )
|
170
|
+
|
171
|
+
rescue LoadError => err
|
172
|
+
task :no_rcov do
|
173
|
+
$stderr.puts "Coverage tasks not defined: RSpec+RCov tasklib not available: %s" %
|
174
|
+
[ err.message ]
|
175
|
+
end
|
176
|
+
|
177
|
+
task :coverage => :no_rcov
|
178
|
+
task :clobber_coverage
|
179
|
+
task :rcov => :no_rcov
|
180
|
+
namespace :coverage do
|
181
|
+
task :text => :no_rcov
|
182
|
+
task :diff => :no_rcov
|
183
|
+
end
|
184
|
+
task :verify => :no_rcov
|
185
|
+
end
|
186
|
+
|
187
|
+
|
data/rake/verifytask.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#####################################################################
|
2
|
+
### S U B V E R S I O N T A S K S A N D H E L P E R S
|
3
|
+
#####################################################################
|
4
|
+
|
5
|
+
require 'rake/tasklib'
|
6
|
+
|
7
|
+
#
|
8
|
+
# Work around the inexplicable behaviour of the original RDoc::VerifyTask, which
|
9
|
+
# errors if your coverage isn't *exactly* the threshold.
|
10
|
+
#
|
11
|
+
|
12
|
+
# A task that can verify that the RCov coverage doesn't
|
13
|
+
# drop below a certain threshold. It should be run after
|
14
|
+
# running Spec::Rake::SpecTask.
|
15
|
+
class VerifyTask < Rake::TaskLib
|
16
|
+
|
17
|
+
COVERAGE_PERCENTAGE_PATTERN =
|
18
|
+
%r{<tt class='coverage_code'>(\d+\.\d+)%</tt>}
|
19
|
+
|
20
|
+
# Name of the task. Defaults to :verify_rcov
|
21
|
+
attr_accessor :name
|
22
|
+
|
23
|
+
# Path to the index.html file generated by RCov, which
|
24
|
+
# is the file containing the total coverage.
|
25
|
+
# Defaults to 'coverage/index.html'
|
26
|
+
attr_accessor :index_html
|
27
|
+
|
28
|
+
# Whether or not to output details. Defaults to true.
|
29
|
+
attr_accessor :verbose
|
30
|
+
|
31
|
+
# The threshold value (in percent) for coverage. If the
|
32
|
+
# actual coverage is not equal to this value, the task will raise an
|
33
|
+
# exception.
|
34
|
+
attr_accessor :threshold
|
35
|
+
|
36
|
+
def initialize( name=:verify )
|
37
|
+
@name = name
|
38
|
+
@index_html = 'coverage/index.html'
|
39
|
+
@verbose = true
|
40
|
+
yield self if block_given?
|
41
|
+
raise "Threshold must be set" if @threshold.nil?
|
42
|
+
define
|
43
|
+
end
|
44
|
+
|
45
|
+
def define
|
46
|
+
desc "Verify that rcov coverage is at least #{threshold}%"
|
47
|
+
|
48
|
+
task @name do
|
49
|
+
total_coverage = nil
|
50
|
+
if match = File.read( index_html ).match( COVERAGE_PERCENTAGE_PATTERN )
|
51
|
+
total_coverage = Float( match[1] )
|
52
|
+
else
|
53
|
+
raise "Couldn't find the coverage percentage in #{index_html}"
|
54
|
+
end
|
55
|
+
|
56
|
+
puts "Coverage: #{total_coverage}% (threshold: #{threshold}%)" if verbose
|
57
|
+
if total_coverage < threshold
|
58
|
+
raise "Coverage must be at least #{threshold}% but was #{total_coverage}%"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# vim: set nosta noet ts=4 sw=4:
|
@@ -0,0 +1,157 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
BEGIN {
|
4
|
+
require 'pathname'
|
5
|
+
basedir = Pathname.new( __FILE__ ).dirname.parent.parent
|
6
|
+
|
7
|
+
libdir = basedir + "lib"
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
|
10
|
+
}
|
11
|
+
|
12
|
+
|
13
|
+
require 'spec'
|
14
|
+
require 'spec/lib/constants'
|
15
|
+
require 'spec/lib/helpers'
|
16
|
+
require 'arrow'
|
17
|
+
require 'arrow/constants'
|
18
|
+
require 'arrow/acceptparam'
|
19
|
+
|
20
|
+
|
21
|
+
#####################################################################
|
22
|
+
### C O N T E X T S
|
23
|
+
#####################################################################
|
24
|
+
|
25
|
+
describe Arrow::AcceptParam do
|
26
|
+
include Arrow::SpecHelpers
|
27
|
+
|
28
|
+
before( :all ) do
|
29
|
+
setup_logging( :crit )
|
30
|
+
end
|
31
|
+
|
32
|
+
after( :all ) do
|
33
|
+
reset_logging()
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
ValidHeaders = {
|
38
|
+
'*/*' =>
|
39
|
+
{:type => nil, :subtype => nil, :qval => 1.0},
|
40
|
+
'*/*; q=0.1' =>
|
41
|
+
{:type => nil, :subtype => nil, :qval => 0.1},
|
42
|
+
'*/*;q=0.1' =>
|
43
|
+
{:type => nil, :subtype => nil, :qval => 0.1},
|
44
|
+
'image/*' =>
|
45
|
+
{:type => 'image', :subtype => nil, :qval => 1.0},
|
46
|
+
'image/*; q=0.18' =>
|
47
|
+
{:type => 'image', :subtype => nil, :qval => 0.18},
|
48
|
+
'image/*;q=0.4' =>
|
49
|
+
{:type => 'image', :subtype => nil, :qval => 0.4},
|
50
|
+
'image/*;q=0.9; porn=0; anseladams=1' =>
|
51
|
+
{:type => 'image', :subtype => nil, :qval => 0.9,
|
52
|
+
:extensions => %w[anseladams=1 porn=0]},
|
53
|
+
'image/png' =>
|
54
|
+
{:type => 'image', :subtype => 'png', :qval => 1.0},
|
55
|
+
'IMAGE/pNg' =>
|
56
|
+
{:type => 'image', :subtype => 'png', :qval => 1.0},
|
57
|
+
'application/x-porno' =>
|
58
|
+
{:type => 'application', :subtype => 'x-porno', :qval => 1.0},
|
59
|
+
'image/png; q=0.2' =>
|
60
|
+
{:type => 'image', :subtype => 'png', :qval => 0.2},
|
61
|
+
'image/x-giraffes;q=0.2' =>
|
62
|
+
{:type => 'image', :subtype => 'x-giraffes', :qval => 0.2},
|
63
|
+
'example/pork; headcheese=0;withfennel=1' =>
|
64
|
+
{:type => 'example', :subtype => 'pork', :qval => 1.0,
|
65
|
+
:extensions => %w[headcheese=0 withfennel=1]},
|
66
|
+
'model/vnd.moml+xml' =>
|
67
|
+
{:type => 'model', :subtype => 'vnd.moml+xml', :qval => 1.0},
|
68
|
+
'model/parasolid.transmit.binary; q=0.2' =>
|
69
|
+
{:type => 'model', :subtype => 'parasolid.transmit.binary',
|
70
|
+
:qval => 0.2},
|
71
|
+
'image/png; q=0.2; compression=1' =>
|
72
|
+
{:type => 'image', :subtype => 'png', :qval => 0.2,
|
73
|
+
:extensions => %w[compression=1]},
|
74
|
+
}
|
75
|
+
|
76
|
+
|
77
|
+
it "parses valid Accept header values" do
|
78
|
+
ValidHeaders.each do |hdr, expectations|
|
79
|
+
rval = Arrow::AcceptParam.parse( hdr )
|
80
|
+
|
81
|
+
rval.should be_an_instance_of( Arrow::AcceptParam )
|
82
|
+
rval.type.should == expectations[:type]
|
83
|
+
rval.subtype.should == expectations[:subtype]
|
84
|
+
rval.qvalue.should == expectations[:qval]
|
85
|
+
if expectations[:extensions]
|
86
|
+
expectations[:extensions].each do |ext|
|
87
|
+
rval.extensions.should include(ext)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "is lenient (but warns) about invalid qvalues" do
|
94
|
+
rval = nil
|
95
|
+
lambda {
|
96
|
+
rval = Arrow::AcceptParam.parse( '*/*; q=18' )
|
97
|
+
}.should_not raise_error()
|
98
|
+
|
99
|
+
rval.should be_an_instance_of( Arrow::AcceptParam )
|
100
|
+
rval.qvalue.should == 1.0
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
it "rejects invalid Accept header values" do
|
105
|
+
lambda {
|
106
|
+
Arrow::AcceptParam.parse( 'porksausage' )
|
107
|
+
}.should raise_error()
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
it "can represent itself in a human-readable object format" do
|
112
|
+
header = "text/html; q=0.9; level=2"
|
113
|
+
acceptparam = Arrow::AcceptParam.parse( header )
|
114
|
+
acceptparam.inspect.should =~ %r{AcceptParam.*text/html.*q=0.9}
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
it "can represent itself as an Accept header" do
|
119
|
+
header = "text/html;q=0.9;level=2"
|
120
|
+
acceptparam = Arrow::AcceptParam.parse( header )
|
121
|
+
acceptparam.to_s.should == header
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
it "can compare and sort on specificity" do
|
126
|
+
header = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9," +
|
127
|
+
"text/html;q=0.9;level=1,text/plain;q=0.8,image/png,*/*;q=0.5"
|
128
|
+
params = header.split(/\s*,\s*/).collect {|par|
|
129
|
+
Arrow::AcceptParam.parse( par )
|
130
|
+
}.sort
|
131
|
+
|
132
|
+
params[0].to_s.should == 'application/xhtml+xml;q=1.0'
|
133
|
+
params[1].to_s.should == 'application/xml;q=1.0'
|
134
|
+
params[2].to_s.should == 'image/png;q=1.0'
|
135
|
+
params[3].to_s.should == 'text/xml;q=1.0'
|
136
|
+
params[4].to_s.should == 'text/html;q=0.9;level=1'
|
137
|
+
params[5].to_s.should == 'text/html;q=0.9'
|
138
|
+
params[6].to_s.should == 'text/plain;q=0.8'
|
139
|
+
params[7].to_s.should == '*/*;q=0.5'
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
it "can be compared against strings" do
|
144
|
+
specific_param = Arrow::AcceptParam.parse( 'text/html' )
|
145
|
+
type_wildcard_param = Arrow::AcceptParam.parse( '*/*' )
|
146
|
+
subtype_wildcard_param = Arrow::AcceptParam.parse( 'image/*' )
|
147
|
+
|
148
|
+
( specific_param =~ 'text/html' ).should be_true()
|
149
|
+
( specific_param =~ 'image/png' ).should be_false()
|
150
|
+
|
151
|
+
( subtype_wildcard_param =~ 'image/png' ).should be_true()
|
152
|
+
( subtype_wildcard_param =~ 'image/jpeg' ).should be_true()
|
153
|
+
( subtype_wildcard_param =~ 'text/plain' ).should be_false()
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# vim: set nosta noet ts=4 sw=4:
|
@@ -0,0 +1,575 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Specification for the Arrow::Applet class
|
4
|
+
# $Id$
|
5
|
+
#
|
6
|
+
# Copyright (c) 2004-2008 The FaerieMUD Consortium. Most rights reserved.
|
7
|
+
#
|
8
|
+
|
9
|
+
BEGIN {
|
10
|
+
require 'pathname'
|
11
|
+
basedir = Pathname.new( __FILE__ ).dirname.parent.parent
|
12
|
+
|
13
|
+
libdir = basedir + "lib"
|
14
|
+
|
15
|
+
$LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
|
16
|
+
}
|
17
|
+
|
18
|
+
require 'spec'
|
19
|
+
|
20
|
+
require 'apache/fakerequest'
|
21
|
+
require 'arrow'
|
22
|
+
require 'arrow/applet'
|
23
|
+
|
24
|
+
require 'spec/lib/helpers'
|
25
|
+
|
26
|
+
|
27
|
+
#####################################################################
|
28
|
+
### C O N T E X T S
|
29
|
+
#####################################################################
|
30
|
+
|
31
|
+
describe Arrow::Applet do
|
32
|
+
include Arrow::SpecHelpers
|
33
|
+
|
34
|
+
before( :all ) do
|
35
|
+
setup_logging( :crit )
|
36
|
+
end
|
37
|
+
|
38
|
+
after( :all ) do
|
39
|
+
reset_logging()
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
it "has a signature even if it doesn't declare one" do
|
44
|
+
plainclass = Class.new( Arrow::Applet )
|
45
|
+
plainclass.signature.should be_an_instance_of( Arrow::Applet::SignatureStruct )
|
46
|
+
plainclass.signature.members.should include( 'name' )
|
47
|
+
end
|
48
|
+
|
49
|
+
it "subclasses know if further subclasses of itself have been loaded" do
|
50
|
+
plainclass = Class.new( Arrow::Applet )
|
51
|
+
plainclass.should_not be_inherited_from()
|
52
|
+
subclass = Class.new( plainclass )
|
53
|
+
plainclass.should be_inherited_from()
|
54
|
+
end
|
55
|
+
|
56
|
+
it "raises an exception if an action method that doesn't accept arguments is declared" do
|
57
|
+
lambda {
|
58
|
+
Class.new( Arrow::Applet ) do
|
59
|
+
def no_arg_action
|
60
|
+
raise "shouldn't be callable"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
}.should raise_error( ::ScriptError, 'Inappropriate arity for no_arg_action' )
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
describe "concrete child and grandchild classes" do
|
68
|
+
before(:each) do
|
69
|
+
@appletclass = Class.new( Arrow::Applet ) do
|
70
|
+
default_action :test
|
71
|
+
|
72
|
+
applet_name "SuperApplet"
|
73
|
+
applet_description "A superclass applet"
|
74
|
+
applet_version 177
|
75
|
+
applet_maintainer "ged@FaerieMUD.org"
|
76
|
+
end
|
77
|
+
@appletsubclass = Class.new( @appletclass )
|
78
|
+
|
79
|
+
@applet = @appletclass.new( nil, nil, nil )
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
it "don't return superclass applets from ::load by default" do
|
84
|
+
Kernel.stub!( :load ).and_return do
|
85
|
+
Arrow::Applet.newly_loaded << @appletclass << @appletsubclass
|
86
|
+
end
|
87
|
+
|
88
|
+
applets = Arrow::Applet.load( 'stubbedapplet' )
|
89
|
+
|
90
|
+
applets.should have(1).member
|
91
|
+
applets.should_not include( @appletclass )
|
92
|
+
applets.should include( @appletsubclass )
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
it "return superclass applets from ::load if asked to do so" do
|
97
|
+
Kernel.stub!( :load ).and_return do
|
98
|
+
Arrow::Applet.newly_loaded << @appletclass << @appletsubclass
|
99
|
+
end
|
100
|
+
|
101
|
+
applets = Arrow::Applet.load( 'stubbedapplet', true )
|
102
|
+
|
103
|
+
applets.should have(2).members
|
104
|
+
applets.should include( @appletclass )
|
105
|
+
applets.should include( @appletsubclass )
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
it "inherit some values from their parent's signature" do
|
110
|
+
@appletsubclass.signature.maintainer.should == @appletclass.signature.maintainer
|
111
|
+
@appletsubclass.signature.maintainer.should_not be_equal(@appletclass.signature.maintainer)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "don't inherit the :version, :name, and :description from their parent's signature" do
|
115
|
+
@appletsubclass.signature.version.should_not == @appletclass.signature.version
|
116
|
+
@appletsubclass.signature.name.should == @appletsubclass.name
|
117
|
+
@appletsubclass.signature.description.should == '(none)'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
describe "instance" do
|
123
|
+
before( :all ) do
|
124
|
+
setup_logging( :crit )
|
125
|
+
end
|
126
|
+
|
127
|
+
before( :each ) do
|
128
|
+
@appletclass = Class.new( Arrow::Applet ) do
|
129
|
+
def test_action( txn, *args )
|
130
|
+
return [txn, args]
|
131
|
+
end
|
132
|
+
|
133
|
+
def one_arg_action( txn, one )
|
134
|
+
return one
|
135
|
+
end
|
136
|
+
|
137
|
+
def two_args_action( txn, one, two )
|
138
|
+
return [ one, two ]
|
139
|
+
end
|
140
|
+
|
141
|
+
def action_missing_action( txn, missing, *args )
|
142
|
+
return [ :missing, missing, *args ]
|
143
|
+
end
|
144
|
+
|
145
|
+
def load_template_action( txn, template_name )
|
146
|
+
return self.load_template( template_name )
|
147
|
+
end
|
148
|
+
template :devdas, "dola/re/dola.tmpl"
|
149
|
+
end
|
150
|
+
|
151
|
+
@uri = '/test'
|
152
|
+
@factory = mock( "template factory" )
|
153
|
+
|
154
|
+
@applet = @appletclass.new( nil, @factory, @uri )
|
155
|
+
|
156
|
+
@txn = stub( "transaction", :vargs => nil, :form_request? => false, :vargs= => nil )
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
it "delegates template-loading to its template factory" do
|
161
|
+
@factory.should_receive( :get_template ).with( 'dola/re/dola.tmpl' ).
|
162
|
+
and_return( :the_template )
|
163
|
+
@applet.load_template_action( @txn, :devdas ).should == :the_template
|
164
|
+
end
|
165
|
+
|
166
|
+
it "eliminates URI arguments to match the arity of actions with only one argument" do
|
167
|
+
@applet.run( @txn, 'one_arg', :first, :second, :third ).should == :first
|
168
|
+
end
|
169
|
+
|
170
|
+
it "eliminates URI arguments to match the arity of actions with two arguments" do
|
171
|
+
@applet.run( @txn, 'two_args', :first, :second, :third ).should == [:first, :second]
|
172
|
+
end
|
173
|
+
|
174
|
+
it "appends nil URI arguments to match the arity of actions with two arguments" do
|
175
|
+
@applet.run( @txn, 'two_args', :first ).should == [:first, nil]
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
it "maps invocations of nonexistent actions to the action_missing action" do
|
180
|
+
@applet.run( @txn, "nonexistent", :first ).should == [ :missing, "nonexistent", :first ]
|
181
|
+
end
|
182
|
+
|
183
|
+
it "doesn't use libapreq's param parser for a POST with content-type " +
|
184
|
+
"other than 'application/www-form-url-encoded" do
|
185
|
+
request = mock( "request", :null_object => true )
|
186
|
+
request.should_not_receive( :paramtable )
|
187
|
+
|
188
|
+
txn = mock( "transaction", :null_object => true )
|
189
|
+
txn.should_receive( :form_request? ).at_least(1).and_return( false )
|
190
|
+
txn.stub!( :request ).and_return( request )
|
191
|
+
|
192
|
+
@applet.run( txn, 'test' )
|
193
|
+
end
|
194
|
+
|
195
|
+
end # describe "instance"
|
196
|
+
|
197
|
+
|
198
|
+
describe "instance with an action that accepts form parameters" do
|
199
|
+
before( :all ) do
|
200
|
+
setup_logging( :crit )
|
201
|
+
end
|
202
|
+
|
203
|
+
it "allows a validator to be declared using 'action, hash' syntax" do
|
204
|
+
appletclass = Class.new( Arrow::Applet ) do
|
205
|
+
def comma_action( txn, *args )
|
206
|
+
return 'yay'
|
207
|
+
end
|
208
|
+
|
209
|
+
validator :comma, :optional => :formy
|
210
|
+
end
|
211
|
+
appletclass.signature.validator_profiles[ :comma ].should == {
|
212
|
+
:optional => :formy
|
213
|
+
}
|
214
|
+
end
|
215
|
+
|
216
|
+
it "allows a validator to be declared using 'action => { hash }' syntax" do
|
217
|
+
appletclass = Class.new( Arrow::Applet ) do
|
218
|
+
def hash_action( txn, *args )
|
219
|
+
return 'yay'
|
220
|
+
end
|
221
|
+
|
222
|
+
validator :hash => { :optional => :formy }
|
223
|
+
end
|
224
|
+
appletclass.signature.validator_profiles[ :hash ].should == {
|
225
|
+
:optional => :formy
|
226
|
+
}
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
describe "instance without an #action_missing_action method" do
|
232
|
+
before( :all ) do
|
233
|
+
setup_logging( :crit )
|
234
|
+
end
|
235
|
+
|
236
|
+
before( :each ) do
|
237
|
+
@appletclass = Class.new( Arrow::Applet ) do
|
238
|
+
template :test => 'test.tmpl'
|
239
|
+
end
|
240
|
+
|
241
|
+
@uri = '/test'
|
242
|
+
@factory = mock( "template factory" )
|
243
|
+
|
244
|
+
@applet = @appletclass.new( nil, @factory, @uri )
|
245
|
+
|
246
|
+
@txn = stub( "transaction", :vargs => nil, :form_request? => false, :vargs= => nil )
|
247
|
+
end
|
248
|
+
|
249
|
+
it "maps missing actions to like-named templates" do
|
250
|
+
template = stub( "test template" )
|
251
|
+
@factory.should_receive( :get_template ).with( 'test.tmpl' ).and_return( template )
|
252
|
+
|
253
|
+
template.should_receive( :txn= ).with( @txn )
|
254
|
+
template.should_receive( :applet= ).with( @applet )
|
255
|
+
|
256
|
+
@applet.run( @txn, 'test' ).should == template
|
257
|
+
end
|
258
|
+
|
259
|
+
it "untaints the action before using it to look up the missing action template" do
|
260
|
+
template = stub( "test template" )
|
261
|
+
@factory.should_receive( :get_template ).with( 'test.tmpl' ).and_return( template )
|
262
|
+
|
263
|
+
template.should_receive( :txn= ).with( @txn )
|
264
|
+
template.should_receive( :applet= ).with( @applet )
|
265
|
+
|
266
|
+
action = 'test'
|
267
|
+
action.taint
|
268
|
+
|
269
|
+
Thread.new do
|
270
|
+
Thread.current.abort_on_exception = true
|
271
|
+
$SAFE = 1
|
272
|
+
lambda {
|
273
|
+
@applet.run( @txn, action )
|
274
|
+
}.should_not raise_error()
|
275
|
+
end.join
|
276
|
+
end
|
277
|
+
|
278
|
+
|
279
|
+
|
280
|
+
### TODO: Convert these to specs
|
281
|
+
|
282
|
+
def test_load_template_should_raise_an_error_for_templates_not_in_the_signature
|
283
|
+
assert_raises( Arrow::AppletError ) do
|
284
|
+
applet = @appletclass.new( nil, nil, nil )
|
285
|
+
applet.__send__( :load_template, :foo )
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
def test_template_directive_should_add_a_template_to_the_signature
|
291
|
+
assert !@appletclass.signature.templates.key?( :foo )
|
292
|
+
|
293
|
+
assert_nothing_raised do
|
294
|
+
@appletclass.class_eval do
|
295
|
+
template :foo, "foo.tmpl"
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
assert_equal "foo.tmpl", @appletclass.signature.templates[:foo]
|
300
|
+
end
|
301
|
+
|
302
|
+
def test_template_directive_should_accept_single_hash_pair
|
303
|
+
assert !@appletclass.signature.templates.key?( :foo )
|
304
|
+
|
305
|
+
assert_nothing_raised do
|
306
|
+
@appletclass.class_eval do
|
307
|
+
template :foo => "foo.tmpl"
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
assert_equal "foo.tmpl", @appletclass.signature.templates[:foo]
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_template_directive_should_accept_multiple_hash_pairs
|
315
|
+
assert !@appletclass.signature.templates.key?( :foo )
|
316
|
+
assert !@appletclass.signature.templates.key?( :bar )
|
317
|
+
|
318
|
+
assert_nothing_raised do
|
319
|
+
@appletclass.class_eval do
|
320
|
+
template :foo => "foo.tmpl",
|
321
|
+
:bar => "bar.tmpl"
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
assert_equal "foo.tmpl", @appletclass.signature.templates[:foo]
|
326
|
+
assert_equal "bar.tmpl", @appletclass.signature.templates[:bar]
|
327
|
+
end
|
328
|
+
|
329
|
+
def test_applet_name_directive_should_set_signature_name
|
330
|
+
assert_not_equal "foo", @appletclass.signature.name
|
331
|
+
|
332
|
+
assert_nothing_raised do
|
333
|
+
@appletclass.class_eval do
|
334
|
+
applet_name "foo"
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
assert_equal "foo", @appletclass.signature.name
|
339
|
+
end
|
340
|
+
|
341
|
+
def test_applet_description_directive_should_set_signature_description
|
342
|
+
assert_not_equal "foo", @appletclass.signature.description
|
343
|
+
|
344
|
+
assert_nothing_raised do
|
345
|
+
@appletclass.class_eval do
|
346
|
+
applet_description "foo"
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
assert_equal "foo", @appletclass.signature.description
|
351
|
+
end
|
352
|
+
|
353
|
+
def test_applet_maintainer_directive_should_set_signature_maintainer
|
354
|
+
assert_not_equal "foo", @appletclass.signature.maintainer
|
355
|
+
|
356
|
+
assert_nothing_raised do
|
357
|
+
@appletclass.class_eval do
|
358
|
+
applet_maintainer "foo"
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
assert_equal "foo", @appletclass.signature.maintainer
|
363
|
+
end
|
364
|
+
|
365
|
+
def test_applet_appicon_directive_should_set_signature_appicon
|
366
|
+
assert_not_equal "foo.png", @appletclass.signature.appicon
|
367
|
+
|
368
|
+
assert_nothing_raised do
|
369
|
+
@appletclass.class_eval do
|
370
|
+
applet_maintainer "foo.png"
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
assert_equal "foo.png", @appletclass.signature.maintainer
|
375
|
+
end
|
376
|
+
|
377
|
+
def test_applet_version_directive_should_set_signature_version
|
378
|
+
assert_not_equal "200.1", @appletclass.signature.version
|
379
|
+
|
380
|
+
assert_nothing_raised do
|
381
|
+
@appletclass.class_eval do
|
382
|
+
applet_version "200.1"
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
assert_equal "200.1", @appletclass.signature.version
|
387
|
+
end
|
388
|
+
|
389
|
+
def test_default_action_directive_should_set_signature_default_action
|
390
|
+
assert_not_equal :edit, @appletclass.signature.default_action
|
391
|
+
|
392
|
+
assert_nothing_raised do
|
393
|
+
@appletclass.class_eval do
|
394
|
+
default_action :edit
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
assert_equal "edit", @appletclass.signature.default_action
|
399
|
+
end
|
400
|
+
|
401
|
+
|
402
|
+
def test_run_should_track_run_times
|
403
|
+
assert_equal 0.0, @applet.total_utime
|
404
|
+
assert_equal 0.0, @applet.total_stime
|
405
|
+
|
406
|
+
@applet.def_action_body do |txn|
|
407
|
+
# This will hopefully take more than 0.0 seconds on any machine.
|
408
|
+
10_000.times do
|
409
|
+
# This causes a system access, which makes for stime
|
410
|
+
# the previous code was only usertime on my linux machine -JJ
|
411
|
+
d = Dir.open('.')
|
412
|
+
d.close
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
with_run_fixtured_transaction do |txn|
|
417
|
+
@applet.run( txn, "test" )
|
418
|
+
end
|
419
|
+
|
420
|
+
assert (@applet.total_utime > 0.0),
|
421
|
+
"Applet utime after run: %0.5f" % [@applet.total_utime]
|
422
|
+
assert (@applet.total_stime > 0.0),
|
423
|
+
"Applet stime after run: %0.5f" % [@applet.total_stime]
|
424
|
+
end
|
425
|
+
|
426
|
+
|
427
|
+
def test_defining_an_action_method_with_inappropriate_arity_should_raise_scripterror
|
428
|
+
assert_raises( ScriptError ) do
|
429
|
+
@appletclass.class_eval { def malformed_action; end }
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
|
434
|
+
def test_running_against_action_method_with_inappropriate_arity_should_raise_appleterror
|
435
|
+
# We have to sneak a method past the ::method_added check...
|
436
|
+
@appletclass.class_eval do
|
437
|
+
def self::method_added(sym); end
|
438
|
+
def malformed_action; end
|
439
|
+
end
|
440
|
+
|
441
|
+
assert_raises( Arrow::AppletError ) do
|
442
|
+
with_run_fixtured_transaction do |txn|
|
443
|
+
@applet.run( txn, "malformed" )
|
444
|
+
end
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
|
449
|
+
def test_run_with_two_arg_action_sends_the_appropriate_number_of_args
|
450
|
+
@appletclass.class_eval do
|
451
|
+
def two_arg_action( txn, arg )
|
452
|
+
[ txn, arg ]
|
453
|
+
end
|
454
|
+
end
|
455
|
+
@applet = @appletclass.new( nil, nil, nil )
|
456
|
+
|
457
|
+
with_run_fixtured_transaction do |txn|
|
458
|
+
rval = @applet.run( txn, "two_arg", "arg1", "arg2", "arg3" )
|
459
|
+
|
460
|
+
assert_instance_of Array, rval
|
461
|
+
assert_equal 2, rval.length
|
462
|
+
assert_same txn, rval.first
|
463
|
+
assert_equal "arg1", rval[1]
|
464
|
+
end
|
465
|
+
|
466
|
+
end
|
467
|
+
|
468
|
+
|
469
|
+
def test_run_with_block_yields_action_method_and_transaction_instead_of_invoking
|
470
|
+
rval, meth, rtxn, rargs = nil
|
471
|
+
|
472
|
+
with_run_fixtured_transaction do |txn|
|
473
|
+
rval = @applet.run( txn, "test", "arg1", "arg2" ) do |metharg, txn2, *args|
|
474
|
+
meth = metharg
|
475
|
+
rtxn = txn2
|
476
|
+
rargs = args
|
477
|
+
|
478
|
+
:passed
|
479
|
+
end
|
480
|
+
|
481
|
+
assert_instance_of Method, meth
|
482
|
+
assert_match( /#test_action/, meth.to_s )
|
483
|
+
assert_same txn, rtxn
|
484
|
+
assert_equal ["arg1", "arg2"], rargs
|
485
|
+
|
486
|
+
assert_equal :passed, rval
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
|
491
|
+
def test_run_with_parameterless_action_method_raises_an_appleterror
|
492
|
+
@applet.def_action_body do
|
493
|
+
flunk "Expected exception before action body was run"
|
494
|
+
end
|
495
|
+
|
496
|
+
with_run_fixtured_transaction do |txn|
|
497
|
+
assert_raises( Arrow::AppletError ) do
|
498
|
+
@applet.run( txn, "malformed" )
|
499
|
+
end
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
|
504
|
+
def test_run_without_an_action_invokes_the_default_action
|
505
|
+
invoked = false
|
506
|
+
|
507
|
+
@applet.def_action_body do
|
508
|
+
invoked = true
|
509
|
+
end
|
510
|
+
|
511
|
+
with_run_fixtured_transaction do |txn|
|
512
|
+
rval = @applet.run( txn )
|
513
|
+
end
|
514
|
+
|
515
|
+
assert_equal true, invoked, "Default action was not invoked"
|
516
|
+
end
|
517
|
+
|
518
|
+
|
519
|
+
def test_looking_up_a_valid_action_method_should_return_method_object_for_it
|
520
|
+
rval = nil
|
521
|
+
args = []
|
522
|
+
|
523
|
+
assert_nothing_raised do
|
524
|
+
rval, *args = @applet.send( :lookup_action_method, nil, "test" )
|
525
|
+
end
|
526
|
+
|
527
|
+
assert_instance_of Method, rval
|
528
|
+
assert_match( /#test_action/, rval.to_s )
|
529
|
+
end
|
530
|
+
|
531
|
+
|
532
|
+
|
533
|
+
|
534
|
+
def test_default_delegation_method_just_yields
|
535
|
+
rval = nil
|
536
|
+
|
537
|
+
assert_nothing_raised do
|
538
|
+
rval = @applet.delegate( nil, [:chain] ) {|arg| rval = arg }
|
539
|
+
end
|
540
|
+
|
541
|
+
assert_equal [:chain], rval
|
542
|
+
end
|
543
|
+
|
544
|
+
|
545
|
+
def test_subrun_from_delegation_populates_txn_vargs
|
546
|
+
|
547
|
+
# Define the delegator and an action to subrun
|
548
|
+
@appletclass.class_eval do
|
549
|
+
def delegate( txn, chain, *args )
|
550
|
+
self.subrun( 'test_vargs', txn, *args )
|
551
|
+
end
|
552
|
+
def test_vargs_action( txn, *args )
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
applet = @appletclass.new( nil, nil, nil )
|
557
|
+
|
558
|
+
# Even though it's not a real #run, the transaction should be
|
559
|
+
# set up the same way passing through #subrun
|
560
|
+
with_run_fixtured_transaction do |txn, req|
|
561
|
+
txn.should_receive( :vargs ).and_return(nil).at_least.once
|
562
|
+
|
563
|
+
assert_nothing_raised do
|
564
|
+
applet.delegate( txn, nil )
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
end
|
569
|
+
|
570
|
+
end # describe "concrete subclass"
|
571
|
+
|
572
|
+
end
|
573
|
+
|
574
|
+
|
575
|
+
# vim: set nosta noet ts=4 sw=4:
|