Class: Sprout::FDBTask

Inherits:
ToolTask
  • Object
show all
Defined in:
lib/sprout/tasks/fdb_task.rb

Overview

The FDBTask provides a procedural rake front end to the FDB command line tool

Here is a decent tutorial on using FDB with SWF or HTML content: installingcats.wordpress.com/tag/adobe-flex/

You can send the fdb task some debug commands directly or simply execute the rake task and interact with the debugger manually.

The FDBTask requires that you have a debug Flash Player installed on your system as the default execution application for SWF files.

Following is an example of setting up a breakpoint in SomeFile at line 23

fdb :debug do |t|
  t.file = 'bin/SomeProject-debug.swf'
  t.run
  t.break = 'SomeFile:23'
  t.continue
end

You can also point the FDBTask at HTML pages. These pages will be launched in your default browser. You will need to manually install a debug Flash Player in that particular browser.

To use a browser instead of the desktop Flash Player, simply point the file argument at an HTML document or remote URL. The SWF file loaded must be compiled using the -debug flag, and executed in a debug Flash Player in order to connect to properly connect to the debugger.

fdb :debug do |t|
  t.file = 'bin/SomeProject-debug.html'
  t.run
  t.continue
end

.h3 Continuous Integration

The FDBTask is also the only effective way to execute SWF content in front of a CI (continuous integration) tool like Cruise Control. The biggest problem facing SWF execution for CI is uncaught runtime exceptions. The debug Flash Player throws uncaught exceptions up to the operating system GUI layer where a user must manually dismiss a dialog. In addition to blocking the CI process indefinitely, these messages are also difficult to capture and log.

Using Sprouts and the FDBTask, we can capture these messages along with additonal information (e.g. local variables and a complete stack trace) about the state of the SWF file, and then cleanly exit the Flash Player and log this information.

The FDBTask has also been configured to work with the ASUnit XMLPrinter so that an XML artifact is created and written to disk that includes the results of running your test suites.

To use FDB with a CI tool do the following:

1) Create a new base runner class (we usually name this XMLRunner.as) and make it look like the following:

package {
  import asunit.textui.TestRunner;
  import asunit.textui.XMLResultPrinter;

  public class XMLRunner extends TestRunner {

    public function XMLRunner() {
      setPrinter(new XMLResultPrinter());
      start(AllTests, null, TestRunner.SHOW_TRACE);
    }
  }
}

2) Create a new MXMLCTask to compile the newly created runner. NOTE: Be sure you set debug to true, otherwise the SWF will not connect to the debugger properly.

library :asunit3

desc 'Compile the CI SWF'
mxmlc 'bin/XMLRunner.swf' => :asunit3 do |t|
  t.input = 'src/XMLRunner.as'
  t.debug = true
  t.source_path << 'test'
  # Add additional configuration here.
end

3) Create a new FDBTask and set kill_on_fault to true.

desc 'Execute the test harness for CI'
fdb :cruise do |t|
  t.kill_on_fault = true
  t.file = 'bin/XMLRunner.swf'
  t.run
  t.continue
end

4) Configure your CI task to call:

rake cruise

5) That’s it!

Constant Summary collapse

TEST_RESULT_PRELUDE =
'<XMLResultPrinter>'
TEST_RESULT_CLOSING =
'</XMLResultPrinter>'
TEST_RESULT_FILE =
'AsUnitResults.xml'

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#kill_on_fault=(value) ⇒ Object (writeonly)

Boolean value that tells fdb whether or not it should automatically shut down when an exception is encountered. This feature is used to prevent GUI prompts for unhandled exceptions, especially when running a test harness under a continuous integration tool - like cruise control. If an exception is encountered, fdb will automatically print the exception, a full stack trace and all local variables in the function where the failure occured.



142
143
144
# File 'lib/sprout/tasks/fdb_task.rb', line 142

def kill_on_fault=(value)
  @kill_on_fault = value
end

#test_result_closingObject



232
233
234
# File 'lib/sprout/tasks/fdb_task.rb', line 232

def test_result_closing
  @test_result_closing ||= TEST_RESULT_CLOSING
end

#test_result_fileObject



224
225
226
# File 'lib/sprout/tasks/fdb_task.rb', line 224

def test_result_file
  @test_result_file ||= TEST_RESULT_FILE
end

#test_result_preludeObject



228
229
230
# File 'lib/sprout/tasks/fdb_task.rb', line 228

def test_result_prelude
  @test_result_prelude ||= TEST_RESULT_PRELUDE
end

Instance Method Details

#break=(point) ⇒ Object

Set breakpoint at specified line or function



242
243
244
# File 'lib/sprout/tasks/fdb_task.rb', line 242

def break=(point)
  @queue << "break #{point}"
end

#btObject

Print backtrace of all stack frames



237
238
239
# File 'lib/sprout/tasks/fdb_task.rb', line 237

def bt
  @queue << "bt"
end

#cObject

Alias for continue



267
268
269
# File 'lib/sprout/tasks/fdb_task.rb', line 267

def c
  @queue << "continue"
end

#cfObject

Display the name and number of the current file



247
248
249
# File 'lib/sprout/tasks/fdb_task.rb', line 247

def cf
  @queue << "cf"
end

#clear=(point) ⇒ Object

Clear breakpoint at specified line or function



252
253
254
# File 'lib/sprout/tasks/fdb_task.rb', line 252

def clear=(point)
  @queue << "clear #{point}"
end

#command_queueObject

:nodoc:



216
217
218
# File 'lib/sprout/tasks/fdb_task.rb', line 216

def command_queue # :nodoc:
  @queue
end

#commands=(cmd) ⇒ Object

Sets commands to execute when breakpoint hit



272
273
274
# File 'lib/sprout/tasks/fdb_task.rb', line 272

def commands=(cmd)
  @queue << "com #{cmd}"
end

#condition=(cond) ⇒ Object

Apply/remove conditional expression to a breakpoint



257
258
259
# File 'lib/sprout/tasks/fdb_task.rb', line 257

def condition=(cond)
  @queue << "condition #{cond}"
end

#continueObject

Continue execution after stopping at breakpoint



262
263
264
# File 'lib/sprout/tasks/fdb_task.rb', line 262

def continue
  @queue << "continue"
end

#defineObject

:nodoc:



151
152
153
154
155
# File 'lib/sprout/tasks/fdb_task.rb', line 151

def define # :nodoc:
  super
  CLEAN.add(test_result_file)
  self
end

#deleteObject

Delete breakpoints or auto-display expressions



277
278
279
# File 'lib/sprout/tasks/fdb_task.rb', line 277

def delete
  @queue << "delete"
end

#directory=(dir) ⇒ Object

Add a directory to the search path for source files



282
283
284
# File 'lib/sprout/tasks/fdb_task.rb', line 282

def directory=(dir)
  @queue << "directory #{dir}"
end

#disableObject

Disable breakpoints or auto-display expressions



287
288
289
# File 'lib/sprout/tasks/fdb_task.rb', line 287

def disable
  @queue << "disable"
end

#disassembleObject

Disassemble source lines or functions



292
293
294
# File 'lib/sprout/tasks/fdb_task.rb', line 292

def disassemble
  @queue << "dissassemble"
end

#display=(disp) ⇒ Object

Add an auto-display expressions



297
298
299
# File 'lib/sprout/tasks/fdb_task.rb', line 297

def display=(disp)
  @queue << "disp #{disp}"
end

#eObject

Enable breakpoints or auto-display expressions



307
308
309
# File 'lib/sprout/tasks/fdb_task.rb', line 307

def e
  @queue << "enable"
end

#enableObject

Enable breakpoints or auto-display expressions



302
303
304
# File 'lib/sprout/tasks/fdb_task.rb', line 302

def enable
  @queue << "enable"
end

#execute(*args) ⇒ Object

:nodoc:



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/sprout/tasks/fdb_task.rb', line 173

def execute(*args) # :nodoc:
  # Ensure that if we load a SWF it's been compiled with debugging turned on!
  file_name = @file

  if(file_name.match(/\.swf$/))
    validate_swf(file_name)
  end

  buffer = FDBBuffer.new(get_executable, stdout)
  buffer.test_result_file = test_result_file
  buffer.test_result_prelude = test_result_prelude
  buffer.test_result_closing = test_result_closing
  buffer.kill_on_fault = kill_on_fault?
  buffer.wait_for_prompt

  @queue.each do |command|
    handle_command(buffer, command)
  end

  buffer.join # wait here until the buffer is closed.

  self
