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

Monitor external requests from tests on Travis #26756

Closed
wants to merge 1 commit into from

Conversation

powerivq
Copy link
Contributor

@powerivq powerivq commented Feb 12, 2020

This PR implements #26754

Currently, it only prints on the log intercepted domains, and does not mark the test as failed. We can test running it for a while, see how stable it is, and enable that in the future.

@amp-owners-bot
Copy link

amp-owners-bot bot commented Feb 12, 2020

Hey @estherkim, these files were changed:

  • build-system/pr-check/e2e-tests.js
  • build-system/pr-check/local-tests.js
  • build-system/pr-check/single-pass-tests.js
  • build-system/pr-check/utils.js

Hey @rsimha, these files were changed:

  • build-system/pr-check/e2e-tests.js
  • build-system/pr-check/local-tests.js
  • build-system/pr-check/single-pass-tests.js
  • build-system/pr-check/utils.js

@powerivq powerivq force-pushed the dns-mon branch 18 times, most recently from e3c06c9 to 2575952 Compare February 14, 2020 08:08
@powerivq powerivq force-pushed the dns-mon branch 7 times, most recently from a1ba9c0 to 2dfa71c Compare February 20, 2020 21:51
@powerivq powerivq changed the title WIP Test DNS monitor Monitor external requests from tests on Travis Feb 20, 2020
Copy link
Contributor

@rsimha rsimha left a comment

Choose a reason for hiding this comment

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

Thanks for working on this PR. I think it will be valuable in reducing flakiness due to network requests.

I've requested a change to how gulp dns-monitor works. Happy to review once again.

Comment on lines +144 to +146
// if (!isTravisBuild()) {
// return Promise.resolve(null);
// }
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this necessary? What is the current behavior during local development?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not strictly necessary because only pr-check/xxx.js references to it. I put it back as an extra layer of protection in case it is needed in special circumstances. It is supposed to be turned off during local dev, since

  1. You might be doing other stuffs on your computer while running tests, and it can't distinguish them from those generated from tests
  2. This needs to be ran as root, which is doable but needs some special handling.

Copy link
Contributor

Choose a reason for hiding this comment

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

Gotcha. In that case, we should just run this on Travis. Speaking of which, Travis VMs do background stuff too. For instance, if you're using this during a sauce labs run, there is a proxy on the Travis VM communicating with the Sauce VM.

Is it safe to say this should only be used for local unit, integration, and e2e tests?

/cc @estherkim for thoughts here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I haven't turned it on for sauce lab runs. If we need to, we could whitelist them. (I've whitelisted Google Cloud-specific stuff travis uses and app engine stuff infra team uses) As long as they remain constant, it's not a problem.

/\.test$/, // .test TLD is safe to use for tests
];

const TCPDUMP_DNS_REGEX = /^(\d{2}:\d{2}:\d{2})\.\d{6} IP6? [^ ]+ > [^ ]+: \d+\+ (A|AAAA)\? ([^ ]+)\. \(\d+\)$/;
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a complicated regex that will be hard to maintain. Can you split it into parts with inline comments for each part? Can you also add a comment above it explaining how it works at a high level?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great idea. Will do.

