You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
2.2 KiB
95 lines
2.2 KiB
// Copyright (c) Tailscale Inc & contributors
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package porttrack
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"testing"
|
|
)
|
|
|
|
func TestCollectorAndListen(t *testing.T) {
|
|
c := NewCollector(t)
|
|
|
|
labels := []string{"main", "plaintext", "debug"}
|
|
ports := make([]int, len(labels))
|
|
|
|
for i, label := range labels {
|
|
ln, err := Listen("tcp", c.Addr(label))
|
|
if err != nil {
|
|
t.Fatalf("Listen(%q): %v", label, err)
|
|
}
|
|
defer ln.Close()
|
|
p, err := c.Port(t.Context(), label)
|
|
if err != nil {
|
|
t.Fatalf("Port(%q): %v", label, err)
|
|
}
|
|
ports[i] = p
|
|
}
|
|
|
|
// All ports should be distinct non-zero values.
|
|
seen := map[int]string{}
|
|
for i, label := range labels {
|
|
if ports[i] == 0 {
|
|
t.Errorf("Port(%q) = 0", label)
|
|
}
|
|
if prev, ok := seen[ports[i]]; ok {
|
|
t.Errorf("Port(%q) = Port(%q) = %d", label, prev, ports[i])
|
|
}
|
|
seen[ports[i]] = label
|
|
}
|
|
}
|
|
|
|
func TestListenPassthrough(t *testing.T) {
|
|
ln, err := Listen("tcp", "localhost:0")
|
|
if err != nil {
|
|
t.Fatalf("Listen passthrough: %v", err)
|
|
}
|
|
defer ln.Close()
|
|
if ln.Addr().(*net.TCPAddr).Port == 0 {
|
|
t.Fatal("expected non-zero port")
|
|
}
|
|
}
|
|
|
|
func TestRoundTrip(t *testing.T) {
|
|
c := NewCollector(t)
|
|
|
|
ln, err := Listen("tcp", c.Addr("http"))
|
|
if err != nil {
|
|
t.Fatalf("Listen: %v", err)
|
|
}
|
|
defer ln.Close()
|
|
|
|
// Start a server on the listener.
|
|
go http.Serve(ln, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}))
|
|
|
|
port, err := c.Port(t.Context(), "http")
|
|
if err != nil {
|
|
t.Fatalf("Port: %v", err)
|
|
}
|
|
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/", port))
|
|
if err != nil {
|
|
t.Fatalf("http.Get: %v", err)
|
|
}
|
|
resp.Body.Close()
|
|
if resp.StatusCode != http.StatusNoContent {
|
|
t.Fatalf("status = %d, want %d", resp.StatusCode, http.StatusNoContent)
|
|
}
|
|
}
|
|
|
|
func TestPortContextCancelled(t *testing.T) {
|
|
c := NewCollector(t)
|
|
// Nobody will ever report "never", so Port should block until ctx is done.
|
|
ctx, cancel := context.WithCancel(t.Context())
|
|
cancel()
|
|
_, err := c.Port(ctx, "never")
|
|
if !errors.Is(err, context.Canceled) {
|
|
t.Fatalf("Port with cancelled context: got %v, want %v", err, context.Canceled)
|
|
}
|
|
}
|
|
|