end

#file=(file) ⇒ Object

Specify application to be debugged.



312
313
314
315
316
# File 'lib/sprout/tasks/fdb_task.rb', line 312

def file=(file)
  @prerequisites << file
  @queue << "file #{file}"
  @file = file
end

#finishObject

Execute until current function returns



324
325
326
# File 'lib/sprout/tasks/fdb_task.rb', line 324

def finish
  @queue << "finish"
end

#get_executableObject

:nodoc:



211
212
213
214
# File 'lib/sprout/tasks/fdb_task.rb', line 211

def get_executable # :nodoc:
  exe = Sprout.get_executable(gem_name, gem_path, gem_version)
  User.clean_path(exe)
end

#handleObject

Specify how to handle a fault



329
330
331
# File 'lib/sprout/tasks/fdb_task.rb', line 329

def handle
  @queue << "handle"
end

#handle_command(buffer, command) ⇒ Object

:nodoc:



197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/sprout/tasks/fdb_task.rb', line 197

def handle_command(buffer, command) # :nodoc:
  parts = command.split(' ')
  name = parts.shift
  value = parts.shift
  case name
    when "sleep"
      buffer.sleep_until value
    when "terminate"
      buffer.kill
    else
      buffer.write command
  end
end

#homeObject

Set listing location to where execution is halted



334
335
336
# File 'lib/sprout/tasks/fdb_task.rb', line 334

def home
  @queue << "home"
end

#infoObject

Display information about the program being debugged



339
340
341
# File 'lib/sprout/tasks/fdb_task.rb', line 339

def info
  @queue << "info"
end

#info_argumentsObject

Argument variables of current stack frame



344
345
346
# File 'lib/sprout/tasks/fdb_task.rb', line 344

def info_arguments
  @queue << "i a"
end

#info_breakpointsObject

Status of user-settable breakpoints



349
350
351
# File 'lib/sprout/tasks/fdb_task.rb', line 349

def info_breakpoints
  @queue << "i b"
end

#info_displayObject

Display list of auto-display expressions



354
355
356
# File 'lib/sprout/tasks/fdb_task.rb', line 354

def info_display
  @queue << "i d"
end

#info_filesObject

Names of targets and files being debugged



359
360
361
# File 'lib/sprout/tasks/fdb_task.rb', line 359

def info_files
  @queue << "i f"
end

#info_functions=(value) ⇒ Object

All function names



364
365
366
# File 'lib/sprout/tasks/fdb_task.rb', line 364

def info_functions=(value)
  @queue << "i fu #{value}"
end

#info_handleObject

How to handle a fault



369
370
371
# File 'lib/sprout/tasks/fdb_task.rb', line 369

def info_handle
  @queue << "i h"
end

#info_localsObject

Local variables of current stack frame



374
375
376
# File 'lib/sprout/tasks/fdb_task.rb', line 374

def info_locals
  @queue << "i l"
end

#info_scopechainObject

Scope chain of current stack frame



379
380
381
# File 'lib/sprout/tasks/fdb_task.rb', line 379

def info_scopechain
  @queue << "i sc"
end

#info_sourcesObject

Source files in the program



384
385
386
# File 'lib/sprout/tasks/fdb_task.rb', line 384

def info_sources
  @queue << "i so"
end

#info_stackObject

Backtrace of the stack



389
390
391
# File 'lib/sprout/tasks/fdb_task.rb', line 389

def info_stack
  @queue << "i s"
end

#info_swfsObject

List of swfs in this session



394
395
396
# File 'lib/sprout/tasks/fdb_task.rb', line 394

def info_swfs
  @queue << "i sw"
end

#info_targetsObject

Application being debugged



399
400
401
# File 'lib/sprout/tasks/fdb_task.rb', line 399

def info_targets
  @queue << "i t"
end

#info_variablesObject

All global and static variable names



404
405
406
# File 'lib/sprout/tasks/fdb_task.rb', line 404

def info_variables
  @queue << "i v"
end

#initialize_taskObject

:nodoc:



144
145
146
147
148
149
# File 'lib/sprout/tasks/fdb_task.rb', line 144

def initialize_task # :nodoc:
  @default_gem_name = 'sprout-flex3sdk-tool'
  @default_gem_path = 'bin/fdb'
  @kill_on_fault = false
  @queue = []
end

#input=(file) ⇒ Object

alias for self.file=



319
320
321
# File 'lib/sprout/tasks/fdb_task.rb', line 319

def input=(file)
  self.file = file
end

#killObject

Kill execution of program being debugged



409
410
411
# File 'lib/sprout/tasks/fdb_task.rb', line 409

def kill
  @queue << "kill"
end

#kill_on_fault?Boolean

Returns:

  • (Boolean)


220
221
222
# File 'lib/sprout/tasks/fdb_task.rb', line 220

def kill_on_fault?
  @kill_on_fault
end

#listObject

List specified function or line



414
415
416
# File 'lib/sprout/tasks/fdb_task.rb', line 414

def list
  @queue << "list"
end

#nextObject

Step program



419
420
421
# File 'lib/sprout/tasks/fdb_task.rb', line 419

def next
  @queue << "next"
end

#print=(msg) ⇒ Object

Print value of variable EXP



424
425
426
# File 'lib/sprout/tasks/fdb_task.rb', line 424

def print=(msg)
  @queue << "print #{msg}"
end

#pwdObject

Print working directory



429
430
431
# File 'lib/sprout/tasks/fdb_task.rb', line 429

def pwd
  @queue << "pwd"
end

#quitObject

Exit fdb



434
435
436
437
438
# File 'lib/sprout/tasks/fdb_task.rb', line 434

def quit
  @queue << "quit"
  @queue << "y"
  @queue << "terminate"
end

#runObject

Start debugged program



441
442
443
# File 'lib/sprout/tasks/fdb_task.rb', line 441

def run
  @queue << "run"
end

#set=(value) ⇒ Object

Set the value of a variable



446
447
448
# File 'lib/sprout/tasks/fdb_task.rb', line 446

def set=(value)
  @queue << "set #{value}"
end

#sleep_until(str) ⇒ Object

Sleep until some ‘str’ String is sent to the output,



451
452
453
# File 'lib/sprout/tasks/fdb_task.rb', line 451

def sleep_until(str)
  @queue << "sleep #{str}"
end

#source=(file) ⇒ Object

Read fdb commands from a file



456
457
458
# File 'lib/sprout/tasks/fdb_task.rb', line 456

def source=(file)
  @queue << "source #{file}"
end

#stdoutObject

:nodoc:



161
162
163
# File 'lib/sprout/tasks/fdb_task.rb', line 161

def stdout # :nodoc:
  @stdout ||= $stdout
end

#stdout=(out) ⇒ Object

:nodoc:



157
158
159
# File 'lib/sprout/tasks/fdb_task.rb', line 157

def stdout=(out) # :nodoc:
  @stdout = out
end

#stepObject

Step program until it reaches a different source line



461
462
463
# File 'lib/sprout/tasks/fdb_task.rb', line 461

def step
  @queue << "step"
end

#terminateObject

Force the Flash Debugger and running SWF to close



466
467
468
# File 'lib/sprout/tasks/fdb_task.rb', line 466

def terminate
  @queue << "terminate"
end

#undisplayObject

Remove an auto-display expression



471
472
473
# File 'lib/sprout/tasks/fdb_task.rb', line 471

def undisplay
  @queue << "undisplay"
end

#validate_swf(swf) ⇒ Object



165
166
167
168
169
170
171
# File 'lib/sprout/tasks/fdb_task.rb', line 165

def validate_swf(swf)
  # TODO: Ensure the SWF has been compiled with debugging
  # turned on.
  # I believe this will require actually parsing the SWF file and
  # scanning for the EnableDebugger2 tag.
  # http://www.adobe.com/devnet/swf/pdf/swf_file_format_spec_v9.pdf
end

#viewswfObject

Set or clear filter for file listing based on swf



476
477
478
# File 'lib/sprout/tasks/fdb_task.rb', line 476

def viewswf
  @queue << "viewswf"
end

#what=(value) ⇒ Object

Displays the context of a variable



481
482
483
# File 'lib/sprout/tasks/fdb_task.rb', line 481

def what=(value)
  @queue << "what #{value}"
end

#whereObject

Same as bt



486
487
488
# File 'lib/sprout/tasks/fdb_task.rb', line 486

def where
  @queue << "bt"
end