Commit Graph

272 Commits

Author SHA1 Message Date
Daniel Martí
958088f83b clarify NewContext's inheritance and cancellation
We have been developing this behavior over the past few weeks, but it
wasn't properly documented anywhere.

Fixes #303.
2019-04-17 13:25:09 +09:00
Daniel Martí
e4c16681d0 expose the default allocator options
For example, this can be useful if a user wants to simply add one flag
of their own, without otherwise messing with the default flags. In the
old codebase, they'd either have to build their own list from scratch,
or copy ours from source, needing to keep it in sync.
2019-04-17 13:23:43 +09:00
Daniel Martí
71ae9f7bbc clarify that Run won't work with an allocator context
We made the function error with ErrInvalidContext in that case, but the
godoc was still a bit ambiguous. Make it clearer to avoid confusion.

For #299.
2019-04-16 14:26:36 +09:00
Daniel Martí
ac47d6ba0e error in Run if passed an allocator context
The correct way to use Run is after NewContext. Using NewExecAllocator
only, which also gives a context, almost worked. This confused some
users into thinking it was a bug in chromedp.

Instead, error immediately with an invalid context error.

Fixes #299.
2019-04-14 19:56:09 +09:00
Daniel Martí
92a77355f6 README: remove obsolete TODO, add godoc examples 2019-04-09 16:21:33 +02:00
Daniel Martí
46982a1cac rework CancelError into Cancel
That way, cancelling a context while checking the error is much simpler.
The context data already holds onto the cancel func, so this requires no
internal changes.

This renders the Browser.Shutdown API obsolete, even though it doesn't
do exactly the same. If we want Cancel to do a proper shutdown action
before cancelling a browser context and killing the process, we could do
that change within the cancel logic.
2019-04-09 13:06:34 +02:00
Kenneth Shaw
e8122e4a26 Add WithDebugf() context option
Adds the high level WithDebugf() context option, and associated lower
level browser and dial options for setting a protocol wire debugger.
Additionally changes the conn.Conn.Read/Write implementations to be more
efficient, using direct easyjson.{Marshal,Unmarshal} calls and logging
to debug func when available.
2019-04-09 10:22:11 +02:00
Daniel Martí
b481eeac51 support fetching errors from cancellation
The API isn't very shiny, but it works. It doesn't matter that much, as
most users won't care about these errors.

Fixes #295.
2019-04-08 18:52:14 +02:00
Daniel Martí
b8efcf0691 support using BrowserOption in NewContext
While at it, remove the error return from BrowserOption, to make it
consistent with all the other option func types.

We don't have a good test for this feature yet, but at least we check
that it doesn't crash or error via an example.

Fixes #292.
2019-04-08 13:03:55 +02:00
Daniel Martí
a29b1ec1d6 deflake TestNavigate
For some reason, this test fails about half the time on Travis, but I
can't get it to fail even after stress-testing hundreds of concurrent
runs.

It might be because Travis is on a much older version of Chrome. We'll
fix that soon, by having chromedp select a specific version of Chrome.

For now, make it more conservative, not assuming that a Location after a
Navigate isn't racy.
2019-04-08 12:38:36 +02:00
Daniel Martí
11b3a5dc8f rename context.go to chromedp.go
And merge context_test.go with chromedp_test.go.

While at it, move the package godoc to chromedp.go, as that's now the
file named after the package.
2019-04-08 12:33:08 +02:00
Daniel Martí
d0484ed1c5 simplify the allocator API
Exposing NewAllocator and AllocatorOption was unnecessary, and it made
the API more complex to use and understand.

Instead, have users call NewExecAllocator directly. This removes some
code, and simplifies the examples and tests.
2019-04-08 12:10:59 +02:00
Daniel Martí
687cf6d766 wait for cleanup when cancelling the first context
We were doing this for extra open tabs, since NewContext was taking care
of detaching and closing the respective target.

And cancelling an entire allocator also properly waited for all the
resources, such as processes and temporary directories, to be cleaned
up.

However, this didn't work for a browser's first context; cancelling it
should wait for that one browser's resources to be cleaned up, but that
wasn't implemented. Do that, fixing the TODO in TestExecAllocator.
2019-04-07 23:40:29 +02:00
Daniel Martí
939d377090 avoid hanging when Chrome is closed separately
It's Run that actually starts a Browser, not NewContext. If the browser
is closed or crashes, the browser handler will fail to read from the
websocket, and its goroutines will stop.

However, the target handler's goroutines may not stop. The browser
handler uses a separate cancel function to stop itself when encountering
a websocket error, so that doesn't propagate to the original context
children, like the target handler.

To fix this, make it so that NewContext can keep the cancel function
around, for Run to use it in this scenario. And add a test case that
tests this very edge case, which used to time out before the fix.

Fixes #289.
2019-04-07 19:28:41 +02:00
Daniel Martí
b977e305d2 fix regression when using Run twice on the first ctx
We don't want to always set c.first, as that can change the field from
true to false.
2019-04-07 18:49:53 +02:00
Daniel Martí
c41ed01b6a close a page when cancelling its context
For all contexts except the first browser context, as in that case the
allocator and browser handler already take care of shutting down the
process and goroutines, respectively.

