tlspretense 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +6 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +41 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +231 -0
- data/Rakefile +44 -0
- data/bin/makeder.sh +6 -0
- data/bin/tlspretense +7 -0
- data/bin/view.sh +3 -0
- data/doc/general_setup.rdoc +288 -0
- data/doc/linux_setup.rdoc +64 -0
- data/lib/certmaker.rb +61 -0
- data/lib/certmaker/certificate_factory.rb +106 -0
- data/lib/certmaker/certificate_suite_generator.rb +120 -0
- data/lib/certmaker/ext_core/hash_indifferent_fetch.rb +12 -0
- data/lib/certmaker/runner.rb +27 -0
- data/lib/certmaker/tasks.rb +20 -0
- data/lib/packetthief.rb +167 -0
- data/lib/packetthief/handlers.rb +14 -0
- data/lib/packetthief/handlers/abstract_ssl_handler.rb +249 -0
- data/lib/packetthief/handlers/proxy_redirector.rb +26 -0
- data/lib/packetthief/handlers/ssl_client.rb +87 -0
- data/lib/packetthief/handlers/ssl_server.rb +174 -0
- data/lib/packetthief/handlers/ssl_smart_proxy.rb +143 -0
- data/lib/packetthief/handlers/ssl_transparent_proxy.rb +225 -0
- data/lib/packetthief/handlers/transparent_proxy.rb +183 -0
- data/lib/packetthief/impl.rb +11 -0
- data/lib/packetthief/impl/ipfw.rb +140 -0
- data/lib/packetthief/impl/manual.rb +54 -0
- data/lib/packetthief/impl/netfilter.rb +109 -0
- data/lib/packetthief/impl/pf_divert.rb +168 -0
- data/lib/packetthief/impl/pf_rdr.rb +192 -0
- data/lib/packetthief/logging.rb +49 -0
- data/lib/packetthief/redirect_rule.rb +29 -0
- data/lib/packetthief/util.rb +36 -0
- data/lib/ssl_test.rb +21 -0
- data/lib/ssl_test/app_context.rb +17 -0
- data/lib/ssl_test/certificate_manager.rb +33 -0
- data/lib/ssl_test/config.rb +79 -0
- data/lib/ssl_test/ext_core/io_raw_input.rb +31 -0
- data/lib/ssl_test/input_handler.rb +35 -0
- data/lib/ssl_test/runner.rb +110 -0
- data/lib/ssl_test/runner_options.rb +68 -0
- data/lib/ssl_test/ssl_test_case.rb +46 -0
- data/lib/ssl_test/ssl_test_report.rb +24 -0
- data/lib/ssl_test/ssl_test_result.rb +30 -0
- data/lib/ssl_test/test_listener.rb +140 -0
- data/lib/ssl_test/test_manager.rb +116 -0
- data/lib/tlspretense.rb +13 -0
- data/lib/tlspretense/app.rb +52 -0
- data/lib/tlspretense/init_runner.rb +115 -0
- data/lib/tlspretense/skel/ca/goodcacert.pem +19 -0
- data/lib/tlspretense/skel/ca/goodcakey.pem +27 -0
- data/lib/tlspretense/skel/config.yml +523 -0
- data/lib/tlspretense/version.rb +3 -0
- data/packetthief_examples/em_ssl_test.rb +73 -0
- data/packetthief_examples/redirector.rb +29 -0
- data/packetthief_examples/setup_iptables.sh +24 -0
- data/packetthief_examples/ssl_client_simple.rb +27 -0
- data/packetthief_examples/ssl_server_simple.rb +44 -0
- data/packetthief_examples/ssl_smart_proxy.rb +115 -0
- data/packetthief_examples/ssl_transparent_proxy.rb +97 -0
- data/packetthief_examples/transparent_proxy.rb +56 -0
- data/spec/packetthief/impl/ipfw_spec.rb +98 -0
- data/spec/packetthief/impl/manual_spec.rb +65 -0
- data/spec/packetthief/impl/netfilter_spec.rb +66 -0
- data/spec/packetthief/impl/pf_divert_spec.rb +82 -0
- data/spec/packetthief/impl/pf_rdr_spec.rb +133 -0
- data/spec/packetthief/logging_spec.rb +78 -0
- data/spec/packetthief_spec.rb +47 -0
- data/spec/spec_helper.rb +53 -0
- data/spec/ssl_test/certificate_manager_spec.rb +222 -0
- data/spec/ssl_test/config_spec.rb +76 -0
- data/spec/ssl_test/runner_spec.rb +360 -0
- data/spec/ssl_test/ssl_test_case_spec.rb +113 -0
- data/spec/ssl_test/test_listener_spec.rb +199 -0
- data/spec/ssl_test/test_manager_spec.rb +324 -0
- data/tlspretense.gemspec +35 -0
- metadata +262 -0
@@ -0,0 +1,360 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','spec_helper'))
|
2
|
+
|
3
|
+
module SSLTest
|
4
|
+
describe Runner do
|
5
|
+
let(:args) { [] }
|
6
|
+
let(:stdin) { double("stdin") }
|
7
|
+
let(:stdout) { double("stdout", :puts => nil) }
|
8
|
+
|
9
|
+
let(:test_foo_data) do
|
10
|
+
{
|
11
|
+
'alias' => 'foo',
|
12
|
+
'name' => 'Baseline Happy Test',
|
13
|
+
'certchain' => ['baseline', 'goodca'],
|
14
|
+
'expected_result' => 'connect'
|
15
|
+
}
|
16
|
+
end
|
17
|
+
let(:test_bar_data) do
|
18
|
+
{
|
19
|
+
'alias' => 'bar',
|
20
|
+
'name' => 'Baseline Happy Test',
|
21
|
+
'certchain' => ['baseline', 'goodca'],
|
22
|
+
'expected_result' => 'connect'
|
23
|
+
}
|
24
|
+
end
|
25
|
+
let(:test_data_list) { [test_foo_data, test_bar_data] }
|
26
|
+
|
27
|
+
let(:test_foo) { SSLTestCase.new(test_foo_data) }
|
28
|
+
let(:test_bar) { SSLTestCase.new(test_bar_data) }
|
29
|
+
let(:test_list) { [test_foo, test_bar] }
|
30
|
+
|
31
|
+
let(:test_listener) { double('test listener', :logger= => nil) }
|
32
|
+
let(:test_manager) { double('test manager') }
|
33
|
+
|
34
|
+
let(:test_wrongcname) { double('test wrongcname') }
|
35
|
+
let(:conf_certs) { double('conf certs') }
|
36
|
+
let(:config) do
|
37
|
+
double(
|
38
|
+
"config",
|
39
|
+
:listener_port => 54321,
|
40
|
+
:tests => test_data_list,
|
41
|
+
'certs' => conf_certs,
|
42
|
+
'action' => :runtests,
|
43
|
+
'pause?' => false,
|
44
|
+
'loglevel' => Logger::INFO,
|
45
|
+
'logfile' => nil,
|
46
|
+
'packetthief' => {},
|
47
|
+
'hosttotest' => double('hosttotest')
|
48
|
+
)
|
49
|
+
end
|
50
|
+
let(:cert_manager) { double("certificate manager") }
|
51
|
+
let(:report) { double('report', :print_results => nil, :add_result => nil) }
|
52
|
+
let(:testcaseresult) { double('test case result') }
|
53
|
+
let(:testcase) { double('test case', :run => testcaseresult) }
|
54
|
+
let(:appcontext) { double('context',
|
55
|
+
:config => config,
|
56
|
+
:test_manager => test_manager,
|
57
|
+
:test_manager= => nil,
|
58
|
+
) }
|
59
|
+
let(:logger) { Logger.new(nil) }
|
60
|
+
|
61
|
+
let(:conf_data) do
|
62
|
+
{
|
63
|
+
'certs' => conf_certs,
|
64
|
+
'tests' => test_data_list,
|
65
|
+
'packetthief' => {},
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
before(:each) do
|
70
|
+
YAML.stub(:load_file).and_return(conf_data)
|
71
|
+
CertificateManager.stub(:new).and_return(cert_manager)
|
72
|
+
SSLTestCase.stub(:new).and_return(testcase)
|
73
|
+
SSLTestReport.stub(:new).and_return(report)
|
74
|
+
AppContext.stub(:new).and_return(appcontext)
|
75
|
+
SSLTestCase.stub(:factory).and_return(test_list)
|
76
|
+
end
|
77
|
+
|
78
|
+
after(:each) do
|
79
|
+
PacketThief.instance_variable_set(:@implementation, nil)
|
80
|
+
end
|
81
|
+
|
82
|
+
subject { Runner.new(args, stdin, stdout) }
|
83
|
+
|
84
|
+
describe "#initialize" do
|
85
|
+
before(:each) do
|
86
|
+
Config.stub(:new).and_return(config)
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when ARGS is empty" do
|
90
|
+
let(:args) { [] }
|
91
|
+
it "loads the config from the default location" do
|
92
|
+
Config.should_receive(:new).and_return(config)
|
93
|
+
|
94
|
+
subject
|
95
|
+
end
|
96
|
+
|
97
|
+
it "initializes a certificate manager" do
|
98
|
+
CertificateManager.should_receive(:new).with(conf_certs).and_return(cert_manager)
|
99
|
+
|
100
|
+
subject
|
101
|
+
end
|
102
|
+
|
103
|
+
it "initializes a logger" do
|
104
|
+
@logger = Logger.new(nil) # logger on the line below is called after Logger.should_receive(:new), meaning that logger() triggers the expectation, or something.
|
105
|
+
Logger.should_receive(:new).and_return(@logger)
|
106
|
+
|
107
|
+
subject
|
108
|
+
end
|
109
|
+
|
110
|
+
it "creates an application context" do
|
111
|
+
AppContext.should_receive(:new).with(config, cert_manager, kind_of(Logger)).and_return(appcontext)
|
112
|
+
|
113
|
+
subject
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "#run" do
|
120
|
+
before(:each) do
|
121
|
+
@logger = Logger.new(nil)
|
122
|
+
Logger.stub(:new).and_return(@logger)
|
123
|
+
Config.stub(:new).and_return(config)
|
124
|
+
subject.stub(:start_packetthief)
|
125
|
+
subject.stub(:stop_packetthief)
|
126
|
+
subject.stub(:run_tests).and_return(report)
|
127
|
+
end
|
128
|
+
|
129
|
+
context "when the action is runtests" do
|
130
|
+
before(:each) do
|
131
|
+
PacketThief.stub_chain(:redirect, :where, :run)
|
132
|
+
PacketThief.stub(:revert)
|
133
|
+
|
134
|
+
config.stub(:action).and_return(:runtests)
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
context "when ARGS is empty" do
|
139
|
+
let(:args) { [] }
|
140
|
+
|
141
|
+
it "creates a default list of test cases" do
|
142
|
+
SSLTestCase.should_receive(:factory).with(appcontext, config.tests,[]).and_return(double('list of SSLTestCases', :length => 10))
|
143
|
+
|
144
|
+
subject.run
|
145
|
+
end
|
146
|
+
|
147
|
+
it "runs the tests" do
|
148
|
+
subject.should_receive(:run_tests).with(test_list).and_return(report)
|
149
|
+
|
150
|
+
subject.run
|
151
|
+
end
|
152
|
+
|
153
|
+
it "starts PacketThief before running the tests" do
|
154
|
+
subject.should_receive(:start_packetthief).ordered
|
155
|
+
subject.should_receive(:run_tests).ordered.and_return(report)
|
156
|
+
|
157
|
+
subject.run
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
it "stops PacketThief after running the tests" do
|
162
|
+
subject.should_receive(:run_tests).ordered.and_return(report)
|
163
|
+
subject.should_receive(:stop_packetthief).ordered
|
164
|
+
|
165
|
+
subject.run
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context "when ARGS is ['wrongcname']" do
|
170
|
+
let(:args) { ['wrongcname'] }
|
171
|
+
it "it tells the SSLTestCase factory to just return the test called 'wrongcname'" do
|
172
|
+
SSLTestCase.should_receive(:factory).with(appcontext, config.tests,['wrongcname']).and_return(double('list with just wrongcname', :length => 1))
|
173
|
+
|
174
|
+
subject.run
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "#run_tests" do
|
183
|
+
before(:each) do
|
184
|
+
Config.stub(:new).and_return(config)
|
185
|
+
EM.stub(:run).and_yield
|
186
|
+
EM.stub(:add_periodic_timer)
|
187
|
+
EM.stub(:open_keyboard)
|
188
|
+
EM.stub(:stop_event_loop)
|
189
|
+
TestListener.stub(:start).and_return(test_listener)
|
190
|
+
TestManager.stub(:new).and_return(test_manager)
|
191
|
+
@logger = logger
|
192
|
+
Logger.should_receive(:new).and_return(logger)
|
193
|
+
end
|
194
|
+
|
195
|
+
it "configures a new TestManager" do
|
196
|
+
TestManager.should_receive(:new).with(appcontext, test_list, report, logger).and_return(test_manager)
|
197
|
+
|
198
|
+
subject.run_tests test_list
|
199
|
+
end
|
200
|
+
|
201
|
+
it "starts an EventMachine event loop" do
|
202
|
+
EM.should_receive(:run)
|
203
|
+
|
204
|
+
subject.run_tests test_list
|
205
|
+
end
|
206
|
+
|
207
|
+
it "starts the TestListener" do
|
208
|
+
TestListener.should_receive(:start).with('', 54321, test_manager).and_return(test_listener)
|
209
|
+
|
210
|
+
subject.run_tests test_list
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "logger options" do
|
215
|
+
context "when the command line sets the log level to WARN" do
|
216
|
+
let(:args) { %w{--log-level=WARN} }
|
217
|
+
it "sets the logger's level to WARN" do
|
218
|
+
@logger = Logger.new(nil)
|
219
|
+
|
220
|
+
Logger.stub(:new).and_return(@logger)
|
221
|
+
|
222
|
+
@logger.should_receive(:level=).with(Logger::WARN)
|
223
|
+
|
224
|
+
subject
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
context "when the command line sets the log file to 'foo.txt'" do
|
229
|
+
let(:args) { %w{--log-file=foo.txt} }
|
230
|
+
it "sets the log file to foo.txt" do
|
231
|
+
@logger = Logger.new(nil)
|
232
|
+
|
233
|
+
Logger.should_receive(:new).with('foo.txt').and_return(@logger)
|
234
|
+
|
235
|
+
subject
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
describe "configuring packetthief" do
|
242
|
+
before(:each) do
|
243
|
+
PacketThief.instance_variable_set(:@implementation, nil)
|
244
|
+
Config.stub(:new).and_return(config)
|
245
|
+
end
|
246
|
+
after(:each) do
|
247
|
+
PacketThief.instance_variable_set(:@implementation, nil)
|
248
|
+
end
|
249
|
+
context "when the config does not specify an implementation" do
|
250
|
+
before(:each) do
|
251
|
+
config.stub(:packetthief).and_return( {} )
|
252
|
+
end
|
253
|
+
|
254
|
+
it "does not explicitly configure a firewall implementation" do
|
255
|
+
PacketThief.should_not_receive(:implementation=)
|
256
|
+
|
257
|
+
subject
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
context "when the config specifies netfilter" do
|
262
|
+
before(:each) do
|
263
|
+
config.stub(:packetthief).and_return( {'implementation' => 'netfilter'} )
|
264
|
+
end
|
265
|
+
|
266
|
+
it "sets the firewall to :netfilter" do
|
267
|
+
PacketThief.should_receive(:implementation=).with('netfilter')
|
268
|
+
|
269
|
+
subject
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
context "when the config specifies manual(somehost)" do
|
274
|
+
before(:each) do
|
275
|
+
config.stub(:packetthief).and_return( {'implementation' => 'manual(somehost)', 'dest_port' => 654} )
|
276
|
+
PacketThief.stub(:set_dest)
|
277
|
+
end
|
278
|
+
|
279
|
+
it "sets the firewall to :manual" do
|
280
|
+
PacketThief.should_receive(:implementation=).with(:manual)
|
281
|
+
|
282
|
+
subject
|
283
|
+
end
|
284
|
+
|
285
|
+
it "sets the manual destination to the given hostname and dest_port" do
|
286
|
+
PacketThief.should_receive(:set_dest).with('somehost', 654)
|
287
|
+
|
288
|
+
subject
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
describe "the 'external' pseudo-implementation" do
|
293
|
+
context "when the config specifies external(netfilter)" do
|
294
|
+
before(:each) do
|
295
|
+
config.stub(:packetthief).and_return( {'implementation' => 'external(netfilter)'} )
|
296
|
+
PacketThief.stub(:set_dest)
|
297
|
+
end
|
298
|
+
|
299
|
+
it "it sets the firewall implementation to netfilter" do
|
300
|
+
PacketThief.should_receive(:implementation=).with(/netfilter/i)
|
301
|
+
|
302
|
+
subject
|
303
|
+
end
|
304
|
+
|
305
|
+
# Not enabling packetthief currently needs to happen in the test runner
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
describe "running packet thief" do
|
312
|
+
before(:each) do
|
313
|
+
Config.stub(:new).and_return(config)
|
314
|
+
end
|
315
|
+
|
316
|
+
describe "#start_packetthief" do
|
317
|
+
before(:each) do
|
318
|
+
config.stub(:listener_port).and_return(54321)
|
319
|
+
config.stub(:packetthief).and_return({
|
320
|
+
:protocol => 'tcp',
|
321
|
+
:dest_port => 443,
|
322
|
+
:in_interface => 'en1'
|
323
|
+
})
|
324
|
+
end
|
325
|
+
|
326
|
+
it "launches packet thief with configuration values" do
|
327
|
+
@ptrule = double("ptrule")
|
328
|
+
PacketThief.should_receive(:redirect).with(:to_ports => 54321).and_return(@ptrule)
|
329
|
+
@ptrule.should_receive(:where).with(:protocol => 'tcp', :dest_port => 443, :in_interface => 'en1').ordered.and_return(@ptrule)
|
330
|
+
@ptrule.should_receive(:run).ordered
|
331
|
+
|
332
|
+
subject.start_packetthief
|
333
|
+
end
|
334
|
+
|
335
|
+
context "when the packetthief implementation is 'external(netfilter)'" do
|
336
|
+
before(:each) do
|
337
|
+
config.stub(:packetthief).and_return( { 'implementation' => 'external(netfilter)' } )
|
338
|
+
end
|
339
|
+
it "does not redirect traffic itself" do
|
340
|
+
PacketThief.should_not_receive(:redirect)
|
341
|
+
|
342
|
+
subject.start_packetthief
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
end
|
347
|
+
|
348
|
+
describe "#stop_packetthief" do
|
349
|
+
it "reverts PacketThief" do
|
350
|
+
PacketThief.should_receive(:revert)
|
351
|
+
|
352
|
+
subject.stop_packetthief
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
end
|
357
|
+
|
358
|
+
|
359
|
+
end
|
360
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','spec_helper'))
|
2
|
+
|
3
|
+
module SSLTest
|
4
|
+
describe SSLTestCase do
|
5
|
+
let(:certchain) { double('certchain') }
|
6
|
+
let(:keychain) { [ double('firstkey'), double('secondkey'), double('cakey') ] }
|
7
|
+
let(:goodcacert) { double('goodcacert') }
|
8
|
+
let(:goodcakey) { double('goodcakey') }
|
9
|
+
let(:cert_manager) do
|
10
|
+
@cert_manager = double(
|
11
|
+
"cert_manager",
|
12
|
+
:get_chain => certchain,
|
13
|
+
:get_keychain => keychain,
|
14
|
+
:get_cert => double('cert'),
|
15
|
+
:get_key => double('key')
|
16
|
+
)
|
17
|
+
@cert_manager.stub(:get_cert).with('goodca').and_return(goodcacert)
|
18
|
+
@cert_manager.stub(:get_key).with('goodca').and_return(goodcakey)
|
19
|
+
@cert_manager
|
20
|
+
end
|
21
|
+
let(:config) do
|
22
|
+
double("config",
|
23
|
+
:dest_port => 443,
|
24
|
+
:listener_port => 54321,
|
25
|
+
:hosttotest => "my.hostname.com",
|
26
|
+
:packetthief => {
|
27
|
+
:protocol => 'tcp',
|
28
|
+
:dest_port => 443,
|
29
|
+
:in_interface => 'en1'
|
30
|
+
},
|
31
|
+
:testing_method => 'tlshandshake'
|
32
|
+
)
|
33
|
+
end
|
34
|
+
let(:testdesc) do
|
35
|
+
{
|
36
|
+
'alias' => 'baseline',
|
37
|
+
'name' => 'Baseline Happy Test',
|
38
|
+
'certchain' => ['baseline', 'goodca'],
|
39
|
+
'expected_result' => 'connect'
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:foo_test_data) do
|
44
|
+
{
|
45
|
+
'alias' => 'foo',
|
46
|
+
'name' => 'test foo',
|
47
|
+
'certchain' => [ 'a', 'b' ]
|
48
|
+
}
|
49
|
+
end
|
50
|
+
let(:bar_test_data) do
|
51
|
+
{
|
52
|
+
'alias' => 'bar',
|
53
|
+
'name' => 'test bar',
|
54
|
+
'certchain' => [ 'c', 'd' ]
|
55
|
+
}
|
56
|
+
end
|
57
|
+
let(:conf_tests_data) { [ foo_test_data, bar_test_data ] }
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
let(:listener) { double("listener", :logger= => nil, :stop_server => nil) }
|
62
|
+
let(:report) { double("report", :add_result => nil) }
|
63
|
+
let(:logger) { Logger.new(nil) }
|
64
|
+
let(:app_context) { AppContext.new(config, cert_manager, logger) }
|
65
|
+
|
66
|
+
|
67
|
+
before(:each) do
|
68
|
+
PacketThief.stub_chain(:redirect, :where, :run)
|
69
|
+
PacketThief.stub(:revert)
|
70
|
+
EM.stub(:run).and_yield
|
71
|
+
EM.stub(:add_periodic_timer)
|
72
|
+
EM.stub(:open_keyboard)
|
73
|
+
EM.stub(:stop_event_loop)
|
74
|
+
TestListener.stub(:start).and_return(listener)
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
# list of configs, list to generate
|
79
|
+
describe ".factory" do
|
80
|
+
subject { SSLTestCase }
|
81
|
+
context "when an empty list of tests to perform is passed" do
|
82
|
+
it "returns SSLTestCases for all of the tests in the config data, in the original order" do
|
83
|
+
@tests = subject.factory(app_context, conf_tests_data, [])
|
84
|
+
|
85
|
+
@tests.length.should == conf_tests_data.length
|
86
|
+
@tests.each do |test|
|
87
|
+
test.class.should == subject
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "when ['foo'] is passed as an argument" do
|
93
|
+
it "returns a list with just a 'foo' test case" do
|
94
|
+
@tests = subject.factory(app_context, conf_tests_data, ['foo'])
|
95
|
+
|
96
|
+
@tests.length.should == 1
|
97
|
+
end
|
98
|
+
end
|
99
|
+
context "when ['bar', 'foo'] is passed as an argument" do
|
100
|
+
it "returns a list with 'bar', then 'foo'" do
|
101
|
+
@tests = subject.factory(app_context, conf_tests_data, ['bar', 'foo'])
|
102
|
+
|
103
|
+
@tests.length.should == 2
|
104
|
+
@tests[0].id.should == 'bar'
|
105
|
+
@tests[1].id.should == 'foo'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|