Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Proposal: emit an event when main package has exited #383

Open
@flimzy

Description

@flimzy

The problem: I'm working on running tests in the browser, and have a proof of concept working to run a good portion of the GopherJS tests in a browser. I'm running each test file in an iframe, and capturing the output to console and displaying it in the parent window's DOM. The big weakness at the moment is that there's no way to tell when a test has completed. For a single test, this is a mild annoyance in the browser, as I must continually check for new output to the console, until the user closes the page. In an automated test environment (i.e. PhantomJS) it's more debilitating, leaving me to fall back to a "reasonable" timeout (if no console updates for N seconds, consider the test run complete).

It's quite a problem when running multiple tests (as in the entire GopherJS test suite) in the browser. I must either wait a 'reasonable' time between tests, or risk locking the browser. Determining a reasonable time isn't easy; some tests run in < 100ms, others multiple tens of seconds.

Possible solutions: An easy solution, for tests I control, is to just to output 'Done.' after all my tests have completed, and I can watch for this output. This doesn't help when running third-party tests (as the GopherJS and upstream Go tests).

Another option might be to heuristically determine, based on standard Go test output format, when a test has completed. I don't think this is realistic, given that the number of tests to run isn't known before hand, and it would break when using other test output formats, which certainly do exist.

So this leaves me trying to divine the state of the GopherJS process, and has lead me to three possible options. I'm hopeful that one of you guys will have a better idea that doesn't require changing GopherJS at all.

  1. Trigger an event after the main package returns:

     var $mainPkg = $packages["main"];                                                                                                                                                                                               
     $packages["runtime"].$init();
     $go($mainPkg.$init, [], true);
    +$global.dispatchEvent("mainFinished");
     $flushConsole();
    
     }).call(this);
    
  2. If defined, execute a user-defined function after the main package exits (an event seems cleaner and more idiomatic, though):

     var $mainPkg = $packages["main"];                                                                                                                                                                                               
     $packages["runtime"].$init();
     $go($mainPkg.$init, [], true);
    +if ( $global.mainFinished ) {
    +    $global.mainFinished();
    +}
     $flushConsole();
    
     }).call(this);
    
  3. Expose some internal state through a global variable/function.

     var $dummyGoroutine = { asleep: false, exit: false, deferStack: [], panicStack: [], canBlock: false };
     var $curGoroutine = $dummyGoroutine, $totalGoroutines = 0, $awakeGoroutines = 0, $checkForDeadlock = true;
     var $mainFinished = false;
    +$global.gopherjsMainFinished = function() {
    +    return $mainFinished;
    +};
     var $go = function(fun, args, direct) {
     $totalGoroutines++;
     $awakeGoroutines++;
    

Any thoughts, or better suggestions?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions