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

print & log port bind failures, dns-related test coverage, test improvements #239

Merged
merged 10 commits into from
Apr 6, 2020

Conversation

nonrational
Copy link
Member

@nonrational nonrational commented Mar 27, 2020

This PR addresses a bug discovered while triaging #237.

Currently, puma-dev only fails to start it can't bind to the configured http port. If the tls or dns goroutines fail (often because the port is already taken), they do so silently and the user is led to believe that everything worked. This change ensures that port bind failures show up in logs and/or stdout if you're running interactively.

Changes

  • check and print return status of http.serve and dns.serve. if these goroutines fail to bind to the specified port, it'll now be logged.
    • use tomb.Tomb in dns.go to allow for easy return of errors
  • expose main.shutdown channel for better control over the puma-dev server launched in tests. This way, each test that needs to boot its own puma-dev server can correctly clean up after itself. this ends up calling os.Exit(0) and we lose test failures, so pulled back on this approach.
  • dns lookup tests for a running puma-dev dns server (on macOS only)
  • dns tests that ensure we listen for tcp and udp on the configured dns port
  • disable high_sierra in circleci. I suspect there's still a bug in fsevents that causes the restart.txt related tests to often (but not always) fail.

Demo

Old

$ puma-dev -dns-port 53  -https-port 443
2020/03/27 18:18:28 Existing valid puma-dev CA keypair found. Assuming previously trusted.
* Directory for apps: /Users/norton/.puma-dev
* Domains: test
* DNS Server port: 53
* HTTP Server port: 9280
* HTTPS Server port: 443
! Puma dev listening on http and https

New

$ ./puma-dev -dns-port 53  -https-port 443
2020/03/27 18:18:16 Existing valid puma-dev CA keypair found. Assuming previously trusted.
* Directory for apps: /Users/norton/.puma-dev
* Domains: test
* DNS Server port: 53
* HTTP Server port: 9280
* HTTPS Server port: 443
! Puma dev running...
! HTTPS Server failed: listen tcp 127.0.0.1:443: bind: permission denied
! DNS Server failed: listen tcp 127.0.0.1:53: bind: permission denied

@@ -98,7 +98,7 @@ workflows:
version: 2
test:
jobs:
- test_high_sierra
# - test_high_sierra
Copy link
Member Author

Choose a reason for hiding this comment

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

this is only used in my fork, but high sierra is flaking a lot, so turning off for now.

