The existing test only exercised the not-found-interface path. Now that
ipForwardingEnabledLinux opens its sysctl key with os.OpenInRoot
(840c6e3d3, #20572), also verify that the global keys and the
per-interface keys for every interface actually present on the machine
can be read without error, for both IPv4 and IPv6.
Updates #20572
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: Ie204a163ab9f8670abedd79a4ac81e400f71aab7
147 lines
3.7 KiB
Go
147 lines
3.7 KiB
Go
// Copyright (c) Tailscale Inc & contributors
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package netutil
|
|
|
|
import (
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
type conn struct {
|
|
net.Conn
|
|
}
|
|
|
|
func TestOneConnListener(t *testing.T) {
|
|
c1 := new(conn)
|
|
a1 := dummyAddr("a1")
|
|
|
|
// Two Accepts
|
|
ln := NewOneConnListener(c1, a1)
|
|
if got := ln.Addr(); got != a1 {
|
|
t.Errorf("Addr = %#v; want %#v", got, a1)
|
|
}
|
|
c, err := ln.Accept()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c != c1 {
|
|
t.Fatalf("didn't get c1; got %p", c)
|
|
}
|
|
c, err = ln.Accept()
|
|
if err != io.EOF {
|
|
t.Errorf("got %v; want EOF", err)
|
|
}
|
|
if c != nil {
|
|
t.Errorf("unexpected non-nil Conn")
|
|
}
|
|
|
|
// Close before Accept
|
|
ln = NewOneConnListener(c1, a1)
|
|
ln.Close()
|
|
_, err = ln.Accept()
|
|
if err != io.EOF {
|
|
t.Fatalf("got %v; want EOF", err)
|
|
}
|
|
|
|
// Implicit addr
|
|
ln = NewOneConnListener(c1, nil)
|
|
if ln.Addr() == nil {
|
|
t.Errorf("nil Addr")
|
|
}
|
|
}
|
|
|
|
// roundTripperFunc is an http.RoundTripper that is not a *http.Transport,
|
|
// used to exercise the fallback path of NewDefaultTransport.
|
|
type roundTripperFunc func(*http.Request) (*http.Response, error)
|
|
|
|
func (f roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) }
|
|
|
|
func TestNewDefaultTransport(t *testing.T) {
|
|
// Standard case: http.DefaultTransport is still a *http.Transport, so we
|
|
// get a clone of it with the stdlib defaults.
|
|
tr := NewDefaultTransport()
|
|
if tr == nil {
|
|
t.Fatal("got nil transport")
|
|
}
|
|
if got, want := tr.MaxIdleConns, 100; got != want {
|
|
t.Errorf("MaxIdleConns = %d; want %d", got, want)
|
|
}
|
|
if got, want := tr.IdleConnTimeout, 90*time.Second; got != want {
|
|
t.Errorf("IdleConnTimeout = %v; want %v", got, want)
|
|
}
|
|
if !tr.ForceAttemptHTTP2 {
|
|
t.Error("ForceAttemptHTTP2 = false; want true")
|
|
}
|
|
|
|
// Regression case: an application has replaced http.DefaultTransport with
|
|
// a RoundTripper that is not a *http.Transport. NewDefaultTransport must
|
|
// not panic and must still return a usable transport with stdlib defaults.
|
|
orig := http.DefaultTransport
|
|
defer func() { http.DefaultTransport = orig }()
|
|
http.DefaultTransport = roundTripperFunc(func(*http.Request) (*http.Response, error) {
|
|
return nil, nil
|
|
})
|
|
|
|
tr = NewDefaultTransport()
|
|
if tr == nil {
|
|
t.Fatal("got nil transport on fallback path")
|
|
}
|
|
if got, want := tr.MaxIdleConns, 100; got != want {
|
|
t.Errorf("fallback MaxIdleConns = %d; want %d", got, want)
|
|
}
|
|
if got, want := tr.IdleConnTimeout, 90*time.Second; got != want {
|
|
t.Errorf("fallback IdleConnTimeout = %v; want %v", got, want)
|
|
}
|
|
if !tr.ForceAttemptHTTP2 {
|
|
t.Error("fallback ForceAttemptHTTP2 = false; want true")
|
|
}
|
|
if tr.DialContext == nil {
|
|
t.Error("fallback DialContext = nil; want non-nil")
|
|
}
|
|
if tr.Proxy == nil {
|
|
t.Error("fallback Proxy = nil; want non-nil")
|
|
}
|
|
}
|
|
|
|
func TestIPForwardingEnabledLinux(t *testing.T) {
|
|
if runtime.GOOS != "linux" {
|
|
t.Skipf("skipping on %s", runtime.GOOS)
|
|
}
|
|
got, err := ipForwardingEnabledLinux(ipv4, "some-not-found-interface")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got {
|
|
t.Errorf("got true; want false")
|
|
}
|
|
|
|
// The global keys and the per-interface keys for each interface on
|
|
// the machine should all be readable without error, whatever their
|
|
// values.
|
|
for _, p := range []protocol{ipv4, ipv6} {
|
|
on, err := ipForwardingEnabledLinux(p, "")
|
|
if err != nil {
|
|
t.Errorf("global (proto %v): %v", p, err)
|
|
}
|
|
t.Logf("global (proto %v) = %v", p, on)
|
|
}
|
|
ifaces, err := net.Interfaces()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, iface := range ifaces {
|
|
for _, p := range []protocol{ipv4, ipv6} {
|
|
on, err := ipForwardingEnabledLinux(p, iface.Name)
|
|
if err != nil {
|
|
t.Errorf("%s (proto %v): %v", iface.Name, p, err)
|
|
}
|
|
t.Logf("%s (proto %v) = %v", iface.Name, p, on)
|
|
}
|
|
}
|
|
}
|