Fixes #293.
2019-04-07 14:22:07 +02:00
Daniel Martí
c313fa1c1d add TargetID to Target
This will be useful later on, for example to be able to close a target
(a page) once it gets cancelled.
2019-04-07 13:37:32 +02:00
Daniel Martí
b647c708b4 don't create an extra tab when starting a browser
Chrome already starts with a blank page, so use that for the first
target context instead of creating a new tab.

Add the first version of the Targets API, which is useful to test this
feature.

Fixes #291.
2019-04-07 01:18:15 +02:00
Daniel Martí
97e80a00d5 make NewAllocator's cancel func block on Wait
This way, the simple examples and tests don't need to do that
separately. Practically all users will want this cleanup work to be
synchronous, and practically all Go APIs are synchronous by default, so
this makes chromedp easier to use.
2019-04-06 22:13:40 +02:00
Daniel Martí
504561eab2 bump cdproto dep to ignore deprecated events
We no longer have to keep a list of deprecated events to avoid panics in
cdproto.
2019-04-06 01:11:43 +02:00
Kenneth Shaw
65a198c84e Generic code cleanup
Adding some comments, removing unused items, and renaming handler.go to
target.go to reflect the internal type name changes.
2019-04-03 09:03:41 +02:00
Daniel Martí
ece2b3ab92 give examples better names to appease vet 2019-04-02 13:51:47 +02:00
Daniel Martí
896fbe60c2 consistently use %02d for subtest index names
"test" as part of the name is redundant, and spaces aren't recommended.

Add a padding for two digits, so that tests with more than a handful of
subtests still print in a nice way.
2019-04-01 19:58:01 +01:00
Daniel Martí
e482cdfc4d clean up uses of Run in the tests
Many consecutive calls to Run can be collapsed into a single call. While
at it, make the error handling style more consistent. Overall removes 70
lines of repetitive code.
2019-04-01 19:55:40 +01:00
Daniel Martí
120628a01c fix data race when spawning tabs concurrently
This fixes the data race uncovered by the recent refactor to run all
tests as tabs under the same browser.

The problem was that a write on the pages map could be done from the
goroutine calling NewContext to create a new map, while other goroutines
could similarly read or write the same map.

Instead of adding a lock around the map, make one of the Browser's
goroutines be the sole user of the map. To make that extra obvious and
avoid potential races in the future, declare the map inside the
goroutine's scope.

For some reason, this makes the Attributes tests flakier than before.
For now, add short sleeps; we can investigate that separately, now that
the data races are gone.
2019-04-01 19:31:05 +01:00
Daniel Martí
7c8529b914 give up on refactoring TestFileUpload
The reason that t.Parallel broke the tests was because the parent test
must finish before the parallel subtests can start. So, we'd be closing
the httptest server and removing the tmpfile before any of the parallel
subtests even began.

We could refactor this to make the subtests parallel, but they're only
two, and the parent is already parallel, so it's not worth the effort.
See the added comment.
2019-04-01 17:26:11 +01:00
Daniel Martí
41e913e571 various minor cleanups
Remove the log option lines from testAllocate; right now, we don't have
these options for Target, and Target doesn't log much anyway. We can
always revisit this in the future.

While at it, simplify some code.
2019-04-01 17:12:17 +01:00
Daniel Martí
ad8809efb7 use time.NewTimer instead of time.After in Sleep
To fix a potential temporary goroutine leak; see the added comment. The
leaked goroutine would eventually stop once the timer is fired, but
until then, the goroutine could be unnecessarily left around.
2019-04-01 17:03:35 +01:00
Daniel Martí
0d568ec2a4 change Run to allow many actions
This can simplify some common use cases, like running a few actions
directly, or running no actions at all. It's also an almost entirely
backwards compatible change, as all Run call sites should continue to
compile and work.

Leave Tasks, as it can still be useful for functions to return complex
sequences of actions as a single Action.
2019-04-01 16:59:23 +01:00
Daniel Martí
fb23c1750a fix data races in table-driven parallel subtests
t.Parallel effectively fires off a goroutine, so we can't use the test
range variable directly. That can result in different subtests using the
same test case data, causing sporadic failures, or some test cases
rarely being actually tested.

This was uncovered while stress-testing the test suite for an unrelated
refactor.

While at it, one test case in TestMouseClickNode was incorrect.
contextmenu fires on a right click, so ModifierNone won't fire it. This
wasn't caught before, as this test case was almost never ran. After the
data race fix, the test case failed consistently, before being fixed.
2019-04-01 16:48:49 +01:00
Daniel Martí
d73caffcd0 make gofumpt happy
Just a stricter gofmt; see mvdan.cc/gofumpt.
2019-04-01 16:43:03 +01:00
Daniel Martí
1decbccd74 store a Target pointer directly in Context
That way, we avoid the racy map access via Browser.executorForTarget. If
a context is attached to a target, the Target field must be non-nil.

