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.
This commit is contained in:
Daniel Martí 2019-04-06 21:58:54 +02:00
parent 504561eab2
commit 97e80a00d5
5 changed files with 23 additions and 37 deletions

View File

@ -22,8 +22,12 @@ type Allocator interface {
// as temporary directories) will be freed. // as temporary directories) will be freed.
Allocate(context.Context) (*Browser, error) Allocate(context.Context) (*Browser, error)
// Wait can be called after cancelling an allocator's context, to block // TODO: Wait should probably return an error, which can then be
// until all of its resources have been freed. // retrieved by the user if just calling cancel().
// Wait blocks until an allocator has freed all of its resources.
// Cancelling the context obtained via NewAllocator will already perform
// this operation, so normally there's no need to call Wait directly.
Wait() Wait()
} }
@ -38,7 +42,11 @@ func NewAllocator(parent context.Context, opts ...AllocatorOption) (context.Cont
} }
ctx = context.WithValue(ctx, contextKey{}, c) ctx = context.WithValue(ctx, contextKey{}, c)
return ctx, cancel cancelWait := func() {
cancel()
c.Allocator.Wait()
}
return ctx, cancelWait
} }
// AllocatorOption is a allocator option. // AllocatorOption is a allocator option.

View File

@ -30,17 +30,14 @@ func TestExecAllocator(t *testing.T) {
t.Fatalf("wanted %q, got %q", want, got) t.Fatalf("wanted %q, got %q", want, got)
} }
// TODO: make cancel() work here too
poolCancel()
tempDir := FromContext(taskCtx).Browser.userDataDir tempDir := FromContext(taskCtx).Browser.userDataDir
pool := FromContext(taskCtx).Allocator if _, err := os.Lstat(tempDir); !os.IsNotExist(err) {
cancel()
pool.Wait()
if _, err := os.Lstat(tempDir); os.IsNotExist(err) {
return
}
t.Fatalf("temporary user data dir %q not deleted", tempDir) t.Fatalf("temporary user data dir %q not deleted", tempDir)
} }
}
func TestExecAllocatorCancelParent(t *testing.T) { func TestExecAllocatorCancelParent(t *testing.T) {
t.Parallel() t.Parallel()
@ -56,15 +53,11 @@ func TestExecAllocatorCancelParent(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
tempDir := FromContext(taskCtx).Browser.userDataDir
pool := FromContext(taskCtx).Allocator
// Canceling the pool context should stop all browsers too. // Canceling the pool context should stop all browsers too.
poolCancel() poolCancel()
pool.Wait()
if _, err := os.Lstat(tempDir); os.IsNotExist(err) { tempDir := FromContext(taskCtx).Browser.userDataDir
return if _, err := os.Lstat(tempDir); !os.IsNotExist(err) {
}
t.Fatalf("temporary user data dir %q not deleted", tempDir) t.Fatalf("temporary user data dir %q not deleted", tempDir)
} }
}

View File

@ -64,6 +64,5 @@ func TestMain(m *testing.M) {
code := m.Run() code := m.Run()
cancel() cancel()
FromContext(allocCtx).Allocator.Wait()
os.Exit(code) os.Exit(code)
} }

View File

@ -26,10 +26,6 @@ func ExampleTitle() {
fmt.Println(title) fmt.Println(title)
// wait for the resources to be cleaned up
cancel()
chromedp.FromContext(ctx).Allocator.Wait()
// no expected output, to not run this test as part of 'go test'; it's // no expected output, to not run this test as part of 'go test'; it's
// too slow, requiring internet access. // too slow, requiring internet access.
} }
@ -69,10 +65,6 @@ func ExampleExecAllocator() {
lines := bytes.Split(bs, []byte("\n")) lines := bytes.Split(bs, []byte("\n"))
fmt.Printf("DevToolsActivePort has %d lines\n", len(lines)) fmt.Printf("DevToolsActivePort has %d lines\n", len(lines))
// wait for the resources to be cleaned up
cancel()
chromedp.FromContext(allocCtx).Allocator.Wait()
// Output: // Output:
// DevToolsActivePort has 2 lines // DevToolsActivePort has 2 lines
} }
@ -101,10 +93,6 @@ func ExampleNewContext_manyTabs() {
fmt.Printf("Same browser: %t\n", c1.Browser == c2.Browser) fmt.Printf("Same browser: %t\n", c1.Browser == c2.Browser)
fmt.Printf("Same tab: %t\n", c1.Target == c2.Target) fmt.Printf("Same tab: %t\n", c1.Target == c2.Target)
// wait for the resources to be cleaned up
cancel()
c1.Allocator.Wait()
// Output: // Output:
// Same browser: true // Same browser: true
// Same tab: false // Same tab: false

View File

@ -9,15 +9,13 @@ import (
"github.com/chromedp/cdproto/input" "github.com/chromedp/cdproto/input"
) )
const (
// inViewportJS is a javascript snippet that will get the specified node // inViewportJS is a javascript snippet that will get the specified node
// position relative to the viewport and returns true if the specified node // position relative to the viewport and returns true if the specified node
// is within the window's viewport. // is within the window's viewport.
inViewportJS = `(function(a) { const inViewportJS = `(function(a) {
var r = a[0].getBoundingClientRect(); var r = a[0].getBoundingClientRect();
return r.top >= 0 && r.left >= 0 && r.bottom <= window.innerHeight && r.right <= window.innerWidth; return r.top >= 0 && r.left >= 0 && r.bottom <= window.innerHeight && r.right <= window.innerWidth;
})($x('%s'))` })($x('%s'))`
)
func TestMouseClickXY(t *testing.T) { func TestMouseClickXY(t *testing.T) {
t.Parallel() t.Parallel()