Skip to content
This repository was archived by the owner on Jan 30, 2025. It is now read-only.
This repository was archived by the owner on Jan 30, 2025. It is now read-only.

browser.on('disconnect') hangs when browser is abstracted from JS API #913

@ka3de

Description

@ka3de

Brief summary

After the work done in #910, now the browser lifecycle is handled by our Go implementation based on the VU context and transparently to the end user. That means that the flow of events is as follows:

  • Iteration starts and VU context is initialized
  • Some interaction is done with the browser API which produces the browser initialization (e.g.: browser.newPage())
  • The browser is initialized and stored in the registry
  • Iteration ends and VU context is canceled
  • browser is closed in response of VU context being done

The problem happens if the test script makes us of browser.on method. Currently this method only supports the disconnect event. When calling browser.on('disconnect'), our implementation will return a promise that will be resolved once the browser is disconnected. Previously this disconnection happened at the end of the test, as browser.close() was being called explicitly by the end user in the JS code. But now, because the browser.close() is handled by the Go implementation, away from the scope of the JS test, the promise waits indefinetly due to a deadlock:

  • The promise waits for the browser to be closed/disconnected
  • The browser waits for the iteration (so the JS code) to finish

We should consider if this functionality brings value given the current implementation. If so, consider implementation options that will allow this functionality at the same time that the restrictions on browser process and browser contexts are fulfilled.

xk6-browser version

Commit b08de58 (PR #910)

OS

Ubuntu 20.04.5 LTS

Chrome version

113.0.5672.126 (Official Build) (64-bit)

Docker version and image (if applicable)

No response

Steps to reproduce the problem

Build a custom k6 binary based on the work done in PR #910 . E.g.:

xk6 build --with github.com/grafana/xk6-browser@b08de58

Run the following test:

import { check } from 'k6';
import { browser } from 'k6/x/browser';

export const options = {
  scenarios: {
    ui: {
      executor: 'shared-iterations',
      options: {
        browser: {
            type: 'chromium',
        },
      },
    },
  },
  thresholds: {
    checks: ["rate==1.0"]
  }
}

export default function() {
  check(browser, {
    'should be connected after launch': browser.isConnected(),
  });
  const handlerCalled = Symbol();

  let p = browser.on('disconnected')
    // The promise resolve/success handler
    .then((val) => {
      check(browser, {
        'should be disconnected on event': !browser.isConnected(),
      });
      return handlerCalled;
      // The promise reject/failure handler
    }, (val) => {
      console.error(`promise rejected: ${val}`);
    });

  p.then((val) => {
    check(val, {
      'the browser.on success handler should be called': val === handlerCalled,
    });
  });

  check(browser, {
    'should be connected before ending iteration': browser.isConnected(),
  });
}

Expected behaviour

Considering the previous implementation, a browser.close() method would be call at the end of the JS test code explicitly, which would make the browser disconnect and resolve the browser.on promise resolve, making the promise handling function being called and passing the checks.

Actual behaviour

The test hangs.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions