-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
Conversation
Hey @estherkim, these files were changed:
Hey @rsimha, these files were changed:
|
e3c06c9
to
2575952
Compare
a1ba9c0
to
2dfa71c
Compare
There was a problem hiding this 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.
// if (!isTravisBuild()) { | ||
// return Promise.resolve(null); | ||
// } |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
- You might be doing other stuffs on your computer while running tests, and it can't distinguish them from those generated from tests
- This needs to be ran as root, which is doable but needs some special handling.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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+\)$/; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea. Will do.
/** | ||
* 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(); | ||
} | ||
}); | ||
} |
There was a problem hiding this comment.
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:
amphtml/build-system/tasks/nailgun.js
Lines 186 to 187 in 1b24138
nailgunStart.description = 'Starts up a nailgun server for closure compiler'; | |
nailgunStop.description = 'Stops an already running nailgun server'; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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.
Have you perused alternatives to doing this in JavaScript during test execution? |
@kristoferbaxter That is possible with unit/integration, but no good js options on e2e are available on browser (except for setting up a proxy). |
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? |
@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? |
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? |
@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 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. |
Is this PR still active? |
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.