The Browser.pages map is still racy, since multiple tabs can be created
concurrently; we'll fix this other data race in another commit.
2019-04-01 14:31:11 +01:00
Daniel Martí
117274bc5d run all tests as separate tabs on one browser
This vastly speeds up 'go test' on my laptop from ~10s to ~3s, as we
save a lot of time spinning up new Chrome browser processes.

In practice, each tab is a separate process anyway, but there's a lot of
added overhead if we're firing up the entire browser, particularly with
an empty user data dir.

This makes 'go test' racy now, as Browser doesn't support creating tabs
concurrently right now. Follow-up commits will fix that, with the help
of 'go test -race' after this commit.
2019-04-01 14:25:24 +01:00
Daniel Martí
661ef78880 don't crash when loading pages with iframes
We broke this in the refactor because of a nil pointer dereference, but
we didn't catch that as none of the tests loaded a page with an iframe.
That is, a page with multiple frames.

Add such a test, and fix the bug by creating an almost-empty frame when
we start receiving events about a new frame before it's navigated to.
2019-04-01 12:18:16 +01:00
Daniel Martí
8ff2971fc5 test cancelling an entire Allocator directly
To ensure that it propagates to each browser correctly.
2019-04-01 12:18:16 +01:00
Daniel Martí
a0a36956a8 add support for opening multiple tabs
On a single browser, that is. And port the example from _example,
proving that it works.
2019-04-01 12:18:16 +01:00
Daniel Martí
2b925df0fb rewrite TestReload without a sleep 2019-04-01 12:18:16 +01:00
Daniel Martí
f742f327a7 speed up the screenshot tests, and test the images
Using a smaller viewport speeds up both tests, and lets us know what
dimensions to expect in TestCaptureScreenshot.

For TestScreenshot, we can know what dimensions to expect in advance, as
we have the images in testdata.

'go test -run Screenshot' goes from ~0.9s to ~0.5s on my machine.

Finally, don't run ExampleTitle as part of 'go test', as it's slow.
2019-04-01 12:18:16 +01:00
Daniel Martí
0e92de5e65 make ExampleExecAllocatorOption less flaky
The Default folder is created asynchronously to Chrome starting to
listen on the debugging protocol port. So we can't expect it to exist.

Instead, base the example on DevToolsActivePort, which we can rely on.
2019-04-01 12:18:16 +01:00
Daniel Martí
32d4bae280 clean up various pieces of the API
First, collapse Browser.Start with NewBrowser. There's no reason to
split them up.

Second, unexport Browser.userDataDir, since it's only needed for a test.
It's also a bad precedent, as only the ExecAllocator will control the
user data directory.

Third, export Context.Browser, since we were already exporting
Context.Allocator.

Finally, remove the Executor interface, a duplicate of cdp.Executor.
2019-04-01 12:18:16 +01:00
Daniel Martí
a93c63124f add some missing godocs on allocators and Run 2019-04-01 12:18:16 +01:00
Daniel Martí
b136a6267e remove Context's Wait method for now
All it did was wait on the entire allocator, which is confusing. From
the user's perspective, this wait method should instead wait for the
resources for its own browser, and not any other browsers sharing the
same allocator.

We haven't decided how to integrate that into our API, so simply replace
it with Allocator.Wait.
2019-04-01 12:18:16 +01:00
Daniel Martí
e698c943b3 make the simple and allocator examples runnable
This way, not only do we ensure that they always build, they're also
verified as part of 'go test'.
2019-04-01 12:18:16 +01:00
Daniel Martí
5fb1c07412 start running the tests on CI again
Now that they're both faster and more reliable than before the refactor.

On my laptop, 'go test' now consistently takes ~10s, and I haven't found
any flakes in the past couple of days.
2019-04-01 12:18:16 +01:00
Daniel Martí
2ca3ea3591 avoid a second map in ExecAllocator
Instead, write the args list directly.
2019-04-01 12:18:16 +01:00
Daniel Martí
6fb5264bbd use DisableGPU in the tests
On my i5-8350U, the option takes 'go test' from ~11s to ~10s, from a
manual look over a few runs.
2019-04-01 12:18:16 +01:00
Daniel Martí
da4ac414ed get rid of all sleeps in tests
The navigate sleeps can be replaced by appropriate wait actions.

Some other tests don't need any sleeps at all. This might be because
work is done synchronously now; I haven't been able to get test flakes
after hundreds of test runs with flags like -parallel=32 -count=200.
2019-04-01 12:18:16 +01:00
Daniel Martí
7c1a9fbf3e get rid of all exceptions
We hadn't noticed a few uncaught exceptions being received from the
browser, because the events were ignored. Start printing them via the
error logger.

The ones we were getting were caused by testAllocate running Navigate
actions when the path argument was empty. Navigating to "testdata/"
causes JS exceptions, as it's not a valid page.

Instead, leave the new target pointing at a blank document.
2019-04-01 12:18:16 +01:00
Daniel Martí
c109f6ebfd use consistent context.Context var names 2019-04-01 12:18:16 +01:00
Daniel Martí
61f0a8da68 make some linters a bit happier 2019-04-01 12:18:16 +01:00