Comment on lines +264 to +291
/**
* Executes the command and check unpermitted DNS requests in the interim. In
* case if failure, it terminates.
* @param {string} cmd
* @param {string} fileName
*/
async function timedExecOrDieWithDnsMonitor(cmd, fileName = 'utils.js') {
return startDnsMonitor_().then(dnsMonitor => {
timedExecOrDie(cmd, fileName);
if (dnsMonitor) {
dnsMonitor.stdout.pipe(process.stdout);
dnsMonitor.stderr.pipe(process.stderr);
dnsMonitor.on('exit', code => {
if (code) {
process.exit(1);
}
resolver();
});
dnsMonitor.kill('SIGTERM');
let resolver;
return new Promise(resolverIn => {
resolver = resolverIn;
});
} else {
return Promise.resolve();
}
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd like to request a fundamental change to the way the gulp dns-monitor task works, which will make this function unnecessary.

Right now, the responsibility of running gulp dns-monitor in the background falls on the caller, and different callers will have to independently figure out how to start a background daemon.

Instead, I suggest you make gulp dns-monitor start as a daemon process on its own. That way, you can run something like this:

gulp dns-monitor --start
gulp e2e
gulp dns-monitor --stop

There is an example for this behavior in the gulp nailgun task:

nailgunStart.description = 'Starts up a nailgun server for closure compiler';
nailgunStop.description = 'Stops an already running nailgun server';

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've used gulp nailgun as the blueprint when writing this! For this dns-monitor, I feel the biggest difference is that its return code (0 or 1) would dictate whether the Travis test should fail. We could do that in theory, but it would require a new way for doing inter-process communication.

Copy link
Contributor

Choose a reason for hiding this comment

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

As discussed offline, my main objection is that most of the code in timedExecOrDieWithDnsMonitor is specific to the dns monitor and doesn't belong in utils.js.

@@ -28,6 +28,7 @@ const {
startTimer,
stopTimer,
timedExecOrDie: timedExecOrDieBase,
timedExecOrDieWithDnsMonitor: timedExecOrDieWithDnsMonitorBase,
Copy link
Contributor

Choose a reason for hiding this comment

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

With my suggestion to change how gulp dns-monitor works, this file can be reverted.

@@ -28,6 +28,7 @@ const {
startTimer,
stopTimer,
timedExecOrDie: timedExecOrDieBase,
timedExecOrDieWithDnsMonitor: timedExecOrDieWithDnsMonitorBase,
Copy link
Contributor

Choose a reason for hiding this comment

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

With my suggestion to change how gulp dns-monitor works, this file can be reverted.

@@ -27,6 +27,7 @@ const {
startTimer,
stopTimer,
timedExecOrDie: timedExecOrDieBase,
timedExecOrDieWithDnsMonitor: timedExecOrDieWithDnsMonitorBase,
Copy link
Contributor

Choose a reason for hiding this comment

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

With my suggestion to change how gulp dns-monitor works, this file can be reverted.

@kristoferbaxter
Copy link
Contributor

Have you perused alternatives to doing this in JavaScript during test execution?

@powerivq
Copy link
Contributor Author

@kristoferbaxter That is possible with unit/integration, but no good js options on e2e are available on browser (except for setting up a proxy).

@kristoferbaxter
Copy link
Contributor

Implementing a proxy in JavaScript might be accomplished with an actual proxy as well.

Also, instead of a proxy have you considered a codemod + eslint rule?

@powerivq
Copy link
Contributor Author

powerivq commented Feb 25, 2020

@kristoferbaxter a lot of times, the code that gives problem is the (AMP) html snippets here and there. I couldn't come up with a clean way to lint it with confidence, and, at the same time, be applicable to unit, integration and e2e. Ideas?

@estherkim
Copy link
Collaborator

I don't think a dns monitor makes sense with e2e tests, because asserting sent network requests is part of the framework. My gut feeling is that blocking external requests for the entire test suite is too prescriptive.

I like the javascript / lint idea; it's lightweight, can be overwritten per test if need be, and provides guidance to the developer in a quicker feedback loop, as opposed to the CI build. In fact, I'm not sure that the CI build is the correct place for this check.

@powerivq - can you post examples of unit and integration tests that send external requests?

@powerivq
Copy link
Contributor Author

@estherkim #26651 this is an example.

It is okay for e2e tests to send out requests and to assert that, but the e2e test should not depend on the result of that external request. The point of this is to ensure that the external request is made against a known test domain. e.g amp-analytics needs to verify beacon URL is called. It can set the beacon URL to be https://example.test/view rather than https://www.example.com/view.

If absolutely necessary, a class of domains can still be whitelisted.

I would like to see linter work, because of the benefits you mentioned. It ended up either over-inclusive or under-inclusive. Also it would be difficult to cover e2e with linting rules, because URLs can appear anywhere in HTML.

@mrjoro
Copy link
Member

mrjoro commented Jun 11, 2020

Is this PR still active?

@powerivq powerivq closed this Aug 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants