Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.2.1 regression: dont crash if there is a single stackframe #605

Merged
merged 6 commits into from
Sep 18, 2016
Merged

1.2.1 regression: dont crash if there is a single stackframe #605

merged 6 commits into from
Sep 18, 2016

Conversation

hmalphettes
Copy link
Contributor

Regression from #538:

(...)/node_modules/cucumber/lib/cucumber/support_code/library.js:53
        var line = stackframes[1].getLineNumber();
                                 ^

Cannot read property 'getLineNumber' of undefined
    at Object.module.exports (/apps/ui.stoic/test/cucumber/features/step_definitions/runtime.js:81:8)

In my setup there is either 1 stackframe or 8 of them.
I am not sure this is the perfect fix but it does re-enable running the testsuite.

@hmalphettes hmalphettes changed the title Dont crash if there is a single stackframe 1.2.1 regression: dont crash if there is a single stackframe Jul 6, 2016
@hmalphettes
Copy link
Contributor Author

For info, comparing callsite and stacktrace-js in the defineHook I am getting:

defineHook: function defineHook(builder, collection) {
...
console.log('we got a site');
stackframes.forEach((s, i) => {
   console.log('  ' + i + ' ' + s.getFileName() + s.getLineNumber());
});
...
# callsite (1.2.0)
we got a site
  0 /myproj/node_modules/cucumber/lib/cucumber/support_code/library.js52
  1 /myproj/test/cucumber/features/step_definitions/runtime.js81
  2 /myproj/node_modules/cucumber/lib/cucumber/cli/support_code_loader.js65
  3 native array.js960
  4 /myproj/node_modules/cucumber/lib/cucumber/cli/support_code_loader.js62
  5 /myproj/node_modules/cucumber/lib/cucumber/cli/support_code_loader.js24
  6 /myproj/node_modules/cucumber/lib/cucumber/support_code/library.js124
  7 /myproj/node_modules/cucumber/lib/cucumber/cli/support_code_loader.js10
  8 /myproj/node_modules/cucumber/lib/cucumber/cli/configuration.js126
  9 /myproj/node_modules/cucumber/lib/cucumber/runtime.js43

# stacktrace-js
we got a site
  0 /myproj/test/cucumber/features/step_definitions/runtime.js81

@charlierudolph
Copy link
Member

I'm very curious about your setup. Can you share a minimal setup to reproduce this or add a feature test that captures your setup (fails without your changes and passes with them)?

@hmalphettes
Copy link
Contributor Author

@charlierudolph tough one! But I hear you. Calling my colleagues (@floribon) to the rescue and reviewing the existing cucumber-js tests to try to spot the difference.

@floribon
Copy link
Contributor

@charlierudolph this happens when using custom stack traces as suggested in this thread #157 (comment)

I am overriding the Error.prepareStackTrace in order to only have traces from our own files, which speeds up debugging a lot:

/** https://github.com/cucumber/cucumber-js/issues/157#issuecomment-43309248 **/
function setCleanStrackTraces() {

  // monkey-patch stack trace more-or-less compatible with webdriver
  const isMyStack = new RegExp(
    path.join(
      __dirname, '../../../..',
      '[^node_modules/]' // exclude node_modules
    ).replace(/\//g, '\\/')
  );

  Error.prepareStackTrace = function (err, stack) {

    let message = err
      .message.split('\n')
      .filter(s => !/Session|Driver|Build|System|Capabilities|Command/.test(s))
      .join('\n') || '';

    if (!message.trim()) {
      // we would rather see something than not see something at all
      message = '[internal] ' + err.message.split('\n')[0].trim();
    }

    if (message) { message += '\n'; }

    const results = [];
    for (const elt of stack) {
      const frame = elt.toString();
      if (isMyStack.test(frame)) {
        results.push('    at ' + frame);
      }
    }

    return message + results.join('\n');
  };
}

Unfortunately this is breaking since 1.2.1

stackframes[i].fileName !== '(native)') {
return stackframes[i];
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use lodash's _.find here instead of the manual for loop and _.includes instead of stackframes[i].fileName.indexOf.

Copy link
Member

@charlierudolph charlierudolph Aug 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually can this just be simplified to

var stackframes = StackTrace.getSync();
if (stackframes.length > 1) {
  return stackframes[1];
} else {
  return stackframes[0];
}

@floribon
Copy link
Contributor

floribon commented Aug 31, 2016

@charlierudolph PR updated with your suggested syntax, it does work for us

function getStackframe() {
var stackframes = StackTrace.getSync();
if (stackframes.length > 1) {
return stackframes[1];
Copy link
Member

@charlierudolph charlierudolph Aug 31, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the failing feature tests, I think this logic needs to actually be

if (stackframes.length > 2) {
  return stackframes[2];
} // ...

Since the defineHook / defineStep is now calling this, we have another function on the stack and thus need to look one level further back.

@charlierudolph
Copy link
Member

Please add a unit test for this to prevent regressions. I believe you can stub out StackTrace.getSync()

hmalphettes and others added 2 commits September 5, 2016 23:48
Regression from #538
In my setup there is either 1 stackframe or 8 of them.
I am not sure this is the perfect fix but it does re-enable running
the testsuite
@floribon
Copy link
Contributor

floribon commented Sep 5, 2016

@charlierudolph I am really sorry I did not follow the contributing guidelines. This time I ran the tests and my use case and everything works. However I studied the specs codebase but could not figure out how to add a unit test for this.

@charlierudolph
Copy link
Member

@floribon let me see if I can help you through being able to write a unit test for it.

The unit test would go in
https://github.com/cucumber/cucumber-js/blob/master/spec/cucumber/support_code/library_spec.js

An example of mocking out another module's function
https://github.com/cucumber/cucumber-js/blob/master/spec/cucumber/ast/filter/scenario_at_line_rule_spec.js#L11

What else can I help with?

@floribon
Copy link
Contributor

floribon commented Sep 8, 2016

@charlierudolph are stacktrace outputs tested somewhere? I believe that's where one could make sure that it succeeds even if the user overrode Error.prepareStackTrace. This PR aimed to be a bug fix and not a new feature.

Now reading more about #157 I realized that I could avoid the error by using these, which is cleaner:

require('hide-stack-frames-from')('cucumber');
require('hide-stack-frames-from')('selenium-webdriver');

So feel free to reject this PR if it is not helping.

@charlierudolph
Copy link
Member

They are not tested anywhere at the moment. If you wanted you could just create a feature where you override Error.prepareStackTrace and ensure it works as expected.

@floribon
Copy link
Contributor

floribon commented Sep 8, 2016

Pushed, confirmed that it fails on master and passes on this branch.

this.When(/^I override Error.prepareStackTrace$/, function() {
Error.prepareStackTrace = function() {
return 'Custom message';
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't fail for me on master. I would expect you to need to override it before this.When() gets called as that is when the stacktrace is captured.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@charlierudolph my bad, it failed for me but because of the missing which I didn't see initially. I've just pushed an update for the test which this time I made sure were giving the error on master:

(...)/node_modules/cucumber/lib/cucumber/support_code/library.js:53
        var line = stackframes[1].getLineNumber();

@charlierudolph charlierudolph merged commit f46fa68 into cucumber:master Sep 18, 2016
@charlierudolph
Copy link
Member

Thank you very much for your contribution!

@lock
Copy link

lock bot commented Oct 25, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Oct 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants