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



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

def test_result_closing
  @test_result_closing ||= TEST_RESULT_CLOSING
end

#test_result_fileObject



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

def test_result_file
  @test_result_file ||= TEST_RESULT_FILE
end

#test_result_preludeObject



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

def test_result_prelude
  @test_result_prelude ||= TEST_RESULT_PRELUDE
end

Instance Method Details

#break=(point) ⇒ Object

Set breakpoint at specified line or function



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

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

#btObject

Print backtrace of all stack frames



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

def bt
  @queue << "bt"
end

#cObject

Alias for continue



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

def c
  @queue << "continue"
end

#cfObject

Display the name and number of the current file



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

def cf
  @queue << "cf"
end

#clear=(point) ⇒ Object

Clear breakpoint at specified line or function



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

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

#command_queueObject

:nodoc:



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

def command_queue # :nodoc:
  @queue
end

#commands=(cmd) ⇒ Object

Sets commands to execute when breakpoint hit



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

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

#condition=(cond) ⇒ Object

Apply/remove conditional expression to a breakpoint



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

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

#continueObject

Continue execution after stopping at breakpoint



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

def continue
  @queue << "continue"
end

#defineObject

:nodoc:



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

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

#deleteObject

Delete breakpoints or auto-display expressions



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

def delete
  @queue << "delete"
end

#directory=(dir) ⇒ Object

Add a directory to the search path for source files



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

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

#disableObject

Disable breakpoints or auto-display expressions



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

def disable
  @queue << "disable"
end

#disassembleObject

Disassemble source lines or functions



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

def disassemble
  @queue << "dissassemble"
end

#display=(disp) ⇒ Object

Add an auto-display expressions



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

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

#eObject

Enable breakpoints or auto-display expressions



311
312
313
# File 'lib/sprout/tasks/fdb_task.rb', line 311

def e
  @queue << "enable"
end

#enableObject

Enable breakpoints or auto-display expressions



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

def enable
  @queue << "enable"
end

#execute(*args) ⇒ Object

:nodoc:



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

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.

  if(buffer.runtime_exception_encountered && kill_on_fault?)
    raise FDBTaskError.new("[ERROR] ActionScript runtime exception encountered")
  end
  self
end

#file=(file) ⇒ Object

Specify application to be debugged.



316
317
318
319
320
# File 'lib/sprout/tasks/fdb_task.rb', line 316

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

#finishObject

Execute until current function returns



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

def finish
  @queue << "finish"
end

#get_executableObject

:nodoc:



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

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



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

def handle
  @queue << "handle"
end

#handle_command(buffer, command) ⇒ Object

:nodoc:



201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/sprout/tasks/fdb_task.rb', line 201

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



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

def home
  @queue << "home"
end

#infoObject

Display information about the program being debugged



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

def info
  @queue << "info"
end

#info_argumentsObject

Argument variables of current stack frame



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

def info_arguments
  @queue << "i a"
end

#info_breakpointsObject

Status of user-settable breakpoints



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

def info_breakpoints
  @queue << "i b"
end

#info_displayObject

Display list of auto-display expressions



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

def info_display
  @queue << "i d"
end

#info_filesObject

Names of targets and files being debugged



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

def info_files
  @queue << "i f"
end

#info_functions=(value) ⇒ Object

All function names



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

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

#info_handleObject

How to handle a fault



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

def info_handle
  @queue << "i h"
end

#info_localsObject

Local variables of current stack frame



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

def info_locals
  @queue << "i l"
end

#info_scopechainObject

Scope chain of current stack frame



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

def info_scopechain
  @queue << "i sc"
end

#info_sourcesObject

Source files in the program



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

def info_sources
  @queue << "i so"
end

#info_stackObject

Backtrace of the stack



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

def info_stack
  @queue << "i s"
end

#info_swfsObject

List of swfs in this session



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

def info_swfs
  @queue << "i sw"
end

#info_targetsObject

Application being debugged



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

def info_targets
  @queue << "i t"
end

#info_variablesObject

All global and static variable names



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

def info_variables
  @queue << "i v"
end

#initialize_taskObject

:nodoc:



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

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

#input=(file) ⇒ Object

alias for self.file=



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

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

#killObject

Kill execution of program being debugged



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

def kill
  @queue << "kill"
end

#kill_on_fault?Boolean

Returns:

  • (Boolean)


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

def kill_on_fault?
  @kill_on_fault
end

#listObject

List specified function or line



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

def list
  @queue << "list"
end

#nextObject

Step program



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

def next
  @queue << "next"
end

#print=(msg) ⇒ Object

Print value of variable EXP



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

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

#pwdObject

Print working directory



433
434
435
# File 'lib/sprout/tasks/fdb_task.rb', line 433

def pwd
  @queue << "pwd"
end

#quitObject

Exit fdb



438
439
440
441
442
# File 'lib/sprout/tasks/fdb_task.rb', line 438

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

#runObject

Start debugged program



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

def run
  @queue << "run"
end

#set=(value) ⇒ Object

Set the value of a variable



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

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

#sleep_until(str) ⇒ Object

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



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

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

#source=(file) ⇒ Object

Read fdb commands from a file



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

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

#stdoutObject

:nodoc:



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

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

#stdout=(out) ⇒ Object

:nodoc:



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

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

#stepObject

Step program until it reaches a different source line



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

def step
  @queue << "step"
end

#terminateObject

Force the Flash Debugger and running SWF to close



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

def terminate
  @queue << "terminate"
end

#undisplayObject

Remove an auto-display expression



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

def undisplay
  @queue << "undisplay"
end

#validate_swf(swf) ⇒ Object



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

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



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

def viewswf
  @queue << "viewswf"
end

#what=(value) ⇒ Object

Displays the context of a variable



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

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

#whereObject

Same as bt



490
491
492
# File 'lib/sprout/tasks/fdb_task.rb', line 490

def where
  @queue << "bt"
end