aboutsummaryrefslogtreecommitdiffstats
path: root/device/device_test.go (follow)
Commit message (Collapse)AuthorAgeFilesLines
* global: buff -> bufJason A. Donenfeld2023-03-131-8/+8
| | | | | | This always struck me as kind of weird and non-standard. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* conn, device, tun: implement vectorized I/O plumbingJordan Whited2023-03-101-0/+69
| | | | | | | | | | | | | | | | | | | | Accept packet vectors for reading and writing in the tun.Device and conn.Bind interfaces, so that the internal plumbing between these interfaces now passes a vector of packets. Vectors move untouched between these interfaces, i.e. if 128 packets are received from conn.Bind.Read(), 128 packets are passed to tun.Device.Write(). There is no internal buffering. Currently, existing implementations are only adjusted to have vectors of length one. Subsequent patches will improve that. Also, as a related fixup, use the unix and windows packages rather than the syscall package when possible. Co-authored-by: James Tucker <james@tailscale.com> Signed-off-by: James Tucker <james@tailscale.com> Signed-off-by: Jordan Whited <jordan@tailscale.com> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* global: bump copyright yearJason A. Donenfeld2023-02-071-1/+1
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* global: bump copyright yearJason A. Donenfeld2022-09-201-1/+1
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* all: use Go 1.19 and its atomic typesBrad Fitzpatrick2022-09-041-3/+3
| | | | | Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* all: update to Go 1.18Josh Bleecher Snyder2022-03-161-1/+1
| | | | | | | | | | Bump go.mod and README. Switch to upstream net/netip. Use strings.Cut. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* global: apply gofumptJason A. Donenfeld2021-12-091-1/+1
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* global: use netip where possible nowJason A. Donenfeld2021-11-231-3/+3
| | | | | | | | There are more places where we'll need to add it later, when Go 1.18 comes out with support for it in the "net" package. Also, allowedips still uses slices internally, which might be suboptimal. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: test up/down using virtual connJason A. Donenfeld2021-02-231-23/+19
| | | | | | This prevents port clashing bugs. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: cleanup unused test componentsJason A. Donenfeld2021-02-231-24/+0
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* conn: make binds replacableJason A. Donenfeld2021-02-231-2/+3
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* global: stop using ioutilJason A. Donenfeld2021-02-171-2/+2
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: retry Up() in up/down testJason A. Donenfeld2021-02-101-2/+13
| | | | | | | | We're loosing our ownership of the port when bringing the device down, which means another test process could reclaim it. Avoid this by retrying for 4 seconds. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: return error from Up() and Down()Jason A. Donenfeld2021-02-101-5/+8
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: run fewer iterations in TestUpDownJosh Bleecher Snyder2021-02-091-2/+2
| | | | | | | | | | The high iteration count was useful when TestUpDown was the nexus of new bugs to investigate. Now that it has stabilized, that's less valuable. And it slows down running the tests and crowds out other tests. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: remove listen port race in testsJason A. Donenfeld2021-02-091-63/+43
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: generate test keys on the flyJason A. Donenfeld2021-02-091-6/+21
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: print direction when ping transit failsJosh Bleecher Snyder2021-02-081-3/+9
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: overhaul device state managementJosh Bleecher Snyder2021-02-081-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | This commit simplifies device state management. It creates a single unified state variable and documents its semantics. It also makes state changes more atomic. As an example of the sort of bug that occurred due to non-atomic state changes, the following sequence of events used to occur approximately every 2.5 million test runs: * RoutineTUNEventReader received an EventDown event. * It called device.Down, which called device.setUpDown. * That set device.state.changing, but did not yet attempt to lock device.state.Mutex. * Test completion called device.Close. * device.Close locked device.state.Mutex. * device.Close blocked on a call to device.state.stopping.Wait. * device.setUpDown then attempted to lock device.state.Mutex and blocked. Deadlock results. setUpDown cannot progress because device.state.Mutex is locked. Until setUpDown returns, RoutineTUNEventReader cannot call device.state.stopping.Done. Until device.state.stopping.Done gets called, device.state.stopping.Wait is blocked. As long as device.state.stopping.Wait is blocked, device.state.Mutex cannot be unlocked. This commit fixes that deadlock by holding device.state.mu when checking that the device is not closed. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: fix goroutine leak testJosh Bleecher Snyder2021-02-031-8/+9
| | | | | | | | | | The leak test had rare flakes. If a system goroutine started at just the wrong moment, you'd get a false positive. Instead of looping until the goroutines look good and then checking, exit completely as soon as the number of goroutines looks good. Also, check more frequently, in an attempt to complete faster. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: add up/down stress testJason A. Donenfeld2021-02-031-0/+35
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: pass cfg strings around in tests instead of readerJason A. Donenfeld2021-02-031-9/+7
| | | | | | This makes it easier to tag things onto the end manually for quick hacks. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: test that we do not leak goroutinesJosh Bleecher Snyder2021-02-031-0/+31
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* global: bump copyrightJason A. Donenfeld2021-01-281-1/+1
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: combine debug and info log levels into 'verbose'Jason A. Donenfeld2021-01-261-1/+1
| | | | | | | | | | | | There are very few cases, if any, in which a user only wants one of these levels, so combine it into a single level. While we're at it, reduce indirection on the loggers by using an empty function rather than a nil function pointer. It's not like we have retpolines anyway, and we were always calling through a function with a branch prior, so this seems like a net gain. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: add benchmark for UAPI Device.IpcGetOperationJosh Bleecher Snyder2021-01-261-0/+12
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: add latency and throughput benchmarksJosh Bleecher Snyder2021-01-071-0/+59
| | | | | | | | | | | These obviously don't perfectly capture real world performance, in which syscalls and network links have a significant impact. Nevertheless, they capture some of the internal performance factors, and they're easy and convenient to work with. Hat tip to Avery Pennarun for help designing the throughput benchmark. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: use LogLevelError for benchmarkingJosh Bleecher Snyder2021-01-071-1/+5
| | | | | | This keeps the output minimal and focused on the benchmark results. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: make test infrastructure usable with benchmarksJosh Bleecher Snyder2021-01-071-14/+14
| | | | | | Switch from *testing.T to testing.TB. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: fix races from changing private_keyJosh Bleecher Snyder2021-01-071-5/+26
| | | | | | | | | | Access keypair.sendNonce atomically. Eliminate one unnecessary initialization to zero. Mutate handshake.lastSentHandshake with the mutex held. Co-authored-by: David Anderson <danderson@tailscale.com> Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: fix persistent_keepalive_interval data racesJosh Bleecher Snyder2021-01-071-1/+14
| | | | | Co-authored-by: David Anderson <danderson@tailscale.com> Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: use channel close to shut down and drain encryption channelJosh Bleecher Snyder2021-01-071-32/+104
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The new test introduced in this commit used to deadlock about 1% of the time. I believe that the deadlock occurs as follows: * The test completes, calling device.Close. * device.Close closes device.signals.stop. * RoutineEncryption stops. * The deferred function in RoutineEncryption drains device.queue.encryption. * RoutineEncryption exits. * A peer's RoutineNonce processes an element queued in peer.queue.nonce. * RoutineNonce puts that element into the outbound and encryption queues. * RoutineSequentialSender reads that elements from the outbound queue. * It waits for that element to get Unlocked by RoutineEncryption. * RoutineEncryption has already exited, so RoutineSequentialSender blocks forever. * device.RemoveAllPeers calls peer.Stop on all peers. * peer.Stop waits for peer.routines.stopping, which blocks forever. Rather than attempt to add even more ordering to the already complex centralized shutdown orchestration, this commit moves towards a data-flow-oriented shutdown. The device.queue.encryption gets closed when there will be no more writes to it. All device.queue.encryption readers always read until the channel is closed and then exit. We thus guarantee that any element that enters the encryption queue also exits it. This removes the need for central control of the lifetime of RoutineEncryption, removes the need to drain the encryption queue on shutdown, and simplifies RoutineEncryption. This commit also fixes a data race. When RoutineSequentialSender drains its queue on shutdown, it needs to lock the elem before operating on it, just as the main body does. The new test in this commit passed 50k iterations with the race detector enabled and 150k iterations with the race detector disabled, with no failures. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: add a helper to generate uapi configsJosh Bleecher Snyder2021-01-071-28/+45
| | | | | | | | This makes it easier to work with configs in tests. It'll see heavier use over upcoming commits; this commit only adds the infrastructure. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: increase timeout in testsJosh Bleecher Snyder2021-01-071-2/+2
| | | | | | | | | When running many concurrent test processing using https://godoc.org/golang.org/x/tools/cmd/stress the processing sometimes cannot complete a ping in under 300ms. Increase the timeout to 5s to reduce the rate of false positives. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: make test setup more robustJosh Bleecher Snyder2021-01-071-28/+64
| | | | | | | | | | | | | | | | | | | | | | | | | Picking two free ports to use for a test is difficult. The free port we selected might no longer be free when we reach for it a second time. On my machine, this failure mode led to failures approximately once per thousand test runs. Since failures are rare, and threading through and checking for all possible errors is complicated, fix this with a big hammer: Retry if either device fails to come up. Also, if you accidentally pick the same port twice, delightful confusion ensues. The handshake failures manifest as crypto errors, which look scary. Again, fix with retries. To make these retries easier to implement, use testing.T.Cleanup instead of defer to close devices. This requires Go 1.14. Update go.mod accordingly. Go 1.13 is no longer supported anyway. With these fixes, 'go test -race' ran 100,000 times without failure. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: get free port when testingSina Siadat2020-07-311-5/+23
| | | | | Signed-off-by: Sina Siadat <siadat@gmail.com> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* global: update header comments and modulesJason A. Donenfeld2020-05-021-1/+1
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* tuntest: split out testing packageDavid Crawshaw2020-05-021-141/+5
| | | | | | This code is useful to other packages writing tests. Signed-off-by: David Crawshaw <crawshaw@tailscale.com>
* device: test packets between two fake devicesDavid Crawshaw2019-10-161-29/+199
| | | | Signed-off-by: David Crawshaw <crawshaw@tailscale.io>
* device: use bytes.Equal for equality check, simplify assertEqualMatt Layher2019-06-041-2/+2
| | | | Signed-off-by: Matt Layher <mdlayher@gmail.com>
* device, tun: rearrange code and fix device testsMatt Layher2019-05-291-10/+30
| | | | Signed-off-by: Matt Layher <mdlayher@gmail.com>
* global: begin modularizationJason A. Donenfeld2019-03-031-0/+48