@@ -17,7 +17,7 @@ import (
var (
fDebug = flag.Bool("debug", false, "enable debug output")
fDomains = flag.String("d", "test", "domains to handle, separate with :, defaults to test")
fPort = flag.Int("dns-port", 9253, "port to listen on dns for")
fDNSPort = flag.Int("dns-port", 9253, "port to listen on dns for")
Copy link
Member Author

Choose a reason for hiding this comment

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

give this flag variable a better name

cmd/puma-dev/main_darwin.go Outdated Show resolved Hide resolved
go func() {
if err := dns.Serve(domains); err != nil {
fmt.Printf("! DNS Server failed: %v\n", err)
}
Copy link
Member Author

Choose a reason for hiding this comment

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

check the return of dns.Serve

go func() {
if err := http.ServeTLS(tlsSocketName); err != nil {
fmt.Printf("! HTTPS Server failed: %v\n", err)
}
Copy link
Member Author

Choose a reason for hiding this comment

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

check the return of http.ServeTLS

Address string
Address string
udpServer *dns.Server
tcpServer *dns.Server
Copy link
Member Author

Choose a reason for hiding this comment

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

expose pointers to the servers were running internally, so we can shut them down gracefully in tests.

Copy link
Member Author

Choose a reason for hiding this comment

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

also, use a constructor so these pointers exist before calling Serve.

dev/dns.go Outdated Show resolved Hide resolved
dev/dns.go Outdated Show resolved Hide resolved
dev/dns.go Show resolved Hide resolved
dev/dns_test.go Outdated Show resolved Hide resolved
@nonrational nonrational changed the title print & log port bind failures, dns-related test coverage, test improvements [wip] print & log port bind failures, dns-related test coverage, test improvements Mar 28, 2020
@nonrational
Copy link
Member Author

nonrational commented Mar 28, 2020

looking into resolving the race i created, marking at work-in-progress done. instantiating the udp and tcp servers in a constructor solves the race.

==================
WARNING: DATA RACE
Read at 0x000000d442d0 by goroutine 8:
  github.com/puma/puma-dev/dev.TestServeDNS_TCP_UDP.func3()
      /home/norton/go/src/github.com/puma/puma-dev/dev/dns_test.go:30 +0x3a
  github.com/puma/puma-dev/dev.TestServeDNS_TCP_UDP.func4.1()
      /home/norton/go/src/github.com/puma/puma-dev/dev/dns_test.go:41 +0x49
  github.com/puma/puma-dev/dev.TestServeDNS_TCP_UDP.func4()
      /home/norton/go/src/github.com/puma/puma-dev/dev/dns_test.go:48 +0x141
  github.com/avast/retry-go.Do()
      /home/norton/go/pkg/mod/github.com/avast/retry-go@v2.5.0+incompatible/retry.go:104 +0x2f8
  github.com/puma/puma-dev/dev.TestServeDNS_TCP_UDP()
      /home/norton/go/src/github.com/puma/puma-dev/dev/dns_test.go:34 +0x38b
  testing.tRunner()
      /home/norton/.asdf/installs/golang/1.13.8/go/src/testing/testing.go:909 +0x199

Previous write at 0x000000d442d0 by goroutine 12:
  github.com/puma/puma-dev/dev.(*DNSResponder).Serve.func1()
      /home/norton/go/src/github.com/puma/puma-dev/dev/dns.go:75 +0x172
  gopkg.in/tomb%2ev2.(*Tomb).run()
      /home/norton/go/pkg/mod/gopkg.in/tomb.v2@v2.0.0-20140626144623-14b3d72120e8/tomb.go:153 +0x4c

is there really no way to specify test-only dependencies?
move unexported methods to the bottom
first pass at catching errors from dns port bind
refactor to use tomb over chan
expose errors in listening for TLS and DNS
remove default error handling. bail if we didn't get a good address
remove "debug" messaging about not regenerating keypair
nevermind -- most folks don't run this interactively, and its handy to have it in the log
for now, just skip dns tests outside darwin
fix compile error
skip high_sierra for now. fsevents are broken
loop over tcp, udp
go mod tidy
map[string](func() interface{}) is awesome.
refactor stdout capture to use return function instead of passed function call
forgot one
see if waiting for the shutdown to finish helps
assert serve doesn't serve an error either
only try to shutdown the server if we have a handle to it
defer shutdown and fail if unable to shutdown
remove timeout. we'll see if that fails.
remove error stubs
use constructor to init dns servers to avoid race
remove retry print
missed one
shorten timeout, add comments to clarify intent of retries
only run one server per set of server test scenarios, so os.Exit will handle the cleanup
put shutdown back inside main -- it calls os.Exit() which borks testing
pull out additional state into each platform spec
ensure we run things on completely non-standard ports
missed an import
@nonrational nonrational changed the title [wip] print & log port bind failures, dns-related test coverage, test improvements print & log port bind failures, dns-related test coverage, test improvements Apr 3, 2020

configureAndBootPumaDevServer(t, map[string]string{
"dir": appLinkDir,
"dns-port": "65053",
Copy link
Member Author

Choose a reason for hiding this comment

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

we need platform specific server runs here, because darwin supports some flags that linux doesn't support.

"https-port": "65443",
})

runPlatformAgnosticTestScenarios(t)
Copy link
Member Author

@nonrational nonrational Apr 3, 2020

Choose a reason for hiding this comment

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

most examples are shared, but platform-specific stuff can live in each file.

stop := make(chan os.Signal, 1)

signal.Notify(stop, os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM)
shutdown := make(chan os.Signal, 1)
Copy link
Member Author

Choose a reason for hiding this comment

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

just a rename here.


assert.True(t, ok)
assert.False(t, exit.Success())
}
Copy link
Member Author

Choose a reason for hiding this comment

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

diff is pretty useless here, since i reordered and renamed a bunch of the private methods.

type DNSResponder struct {
Address string
Domains []string
Copy link
Member Author

@nonrational nonrational Apr 3, 2020

Choose a reason for hiding this comment

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

now a single DNSResponder instance is bound to its domains, rather than being able to call Serve multiple times with diff arguments on the same instance.

Copy link
Member

@evanphx evanphx left a comment

Choose a reason for hiding this comment

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

Looks goooooooood!

@nonrational nonrational merged commit b98aa54 into puma:master Apr 6, 2020
@nonrational nonrational deleted the log-port-bind-failures branch April 6, 2020 17:50
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.

2 participants